1
0
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:
Nikita Zimin 2013-11-09 10:07:14 +00:00
parent 96969f11d6
commit 2408c4f8ef
19 changed files with 2882 additions and 2325 deletions

6
!doxygen.bat Normal file
View 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
View File

@ -0,0 +1,2 @@
cd debug
QtUkncBtl.exe -test

View File

@ -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

View File

@ -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];
}
//////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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;

View File

@ -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);
//////////////////////////////////////////////////////////////////////

View File

@ -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
};

View File

@ -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++];

View File

@ -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()

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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
}

View File

@ -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();

View File

@ -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--;

View File

@ -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);

View File

@ -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)
{