mirror of
https://github.com/nzeemin/ukncbtl-qt.git
synced 2025-04-18 06:04:01 +03:00
[*] UKNCBTL.Qt: emubase update, doxygen comments, minor changes.
This commit is contained in:
parent
96969f11d6
commit
2408c4f8ef
6
!doxygen.bat
Normal file
6
!doxygen.bat
Normal file
@ -0,0 +1,6 @@
|
||||
"C:\Program Files\doxygen\bin\doxygen.exe"
|
||||
if not errorlevel 0 goto End
|
||||
|
||||
start doc\html\index.html
|
||||
|
||||
:End
|
2
!rununitest.bat
Normal file
2
!rununitest.bat
Normal file
@ -0,0 +1,2 @@
|
||||
cd debug
|
||||
QtUkncBtl.exe -test
|
@ -33,7 +33,6 @@ HEADERS += mainwindow.h \
|
||||
emubase/Processor.h \
|
||||
emubase/Memory.h \
|
||||
emubase/Emubase.h \
|
||||
emubase/Disasm.h \
|
||||
emubase/Defines.h \
|
||||
emubase/Board.h \
|
||||
Emulator.h \
|
||||
|
File diff suppressed because it is too large
Load Diff
192
emubase/Board.h
192
emubase/Board.h
@ -8,8 +8,7 @@ See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
UKNCBTL. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
// Board.h
|
||||
//
|
||||
/// \file Board.h Motherboard class
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -45,8 +44,8 @@ typedef struct chan_tag
|
||||
|
||||
typedef struct kbd_row_tag
|
||||
{
|
||||
BYTE processed;
|
||||
BYTE row_Y;
|
||||
BYTE processed;
|
||||
BYTE row_Y;
|
||||
} kbd_row;
|
||||
|
||||
// Tape emulator callback used to read a tape recorded data.
|
||||
@ -64,6 +63,19 @@ typedef void (CALLBACK* TAPEWRITECALLBACK)(int value, unsigned int samples);
|
||||
// Sound generator callback function type
|
||||
typedef void (CALLBACK* SOUNDGENCALLBACK)(unsigned short L, unsigned short R);
|
||||
|
||||
// Network port callback for receiving
|
||||
// Output:
|
||||
// pbyte Byte received
|
||||
// result TRUE means we have a new byte, FALSE means not ready yet
|
||||
typedef BOOL (CALLBACK* NETWORKINCALLBACK)(BYTE* pbyte);
|
||||
|
||||
// Network port callback for translating
|
||||
// Input:
|
||||
// byte A byte to translate
|
||||
// Output:
|
||||
// result TRUE means we translated the byte successfully, FALSE means we have an error
|
||||
typedef BOOL (CALLBACK* NETWORKOUTCALLBACK)(BYTE byte);
|
||||
|
||||
// Serial port callback for receiving
|
||||
// Output:
|
||||
// pbyte Byte received
|
||||
@ -90,7 +102,19 @@ class CHardDrive;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CMotherboard // UKNC computer
|
||||
|
||||
/// \brief Bus device
|
||||
class CBusDevice
|
||||
{
|
||||
public:
|
||||
/// \brief Name of the device
|
||||
virtual LPCTSTR GetName() const = 0;
|
||||
/// \brief Device address ranges: [address, length] pairs, last pair is [0,0]
|
||||
virtual const WORD* GetAddressRanges() const = 0;
|
||||
};
|
||||
|
||||
/// \brief UKNC computer
|
||||
class CMotherboard
|
||||
{
|
||||
|
||||
public: // Construct / destruct
|
||||
@ -98,47 +122,56 @@ public: // Construct / destruct
|
||||
~CMotherboard();
|
||||
|
||||
protected: // Devices
|
||||
CProcessor* m_pCPU; // CPU device
|
||||
CProcessor* m_pPPU; // PPU device
|
||||
CMemoryController* m_pFirstMemCtl; // CPU memory control
|
||||
CMemoryController* m_pSecondMemCtl; // PPU memory control
|
||||
CFloppyController* m_pFloppyCtl; // FDD control
|
||||
CHardDrive* m_pHardDrives[2]; // HDD control
|
||||
CProcessor* m_pCPU; ///< CPU device
|
||||
CProcessor* m_pPPU; ///< PPU device
|
||||
CMemoryController* m_pFirstMemCtl; ///< CPU memory control
|
||||
CMemoryController* m_pSecondMemCtl; ///< PPU memory control
|
||||
CFloppyController* m_pFloppyCtl; ///< FDD control
|
||||
CHardDrive* m_pHardDrives[2]; ///< HDD control
|
||||
|
||||
public: // Getting devices
|
||||
CProcessor* GetCPU() { return m_pCPU; }
|
||||
CProcessor* GetPPU() { return m_pPPU; }
|
||||
CMemoryController* GetCPUMemoryController() { return m_pFirstMemCtl; }
|
||||
CMemoryController* GetPPUMemoryController() { return m_pSecondMemCtl; }
|
||||
CProcessor* GetCPU() { return m_pCPU; } ///< Getter for m_pCPU
|
||||
CProcessor* GetPPU() { return m_pPPU; } ///< Getter for m_pPPU
|
||||
CMemoryController* GetCPUMemoryController() { return m_pFirstMemCtl; } ///< Get CPU memory controller
|
||||
CMemoryController* GetPPUMemoryController() { return m_pSecondMemCtl; } ///< Get PPU memory controller
|
||||
|
||||
protected:
|
||||
CBusDevice** m_pCpuDevices; ///< List of CPU bus devices
|
||||
CBusDevice** m_pPpuDevices; ///< List of PPU bus devices
|
||||
public:
|
||||
const CBusDevice** GetCPUBusDevices() { return (const CBusDevice**) m_pCpuDevices; }
|
||||
const CBusDevice** GetPPUBusDevices() { return (const CBusDevice**) m_pPpuDevices; }
|
||||
|
||||
protected: // Memory
|
||||
BYTE* m_pRAM[3]; // RAM, three planes, 64 KB each
|
||||
BYTE* m_pROM; // System ROM, 32 KB
|
||||
BYTE* m_pROMCart[2]; // ROM cartridges #1 and #2, 24 KB each
|
||||
BYTE* m_pRAM[3]; ///< RAM, three planes, 64 KB each
|
||||
BYTE* m_pROM; ///< System ROM, 32 KB
|
||||
BYTE* m_pROMCart[2]; ///< ROM cartridges #1 and #2, 24 KB each
|
||||
public: // Memory access
|
||||
WORD GetRAMWord(int plan, WORD offset);
|
||||
BYTE GetRAMByte(int plan, WORD offset);
|
||||
WORD GetRAMWord(int plan, WORD offset) const;
|
||||
BYTE GetRAMByte(int plan, WORD offset) const;
|
||||
void SetRAMWord(int plan, WORD offset, WORD word);
|
||||
void SetRAMByte(int plan, WORD offset, BYTE byte);
|
||||
WORD GetROMWord(WORD offset);
|
||||
BYTE GetROMByte(WORD offset);
|
||||
WORD GetROMCartWord(int cartno, WORD offset);
|
||||
BYTE GetROMCartByte(int cartno, WORD offset);
|
||||
WORD GetROMWord(WORD offset) const;
|
||||
BYTE GetROMByte(WORD offset) const;
|
||||
WORD GetROMCartWord(int cartno, WORD offset) const;
|
||||
BYTE GetROMCartByte(int cartno, WORD offset) const;
|
||||
public: // Debug
|
||||
void DebugTicks(); // One Debug PPU tick -- use for debug step or debug breakpoint
|
||||
void SetCPUBreakpoint(WORD bp) { m_CPUbp = bp; } // Set CPU breakpoint
|
||||
void SetPPUBreakpoint(WORD bp) { m_PPUbp = bp; } // Set PPU breakpoint
|
||||
chan_stc GetChannelStruct(unsigned char cpu,unsigned char chan, unsigned char tx)
|
||||
{//cpu==1 ,ppu==0; tx==1, rx==0
|
||||
if(cpu)
|
||||
void DebugTicks(); ///< One Debug PPU tick -- use for debug step or debug breakpoint
|
||||
void SetCPUBreakpoint(WORD bp) { m_CPUbp = bp; } ///< Set current CPU breakpoint
|
||||
void SetPPUBreakpoint(WORD bp) { m_PPUbp = bp; } ///< Set current PPU breakpoint
|
||||
chan_stc GetChannelStruct(unsigned char cpu, unsigned char chan, unsigned char tx)
|
||||
{
|
||||
//cpu==1 ,ppu==0; tx==1, rx==0
|
||||
if (cpu)
|
||||
{
|
||||
if(tx)
|
||||
if (tx)
|
||||
return m_chancputx[chan];
|
||||
else
|
||||
return m_chancpurx[chan];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(tx)
|
||||
if (tx)
|
||||
return m_chanpputx[chan];
|
||||
else
|
||||
return m_chanppurx[chan];
|
||||
@ -146,27 +179,28 @@ public: // Debug
|
||||
}
|
||||
|
||||
public: // System control
|
||||
void Reset(); // Reset computer
|
||||
void LoadROM(const BYTE* pBuffer); // Load 32 KB ROM image from the biffer
|
||||
void LoadROMCartridge(int cartno, const BYTE* pBuffer); // Load 24 KB ROM cartridge image
|
||||
void LoadRAM(int plan, const BYTE* pBuffer); // Load 32 KB RAM image from the biffer
|
||||
void Tick8000(); // Tick 8.00 MHz
|
||||
void Tick6250(); // Tick 6.25 MHz
|
||||
void Tick50(); // Tick 50 Hz - goes to CPU/PPU EVNT line
|
||||
void TimerTick(); // Timer Tick, 2uS -- dividers are within timer routine
|
||||
void ResetFloppy(); // INIT signal for FDD
|
||||
WORD GetTimerValue(); // returns current timer value
|
||||
WORD GetTimerValueView() { return m_timer; } // Returns current timer value for debugger
|
||||
WORD GetTimerReload(); // returns timer reload value
|
||||
WORD GetTimerReloadView() { return m_timerreload; } // Returns timer reload value for debugger
|
||||
WORD GetTimerState(); // returns timer state
|
||||
WORD GetTimerStateView() { return m_timerflags; } // Returns timer state for debugger
|
||||
void Reset(); ///< Reset computer
|
||||
void LoadROM(const BYTE* pBuffer); ///< Load 32 KB ROM image from the biffer
|
||||
void LoadROMCartridge(int cartno, const BYTE* pBuffer); ///< Load 24 KB ROM cartridge image
|
||||
void LoadRAM(int plan, const BYTE* pBuffer); ///< Load 32 KB RAM image from the biffer
|
||||
void SetNetStation(int station); // Network station number
|
||||
void Tick8000(); ///< Tick 8.00 MHz
|
||||
void Tick6250(); ///< Tick 6.25 MHz
|
||||
void Tick50(); ///< Tick 50 Hz - goes to CPU/PPU EVNT line
|
||||
void TimerTick(); ///< Timer Tick, 2uS -- dividers are within timer routine
|
||||
void ResetFloppy(); ///< INIT signal for FDD
|
||||
WORD GetTimerValue(); ///< Returns current timer value
|
||||
WORD GetTimerValueView() { return m_timer; } ///< Returns current timer value for debugger
|
||||
WORD GetTimerReload(); ///< Returns timer reload value
|
||||
WORD GetTimerReloadView() { return m_timerreload; } ///< Returns timer reload value for debugger
|
||||
WORD GetTimerState(); ///< Returns timer state
|
||||
WORD GetTimerStateView() { return m_timerflags; } ///< Returns timer state for debugger
|
||||
|
||||
void ChanWriteByCPU(BYTE chan, BYTE data);
|
||||
void ChanWriteByPPU(BYTE chan, BYTE data);
|
||||
BYTE ChanReadByCPU(BYTE chan);
|
||||
BYTE ChanReadByPPU(BYTE chan);
|
||||
|
||||
|
||||
BYTE ChanRxStateGetCPU(BYTE chan);
|
||||
BYTE ChanTxStateGetCPU(BYTE chan);
|
||||
BYTE ChanRxStateGetPPU();
|
||||
@ -181,41 +215,58 @@ public: // System control
|
||||
|
||||
//void FloppyDebug(BYTE val);
|
||||
|
||||
void SetTimerReload(WORD val); //sets timer reload value
|
||||
void SetTimerState(WORD val); //sets timer state
|
||||
void ExecuteCPU(); // Execute one CPU instruction
|
||||
void ExecutePPU(); // Execute one PPU instruction
|
||||
BOOL SystemFrame(); // Do one frame -- use for normal run
|
||||
void KeyboardEvent(BYTE scancode, BOOL okPressed); // Key pressed or released
|
||||
void SetTimerReload(WORD val); ///< Sets timer reload value
|
||||
void SetTimerState(WORD val); ///< Sets timer state
|
||||
void ExecuteCPU(); ///< Execute one CPU instruction
|
||||
void ExecutePPU(); ///< Execute one PPU instruction
|
||||
BOOL SystemFrame(); ///< Do one frame -- use for normal run
|
||||
void KeyboardEvent(BYTE scancode, BOOL okPressed); ///< Key pressed or released
|
||||
WORD GetKeyboardRegister(void);
|
||||
WORD GetScannedKey() {return m_scanned_key; }
|
||||
WORD GetScannedKey() { return m_scanned_key; }
|
||||
|
||||
/// \brief Attach floppy image to the slot -- insert the disk.
|
||||
BOOL AttachFloppyImage(int slot, LPCTSTR sFileName);
|
||||
/// \brief Empty the floppy slot -- remove the disk.
|
||||
void DetachFloppyImage(int slot);
|
||||
/// \brief Check if the floppy attached.
|
||||
BOOL IsFloppyImageAttached(int slot) const;
|
||||
/// \brief Check if the attached floppy image is read-only.
|
||||
BOOL IsFloppyReadOnly(int slot) const;
|
||||
/// \brief Check if the floppy drive engine rotates the disks.
|
||||
BOOL IsFloppyEngineOn() const;
|
||||
WORD GetFloppyState();
|
||||
WORD GetFloppyData();
|
||||
void SetFloppyState(WORD val);
|
||||
void SetFloppyData(WORD val);
|
||||
|
||||
/// \brief Check if ROM cartridge image assigned to the cartridge slot.
|
||||
BOOL IsROMCartridgeLoaded(int cartno) const;
|
||||
/// \brief Empty the ROM cartridge slot.
|
||||
void UnloadROMCartridge(int cartno);
|
||||
|
||||
/// \brief Attach hard drive image to the slot.
|
||||
BOOL AttachHardImage(int slot, LPCTSTR sFileName);
|
||||
/// \brief Empty hard drive slot.
|
||||
void DetachHardImage(int slot);
|
||||
/// \brief Check if the hard drive attached.
|
||||
BOOL IsHardImageAttached(int slot) const;
|
||||
/// \brief Check if the attached hard drive image is read-only.
|
||||
BOOL IsHardImageReadOnly(int slot) const;
|
||||
WORD GetHardPortWord(int slot, WORD port); // To use from CSecondMemoryController only
|
||||
void SetHardPortWord(int slot, WORD port, WORD data); // To use from CSecondMemoryController only
|
||||
WORD GetHardPortWord(int slot, WORD port); ///< To use from CSecondMemoryController only
|
||||
void SetHardPortWord(int slot, WORD port, WORD data); ///< To use from CSecondMemoryController only
|
||||
|
||||
/// \brief Assign tape read callback function.
|
||||
void SetTapeReadCallback(TAPEREADCALLBACK callback, int sampleRate);
|
||||
/// \brief Assign write read callback function.
|
||||
void SetTapeWriteCallback(TAPEWRITECALLBACK callback, int sampleRate);
|
||||
/// \brief Assign sound output callback function.
|
||||
void SetSoundGenCallback(SOUNDGENCALLBACK callback);
|
||||
/// \brief Assign serial port input/output callback functions.
|
||||
void SetSerialCallbacks(SERIALINCALLBACK incallback, SERIALOUTCALLBACK outcallback);
|
||||
/// \brief Assign parallel port output callback function.
|
||||
void SetParallelOutCallback(PARALLELOUTCALLBACK outcallback);
|
||||
|
||||
/// \brief Assign network port input/output callback functions.
|
||||
void SetNetworkCallbacks(NETWORKINCALLBACK incallback, NETWORKOUTCALLBACK outcallback);
|
||||
public: // Saving/loading emulator status
|
||||
void SaveToImage(BYTE* pImage);
|
||||
void LoadFromImage(const BYTE* pImage);
|
||||
@ -229,14 +280,14 @@ private: // Timing
|
||||
int m_cputicks;
|
||||
unsigned int m_lineticks;
|
||||
private:
|
||||
WORD m_CPUbp;
|
||||
WORD m_PPUbp;
|
||||
WORD m_CPUbp; ///< Current CPU breakpoint, 177777 if not set
|
||||
WORD m_PPUbp; ///< Current PPU breakpoint, 177777 if not set
|
||||
|
||||
WORD m_timer;
|
||||
WORD m_timerreload;
|
||||
WORD m_timerflags;
|
||||
WORD m_timerdivider;
|
||||
|
||||
|
||||
chan_stc m_chancputx[3];
|
||||
chan_stc m_chancpurx[2];
|
||||
chan_stc m_chanpputx[2];
|
||||
@ -245,8 +296,8 @@ private:
|
||||
BYTE m_chan0disabled;
|
||||
BYTE m_irq_cpureset;
|
||||
|
||||
BYTE m_scanned_key;
|
||||
kbd_row m_kbd_matrix[16];
|
||||
BYTE m_scanned_key;
|
||||
kbd_row m_kbd_matrix[16];
|
||||
|
||||
private:
|
||||
TAPEREADCALLBACK m_TapeReadCallback;
|
||||
@ -256,20 +307,23 @@ private:
|
||||
SERIALINCALLBACK m_SerialInCallback;
|
||||
SERIALOUTCALLBACK m_SerialOutCallback;
|
||||
PARALLELOUTCALLBACK m_ParallelOutCallback;
|
||||
NETWORKINCALLBACK m_NetworkInCallback;
|
||||
NETWORKOUTCALLBACK m_NetworkOutCallback;
|
||||
|
||||
void DoSound(void);
|
||||
|
||||
|
||||
};
|
||||
|
||||
inline WORD CMotherboard::GetRAMWord(int plan, WORD offset)
|
||||
inline WORD CMotherboard::GetRAMWord(int plan, WORD offset) const
|
||||
{
|
||||
ASSERT(plan >= 0 && plan <= 2);
|
||||
return *((WORD*)(m_pRAM[plan] + (offset & 0xFFFE)));
|
||||
return *((WORD*)(m_pRAM[plan] + (offset & 0xFFFE)));
|
||||
}
|
||||
inline BYTE CMotherboard::GetRAMByte(int plan, WORD offset)
|
||||
{
|
||||
inline BYTE CMotherboard::GetRAMByte(int plan, WORD offset) const
|
||||
{
|
||||
ASSERT(plan >= 0 && plan <= 2);
|
||||
return m_pRAM[plan][offset];
|
||||
return m_pRAM[plan][offset];
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -8,8 +8,7 @@ See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
UKNCBTL. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
// Defines.h
|
||||
// PDP11-like processor defines
|
||||
/// \file Defines.h PDP11-like processor defines
|
||||
|
||||
#pragma once
|
||||
|
||||
|
@ -8,32 +8,39 @@ See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
UKNCBTL. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
// Disasm.cpp
|
||||
// See defines in header file Emubase.h
|
||||
/// \file Disasm.cpp
|
||||
/// \brief Disassembler for KM1801VM2 processor
|
||||
/// \details See defines in header file Emubase.h
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Disasm.h"
|
||||
#include "Defines.h"
|
||||
|
||||
|
||||
// Ôîðìàò îòîáðàæåíèÿ ðåæèìîâ àäðåñàöèè
|
||||
const LPCTSTR ADDRESS_MODE_FORMAT[] = {
|
||||
_T("%s"), _T("(%s)"), _T("(%s)+"), _T("@(%s)+"), _T("-(%s)"), _T("@-(%s)"), _T("%06o(%s)"), _T("@%06o(%s)") };
|
||||
const LPCTSTR ADDRESS_MODE_FORMAT[] =
|
||||
{
|
||||
_T("%s"), _T("(%s)"), _T("(%s)+"), _T("@(%s)+"), _T("-(%s)"), _T("@-(%s)"), _T("%06o(%s)"), _T("@%06o(%s)")
|
||||
};
|
||||
// Ôîðìàò îòîáðàæåíèÿ ðåæèìîâ àäðåñàöèè äëÿ ðåãèñòðà PC
|
||||
const LPCTSTR ADDRESS_MODE_PC_FORMAT[] = {
|
||||
_T("PC"), _T("(PC)"), _T("#%06o"), _T("@#%06o"), _T("-(PC)"), _T("@-(PC)"), _T("%06o"), _T("@%06o") };
|
||||
const LPCTSTR ADDRESS_MODE_PC_FORMAT[] =
|
||||
{
|
||||
_T("PC"), _T("(PC)"), _T("#%06o"), _T("@#%06o"), _T("-(PC)"), _T("@-(PC)"), _T("%06o"), _T("@%06o")
|
||||
};
|
||||
|
||||
// strSrc - at least 24 characters
|
||||
BOOL ConvertSrcToString(WORD instr, WORD addr, TCHAR* strSrc, WORD code) {
|
||||
BOOL ConvertSrcToString(WORD instr, WORD addr, TCHAR* strSrc, WORD code)
|
||||
{
|
||||
int reg = GetDigit(instr, 2);
|
||||
int param = GetDigit(instr, 3);
|
||||
|
||||
LPCTSTR pszReg = REGISTER_NAME[reg];
|
||||
|
||||
if (reg != 7) {
|
||||
if (reg != 7)
|
||||
{
|
||||
LPCTSTR format = ADDRESS_MODE_FORMAT[param];
|
||||
|
||||
if (param == 6 || param == 7) {
|
||||
if (param == 6 || param == 7)
|
||||
{
|
||||
WORD word = code; //TODO: pMemory
|
||||
_sntprintf(strSrc, 24, format, word, pszReg);
|
||||
return TRUE;
|
||||
@ -41,15 +48,18 @@ BOOL ConvertSrcToString(WORD instr, WORD addr, TCHAR* strSrc, WORD code) {
|
||||
else
|
||||
_sntprintf(strSrc, 24, format, pszReg);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
LPCTSTR format = ADDRESS_MODE_PC_FORMAT[param];
|
||||
|
||||
if (param == 2 || param == 3) {
|
||||
if (param == 2 || param == 3)
|
||||
{
|
||||
WORD word = code; //TODO: pMemory
|
||||
_sntprintf(strSrc, 24, format, word);
|
||||
return TRUE;
|
||||
}
|
||||
else if (param == 6 || param == 7) {
|
||||
else if (param == 6 || param == 7)
|
||||
{
|
||||
WORD word = code; //TODO: pMemory
|
||||
_sntprintf(strSrc, 24, format, (WORD)(addr + word + 2));
|
||||
return TRUE;
|
||||
@ -62,30 +72,36 @@ BOOL ConvertSrcToString(WORD instr, WORD addr, TCHAR* strSrc, WORD code) {
|
||||
}
|
||||
|
||||
// strDst - at least 24 characters
|
||||
BOOL ConvertDstToString (WORD instr, WORD addr, TCHAR* strDst, WORD code) {
|
||||
BOOL ConvertDstToString (WORD instr, WORD addr, TCHAR* strDst, WORD code)
|
||||
{
|
||||
int reg = GetDigit(instr, 0);
|
||||
int param = GetDigit(instr, 1);
|
||||
|
||||
LPCTSTR pszReg = REGISTER_NAME[reg];
|
||||
|
||||
if (reg != 7) {
|
||||
if (reg != 7)
|
||||
{
|
||||
LPCTSTR format = ADDRESS_MODE_FORMAT[param];
|
||||
|
||||
if (param == 6 || param == 7) {
|
||||
if (param == 6 || param == 7)
|
||||
{
|
||||
_sntprintf(strDst, 24, format, code, pszReg);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
_sntprintf(strDst, 24, format, pszReg);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
LPCTSTR format = ADDRESS_MODE_PC_FORMAT[param];
|
||||
|
||||
if (param == 2 || param == 3) {
|
||||
if (param == 2 || param == 3)
|
||||
{
|
||||
_sntprintf(strDst, 24, format, code);
|
||||
return TRUE;
|
||||
}
|
||||
else if (param == 6 || param == 7) {
|
||||
else if (param == 6 || param == 7)
|
||||
{
|
||||
_sntprintf(strDst, 24, format, (WORD)(addr + code + 2));
|
||||
return TRUE;
|
||||
}
|
||||
@ -115,61 +131,63 @@ int DisassembleInstruction(WORD* pMemory, WORD addr, TCHAR* strInstr, TCHAR* str
|
||||
BOOL okByte;
|
||||
|
||||
// No fields
|
||||
switch (instr) {
|
||||
case PI_HALT: _tcscpy(strInstr, _T("HALT")); return 1;
|
||||
case PI_WAIT: _tcscpy(strInstr, _T("WAIT")); return 1;
|
||||
case PI_RTI: _tcscpy(strInstr, _T("RTI")); return 1;
|
||||
case PI_BPT: _tcscpy(strInstr, _T("BPT")); return 1;
|
||||
case PI_IOT: _tcscpy(strInstr, _T("IOT")); return 1;
|
||||
case PI_RESET: _tcscpy(strInstr, _T("RESET")); return 1;
|
||||
case PI_RTT: _tcscpy(strInstr, _T("RTT")); return 1;
|
||||
case PI_NOP: _tcscpy(strInstr, _T("NOP")); return 1;
|
||||
case PI_CLC: _tcscpy(strInstr, _T("CLC")); return 1;
|
||||
case PI_CLV: _tcscpy(strInstr, _T("CLV")); return 1;
|
||||
case PI_CLVC: _tcscpy(strInstr, _T("CLVC")); return 1;
|
||||
case PI_CLZ: _tcscpy(strInstr, _T("CLZ")); return 1;
|
||||
case PI_CLZC: _tcscpy(strInstr, _T("CLZC")); return 1;
|
||||
case PI_CLZV: _tcscpy(strInstr, _T("CLZV")); return 1;
|
||||
case PI_CLZVC: _tcscpy(strInstr, _T("CLZVC")); return 1;
|
||||
case PI_CLN: _tcscpy(strInstr, _T("CLN")); return 1;
|
||||
case PI_CLNC: _tcscpy(strInstr, _T("CLNC")); return 1;
|
||||
case PI_CLNV: _tcscpy(strInstr, _T("CLNV")); return 1;
|
||||
case PI_CLNVC: _tcscpy(strInstr, _T("CLNVC")); return 1;
|
||||
case PI_CLNZ: _tcscpy(strInstr, _T("CLNZ")); return 1;
|
||||
case PI_CLNZC: _tcscpy(strInstr, _T("CLNZC")); return 1;
|
||||
case PI_CLNZV: _tcscpy(strInstr, _T("CLNZV")); return 1;
|
||||
case PI_CCC: _tcscpy(strInstr, _T("CCC")); return 1;
|
||||
case PI_NOP260: _tcscpy(strInstr, _T("NOP260")); return 1;
|
||||
case PI_SEC: _tcscpy(strInstr, _T("SEC")); return 1;
|
||||
case PI_SEV: _tcscpy(strInstr, _T("SEV")); return 1;
|
||||
case PI_SEVC: _tcscpy(strInstr, _T("SEVC")); return 1;
|
||||
case PI_SEZ: _tcscpy(strInstr, _T("SEZ")); return 1;
|
||||
case PI_SEZC: _tcscpy(strInstr, _T("SEZC")); return 1;
|
||||
case PI_SEZV: _tcscpy(strInstr, _T("SEZV")); return 1;
|
||||
case PI_SEZVC: _tcscpy(strInstr, _T("SEZVC")); return 1;
|
||||
case PI_SEN: _tcscpy(strInstr, _T("SEN")); return 1;
|
||||
case PI_SENC: _tcscpy(strInstr, _T("SENC")); return 1;
|
||||
case PI_SENV: _tcscpy(strInstr, _T("SENV")); return 1;
|
||||
case PI_SENVC: _tcscpy(strInstr, _T("SENVC")); return 1;
|
||||
case PI_SENZ: _tcscpy(strInstr, _T("SENZ")); return 1;
|
||||
case PI_SENZC: _tcscpy(strInstr, _T("SENZC")); return 1;
|
||||
case PI_SENZV: _tcscpy(strInstr, _T("SENZV")); return 1;
|
||||
case PI_SCC: _tcscpy(strInstr, _T("SCC")); return 1;
|
||||
switch (instr)
|
||||
{
|
||||
case PI_HALT: _tcscpy(strInstr, _T("HALT")); return 1;
|
||||
case PI_WAIT: _tcscpy(strInstr, _T("WAIT")); return 1;
|
||||
case PI_RTI: _tcscpy(strInstr, _T("RTI")); return 1;
|
||||
case PI_BPT: _tcscpy(strInstr, _T("BPT")); return 1;
|
||||
case PI_IOT: _tcscpy(strInstr, _T("IOT")); return 1;
|
||||
case PI_RESET: _tcscpy(strInstr, _T("RESET")); return 1;
|
||||
case PI_RTT: _tcscpy(strInstr, _T("RTT")); return 1;
|
||||
case PI_NOP: _tcscpy(strInstr, _T("NOP")); return 1;
|
||||
case PI_CLC: _tcscpy(strInstr, _T("CLC")); return 1;
|
||||
case PI_CLV: _tcscpy(strInstr, _T("CLV")); return 1;
|
||||
case PI_CLVC: _tcscpy(strInstr, _T("CLVC")); return 1;
|
||||
case PI_CLZ: _tcscpy(strInstr, _T("CLZ")); return 1;
|
||||
case PI_CLZC: _tcscpy(strInstr, _T("CLZC")); return 1;
|
||||
case PI_CLZV: _tcscpy(strInstr, _T("CLZV")); return 1;
|
||||
case PI_CLZVC: _tcscpy(strInstr, _T("CLZVC")); return 1;
|
||||
case PI_CLN: _tcscpy(strInstr, _T("CLN")); return 1;
|
||||
case PI_CLNC: _tcscpy(strInstr, _T("CLNC")); return 1;
|
||||
case PI_CLNV: _tcscpy(strInstr, _T("CLNV")); return 1;
|
||||
case PI_CLNVC: _tcscpy(strInstr, _T("CLNVC")); return 1;
|
||||
case PI_CLNZ: _tcscpy(strInstr, _T("CLNZ")); return 1;
|
||||
case PI_CLNZC: _tcscpy(strInstr, _T("CLNZC")); return 1;
|
||||
case PI_CLNZV: _tcscpy(strInstr, _T("CLNZV")); return 1;
|
||||
case PI_CCC: _tcscpy(strInstr, _T("CCC")); return 1;
|
||||
case PI_NOP260: _tcscpy(strInstr, _T("NOP260")); return 1;
|
||||
case PI_SEC: _tcscpy(strInstr, _T("SEC")); return 1;
|
||||
case PI_SEV: _tcscpy(strInstr, _T("SEV")); return 1;
|
||||
case PI_SEVC: _tcscpy(strInstr, _T("SEVC")); return 1;
|
||||
case PI_SEZ: _tcscpy(strInstr, _T("SEZ")); return 1;
|
||||
case PI_SEZC: _tcscpy(strInstr, _T("SEZC")); return 1;
|
||||
case PI_SEZV: _tcscpy(strInstr, _T("SEZV")); return 1;
|
||||
case PI_SEZVC: _tcscpy(strInstr, _T("SEZVC")); return 1;
|
||||
case PI_SEN: _tcscpy(strInstr, _T("SEN")); return 1;
|
||||
case PI_SENC: _tcscpy(strInstr, _T("SENC")); return 1;
|
||||
case PI_SENV: _tcscpy(strInstr, _T("SENV")); return 1;
|
||||
case PI_SENVC: _tcscpy(strInstr, _T("SENVC")); return 1;
|
||||
case PI_SENZ: _tcscpy(strInstr, _T("SENZ")); return 1;
|
||||
case PI_SENZC: _tcscpy(strInstr, _T("SENZC")); return 1;
|
||||
case PI_SENZV: _tcscpy(strInstr, _T("SENZV")); return 1;
|
||||
case PI_SCC: _tcscpy(strInstr, _T("SCC")); return 1;
|
||||
|
||||
// Ñïåöêîìàíäû ðåæèìà HALT ÂÌ2
|
||||
case PI_GO: _tcscpy(strInstr, _T("GO")); return 1;
|
||||
case PI_STEP: _tcscpy(strInstr, _T("STEP")); return 1;
|
||||
case PI_RSEL: _tcscpy(strInstr, _T("RSEL")); return 1;
|
||||
case PI_MFUS: _tcscpy(strInstr, _T("MFUS")); return 1;
|
||||
case PI_RCPC: _tcscpy(strInstr, _T("RCPC")); return 1;
|
||||
case PI_RCPS: _tcscpy(strInstr, _T("RCPS")); return 1;
|
||||
case PI_MTUS: _tcscpy(strInstr, _T("MTUS")); return 1;
|
||||
case PI_WCPC: _tcscpy(strInstr, _T("WCPC")); return 1;
|
||||
case PI_WCPS: _tcscpy(strInstr, _T("WCPS")); return 1;
|
||||
case PI_GO: _tcscpy(strInstr, _T("GO")); return 1;
|
||||
case PI_STEP: _tcscpy(strInstr, _T("STEP")); return 1;
|
||||
case PI_RSEL: _tcscpy(strInstr, _T("RSEL")); return 1;
|
||||
case PI_MFUS: _tcscpy(strInstr, _T("MFUS")); return 1;
|
||||
case PI_RCPC: _tcscpy(strInstr, _T("RCPC")); return 1;
|
||||
case PI_RCPS: _tcscpy(strInstr, _T("RCPS")); return 1;
|
||||
case PI_MTUS: _tcscpy(strInstr, _T("MTUS")); return 1;
|
||||
case PI_WCPC: _tcscpy(strInstr, _T("WCPC")); return 1;
|
||||
case PI_WCPS: _tcscpy(strInstr, _T("WCPS")); return 1;
|
||||
}
|
||||
|
||||
// One field
|
||||
if ((instr & ~(WORD)7) == PI_RTS) {
|
||||
if ((instr & ~(WORD)7) == PI_RTS)
|
||||
{
|
||||
if (GetDigit(instr, 0) == 7)
|
||||
{
|
||||
_tcscpy(strInstr, _T("RETURN"));
|
||||
@ -185,63 +203,68 @@ int DisassembleInstruction(WORD* pMemory, WORD addr, TCHAR* strInstr, TCHAR* str
|
||||
// Two fields
|
||||
length += ConvertDstToString(instr, addr + 2, strDst, pMemory[1]);
|
||||
|
||||
switch (instr & ~(WORD)077) {
|
||||
case PI_JMP: _tcscpy(strInstr, _T("JMP")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_SWAB: _tcscpy(strInstr, _T("SWAB")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_MARK: _tcscpy(strInstr, _T("MARK")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_SXT: _tcscpy(strInstr, _T("SXT")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_MTPS: _tcscpy(strInstr, _T("MTPS")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_MFPS: _tcscpy(strInstr, _T("MFPS")); _tcscpy(strArg, strDst); return length;
|
||||
switch (instr & ~(WORD)077)
|
||||
{
|
||||
case PI_JMP: _tcscpy(strInstr, _T("JMP")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_SWAB: _tcscpy(strInstr, _T("SWAB")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_MARK: _tcscpy(strInstr, _T("MARK")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_SXT: _tcscpy(strInstr, _T("SXT")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_MTPS: _tcscpy(strInstr, _T("MTPS")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_MFPS: _tcscpy(strInstr, _T("MFPS")); _tcscpy(strArg, strDst); return length;
|
||||
}
|
||||
|
||||
|
||||
okByte = (instr & 0100000);
|
||||
|
||||
switch (instr & ~(WORD)0100077) {
|
||||
case PI_CLR: _tcscpy(strInstr, okByte ? _T("CLRB") : _T("CLR")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_COM: _tcscpy(strInstr, okByte ? _T("COMB") : _T("COM")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_INC: _tcscpy(strInstr, okByte ? _T("INCB") : _T("INC")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_DEC: _tcscpy(strInstr, okByte ? _T("DECB") : _T("DEC")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_NEG: _tcscpy(strInstr, okByte ? _T("NEGB") : _T("NEG")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_ADC: _tcscpy(strInstr, okByte ? _T("ADCB") : _T("ADC")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_SBC: _tcscpy(strInstr, okByte ? _T("SBCB") : _T("SBC")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_TST: _tcscpy(strInstr, okByte ? _T("TSTB") : _T("TST")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_ROR: _tcscpy(strInstr, okByte ? _T("RORB") : _T("ROR")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_ROL: _tcscpy(strInstr, okByte ? _T("ROLB") : _T("ROL")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_ASR: _tcscpy(strInstr, okByte ? _T("ASRB") : _T("ASR")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_ASL: _tcscpy(strInstr, okByte ? _T("ASLB") : _T("ASL")); _tcscpy(strArg, strDst); return length;
|
||||
switch (instr & ~(WORD)0100077)
|
||||
{
|
||||
case PI_CLR: _tcscpy(strInstr, okByte ? _T("CLRB") : _T("CLR")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_COM: _tcscpy(strInstr, okByte ? _T("COMB") : _T("COM")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_INC: _tcscpy(strInstr, okByte ? _T("INCB") : _T("INC")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_DEC: _tcscpy(strInstr, okByte ? _T("DECB") : _T("DEC")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_NEG: _tcscpy(strInstr, okByte ? _T("NEGB") : _T("NEG")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_ADC: _tcscpy(strInstr, okByte ? _T("ADCB") : _T("ADC")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_SBC: _tcscpy(strInstr, okByte ? _T("SBCB") : _T("SBC")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_TST: _tcscpy(strInstr, okByte ? _T("TSTB") : _T("TST")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_ROR: _tcscpy(strInstr, okByte ? _T("RORB") : _T("ROR")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_ROL: _tcscpy(strInstr, okByte ? _T("ROLB") : _T("ROL")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_ASR: _tcscpy(strInstr, okByte ? _T("ASRB") : _T("ASR")); _tcscpy(strArg, strDst); return length;
|
||||
case PI_ASL: _tcscpy(strInstr, okByte ? _T("ASLB") : _T("ASL")); _tcscpy(strArg, strDst); return length;
|
||||
}
|
||||
|
||||
length = 1;
|
||||
_sntprintf(strDst, 24, _T("%06o"), addr + ((short)(char)LOBYTE (instr) * 2) + 2);
|
||||
|
||||
// Branchs & interrupts
|
||||
switch (instr & ~(WORD)0377) {
|
||||
case PI_BR: _tcscpy(strInstr, _T("BR")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BNE: _tcscpy(strInstr, _T("BNE")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BEQ: _tcscpy(strInstr, _T("BEQ")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BGE: _tcscpy(strInstr, _T("BGE")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BLT: _tcscpy(strInstr, _T("BLT")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BGT: _tcscpy(strInstr, _T("BGT")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BLE: _tcscpy(strInstr, _T("BLE")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BPL: _tcscpy(strInstr, _T("BPL")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BMI: _tcscpy(strInstr, _T("BMI")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BHI: _tcscpy(strInstr, _T("BHI")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BLOS: _tcscpy(strInstr, _T("BLOS")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BVC: _tcscpy(strInstr, _T("BVC")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BVS: _tcscpy(strInstr, _T("BVS")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BHIS: _tcscpy(strInstr, _T("BHIS")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BLO: _tcscpy(strInstr, _T("BLO")); _tcscpy(strArg, strDst); return 1;
|
||||
switch (instr & ~(WORD)0377)
|
||||
{
|
||||
case PI_BR: _tcscpy(strInstr, _T("BR")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BNE: _tcscpy(strInstr, _T("BNE")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BEQ: _tcscpy(strInstr, _T("BEQ")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BGE: _tcscpy(strInstr, _T("BGE")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BLT: _tcscpy(strInstr, _T("BLT")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BGT: _tcscpy(strInstr, _T("BGT")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BLE: _tcscpy(strInstr, _T("BLE")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BPL: _tcscpy(strInstr, _T("BPL")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BMI: _tcscpy(strInstr, _T("BMI")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BHI: _tcscpy(strInstr, _T("BHI")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BLOS: _tcscpy(strInstr, _T("BLOS")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BVC: _tcscpy(strInstr, _T("BVC")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BVS: _tcscpy(strInstr, _T("BVS")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BHIS: _tcscpy(strInstr, _T("BHIS")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_BLO: _tcscpy(strInstr, _T("BLO")); _tcscpy(strArg, strDst); return 1;
|
||||
}
|
||||
|
||||
_sntprintf(strDst, 24, _T("%06o"), LOBYTE (instr));
|
||||
|
||||
switch (instr & ~(WORD)0377) {
|
||||
case PI_EMT: _tcscpy(strInstr, _T("EMT")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_TRAP: _tcscpy(strInstr, _T("TRAP")); _tcscpy(strArg, strDst); return 1;
|
||||
switch (instr & ~(WORD)0377)
|
||||
{
|
||||
case PI_EMT: _tcscpy(strInstr, _T("EMT")); _tcscpy(strArg, strDst); return 1;
|
||||
case PI_TRAP: _tcscpy(strInstr, _T("TRAP")); _tcscpy(strArg, strDst); return 1;
|
||||
}
|
||||
|
||||
// Three fields
|
||||
switch(instr & ~(WORD)0777) {
|
||||
switch (instr & ~(WORD)0777)
|
||||
{
|
||||
case PI_JSR:
|
||||
if (GetDigit(instr, 2) == 7)
|
||||
{
|
||||
@ -300,9 +323,10 @@ int DisassembleInstruction(WORD* pMemory, WORD addr, TCHAR* strInstr, TCHAR* str
|
||||
okByte = (instr & 0100000);
|
||||
|
||||
length += ConvertSrcToString(instr, addr + 2, strSrc, pMemory[1]);
|
||||
length += ConvertDstToString(instr, addr + 2 + (length - 1) * 2, strDst, pMemory[length]);
|
||||
length += ConvertDstToString(instr, (WORD)(addr + 2 + (length - 1) * 2), strDst, pMemory[length]);
|
||||
|
||||
switch(instr & ~(WORD)0107777) {
|
||||
switch (instr & ~(WORD)0107777)
|
||||
{
|
||||
case PI_MOV:
|
||||
_tcscpy(strInstr, okByte ? _T("MOVB") : _T("MOV"));
|
||||
_sntprintf(strArg, 32, _T("%s, %s"), strSrc, strDst); // strArg = strSrc + ", " + strDst;
|
||||
@ -325,7 +349,8 @@ int DisassembleInstruction(WORD* pMemory, WORD addr, TCHAR* strInstr, TCHAR* str
|
||||
return length;
|
||||
}
|
||||
|
||||
switch (instr & ~(WORD)0007777) {
|
||||
switch (instr & ~(WORD)0007777)
|
||||
{
|
||||
case PI_ADD:
|
||||
_tcscpy(strInstr, _T("ADD"));
|
||||
_sntprintf(strArg, 32, _T("%s, %s"), strSrc, strDst); // strArg = strSrc + ", " + strDst;
|
||||
|
@ -1,27 +0,0 @@
|
||||
/* This file is part of UKNCBTL.
|
||||
UKNCBTL is free software: you can redistribute it and/or modify it under the terms
|
||||
of the GNU Lesser General Public License as published by the Free Software Foundation,
|
||||
either version 3 of the License, or (at your option) any later version.
|
||||
UKNCBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
UKNCBTL. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
// Disasm.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Disassemble one instruction of KM1801VM2 processor
|
||||
// pMemory - memory image (we read only words of the instruction)
|
||||
// sInstr - instruction mnemonics buffer - at least 8 characters
|
||||
// sArg - instruction arguments buffer - at least 32 characters
|
||||
// Return value: number of words in the instruction
|
||||
int DisassembleInstruction(WORD* pMemory, WORD addr, TCHAR* sInstr, TCHAR* sArg);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
@ -8,8 +8,7 @@ See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
UKNCBTL. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
// Emubase.h Header for use of all emubase classes
|
||||
//
|
||||
/// \file Emubase.h Header for use of all emubase classes
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -21,11 +20,12 @@ UKNCBTL. If not, see <http://www.gnu.org/licenses/>. */
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Disassembler
|
||||
|
||||
// Disassemble one instruction of KM1801VM2 processor
|
||||
// pMemory - memory image (we read only words of the instruction)
|
||||
// sInstr - instruction mnemonics buffer - at least 8 characters
|
||||
// sArg - instruction arguments buffer - at least 32 characters
|
||||
// Return value: number of words in the instruction
|
||||
/// \brief Disassemble one instruction of KM1801VM2 processor
|
||||
/// \param[in] pMemory Memory image (we read only words of the instruction)
|
||||
/// \param[in] addr Address of the instruction
|
||||
/// \param[out] sInstr Instruction mnemonics buffer - at least 8 characters
|
||||
/// \param[out] sArg Instruction arguments buffer - at least 32 characters
|
||||
/// \return Number of words in the instruction
|
||||
int DisassembleInstruction(WORD* pMemory, WORD addr, TCHAR* sInstr, TCHAR* sArg);
|
||||
|
||||
|
||||
@ -34,91 +34,97 @@ int DisassembleInstruction(WORD* pMemory, WORD addr, TCHAR* sInstr, TCHAR* sArg)
|
||||
|
||||
#define SAMPLERATE 22050
|
||||
|
||||
|
||||
#define FLOPPY_FSM_IDLE 0
|
||||
|
||||
#define FLOPPY_CMD_CORRECTION250 04
|
||||
#define FLOPPY_CMD_ENGINESTART 020
|
||||
#define FLOPPY_CMD_CORRECTION500 010
|
||||
#define FLOPPY_CMD_SIDEUP 040
|
||||
#define FLOPPY_CMD_DIR 0100
|
||||
#define FLOPPY_CMD_STEP 0200
|
||||
#define FLOPPY_CMD_SEARCHSYNC 0400
|
||||
#define FLOPPY_CMD_SKIPSYNC 01000
|
||||
//dir == 0 to center (towards trk0)
|
||||
//dir == 1 from center (towards trk80)
|
||||
#define FLOPPY_CMD_ENGINESTART 020 ///< Engine on/off
|
||||
#define FLOPPY_CMD_SIDEUP 040 ///< Side: 1 -- upper head, 0 -- lower head
|
||||
#define FLOPPY_CMD_DIR 0100 ///< Direction: 0 -- to center (towards trk0), 1 -- from center (towards trk80)
|
||||
#define FLOPPY_CMD_STEP 0200 ///< Step / ready
|
||||
#define FLOPPY_CMD_SEARCHSYNC 0400 ///< Search sync
|
||||
#define FLOPPY_CMD_SKIPSYNC 01000 ///< Skip sync
|
||||
|
||||
#define FLOPPY_STATUS_TRACK0 01
|
||||
#define FLOPPY_STATUS_RDY 02
|
||||
#define FLOPPY_STATUS_WRITEPROTECT 04
|
||||
#define FLOPPY_STATUS_MOREDATA 0200
|
||||
#define FLOPPY_STATUS_CHECKSUMOK 040000
|
||||
#define FLOPPY_STATUS_INDEXMARK 0100000
|
||||
#define FLOPPY_STATUS_TRACK0 01 ///< Track 0 flag
|
||||
#define FLOPPY_STATUS_RDY 02 ///< Ready status
|
||||
#define FLOPPY_STATUS_WRITEPROTECT 04 ///< Write protect
|
||||
#define FLOPPY_STATUS_MOREDATA 0200 ///< Need more data flag
|
||||
#define FLOPPY_STATUS_CHECKSUMOK 040000 ///< Checksum verified OK
|
||||
#define FLOPPY_STATUS_INDEXMARK 0100000 ///< Index flag, indicates the beginning of track
|
||||
|
||||
#define FLOPPY_RAWTRACKSIZE 6250
|
||||
#define FLOPPY_RAWTRACKSIZE 6250 ///< Raw track size, bytes
|
||||
#define FLOPPY_RAWMARKERSIZE (FLOPPY_RAWTRACKSIZE / 2)
|
||||
#define FLOPPY_INDEXLENGTH 150
|
||||
#define FLOPPY_INDEXLENGTH 150 ///< Length of index hole, in bytes of raw track image
|
||||
|
||||
/// \brief Floppy drive (one of four drives in the floppy controller)
|
||||
/// \sa CFloppyController
|
||||
struct CFloppyDrive
|
||||
{
|
||||
FILE* fpFile;
|
||||
BOOL okNetRT11Image; // TRUE - .rtd image, FALSE - .dsk image
|
||||
BOOL okReadOnly; // Write protection flag
|
||||
WORD track; // Track number: from 0 to 79
|
||||
WORD side; // Disk side: 0 or 1
|
||||
WORD dataptr; // Data offset within m_data - "head" position
|
||||
BYTE data[FLOPPY_RAWTRACKSIZE]; // Raw track image for the current track
|
||||
BYTE marker[FLOPPY_RAWMARKERSIZE]; // Marker positions
|
||||
WORD datatrack; // Track number of data in m_data array
|
||||
WORD dataside; // Disk side of data in m_data array
|
||||
FILE* fpFile; ///< File pointer of the disk image file
|
||||
BOOL okNetRT11Image; ///< TRUE - .rtd image, FALSE - .dsk image
|
||||
BOOL okReadOnly; ///< Write protection flag
|
||||
WORD track; ///< Track number: from 0 to 79
|
||||
WORD side; ///< Disk side: 0 or 1
|
||||
WORD dataptr; ///< Data offset within m_data - "head" position
|
||||
BYTE data[FLOPPY_RAWTRACKSIZE]; ///< Raw track image for the current track
|
||||
BYTE marker[FLOPPY_RAWMARKERSIZE]; ///< Marker positions
|
||||
WORD datatrack; ///< Track number of data in m_data array
|
||||
WORD dataside; ///< Disk side of data in m_data array
|
||||
|
||||
public:
|
||||
CFloppyDrive();
|
||||
void Reset();
|
||||
void Reset(); ///< Reset the device
|
||||
};
|
||||
|
||||
/// \brief UKNC floppy controller (MZ standard)
|
||||
/// \sa CFloppyDrive
|
||||
class CFloppyController
|
||||
{
|
||||
protected:
|
||||
CFloppyDrive m_drivedata[4];
|
||||
WORD m_drive; // Drive number: from 0 to 3
|
||||
CFloppyDrive* m_pDrive; // Current drive
|
||||
WORD m_track; // Track number: from 0 to 79
|
||||
WORD m_side; // Disk side: 0 or 1
|
||||
WORD m_status; // See FLOPPY_STATUS_XXX defines
|
||||
WORD m_flags; // See FLOPPY_CMD_XXX defines
|
||||
WORD m_datareg; // Read mode data register
|
||||
WORD m_writereg; // Write mode data register
|
||||
BOOL m_writeflag; // Write mode data register has data
|
||||
BOOL m_writemarker; // Write marker in m_marker
|
||||
WORD m_shiftreg; // Write mode shift register
|
||||
BOOL m_shiftflag; // Write mode shift register has data
|
||||
BOOL m_shiftmarker; // Write marker in m_marker
|
||||
BOOL m_writing; // TRUE = write mode, FALSE = read mode
|
||||
BOOL m_searchsync; // Read sub-mode: TRUE = search for sync, FALSE = just read
|
||||
BOOL m_crccalculus; // TRUE = CRC is calculated now
|
||||
BOOL m_trackchanged; // TRUE = m_data was changed - need to save it into the file
|
||||
CFloppyDrive m_drivedata[4]; ///< Floppy drives
|
||||
WORD m_drive; ///< Current drive number: from 0 to 3
|
||||
CFloppyDrive* m_pDrive; ///< Current drive
|
||||
WORD m_track; ///< Track number: from 0 to 79
|
||||
WORD m_side; ///< Disk side: 0 or 1
|
||||
WORD m_status; ///< See FLOPPY_STATUS_XXX defines
|
||||
WORD m_flags; ///< See FLOPPY_CMD_XXX defines
|
||||
WORD m_datareg; ///< Read mode data register
|
||||
WORD m_writereg; ///< Write mode data register
|
||||
BOOL m_writeflag; ///< Write mode data register has data
|
||||
BOOL m_writemarker; ///< Write marker in m_marker
|
||||
WORD m_shiftreg; ///< Write mode shift register
|
||||
BOOL m_shiftflag; ///< Write mode shift register has data
|
||||
BOOL m_shiftmarker; ///< Write marker in m_marker
|
||||
BOOL m_writing; ///< TRUE = write mode, FALSE = read mode
|
||||
BOOL m_searchsync; ///< Read sub-mode: TRUE = search for sync, FALSE = just read
|
||||
BOOL m_crccalculus; ///< TRUE = CRC is calculated now
|
||||
BOOL m_trackchanged; ///< TRUE = m_data was changed - need to save it into the file
|
||||
|
||||
public:
|
||||
CFloppyController();
|
||||
~CFloppyController();
|
||||
void Reset();
|
||||
void Reset(); ///< Reset the device
|
||||
|
||||
public:
|
||||
/// \brief Attach the image to the drive -- insert disk
|
||||
BOOL AttachImage(int drive, LPCTSTR sFileName);
|
||||
/// \brief Detach image from the drive -- remove disk
|
||||
void DetachImage(int drive);
|
||||
/// \brief Check if the drive has an image attached
|
||||
BOOL IsAttached(int drive) const { return (m_drivedata[drive].fpFile != NULL); }
|
||||
/// \brief Check if the drive's attached image is read-only
|
||||
BOOL IsReadOnly(int drive) const { return m_drivedata[drive].okReadOnly; }
|
||||
/// \brief Check if floppy engine now rotates
|
||||
BOOL IsEngineOn() const { return (m_flags & FLOPPY_CMD_ENGINESTART) != 0; }
|
||||
WORD GetData(void); // Reading port 177132 - data
|
||||
WORD GetState(void); // Reading port 177130 - device status
|
||||
void SetCommand(WORD cmd); // Writing to port 177130 - commands
|
||||
void WriteData(WORD Data); // Writing to port 177132 - data
|
||||
void Periodic(); // Rotate disk; call it each 64 us - 15625 times per second
|
||||
WORD GetData(void); ///< Reading port 177132 -- data
|
||||
WORD GetState(void); ///< Reading port 177130 -- device status
|
||||
void SetCommand(WORD cmd); ///< Writing to port 177130 -- commands
|
||||
void WriteData(WORD Data); ///< Writing to port 177132 -- data
|
||||
void Periodic(); ///< Rotate disk; call it each 64 us -- 15625 times per second
|
||||
|
||||
private:
|
||||
void PrepareTrack();
|
||||
void FlushChanges(); // If current track was changed - save it
|
||||
void FlushChanges(); ///< If current track was changed - save it
|
||||
|
||||
};
|
||||
|
||||
@ -128,51 +134,59 @@ private:
|
||||
|
||||
#define IDE_DISK_SECTOR_SIZE 512
|
||||
|
||||
/// \brief UKNC IDE hard drive
|
||||
class CHardDrive
|
||||
{
|
||||
protected:
|
||||
FILE* m_fpFile;
|
||||
BOOL m_okReadOnly;
|
||||
BOOL m_okInverted;
|
||||
BYTE m_status;
|
||||
BYTE m_error;
|
||||
BYTE m_command;
|
||||
int m_numcylinders; // Cylinder count
|
||||
int m_numheads; // Head count
|
||||
int m_numsectors; // Sectors per track
|
||||
int m_curcylinder;
|
||||
int m_curhead;
|
||||
int m_cursector;
|
||||
int m_curheadreg;
|
||||
int m_sectorcount;
|
||||
BYTE m_buffer[IDE_DISK_SECTOR_SIZE];
|
||||
int m_bufferoffset; // Current offset within sector: 0..511
|
||||
int m_timeoutcount; // Timeout counter to wait for the next event
|
||||
int m_timeoutevent;
|
||||
FILE* m_fpFile; ///< File pointer for the attached HDD image
|
||||
BOOL m_okReadOnly; ///< Flag indicating that the HDD image file is read-only
|
||||
BOOL m_okInverted; ///< Flag indicating that the HDD image has inverted bits
|
||||
BYTE m_status; ///< IDE status register, see IDE_STATUS_XXX constants
|
||||
BYTE m_error; ///< IDE error register, see IDE_ERROR_XXX constants
|
||||
BYTE m_command; ///< Current IDE command, see IDE_COMMAND_XXX constants
|
||||
int m_numcylinders; ///< Cylinder count
|
||||
int m_numheads; ///< Head count
|
||||
int m_numsectors; ///< Sectors per track
|
||||
int m_curcylinder; ///< Current cylinder number
|
||||
int m_curhead; ///< Current head number
|
||||
int m_cursector; ///< Current sector number
|
||||
int m_curheadreg; ///< Current head number
|
||||
int m_sectorcount; ///< Sector counter for read/write operations
|
||||
BYTE m_buffer[IDE_DISK_SECTOR_SIZE]; ///< Sector data buffer
|
||||
int m_bufferoffset; ///< Current offset within sector: 0..511
|
||||
int m_timeoutcount; ///< Timeout counter to wait for the next event
|
||||
int m_timeoutevent; ///< Current stage of operation, see TimeoutEvent enum
|
||||
|
||||
public:
|
||||
CHardDrive();
|
||||
~CHardDrive();
|
||||
/// \brief Reset the device.
|
||||
void Reset();
|
||||
/// \brief Attach HDD image file to the device
|
||||
BOOL AttachImage(LPCTSTR sFileName);
|
||||
/// \brief Detach HDD image file from the device
|
||||
void DetachImage();
|
||||
/// \brief Check if the attached hard drive image is read-only
|
||||
BOOL IsReadOnly() const { return m_okReadOnly; }
|
||||
|
||||
public:
|
||||
/// \brief Read word from the device port
|
||||
WORD ReadPort(WORD port);
|
||||
/// \brief Write word th the device port
|
||||
void WritePort(WORD port, WORD data);
|
||||
/// \brief Rotate disk
|
||||
void Periodic();
|
||||
|
||||
private:
|
||||
DWORD CalculateOffset() const; // Calculate sector offset in the HDD image
|
||||
void HandleCommand(BYTE command); // Handle IDE command
|
||||
DWORD CalculateOffset() const; ///< Calculate sector offset in the HDD image
|
||||
void HandleCommand(BYTE command); ///< Handle the IDE command
|
||||
void ReadNextSector();
|
||||
void ReadSectorDone();
|
||||
void WriteSectorDone();
|
||||
void NextSector(); // Advance to the next sector, CHS-based
|
||||
void NextSector(); ///< Advance to the next sector, CHS-based
|
||||
void ContinueRead();
|
||||
void ContinueWrite();
|
||||
void IdentifyDrive(); // Prepare m_buffer for the IDENTIFY DRIVE command
|
||||
void IdentifyDrive(); ///< Prepare m_buffer for the IDENTIFY DRIVE command
|
||||
};
|
||||
|
||||
|
||||
|
@ -8,9 +8,9 @@ See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
UKNCBTL. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
// Floppy.cpp
|
||||
// Floppy controller and drives emulation
|
||||
// See defines in header file Emubase.h
|
||||
/// \file Floppy.cpp
|
||||
/// \brief Floppy controller and drives emulation
|
||||
/// \details See defines in header file Emubase.h
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <sys/stat.h>
|
||||
@ -56,8 +56,8 @@ CFloppyController::CFloppyController()
|
||||
m_writing = m_searchsync = m_writemarker = m_crccalculus = FALSE;
|
||||
m_writeflag = m_shiftflag = FALSE;
|
||||
m_trackchanged = FALSE;
|
||||
m_status = FLOPPY_STATUS_TRACK0|FLOPPY_STATUS_WRITEPROTECT;
|
||||
m_flags = FLOPPY_CMD_CORRECTION500|FLOPPY_CMD_SIDEUP|FLOPPY_CMD_DIR|FLOPPY_CMD_SKIPSYNC;
|
||||
m_status = FLOPPY_STATUS_TRACK0 | FLOPPY_STATUS_WRITEPROTECT;
|
||||
m_flags = FLOPPY_CMD_CORRECTION500 | FLOPPY_CMD_SIDEUP | FLOPPY_CMD_DIR | FLOPPY_CMD_SKIPSYNC;
|
||||
}
|
||||
|
||||
CFloppyController::~CFloppyController()
|
||||
@ -76,8 +76,8 @@ void CFloppyController::Reset()
|
||||
m_writing = m_searchsync = m_writemarker = m_crccalculus = FALSE;
|
||||
m_writeflag = m_shiftflag = FALSE;
|
||||
m_trackchanged = FALSE;
|
||||
m_status = (m_pDrive->okReadOnly) ? FLOPPY_STATUS_TRACK0|FLOPPY_STATUS_WRITEPROTECT : FLOPPY_STATUS_TRACK0;
|
||||
m_flags = FLOPPY_CMD_CORRECTION500|FLOPPY_CMD_SIDEUP|FLOPPY_CMD_DIR|FLOPPY_CMD_SKIPSYNC;
|
||||
m_status = (m_pDrive->okReadOnly) ? FLOPPY_STATUS_TRACK0 | FLOPPY_STATUS_WRITEPROTECT : FLOPPY_STATUS_TRACK0;
|
||||
m_flags = FLOPPY_CMD_CORRECTION500 | FLOPPY_CMD_SIDEUP | FLOPPY_CMD_DIR | FLOPPY_CMD_SKIPSYNC;
|
||||
|
||||
PrepareTrack();
|
||||
}
|
||||
@ -113,8 +113,8 @@ BOOL CFloppyController::AttachImage(int drive, LPCTSTR sFileName)
|
||||
m_writing = m_searchsync = m_writemarker = m_crccalculus = FALSE;
|
||||
m_writeflag = m_shiftflag = FALSE;
|
||||
m_trackchanged = FALSE;
|
||||
m_status = (m_pDrive->okReadOnly) ? FLOPPY_STATUS_TRACK0|FLOPPY_STATUS_WRITEPROTECT : FLOPPY_STATUS_TRACK0;
|
||||
m_flags = FLOPPY_CMD_CORRECTION500|FLOPPY_CMD_SIDEUP|FLOPPY_CMD_DIR|FLOPPY_CMD_SKIPSYNC;
|
||||
m_status = (m_pDrive->okReadOnly) ? FLOPPY_STATUS_TRACK0 | FLOPPY_STATUS_WRITEPROTECT : FLOPPY_STATUS_TRACK0;
|
||||
m_flags = FLOPPY_CMD_CORRECTION500 | FLOPPY_CMD_SIDEUP | FLOPPY_CMD_DIR | FLOPPY_CMD_SKIPSYNC;
|
||||
|
||||
PrepareTrack();
|
||||
|
||||
@ -190,7 +190,7 @@ void CFloppyController::SetCommand(WORD cmd)
|
||||
// Copy new flags to m_flags
|
||||
m_flags &= ~FLOPPY_CMD_MASKSTORED;
|
||||
m_flags |= cmd & FLOPPY_CMD_MASKSTORED;
|
||||
|
||||
|
||||
// Ïðîâåðÿåì, íå ñìåíèëàñü ëè ñòîðîíà
|
||||
if (m_flags & FLOPPY_CMD_SIDEUP) // Side selection: 0 - down, 1 - up
|
||||
{
|
||||
@ -198,7 +198,7 @@ void CFloppyController::SetCommand(WORD cmd)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_side == 1) { m_side = 0; okPrepareTrack = TRUE; }
|
||||
if (m_side == 1) { m_side = 0; okPrepareTrack = TRUE; }
|
||||
}
|
||||
|
||||
if (cmd & FLOPPY_CMD_STEP) // Move head for one track to center or from center
|
||||
@ -226,7 +226,7 @@ void CFloppyController::SetCommand(WORD cmd)
|
||||
//#endif
|
||||
}
|
||||
|
||||
if(cmd & FLOPPY_CMD_SEARCHSYNC) // Search for marker
|
||||
if (cmd & FLOPPY_CMD_SEARCHSYNC) // Search for marker
|
||||
{
|
||||
//#if !defined(PRODUCT)
|
||||
// DebugLog(_T("Floppy SEARCHSYNC\r\n")); //DEBUG
|
||||
@ -252,7 +252,7 @@ WORD CFloppyController::GetData(void)
|
||||
//#if !defined(PRODUCT)
|
||||
// DebugLogFormat(_T("Floppy READ\t\t%04x\r\n"), m_datareg); //DEBUG
|
||||
//#endif
|
||||
|
||||
|
||||
m_status &= ~FLOPPY_STATUS_MOREDATA;
|
||||
m_writing = m_searchsync = FALSE;
|
||||
m_writeflag = m_shiftflag = FALSE;
|
||||
@ -472,7 +472,8 @@ void CFloppyController::FlushChanges()
|
||||
size_t dwBytesWritten = ::fwrite(&data, 1, 5120, m_pDrive->fpFile);
|
||||
//TODO: Ïðîâåðêà íà îøèáêè çàïèñè
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
//#if !defined(PRODUCT)
|
||||
// DebugLog(_T("Floppy FLUSH FAILED\r\n")); //DEBUG
|
||||
//#endif
|
||||
@ -508,9 +509,9 @@ static void EncodeTrackData(const BYTE* pSrc, BYTE* data, BYTE* marker, WORD tra
|
||||
marker[ptr / 2] = TRUE; // ID marker; start CRC calculus
|
||||
data[ptr++] = 0xa1; data[ptr++] = 0xa1; data[ptr++] = 0xa1;
|
||||
data[ptr++] = 0xfe;
|
||||
|
||||
|
||||
data[ptr++] = (BYTE) track; data[ptr++] = (side != 0);
|
||||
data[ptr++] = sect + 1; data[ptr++] = 2; // Assume 512 bytes per sector;
|
||||
data[ptr++] = (BYTE)sect + 1; data[ptr++] = 2; // Assume 512 bytes per sector;
|
||||
// crc
|
||||
//TODO: Calculate CRC
|
||||
data[ptr++] = 0x12; data[ptr++] = 0x34; // CRC stub
|
||||
@ -521,7 +522,7 @@ static void EncodeTrackData(const BYTE* pSrc, BYTE* data, BYTE* marker, WORD tra
|
||||
for (count = 0; count < 12; count++) data[ptr++] = 0x00;
|
||||
// marker
|
||||
marker[ptr / 2] = TRUE; // Data marker; start CRC calculus
|
||||
data[ptr++] = 0xa1; data[ptr++] = 0xa1; data[ptr++]=0xa1;
|
||||
data[ptr++] = 0xa1; data[ptr++] = 0xa1; data[ptr++] = 0xa1;
|
||||
data[ptr++] = 0xfb;
|
||||
// data
|
||||
for (count = 0; count < 512; count++)
|
||||
@ -558,7 +559,7 @@ static BOOL DecodeTrackData(const BYTE* pRaw, BYTE* pDest)
|
||||
if (pRaw[dataptr++] != 0xfe)
|
||||
return FALSE; // Marker not found
|
||||
|
||||
BYTE sectcyl, secthd, sectsec, sectno;
|
||||
BYTE sectcyl, secthd, sectsec, sectno = 0;
|
||||
if (dataptr < FLOPPY_RAWTRACKSIZE) sectcyl = pRaw[dataptr++];
|
||||
if (dataptr < FLOPPY_RAWTRACKSIZE) secthd = pRaw[dataptr++];
|
||||
if (dataptr < FLOPPY_RAWTRACKSIZE) sectsec = pRaw[dataptr++];
|
||||
|
@ -8,9 +8,9 @@ See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
UKNCBTL. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
// Hard.cpp
|
||||
// Hard disk drive emulation
|
||||
// See defines in header file Emubase.h
|
||||
/// \file Hard.cpp
|
||||
/// \brief Hard disk drive emulation.
|
||||
/// \details See defines in header file Emubase.h
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <sys/stat.h>
|
||||
@ -140,7 +140,7 @@ BOOL CHardDrive::AttachImage(LPCTSTR sFileName)
|
||||
// Invert the buffer if needed
|
||||
if (m_okInverted)
|
||||
InvertBuffer(m_buffer);
|
||||
|
||||
|
||||
// Calculate geometry
|
||||
m_numsectors = *(m_buffer + 0);
|
||||
m_numheads = *(m_buffer + 1);
|
||||
@ -196,19 +196,19 @@ WORD CHardDrive::ReadPort(WORD port)
|
||||
data = 0xff00 | m_error;
|
||||
break;
|
||||
case IDE_PORT_SECTOR_COUNT:
|
||||
data = 0xff00 | m_sectorcount;
|
||||
data = 0xff00 | (WORD)m_sectorcount;
|
||||
break;
|
||||
case IDE_PORT_SECTOR_NUMBER:
|
||||
data = 0xff00 | m_cursector;
|
||||
data = 0xff00 | (WORD)m_cursector;
|
||||
break;
|
||||
case IDE_PORT_CYLINDER_LSB:
|
||||
data = 0xff00 | (m_curcylinder & 0xff);
|
||||
data = 0xff00 | (WORD)(m_curcylinder & 0xff);
|
||||
break;
|
||||
case IDE_PORT_CYLINDER_MSB:
|
||||
data = 0xff00 | ((m_curcylinder >> 8) & 0xff);
|
||||
data = 0xff00 | (WORD)((m_curcylinder >> 8) & 0xff);
|
||||
break;
|
||||
case IDE_PORT_HEAD_NUMBER:
|
||||
data = 0xff00 | m_curheadreg;
|
||||
data = 0xff00 | (WORD)m_curheadreg;
|
||||
break;
|
||||
case IDE_PORT_STATUS_COMMAND:
|
||||
data = 0xff00 | m_status;
|
||||
@ -308,56 +308,56 @@ void CHardDrive::HandleCommand(BYTE command)
|
||||
m_command = command;
|
||||
switch (command)
|
||||
{
|
||||
case IDE_COMMAND_READ_MULTIPLE:
|
||||
case IDE_COMMAND_READ_MULTIPLE1:
|
||||
case IDE_COMMAND_READ_MULTIPLE:
|
||||
case IDE_COMMAND_READ_MULTIPLE1:
|
||||
//#if !defined(PRODUCT)
|
||||
// DebugPrintFormat(_T("HDD COMMAND %02x (READ MULT): C=%d, H=%d, SN=%d, SC=%d\r\n"),
|
||||
// command, m_curcylinder, m_curhead, m_cursector, m_sectorcount);
|
||||
//#endif
|
||||
m_status |= IDE_STATUS_BUSY;
|
||||
m_status |= IDE_STATUS_BUSY;
|
||||
|
||||
m_timeoutcount = TIME_PER_SECTOR * 3; // Timeout while seek for track
|
||||
m_timeoutevent = TIMEEVT_READ_SECTOR_DONE;
|
||||
break;
|
||||
m_timeoutcount = TIME_PER_SECTOR * 3; // Timeout while seek for track
|
||||
m_timeoutevent = TIMEEVT_READ_SECTOR_DONE;
|
||||
break;
|
||||
|
||||
case IDE_COMMAND_SET_CONFIG:
|
||||
case IDE_COMMAND_SET_CONFIG:
|
||||
//#if !defined(PRODUCT)
|
||||
// DebugPrintFormat(_T("HDD COMMAND %02x (SET CONFIG): H=%d, SC=%d\r\n"),
|
||||
// command, m_curhead, m_sectorcount);
|
||||
//#endif
|
||||
m_numsectors = m_sectorcount;
|
||||
m_numheads = m_curhead + 1;
|
||||
break;
|
||||
m_numsectors = m_sectorcount;
|
||||
m_numheads = m_curhead + 1;
|
||||
break;
|
||||
|
||||
case IDE_COMMAND_WRITE_MULTIPLE:
|
||||
case IDE_COMMAND_WRITE_MULTIPLE1:
|
||||
case IDE_COMMAND_WRITE_MULTIPLE:
|
||||
case IDE_COMMAND_WRITE_MULTIPLE1:
|
||||
//#if !defined(PRODUCT)
|
||||
// DebugPrintFormat(_T("HDD COMMAND %02x (WRITE MULT): C=%d, H=%d, SN=%d, SC=%d\r\n"),
|
||||
// command, m_curcylinder, m_curhead, m_cursector, m_sectorcount);
|
||||
//#endif
|
||||
m_bufferoffset = 0;
|
||||
m_status |= IDE_STATUS_BUFFER_READY;
|
||||
break;
|
||||
m_bufferoffset = 0;
|
||||
m_status |= IDE_STATUS_BUFFER_READY;
|
||||
break;
|
||||
|
||||
case IDE_COMMAND_IDENTIFY:
|
||||
case IDE_COMMAND_IDENTIFY:
|
||||
//#if !defined(PRODUCT)
|
||||
// DebugPrintFormat(_T("HDD COMMAND %02x (IDENTIFY)\r\n"), command);
|
||||
//#endif
|
||||
IdentifyDrive(); // Prepare the buffer
|
||||
m_bufferoffset = 0;
|
||||
m_sectorcount = 1;
|
||||
m_status |= IDE_STATUS_BUFFER_READY | IDE_STATUS_SEEK_COMPLETE | IDE_STATUS_DRIVE_READY;
|
||||
m_status &= ~IDE_STATUS_BUSY;
|
||||
m_status &= ~IDE_STATUS_ERROR;
|
||||
break;
|
||||
IdentifyDrive(); // Prepare the buffer
|
||||
m_bufferoffset = 0;
|
||||
m_sectorcount = 1;
|
||||
m_status |= IDE_STATUS_BUFFER_READY | IDE_STATUS_SEEK_COMPLETE | IDE_STATUS_DRIVE_READY;
|
||||
m_status &= ~IDE_STATUS_BUSY;
|
||||
m_status &= ~IDE_STATUS_ERROR;
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
//#if !defined(PRODUCT)
|
||||
// DebugPrintFormat(_T("HDD COMMAND %02x (UNKNOWN): C=%d, H=%d, SN=%d, SC=%d\r\n"),
|
||||
// command, m_curcylinder, m_curhead, m_cursector, m_sectorcount);
|
||||
// //DebugBreak(); // Implement this IDE command!
|
||||
//#endif
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,11 +365,11 @@ void CHardDrive::HandleCommand(BYTE command)
|
||||
// For use in CHardDrive::IdentifyDrive() method.
|
||||
static void swap_strncpy(BYTE* dst, const char* src, int words)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (int)strlen(src); i++)
|
||||
dst[i ^ 1] = src[i];
|
||||
for ( ; i < words * 2; i++)
|
||||
dst[i ^ 1] = ' ';
|
||||
int i;
|
||||
for (i = 0; src[i] != 0; i++)
|
||||
dst[i ^ 1] = src[i];
|
||||
for ( ; i < words * 2; i++)
|
||||
dst[i ^ 1] = ' ';
|
||||
}
|
||||
|
||||
void CHardDrive::IdentifyDrive()
|
||||
|
1862
emubase/Memory.cpp
1862
emubase/Memory.cpp
File diff suppressed because it is too large
Load Diff
152
emubase/Memory.h
152
emubase/Memory.h
@ -8,77 +8,83 @@ See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
UKNCBTL. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
// Memory.h
|
||||
//
|
||||
/// \file Memory.h Memory controller class
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Defines.h"
|
||||
#include "Board.h"
|
||||
|
||||
class CProcessor;
|
||||
class CMotherboard;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TranslateAddress result code
|
||||
#define ADDRTYPE_RAM0 0 // RAM plane 0
|
||||
#define ADDRTYPE_RAM1 1 // RAM plane 1
|
||||
#define ADDRTYPE_RAM2 2 // RAM plane 2
|
||||
#define ADDRTYPE_RAM12 4 // RAM plane 1 & 2 - a special case for CPU memory
|
||||
#define ADDRTYPE_ROM 8 // ROM
|
||||
#define ADDRTYPE_IO 16 // I/O port
|
||||
#define ADDRTYPE_ROMCART1 32 // ROM cartridge #1
|
||||
#define ADDRTYPE_ROMCART2 64 // ROM cartridge #2
|
||||
#define ADDRTYPE_NONE 128 // No data
|
||||
#define ADDRTYPE_DENY 255 // Access denied
|
||||
#define ADDRTYPE_MASK_RAM 7 // Mask to get memory plane number
|
||||
#define ADDRTYPE_RAM0 0 ///< RAM plane 0
|
||||
#define ADDRTYPE_RAM1 1 ///< RAM plane 1
|
||||
#define ADDRTYPE_RAM2 2 ///< RAM plane 2
|
||||
#define ADDRTYPE_RAM12 4 ///< RAM plane 1 & 2 - a special case for CPU memory
|
||||
#define ADDRTYPE_ROM 32 ///< ROM
|
||||
#define ADDRTYPE_ROMCART1 40 ///< ADDRTYPE_ROM + 8 -- ROM cartridge #1
|
||||
#define ADDRTYPE_ROMCART2 48 ///< ADDRTYPE_ROM + 16 -- ROM cartridge #2
|
||||
#define ADDRTYPE_IO 64 ///< I/O port; bits 5..0 -- device number
|
||||
#define ADDRTYPE_NONE 128 ///< No data
|
||||
#define ADDRTYPE_DENY 255 ///< Access denied
|
||||
#define ADDRTYPE_MASK_RAM 7 ///< Mask to get memory plane number
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Memory control device for CPU or PPU (abstract class)
|
||||
/// \brief Memory control device for CPU or PPU (abstract class)
|
||||
class CMemoryController
|
||||
{
|
||||
protected:
|
||||
CMotherboard* m_pBoard;
|
||||
CProcessor* m_pProcessor;
|
||||
CMotherboard* m_pBoard; ///< Motherboard attached
|
||||
CProcessor* m_pProcessor; ///< Processor attached
|
||||
BYTE* m_pMapping; ///< Memory mapping
|
||||
CBusDevice** m_pDevices; ///< Attached bus devices
|
||||
int m_nDeviceCount;
|
||||
public:
|
||||
CMemoryController();
|
||||
~CMemoryController();
|
||||
void Attach(CMotherboard* board, CProcessor* processor)
|
||||
{ m_pBoard = board; m_pProcessor = processor; }
|
||||
{ m_pBoard = board; m_pProcessor = processor; }
|
||||
/// \brief Attach/reattach bus devices
|
||||
void AttachDevices(const CBusDevice** pDevices);
|
||||
virtual void UpdateMemoryMap();
|
||||
// Reset to initial state
|
||||
virtual void DCLO_Signal() = 0; // DCLO signal
|
||||
virtual void ResetDevices() = 0; // INIT signal
|
||||
virtual void DCLO_Signal() = 0; ///< DCLO signal
|
||||
virtual void ResetDevices() = 0; ///< INIT signal
|
||||
public: // Access to memory
|
||||
// Read command for execution
|
||||
/// \brief Read command for execution
|
||||
WORD GetWordExec(WORD address, BOOL okHaltMode) { return GetWord(address, okHaltMode, TRUE); }
|
||||
// Read word from memory
|
||||
/// \brief Read word from memory
|
||||
WORD GetWord(WORD address, BOOL okHaltMode) { return GetWord(address, okHaltMode, FALSE); }
|
||||
// Read word
|
||||
/// \brief Read word
|
||||
WORD GetWord(WORD address, BOOL okHaltMode, BOOL okExec);
|
||||
// Write word
|
||||
/// \brief Write word
|
||||
void SetWord(WORD address, BOOL okHaltMode, WORD word);
|
||||
// Read byte
|
||||
/// \brief Read byte
|
||||
BYTE GetByte(WORD address, BOOL okHaltMode);
|
||||
// Write byte
|
||||
/// \brief Write byte
|
||||
void SetByte(WORD address, BOOL okHaltMode, BYTE byte);
|
||||
// Read word from memory for debugger
|
||||
WORD GetWordView(WORD address, BOOL okHaltMode, BOOL okExec, BOOL* pValid);
|
||||
// Read word from port for debugger
|
||||
virtual WORD GetPortView(WORD address) = 0;
|
||||
// Read SEL register
|
||||
/// \brief Read word from memory for debugger
|
||||
WORD GetWordView(WORD address, BOOL okHaltMode, BOOL okExec, BOOL* pValid) const;
|
||||
/// \brief Read word from port for debugger
|
||||
virtual WORD GetPortView(WORD address) const = 0;
|
||||
/// \brief Read SEL register
|
||||
virtual WORD GetSelRegister() = 0;
|
||||
public: // Saving/loading emulator status (64 bytes)
|
||||
virtual void SaveToImage(BYTE* pImage) = 0;
|
||||
virtual void LoadFromImage(const BYTE* pImage) = 0;
|
||||
protected:
|
||||
// Determite memory type for given address - see ADDRTYPE_Xxx constants
|
||||
// okHaltMode - processor mode (USER/HALT)
|
||||
// okExec - TRUE: read instruction for execution; FALSE: read memory
|
||||
// pOffset - result - offset in memory plane
|
||||
virtual int TranslateAddress(WORD address, BOOL okHaltMode, BOOL okExec, WORD* pOffset, BOOL okView = FALSE) = 0;
|
||||
/// \brief Determite memory type for given address - see ADDRTYPE_Xxx constants
|
||||
/// \param okHaltMode processor mode (USER/HALT)
|
||||
/// \param okExec TRUE: read instruction for execution; FALSE: read memory
|
||||
/// \param pOffset result -- offset in memory plane
|
||||
virtual int TranslateAddress(WORD address, BOOL okHaltMode, BOOL okExec, WORD* pOffset, BOOL okView = FALSE) const = 0;
|
||||
protected: // Access to I/O ports
|
||||
virtual WORD GetPortWord(WORD address) = 0;
|
||||
virtual void SetPortWord(WORD address, WORD word) = 0;
|
||||
@ -86,17 +92,18 @@ protected: // Access to I/O ports
|
||||
virtual void SetPortByte(WORD address, BYTE byte) = 0;
|
||||
};
|
||||
|
||||
class CFirstMemoryController : public CMemoryController // CPU memory control device
|
||||
/// \brief CPU memory control device
|
||||
class CFirstMemoryController : public CMemoryController
|
||||
{
|
||||
friend class CMotherboard;
|
||||
public:
|
||||
CFirstMemoryController();
|
||||
virtual void DCLO_Signal(); // DCLO signal
|
||||
virtual void ResetDevices(); // INIT signal
|
||||
virtual void DCLO_Signal(); ///< DCLO signal
|
||||
virtual void ResetDevices(); ///< INIT signal
|
||||
public:
|
||||
virtual int TranslateAddress(WORD address, BOOL okHaltMode, BOOL okExec, WORD* pOffset, BOOL okView);
|
||||
virtual int TranslateAddress(WORD address, BOOL okHaltMode, BOOL okExec, WORD* pOffset, BOOL okView) const;
|
||||
virtual WORD GetSelRegister() { return 0160000; }
|
||||
virtual WORD GetPortView(WORD address);
|
||||
virtual WORD GetPortView(WORD address) const;
|
||||
protected: // Access to I/O ports
|
||||
virtual WORD GetPortWord(WORD address);
|
||||
virtual void SetPortWord(WORD address, WORD word);
|
||||
@ -107,31 +114,38 @@ public: // Saving/loading emulator status (64 bytes)
|
||||
virtual void LoadFromImage(const BYTE* pImage);
|
||||
public: // CPU specific
|
||||
BOOL SerialInput(BYTE inputByte);
|
||||
|
||||
BOOL NetworkInput(BYTE inputByte);
|
||||
protected: // Implementation
|
||||
WORD m_Port176640; // Plane address register
|
||||
WORD m_Port176642; // Plane 1 & 2 data register
|
||||
int m_NetStation; ///< Network station number
|
||||
WORD m_Port176560; ///< Network receiver state
|
||||
WORD m_Port176562; ///< Network receiver data (bits 0-7)
|
||||
WORD m_Port176564; ///< Network translator state
|
||||
WORD m_Port176566; ///< Network translator data (bits 0-7)
|
||||
WORD m_Port176640; ///< Plane address register
|
||||
WORD m_Port176642; ///< Plane 1 & 2 data register
|
||||
WORD m_Port176644;
|
||||
WORD m_Port176646;
|
||||
WORD m_Port176570; // RS-232 receiver state
|
||||
WORD m_Port176572; // RS-232 receiver data (bits 0-7)
|
||||
WORD m_Port176574; // RS-232 translator state
|
||||
WORD m_Port176576; // RS-232 translator data (bits 0-7)
|
||||
WORD m_Port176570; ///< RS-232 receiver state
|
||||
WORD m_Port176572; ///< RS-232 receiver data (bits 0-7)
|
||||
WORD m_Port176574; ///< RS-232 translator state
|
||||
WORD m_Port176576; ///< RS-232 translator data (bits 0-7)
|
||||
};
|
||||
|
||||
class CSecondMemoryController : public CMemoryController // PPU memory control device
|
||||
/// \brief PPU memory control device
|
||||
class CSecondMemoryController : public CMemoryController
|
||||
{
|
||||
friend class CMotherboard;
|
||||
public:
|
||||
CSecondMemoryController();
|
||||
virtual void DCLO_Signal(); // DCLO signal
|
||||
virtual void ResetDevices(); // INIT signal
|
||||
virtual void UpdateMemoryMap();
|
||||
virtual void DCLO_Signal(); ///< DCLO signal
|
||||
virtual void ResetDevices(); ///< INIT signal
|
||||
virtual void DCLO_177716();
|
||||
virtual void Init_177716();
|
||||
public:
|
||||
virtual int TranslateAddress(WORD address, BOOL okHaltMode, BOOL okExec, WORD* pOffset, BOOL okView);
|
||||
virtual int TranslateAddress(WORD address, BOOL okHaltMode, BOOL okExec, WORD* pOffset, BOOL okView) const;
|
||||
virtual WORD GetSelRegister() { return 0160000; }
|
||||
virtual WORD GetPortView(WORD address);
|
||||
virtual WORD GetPortView(WORD address) const;
|
||||
protected: // Access to I/O ports
|
||||
virtual WORD GetPortWord(WORD address);
|
||||
virtual void SetPortWord(WORD address, WORD word);
|
||||
@ -141,29 +155,29 @@ public: // Saving/loading emulator status (64 bytes)
|
||||
virtual void SaveToImage(BYTE* pImage);
|
||||
virtual void LoadFromImage(const BYTE* pImage);
|
||||
public: // PPU specifics
|
||||
void KeyboardEvent(BYTE scancode, BOOL okPressed); // Keyboard key pressed or released
|
||||
void KeyboardEvent(BYTE scancode, BOOL okPressed); ///< Keyboard key pressed or released
|
||||
BOOL TapeInput(BOOL inputBit);
|
||||
BOOL TapeOutput();
|
||||
protected: // Implementation
|
||||
WORD m_Port177010; // Plane address register
|
||||
WORD m_Port177012; // Plane 0 data register
|
||||
WORD m_Port177014; // Plane 1 & 2 data register
|
||||
WORD m_Port177010; ///< Plane address register
|
||||
WORD m_Port177012; ///< Plane 0 data register
|
||||
WORD m_Port177014; ///< Plane 1 & 2 data register
|
||||
|
||||
WORD m_Port177026; // Plane mask
|
||||
WORD m_Port177024; // SpriteByte
|
||||
WORD m_Port177020; // Background color 1
|
||||
WORD m_Port177022; // Background color 2
|
||||
WORD m_Port177016; // Pixel Color
|
||||
WORD m_Port177026; ///< Plane mask
|
||||
WORD m_Port177024; ///< SpriteByte
|
||||
WORD m_Port177020; ///< Background color 1
|
||||
WORD m_Port177022; ///< Background color 2
|
||||
WORD m_Port177016; ///< Pixel Color
|
||||
|
||||
WORD m_Port177700; // Keyboard status
|
||||
WORD m_Port177702; // Keyboard data
|
||||
WORD m_Port177716; // System control register
|
||||
WORD m_Port177700; ///< Keyboard status
|
||||
WORD m_Port177702; ///< Keyboard data
|
||||
WORD m_Port177716; ///< System control register
|
||||
|
||||
WORD m_Port177054; // address space control
|
||||
WORD m_Port177054; ///< address space control
|
||||
|
||||
BYTE m_Port177100; // i8255 port A -- Parallel port output data
|
||||
BYTE m_Port177101; // i8255 port B
|
||||
BYTE m_Port177102; // i8255 port C
|
||||
BYTE m_Port177100; ///< i8255 port A -- Parallel port output data
|
||||
BYTE m_Port177101; ///< i8255 port B
|
||||
BYTE m_Port177102; ///< i8255 port C
|
||||
};
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,8 +8,7 @@ See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
UKNCBTL. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
// Processor.h
|
||||
// KM1801VM2 processor
|
||||
/// \file Processor.h KM1801VM2 processor class
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -21,68 +20,70 @@ class CMemoryController;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class CProcessor // KM1801VM2 processor
|
||||
/// \brief KM1801VM2 processor
|
||||
class CProcessor
|
||||
{
|
||||
|
||||
public: // Constructor / initialization
|
||||
CProcessor(LPCTSTR name);
|
||||
CProcessor(LPCTSTR name);
|
||||
/// \brief Link the processor and memory controller
|
||||
void AttachMemoryController(CMemoryController* ctl) { m_pMemoryController = ctl; }
|
||||
void SetHALTPin(BOOL value);
|
||||
void SetDCLOPin(BOOL value);
|
||||
void SetACLOPin(BOOL value);
|
||||
void MemoryError();
|
||||
/// \brief Get the processor name, assigned in the constructor
|
||||
LPCTSTR GetName() const { return m_name; }
|
||||
|
||||
public:
|
||||
static void Init(); // Initialize static tables
|
||||
static void Done(); // Release memory used for static tables
|
||||
static void Init(); ///< Initialize static tables
|
||||
static void Done(); ///< Release memory used for static tables
|
||||
protected: // Statics
|
||||
typedef void ( CProcessor::*ExecuteMethodRef )();
|
||||
static ExecuteMethodRef* m_pExecuteMethodMap;
|
||||
static void RegisterMethodRef(WORD start, WORD end, CProcessor::ExecuteMethodRef methodref);
|
||||
|
||||
protected: // Processor state
|
||||
TCHAR m_name[5]; // Processor name (DO NOT use it inside the processor code!!!)
|
||||
WORD m_internalTick; // How many ticks waiting to the end of current instruction
|
||||
WORD m_psw; // Processor Status Word (PSW)
|
||||
WORD m_R[8]; // Registers (R0..R5, R6=SP, R7=PC)
|
||||
BOOL m_okStopped; // "Processor stopped" flag
|
||||
WORD m_savepc; // CPC register
|
||||
WORD m_savepsw; // CPSW register
|
||||
BOOL m_stepmode; // Read TRUE if it's step mode
|
||||
BOOL m_buserror; // Read TRUE if occured bus error for implementing double bus error if needed
|
||||
BOOL m_haltpin; // HALT pin
|
||||
BOOL m_DCLOpin; // DCLO pin
|
||||
BOOL m_ACLOpin; // ACLO pin
|
||||
BOOL m_waitmode; // WAIT
|
||||
TCHAR m_name[5]; ///< Processor name (DO NOT use it inside the processor code!!!)
|
||||
WORD m_internalTick; ///< How many ticks waiting to the end of current instruction
|
||||
WORD m_psw; ///< Processor Status Word (PSW)
|
||||
WORD m_R[8]; ///< Registers (R0..R5, R6=SP, R7=PC)
|
||||
BOOL m_okStopped; ///< "Processor stopped" flag
|
||||
WORD m_savepc; ///< CPC register
|
||||
WORD m_savepsw; ///< CPSW register
|
||||
BOOL m_stepmode; ///< Read TRUE if it's step mode
|
||||
BOOL m_buserror; ///< Read TRUE if occured bus error for implementing double bus error if needed
|
||||
BOOL m_haltpin; ///< HALT pin
|
||||
BOOL m_DCLOpin; ///< DCLO pin
|
||||
BOOL m_ACLOpin; ///< ACLO pin
|
||||
BOOL m_waitmode; ///< WAIT
|
||||
|
||||
protected: // Current instruction processing
|
||||
WORD m_instruction; // Curent instruction
|
||||
int m_regsrc; // Source register number
|
||||
int m_methsrc; // Source address mode
|
||||
WORD m_addrsrc; // Source address
|
||||
int m_regdest; // Destination register number
|
||||
int m_methdest; // Destination address mode
|
||||
WORD m_addrdest; // Destination address
|
||||
WORD m_instruction; ///< Curent instruction
|
||||
int m_regsrc; ///< Source register number
|
||||
int m_methsrc; ///< Source address mode
|
||||
WORD m_addrsrc; ///< Source address
|
||||
int m_regdest; ///< Destination register number
|
||||
int m_methdest; ///< Destination address mode
|
||||
WORD m_addrdest; ///< Destination address
|
||||
protected: // Interrupt processing
|
||||
BOOL m_STRTrq; // Start interrupt pending
|
||||
BOOL m_RPLYrq; // Hangup interrupt pending
|
||||
BOOL m_ILLGrq; // Illegal instruction interrupt pending
|
||||
BOOL m_RSVDrq; // Reserved instruction interrupt pending
|
||||
BOOL m_TBITrq; // T-bit interrupt pending
|
||||
BOOL m_ACLOrq; // Power down interrupt pending
|
||||
BOOL m_HALTrq; // HALT command or HALT signal
|
||||
BOOL m_EVNTrq; // Timer event interrupt pending
|
||||
BOOL m_FIS_rq; // FIS command interrupt pending
|
||||
BOOL m_BPT_rq; // BPT command interrupt pending
|
||||
BOOL m_IOT_rq; // IOT command interrupt pending
|
||||
BOOL m_EMT_rq; // EMT command interrupt pending
|
||||
BOOL m_TRAPrq; // TRAP command interrupt pending
|
||||
WORD m_virq[16]; // VIRQ vector
|
||||
BOOL m_ACLOreset; // Power fail interrupt request reset
|
||||
BOOL m_EVNTreset; // EVNT interrupt request reset;
|
||||
int m_VIRQreset; // VIRQ request reset for given device
|
||||
BOOL m_STRTrq; ///< Start interrupt pending
|
||||
BOOL m_RPLYrq; ///< Hangup interrupt pending
|
||||
BOOL m_ILLGrq; ///< Illegal instruction interrupt pending
|
||||
BOOL m_RSVDrq; ///< Reserved instruction interrupt pending
|
||||
BOOL m_TBITrq; ///< T-bit interrupt pending
|
||||
BOOL m_ACLOrq; ///< Power down interrupt pending
|
||||
BOOL m_HALTrq; ///< HALT command or HALT signal
|
||||
BOOL m_EVNTrq; ///< Timer event interrupt pending
|
||||
BOOL m_FIS_rq; ///< FIS command interrupt pending
|
||||
BOOL m_BPT_rq; ///< BPT command interrupt pending
|
||||
BOOL m_IOT_rq; ///< IOT command interrupt pending
|
||||
BOOL m_EMT_rq; ///< EMT command interrupt pending
|
||||
BOOL m_TRAPrq; ///< TRAP command interrupt pending
|
||||
WORD m_virq[16]; ///< VIRQ vector
|
||||
BOOL m_ACLOreset; ///< Power fail interrupt request reset
|
||||
BOOL m_EVNTreset; ///< EVNT interrupt request reset;
|
||||
int m_VIRQreset; ///< VIRQ request reset for given device
|
||||
protected:
|
||||
CMemoryController* m_pMemoryController;
|
||||
|
||||
@ -90,9 +91,10 @@ public:
|
||||
CMemoryController* GetMemoryController() { return m_pMemoryController; }
|
||||
|
||||
public: // Register control
|
||||
WORD GetPSW() const { return m_psw; }
|
||||
WORD GetPSW() const { return m_psw; } ///< Get the processor status word register value
|
||||
WORD GetCPSW() const { return m_savepsw; }
|
||||
BYTE GetLPSW() const { return LOBYTE(m_psw); }
|
||||
BYTE GetLPSW() const { return LOBYTE(m_psw); } ///< Get PSW lower byte
|
||||
/// \brief Set the processor status word register value
|
||||
void SetPSW(WORD word)
|
||||
{
|
||||
m_psw = word & 0777;
|
||||
@ -104,24 +106,25 @@ public: // Register control
|
||||
m_psw = (m_psw & 0xFF00) | (WORD)byte;
|
||||
if ((m_psw & 0600) != 0600) m_savepsw = m_psw;
|
||||
}
|
||||
WORD GetReg(int regno) const { return m_R[regno]; }
|
||||
WORD GetReg(int regno) const { return m_R[regno]; } ///< Get register value, regno=0..7
|
||||
/// \brief Set register value
|
||||
void SetReg(int regno, WORD word)
|
||||
{
|
||||
m_R[regno] = word;
|
||||
if ((regno == 7) && ((m_psw & 0600)!=0600)) m_savepc = word;
|
||||
if ((regno == 7) && ((m_psw & 0600) != 0600)) m_savepc = word;
|
||||
}
|
||||
BYTE GetLReg(int regno) const { return LOBYTE(m_R[regno]); }
|
||||
void SetLReg(int regno, BYTE byte)
|
||||
{
|
||||
m_R[regno] = (m_R[regno] & 0xFF00) | (WORD)byte;
|
||||
if ((regno == 7) && ((m_psw & 0600)!=0600)) m_savepc = m_R[7];
|
||||
if ((regno == 7) && ((m_psw & 0600) != 0600)) m_savepc = m_R[7];
|
||||
}
|
||||
WORD GetSP() const { return m_R[6]; }
|
||||
void SetSP(WORD word) { m_R[6] = word; }
|
||||
WORD GetPC() const { return m_R[7]; }
|
||||
WORD GetCPC() const { return m_savepc; }
|
||||
void SetPC(WORD word)
|
||||
{
|
||||
{
|
||||
m_R[7] = word;
|
||||
if ((m_psw & 0600) != 0600) m_savepc = word;
|
||||
}
|
||||
@ -140,30 +143,35 @@ public: // PSW bits control
|
||||
WORD GetHALT() const { return (m_psw & PSW_HALT) != 0; }
|
||||
|
||||
public: // Processor state
|
||||
// "Processor stopped" flag
|
||||
/// \brief "Processor stopped" flag
|
||||
BOOL IsStopped() const { return m_okStopped; }
|
||||
// HALT flag (TRUE - HALT mode, FALSE - USER mode)
|
||||
/// \brief HALT flag (TRUE - HALT mode, FALSE - USER mode)
|
||||
BOOL IsHaltMode() const
|
||||
{
|
||||
return ((m_psw & 0400) != 0);
|
||||
{
|
||||
return ((m_psw & 0400) != 0);
|
||||
}
|
||||
public: // Processor control
|
||||
void TickEVNT(); // EVNT signal
|
||||
void InterruptVIRQ(int que, WORD interrupt); // External interrupt via VIRQ signal
|
||||
void TickEVNT(); ///< EVNT signal
|
||||
void InterruptVIRQ(int que, WORD interrupt); ///< External interrupt via VIRQ signal
|
||||
WORD GetVIRQ(int que);
|
||||
void Execute(); // Execute one instruction - for debugger only
|
||||
/// \brief Execute one processor tick
|
||||
void Execute();
|
||||
/// \brief Process pending interrupt requests
|
||||
BOOL InterruptProcessing();
|
||||
/// \brief Execute next command and process interrupts
|
||||
void CommandExecution();
|
||||
|
||||
|
||||
public: // Saving/loading emulator status (pImage addresses up to 32 bytes)
|
||||
void SaveToImage(BYTE* pImage) const;
|
||||
void LoadFromImage(const BYTE* pImage);
|
||||
|
||||
protected: // Implementation
|
||||
void FetchInstruction(); // Read next instruction
|
||||
void TranslateInstruction(); // Execute the instruction
|
||||
void FetchInstruction(); ///< Read next instruction
|
||||
void TranslateInstruction(); ///< Execute the instruction
|
||||
protected: // Implementation - memory access
|
||||
/// \brief Read word from the bus for execution
|
||||
WORD GetWordExec(WORD address) { return m_pMemoryController->GetWordExec(address, IsHaltMode()); }
|
||||
/// \brief Read word from the bus
|
||||
WORD GetWord(WORD address) { return m_pMemoryController->GetWord(address, IsHaltMode()); }
|
||||
void SetWord(WORD address, WORD word) { m_pMemoryController->SetWord(address, IsHaltMode(), word); }
|
||||
BYTE GetByte(WORD address) { return m_pMemoryController->GetByte(address, IsHaltMode()); }
|
||||
@ -188,7 +196,7 @@ protected: // Implementation - instruction execution
|
||||
WORD GetWordAddr (BYTE meth, BYTE reg);
|
||||
WORD GetByteAddr (BYTE meth, BYTE reg);
|
||||
|
||||
void ExecuteUNKNOWN (); // Íåò òàêîé èíñòðóêöèè - ïðîñòî âûçûâàåòñÿ TRAP 10
|
||||
void ExecuteUNKNOWN (); ///< There is no such instruction -- just call TRAP 10
|
||||
void ExecuteHALT ();
|
||||
void ExecuteWAIT ();
|
||||
void ExecuteRCPC ();
|
||||
@ -217,6 +225,7 @@ protected: // Implementation - instruction execution
|
||||
void ExecuteJMP ();
|
||||
void ExecuteSWAB ();
|
||||
void ExecuteCLR ();
|
||||
void ExecuteCLRB ();
|
||||
void ExecuteCOM ();
|
||||
void ExecuteINC ();
|
||||
void ExecuteDEC ();
|
||||
@ -224,6 +233,7 @@ protected: // Implementation - instruction execution
|
||||
void ExecuteADC ();
|
||||
void ExecuteSBC ();
|
||||
void ExecuteTST ();
|
||||
void ExecuteTSTB ();
|
||||
void ExecuteROR ();
|
||||
void ExecuteROL ();
|
||||
void ExecuteASR ();
|
||||
@ -232,7 +242,7 @@ protected: // Implementation - instruction execution
|
||||
void ExecuteSXT ();
|
||||
void ExecuteMTPS ();
|
||||
void ExecuteMFPS ();
|
||||
|
||||
|
||||
// Branchs & interrupts
|
||||
void ExecuteBR ();
|
||||
void ExecuteBNE ();
|
||||
@ -264,7 +274,9 @@ protected: // Implementation - instruction execution
|
||||
|
||||
// Four fields
|
||||
void ExecuteMOV ();
|
||||
void ExecuteMOVB ();
|
||||
void ExecuteCMP ();
|
||||
void ExecuteCMPB ();
|
||||
void ExecuteBIT ();
|
||||
void ExecuteBIC ();
|
||||
void ExecuteBIS ();
|
||||
@ -304,17 +316,17 @@ inline void CProcessor::SetHALT (BOOL bFlag)
|
||||
// PSW bits calculations - implementation
|
||||
inline BOOL CProcessor::CheckAddForOverflow (BYTE a, BYTE b)
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
#if defined(_M_IX86) && !defined(_MANAGED)
|
||||
BOOL bOverflow = FALSE;
|
||||
_asm
|
||||
{
|
||||
pushf
|
||||
push cx
|
||||
mov cl,byte ptr [a]
|
||||
add cl,byte ptr [b]
|
||||
mov cl, byte ptr [a]
|
||||
add cl, byte ptr [b]
|
||||
jno end
|
||||
mov dword ptr [bOverflow],1
|
||||
end:
|
||||
mov dword ptr [bOverflow], 1
|
||||
end:
|
||||
pop cx
|
||||
popf
|
||||
}
|
||||
@ -328,17 +340,17 @@ inline BOOL CProcessor::CheckAddForOverflow (BYTE a, BYTE b)
|
||||
}
|
||||
inline BOOL CProcessor::CheckAddForOverflow (WORD a, WORD b)
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
#if defined(_M_IX86) && !defined(_MANAGED)
|
||||
BOOL bOverflow = FALSE;
|
||||
_asm
|
||||
{
|
||||
pushf
|
||||
push cx
|
||||
mov cx,word ptr [a]
|
||||
add cx,word ptr [b]
|
||||
mov cx, word ptr [a]
|
||||
add cx, word ptr [b]
|
||||
jno end
|
||||
mov dword ptr [bOverflow],1
|
||||
end:
|
||||
mov dword ptr [bOverflow], 1
|
||||
end:
|
||||
pop cx
|
||||
popf
|
||||
}
|
||||
@ -353,17 +365,17 @@ inline BOOL CProcessor::CheckAddForOverflow (WORD a, WORD b)
|
||||
|
||||
inline BOOL CProcessor::CheckSubForOverflow (BYTE a, BYTE b)
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
#if defined(_M_IX86) && !defined(_MANAGED)
|
||||
BOOL bOverflow = FALSE;
|
||||
_asm
|
||||
{
|
||||
pushf
|
||||
push cx
|
||||
mov cl,byte ptr [a]
|
||||
sub cl,byte ptr [b]
|
||||
mov cl, byte ptr [a]
|
||||
sub cl, byte ptr [b]
|
||||
jno end
|
||||
mov dword ptr [bOverflow],1
|
||||
end:
|
||||
mov dword ptr [bOverflow], 1
|
||||
end:
|
||||
pop cx
|
||||
popf
|
||||
}
|
||||
@ -377,17 +389,17 @@ inline BOOL CProcessor::CheckSubForOverflow (BYTE a, BYTE b)
|
||||
}
|
||||
inline BOOL CProcessor::CheckSubForOverflow (WORD a, WORD b)
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
#if defined(_M_IX86) && !defined(_MANAGED)
|
||||
BOOL bOverflow = FALSE;
|
||||
_asm
|
||||
{
|
||||
pushf
|
||||
push cx
|
||||
mov cx,word ptr [a]
|
||||
sub cx,word ptr [b]
|
||||
mov cx, word ptr [a]
|
||||
sub cx, word ptr [b]
|
||||
jno end
|
||||
mov dword ptr [bOverflow],1
|
||||
end:
|
||||
mov dword ptr [bOverflow], 1
|
||||
end:
|
||||
pop cx
|
||||
popf
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ void MainWindow::helpAbout()
|
||||
{
|
||||
QMessageBox::about(this, _T("About"), _T(
|
||||
"QtUkncBtl Version 1.0\n"
|
||||
"Copyright (C) 2007-2012\n\n"
|
||||
"Copyright (C) 2007-2013\n\n"
|
||||
"http://www.felixl.com/Uknc\r\nhttp://code.google.com/p/ukncbtl/\n\n"
|
||||
"Authors:\r\nNikita Zeemin (nzeemin@gmail.com)\nFelix Lazarev (felix.lazarev@gmail.com)\nAlexey Kisly\n\n"
|
||||
"Special thanks to:\nArseny Gordin\n\n"
|
||||
@ -399,6 +399,8 @@ void MainWindow::emulatorFrame()
|
||||
{
|
||||
if (!g_okEmulatorRunning)
|
||||
return;
|
||||
if (!isActiveWindow())
|
||||
return;
|
||||
|
||||
if (Emulator_IsBreakpoint())
|
||||
Emulator_Stop();
|
||||
|
@ -85,8 +85,8 @@ static void UpscaleScreen3(void* pImageBits)
|
||||
DWORD c2 = *psrc; psrc--;
|
||||
DWORD c12 =
|
||||
(((c1 & 0xff) + (c2 & 0xff)) >> 1) |
|
||||
(((c1 & 0xff00) + (c2 & 0xff00)) >> 1) & 0xff00 |
|
||||
(((c1 & 0xff0000) + (c2 & 0xff0000)) >> 1) & 0xff0000;
|
||||
((((c1 & 0xff00) + (c2 & 0xff00)) >> 1) & 0xff00) |
|
||||
((((c1 & 0xff0000) + (c2 & 0xff0000)) >> 1) & 0xff0000);
|
||||
*pdest = c1; pdest--;
|
||||
*pdest = c12; pdest--;
|
||||
*pdest = c2; pdest--;
|
||||
|
30
qscripting.h
30
qscripting.h
@ -1,6 +1,8 @@
|
||||
#ifndef QSCRIPTING_H
|
||||
#define QSCRIPTING_H
|
||||
|
||||
/// \file qscripting.h Scripting support for Qt version of the emulator
|
||||
|
||||
#include <QObject>
|
||||
#include <QDialog>
|
||||
#include <QVBoxLayout>
|
||||
@ -22,11 +24,11 @@ class QEmulatorProcessor : public QObject
|
||||
|
||||
/// \brief Get the name of the processor: "CPU" or "PPU", short form for getName().
|
||||
Q_PROPERTY(QString name READ getName)
|
||||
/// \brief Get the processor stack register value, short form for getSP().
|
||||
/// \brief Get/set the processor stack register value, short form for getSP().
|
||||
Q_PROPERTY(ushort sp READ getSP WRITE setSP)
|
||||
/// \brief Get the processor PC register value, short form for getPC().
|
||||
/// \brief Get/set the processor PC register value, short form for getPC().
|
||||
Q_PROPERTY(ushort pc READ getPC WRITE setPC)
|
||||
/// \brief Get the processor status word value, short form for getPSW().
|
||||
/// \brief Get/set the processor status word value, short form for getPSW().
|
||||
Q_PROPERTY(ushort psw READ getPSW WRITE setPSW)
|
||||
/// \brief Get the processor HALT/USER mode flag, short form for isHalt().
|
||||
Q_PROPERTY(bool halt READ isHalt)
|
||||
@ -39,10 +41,10 @@ public slots:
|
||||
QString getName();
|
||||
|
||||
/// \brief Get the processor register value.
|
||||
/// \param regno 0..7 */
|
||||
/// \param regno 0..7
|
||||
ushort getReg(int regno);
|
||||
/// \brief Get the processor register value, short form for getReg().
|
||||
/// \param regno 0..7 */
|
||||
/// \param regno 0..7
|
||||
ushort r(int regno) { return getReg(regno); }
|
||||
/// \brief Get the processor stack register value.
|
||||
ushort getSP() { return getReg(6); }
|
||||
@ -54,8 +56,8 @@ public slots:
|
||||
bool isHalt();
|
||||
|
||||
/// \brief Put the given value to the given processor register.
|
||||
/// \param regno 0..7 */
|
||||
/// \param value Value to put in the processor register. */
|
||||
/// \param regno 0..7
|
||||
/// \param value Value to put in the processor register.
|
||||
void setReg(int regno, ushort value);
|
||||
/// \brief Set the processor SP register value.
|
||||
void setSP(ushort value) { setReg(6, value); }
|
||||
@ -65,10 +67,10 @@ public slots:
|
||||
void setPSW(ushort value);
|
||||
|
||||
/// \brief Read word from the processor memory.
|
||||
/// \param addr memory address */
|
||||
/// \param addr memory address
|
||||
ushort readWord(ushort addr);
|
||||
/// \brief Read byte from the processor memory.
|
||||
/// \param addr memory address */
|
||||
/// \param addr memory address
|
||||
uchar readByte(ushort addr);
|
||||
|
||||
/// \brief Disassemble one instruction at the given address.
|
||||
@ -124,35 +126,40 @@ public slots:
|
||||
|
||||
/// \brief Load the cartridge image file.
|
||||
/// \param slot cartridge slot 1..2
|
||||
/// \param filename Cartridge image file name.
|
||||
bool attachCartridge(int slot, const QString& filename);
|
||||
/// \brief Empty the cartridge slot.
|
||||
/// \param slot cartridge slot 1..2
|
||||
void detachCartridge(int slot);
|
||||
/// \brief Attach the floppy image file -- insert the disk.
|
||||
/// \param slot floppy slot 1..4
|
||||
/// \param filename Floppy image file name.
|
||||
bool attachFloppy(int slot, const QString& filename);
|
||||
/// \brief Detach the floppy image file -- remove the disk.
|
||||
/// \param slot floppy slot 1..4
|
||||
void detachFloppy(int slot);
|
||||
/// \brief Attach the hard drive image file.
|
||||
/// \param slot hard drive slot 1..2
|
||||
/// \param filename Hard drive image file name.
|
||||
bool attachHard(int slot, const QString& filename);
|
||||
/// \brief Detach the hard drive image file.
|
||||
/// \param slot hard drive slot 1..2
|
||||
void detachHard(int slot);
|
||||
|
||||
/// \brief Get CPU object.
|
||||
/// \return QProcessor object.
|
||||
/// \return QEmulatorProcessor object.
|
||||
QObject* getCPU() { return &m_cpu; }
|
||||
/// \brief Get PPU object.
|
||||
/// \return QProcessor object.
|
||||
/// \return QEmulatorProcessor object.
|
||||
QObject* getPPU() { return &m_ppu; }
|
||||
|
||||
/// \brief Press the key (by scan code), wait timeout frames, release the key, wait 3 frames.
|
||||
/// \param ukncscan UKNC scan code
|
||||
/// \param timeout Number of frames to wait before key release.
|
||||
void keyScan(uchar ukncscan, int timeout = 3);
|
||||
/// \brief Press SHIFT, press the key, wait timeout frames, release the key, release SHIFT, wait 3 frames.
|
||||
/// \param ukncscan UKNC scan code
|
||||
/// \param timeout Number of frames to wait before key release.
|
||||
void keyScanShift(uchar ukncscan, int timeout = 3);
|
||||
/// \brief Type the key sequence.
|
||||
void keyString(QString str);
|
||||
@ -167,6 +174,7 @@ public slots:
|
||||
void consolePrint(const QString& message);
|
||||
|
||||
//TODO: Change screen modes, enableSound()
|
||||
//TODO: Degugger Step In, Step Over
|
||||
|
||||
private:
|
||||
void keyChar(char ch, int timeout = 3);
|
||||
|
@ -162,7 +162,7 @@ HWAVPCMFILE WavPcmFile_Open(LPCTSTR filename)
|
||||
statedSize = fileSize;
|
||||
|
||||
BYTE tagHeader[8];
|
||||
BYTE formatTag[16];
|
||||
WORD formatTag[8];
|
||||
BOOL formatSpecified = FALSE;
|
||||
int formatType, channels = 1, bitsPerSample, blockAlign;
|
||||
DWORD sampleFrequency, bytesPerSecond, dataOffset, dataSize = 0;
|
||||
@ -193,12 +193,12 @@ HWAVPCMFILE WavPcmFile_Open(LPCTSTR filename)
|
||||
return (HWAVPCMFILE) INVALID_HANDLE_VALUE; // Failed to read format tag
|
||||
}
|
||||
|
||||
formatType = *(WORD*)(formatTag);
|
||||
channels = *(WORD*)(formatTag + 2);
|
||||
sampleFrequency = *(DWORD*)(formatTag + 4);
|
||||
bytesPerSecond = *(DWORD*)(formatTag + 8);
|
||||
blockAlign = *(WORD*)(formatTag + 12);
|
||||
bitsPerSample = *(WORD*)(formatTag + 14);
|
||||
formatType = formatTag[0];
|
||||
channels = formatTag[1];
|
||||
sampleFrequency = formatTag[2];
|
||||
bytesPerSecond = formatTag[4];
|
||||
blockAlign = formatTag[6];
|
||||
bitsPerSample = formatTag[7];
|
||||
|
||||
if (formatType != WAV_FORMAT_PCM)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user