-#include "Memory.h"
#include <QFile>
#include <QDebug>
#include <stdio.h>
+#include "Memory.h"
+#include "MemoryMap.h"
+
// 0000 to 7FFF - RAM
// 8000 to BFFF - one or more language ROMs
// C000 to FFFF - MOS ROM
// Language ROM read.
return m_languageRom[position-0x8000] & 0xFF;
- } else if (position>=0xFC00 && position<=0xFCFF) {
-
- // FRED read.
- qDebug() << "FRED read";
- return 0;
-
- } else if (position>=0xFD00 && position<=0xFDFF) {
-
- // JIM read.
- qDebug() << "JIM read";
- return 0;
+ } else if (position>=0xFC00 && position<=0xFEFF) {
- } else if (position>=0xFE00 && position<=0xFEFF) {
+ // FRED/JIM/SHEILA read.
- // SHEILA read.
- qDebug() << QString("SHEILA read %1").arg(position, 0, 16);
- return 0;
+ if (mMemoryMap.contains(position)) {
+ return mMemoryMap[position]->read(position);
+ } else {
+ qDebug() << QString("Unknown FRED/JIM/SHEILA read %1").arg(position, 0, 16);
+ return 0;
+ }
} else if (position>=0xC000 && position<=0xFFFF) {
printf("%c", byte);
}
- } else if (position>=0xFC00 && position<=0xFCFF) {
+ } else if (position>=0xFC00 && position<=0xFEFF) {
- // FRED write.
- qDebug() << "FRED write";
+ // FRED/JIM/SHEILA write.
+ // === FRED ===
+ //
// FC10 to FC13 - Teletext
// FC40 to FC43 - SCSI
- } else if (position>=0xFD00 && position<=0xFDFF) {
-
- // JIM write.
- qDebug() << "JIM write";
-
+ // === JIM ===
+ //
// FDF0 to FDF3 - SASI
- } else if (position>=0xFE00 && position<=0xFEFF) {
-
- // SHEILA write.
+ // === SHEILA ===
+ //
// FE00 to FE07 - CRTC
// FE08 - ACIA Status
// FE09 - ACIA Data
// FEEx - Tube
// FEFx - Tube
- qDebug() << QString("SHEILA write %1 %2").arg(position, 0, 16).arg(byte, 0, 16);
+
+ if (mMemoryMap.contains(position)) {
+ mMemoryMap[position]->write(position, byte);
+ } else {
+ qDebug() << QString("Unknown FRED/JIM/SHEILA write %1 %2").arg(position, 0, 16).arg(byte, 0, 16);
+ }
} else {
}
}
+
+void Memory::hookMemoryMap(int startAddress,
+ int endAddress,
+ MemoryMap *map)
+{
+ for (int i=startAddress; i<=endAddress; i++) {
+ mMemoryMap[i] = map;
+ }
+}
#include "opcodes.cpp"
-Processor::Processor(Memory *memory):
+Processor::Processor(Memory *memory, Clock *clock):
QObject()
{
m_memory = memory;
+ m_clock = clock;
m_programCounter = memory->readWordFrom(0xFFFC);
m_interrupt = false;
m_break = false;
- m_waiting = 0;
-
m_goldenTrailPosition = 0;
}
#endif
opcode = m_memory->readByteFrom(m_programCounter++);
- m_waiting = opcodes[opcode].cycles;
+ // A machine cycle is two clock cycles.
+ m_clock->advance(opcodes[opcode].cycles * 2);
switch (opcodes[opcode].mode) {
OpcodeDetails(0x10, MODE_BRANCH, 2);
if (!m_sign) {
m_programCounter += branchDisplacement;
- m_waiting++;
+ m_clock->advance(1);
}
break;
OpcodeDetails(0x30, MODE_BRANCH, 2);
if (m_sign) {
m_programCounter += branchDisplacement;
- m_waiting++;
+ m_clock->advance(1);
}
break;
OpcodeDetails(0x50, MODE_BRANCH, 2);
if (!m_overflow) {
m_programCounter += branchDisplacement;
- m_waiting++;
+ m_clock->advance(1);
}
break;
OpcodeDetails(0x70, MODE_BRANCH, 2);
if (m_overflow) {
m_programCounter += branchDisplacement;
- m_waiting++;
+ m_clock->advance(1);
}
break;
OpcodeDetails(0x90, MODE_BRANCH, 2);
if (!m_carry) {
m_programCounter += branchDisplacement;
- m_waiting++;
+ m_clock->advance(1);
}
break;
OpcodeDetails(0xb0, MODE_BRANCH, 2);
if (m_carry) {
m_programCounter += branchDisplacement;
- m_waiting++;
+ m_clock->advance(1);
}
break;
OpcodeDetails(0xd0, MODE_BRANCH, 2);
if (!m_zero) {
m_programCounter += branchDisplacement;
- m_waiting++;
+ m_clock->advance(1);
}
break;
OpcodeDetails(0xf0, MODE_BRANCH, 2);
if (m_zero) {
m_programCounter += branchDisplacement;
- m_waiting++;
+ m_clock->advance(1);
}
break;
break;
- case OP_JMP:
+ case OP_JMP: // Jump
OpcodeDetails(0x4c, MODE_ABSOLUTE, 3);
OpcodeDetails(0x6c, MODE_INDIRECT, 5);
m_programCounter = address;
break;
- ////////////////////////////////////////////////////////////////
+ case OP_LSR: // Logical shift right
+ OpcodeDetails(0x46, MODE_ZERO_PAGE, 5);
+ OpcodeDetails(0x4a, MODE_ACCUMULATOR, 2);
+ OpcodeDetails(0x4e, MODE_ABSOLUTE, 6);
+ OpcodeDetails(0x56, MODE_ZERO_PAGE_X, 6);
+ OpcodeDetails(0x5e, MODE_ABSOLUTE_X, 7);
- case OP_XXX:
- qDebug() << "Alert! Unknown opcode: " << QString("%1").arg(opcode, 2, 16);
- throw "Unknown opcode.";
+ param = this->readParam(address);
+ m_carry = (param & 0x01) != 0;
+ if (param & 0x01) {
+ param |= 0x100;
+ }
+ param >>= 1;
+ m_zero = param == 0;
+ m_sign = (param & 0x80) != 0;
+ this->writeParam(address, param);
break;
- // Not implemented:
-
- case OP_SBC:
- OpcodeDetails(0xe1, MODE_INDIRECT_X, 6);
- OpcodeDetails(0xe5, MODE_ZERO_PAGE, 3);
- OpcodeDetails(0xe9, MODE_IMMEDIATE, 2);
- OpcodeDetails(0xed, MODE_ABSOLUTE, 4);
- OpcodeDetails(0xf1, MODE_INDIRECT_Y, 5);
- OpcodeDetails(0xf5, MODE_ZERO_PAGE_X, 4);
- OpcodeDetails(0xf9, MODE_ABSOLUTE_Y, 4);
- OpcodeDetails(0xfd, MODE_ABSOLUTE_X, 4);
-
- case OP_AND:
+ case OP_AND: // Bitwise AND with accumulator
OpcodeDetails(0x21, MODE_INDIRECT_X, 6);
OpcodeDetails(0x25, MODE_ZERO_PAGE, 2);
OpcodeDetails(0x29, MODE_IMMEDIATE, 2);
OpcodeDetails(0x39, MODE_ABSOLUTE_Y, 4);
OpcodeDetails(0x3d, MODE_ABSOLUTE_X, 4);
- case OP_EOR:
+ param = this->readParam(address);
+ param &= m_accumulator;
+ m_zero = param == 0;
+ m_sign = (param & 0x80) != 0;
+ this->writeParam(address, param);
+ break;
+
+ case OP_EOR: // Bitwise exclusive OR with accumulator
OpcodeDetails(0x41, MODE_INDIRECT_X, 6);
OpcodeDetails(0x45, MODE_ZERO_PAGE, 3);
OpcodeDetails(0x49, MODE_IMMEDIATE, 2);
OpcodeDetails(0x59, MODE_ABSOLUTE_Y, 4);
OpcodeDetails(0x5d, MODE_ABSOLUTE_X, 4);
- case OP_RTI:
- OpcodeDetails(0x40, MODE_IMPLIED, 6);
+ param = this->readParam(address);
+ param ^= m_accumulator;
+ m_zero = param == 0;
+ m_sign = (param & 0x80) != 0;
+ this->writeParam(address, param);
+ break;
- case OP_ORA:
+ case OP_ORA: // Bitwise OR with accumulator
OpcodeDetails(0x01, MODE_INDIRECT_X, 6);
OpcodeDetails(0x05, MODE_ZERO_PAGE, 2);
OpcodeDetails(0x09, MODE_IMMEDIATE, 2);
OpcodeDetails(0x19, MODE_ABSOLUTE_Y, 4);
OpcodeDetails(0x1d, MODE_ABSOLUTE_X, 4);
- case OP_BIT:
+ param = this->readParam(address);
+ param |= m_accumulator;
+ m_zero = param == 0;
+ m_sign = (param & 0x80) != 0;
+ this->writeParam(address, param);
+ break;
+
+ case OP_BIT: // Test bits
OpcodeDetails(0x24, MODE_ZERO_PAGE, 3);
OpcodeDetails(0x2c, MODE_ABSOLUTE, 4);
- case OP_LSR:
- OpcodeDetails(0x46, MODE_ZERO_PAGE, 5);
- OpcodeDetails(0x4a, MODE_ACCUMULATOR, 2);
- OpcodeDetails(0x4e, MODE_ABSOLUTE, 6);
- OpcodeDetails(0x56, MODE_ZERO_PAGE_X, 6);
- OpcodeDetails(0x5e, MODE_ABSOLUTE_X, 7);
+ param = this->readParam(address);
+ m_sign = (param & 0x80) != 0;
+ m_overflow = (param & 0x40) != 0;
+ m_zero = (param & m_accumulator) == 0;
+ break;
+
+ ////////////////////////////////////////////////////////////////
+
+ case OP_XXX:
+ qDebug() << "Alert! Unknown opcode: " << QString("%1").arg(opcode, 2, 16);
+ throw "Unknown opcode.";
+ break;
+
+ // Not implemented:
+
+ case OP_SBC:
+ OpcodeDetails(0xe1, MODE_INDIRECT_X, 6);
+ OpcodeDetails(0xe5, MODE_ZERO_PAGE, 3);
+ OpcodeDetails(0xe9, MODE_IMMEDIATE, 2);
+ OpcodeDetails(0xed, MODE_ABSOLUTE, 4);
+ OpcodeDetails(0xf1, MODE_INDIRECT_Y, 5);
+ OpcodeDetails(0xf5, MODE_ZERO_PAGE_X, 4);
+ OpcodeDetails(0xf9, MODE_ABSOLUTE_Y, 4);
+ OpcodeDetails(0xfd, MODE_ABSOLUTE_X, 4);
+
+ case OP_RTI:
+ OpcodeDetails(0x40, MODE_IMPLIED, 6);
case OP_ADC:
OpcodeDetails(0x61, MODE_INDIRECT_X, 6);
void Processor::runCycles(int count) {
- if (m_waiting >= count) {
- m_waiting -= count;
- return;
- }
-
- int cyclesTaken = m_waiting;
-
- while (cyclesTaken < count) {
- m_waiting = 0;
+ unsigned long endTime = m_clock->getTime() + count;
+ do {
this->oneShot();
-
- cyclesTaken += m_waiting;
- }
+ } while (m_clock->getTime() < endTime);
}