Added debugging NOP opcode support.

This commit is contained in:
Brendan Robert 2015-12-20 22:43:00 -06:00
parent 9f838d11f1
commit 893052b004
4 changed files with 128 additions and 22 deletions

View File

@ -24,6 +24,7 @@ import jace.core.Computer;
import jace.core.RAM;
import jace.core.RAMEvent.TYPE;
import jace.state.Stateful;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
@ -36,6 +37,7 @@ import java.util.logging.Logger;
*/
@Stateful
public class MOS65C02 extends CPU {
private static final Logger LOG = Logger.getLogger(MOS65C02.class.getName());
public boolean readAddressTriggersEvent = true;
static int RESET_VECTOR = 0x00FFFC;
@ -209,6 +211,7 @@ public class MOS65C02 extends CPU {
LSR_AB(0x004E, COMMAND.LSR, MODE.ABSOLUTE, 6),
LSR_AB_X(0x005E, COMMAND.LSR, MODE.ABSOLUTE_X, 7),
NOP(0x00EA, COMMAND.NOP, MODE.IMPLIED, 2),
SPECIAL(0x00FC, COMMAND.NOP_SPECIAL, MODE.ABSOLUTE, 4),
ORA_IMM(0x0009, COMMAND.ORA, MODE.IMMEDIATE, 2),
ORA_ZP(0x0005, COMMAND.ORA, MODE.ZEROPAGE, 3),
ORA_ZP_X(0x0015, COMMAND.ORA, MODE.ZEROPAGE_X, 4),
@ -583,7 +586,6 @@ public class MOS65C02 extends CPU {
}
public enum COMMAND {
ADC((address, value, addressMode, cpu) -> {
int w;
cpu.V = ((cpu.A ^ value) & 0x080) == 0;
@ -824,6 +826,11 @@ public class MOS65C02 extends CPU {
}),
NOP((address, value, addressMode, cpu) -> {
}),
NOP_SPECIAL((address, value, addressMode, cpu) -> {
byte param1 = (byte) (address & 0x0ff);
byte param2 = (byte) (address >> 8);
cpu.performExtendedCommand(param1, param2);
}),
ORA((address, value, addressMode, cpu) -> {
cpu.A |= value;
cpu.setNZ(cpu.A);
@ -1049,7 +1056,7 @@ public class MOS65C02 extends CPU {
traceEntry = getState().toUpperCase() + " " + Integer.toString(pc, 16) + " : " + disassemble();
captureSingleTrace(traceEntry);
if (isTraceEnabled()) {
Logger.getLogger(getClass().getName()).info(traceEntry);
LOG.log(Level.INFO, traceEntry);
}
if (isLogEnabled()) {
log(traceEntry);
@ -1059,8 +1066,8 @@ public class MOS65C02 extends CPU {
int op = 0x00ff & getMemory().read(pc, TYPE.EXECUTE, true, false);
OPCODE opcode = opcodes[op];
if (traceEntry != null && warnAboutExtendedOpcodes && opcode != null && opcode.isExtendedOpcode) {
System.out.println(">>EXTENDED OPCODE DETECTED " + Integer.toHexString(opcode.code) + "<<");
System.out.println(traceEntry);
LOG.log(Level.WARNING, ">>EXTENDED OPCODE DETECTED {0}<<", Integer.toHexString(opcode.code));
LOG.log(Level.WARNING, traceEntry);
if (isLogEnabled()) {
log(">>EXTENDED OPCODE DETECTED " + Integer.toHexString(opcode.code) + "<<");
log(traceEntry);
@ -1102,9 +1109,7 @@ public class MOS65C02 extends CPU {
addWaitCycles(wait);
if (isLogEnabled() || breakOnBadOpcode) {
System.out.println("Unrecognized opcode "
+ Integer.toHexString(op)
+ " at " + Integer.toHexString(pc));
LOG.log(Level.WARNING, "Unrecognized opcode {0} at {1}", new Object[]{Integer.toHexString(op), Integer.toHexString(pc)});
}
if (breakOnBadOpcode) {
OPCODE.BRK.execute(this);
@ -1175,13 +1180,13 @@ public class MOS65C02 extends CPU {
@Override
public void JSR(int address) {
pushWord(getProgramCounter() - 1);
pushPC();
setProgramCounter(address);
}
public void BRK() {
if (isLogEnabled()) {
System.out.println("BRK at $" + Integer.toString(getProgramCounter(), 16));
LOG.log(Level.WARNING, "BRK at ${0}", Integer.toString(getProgramCounter(), 16));
dumpTrace();
}
B = true;
@ -1233,7 +1238,7 @@ public class MOS65C02 extends CPU {
// V = true;
// Z = true;
int newPC = getMemory().readWord(RESET_VECTOR, TYPE.READ_DATA, true, false);
System.out.println("Reset called, setting PC to (" + Integer.toString(RESET_VECTOR, 16) + ") = " + Integer.toString(newPC, 16));
LOG.log(Level.WARNING, "Reset called, setting PC to ({0}) = {1}", new Object[]{Integer.toString(RESET_VECTOR, 16), Integer.toString(newPC, 16)});
setProgramCounter(newPC);
}
@ -1321,4 +1326,34 @@ public class MOS65C02 extends CPU {
public void pushPC() {
pushWord(getProgramCounter() - 1);
}
/**
* Special commands -- these are usually treated as NOP but can be reused for emulator controls
* !byte $fc, $65, $00 ; Turn off tracing
* !byte $fc, $65, $01 ; Turn on tracing
* @param param1
* @param param2
*/
public void performExtendedCommand(byte param1, byte param2) {
LOG.log(Level.INFO, "Extended command {0},{1}", new Object[]{Integer.toHexString(param1), Integer.toHexString(param2)});
switch (param1 & 0x0ff) {
case 0x65:
// CPU functions
switch (param2 & 0x0ff) {
case 0x00:
// Turn off tracing
trace = false;
break;
case 0x01:
// Turn on tracing
trace = true;
break;
}
break;
case 0x64:
// Memory functions
getMemory().performExtendedCommand(param2 & 0x0ff);
default:
}
}
}

View File

@ -26,6 +26,8 @@ import jace.core.RAM;
import jace.state.Stateful;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -38,6 +40,74 @@ import java.util.logging.Logger;
*/
@Stateful
abstract public class RAM128k extends RAM {
Logger LOG = Logger.getLogger(RAM128k.class.getName());
Map<String, PagedMemory> banks;
private Map<String, PagedMemory> getBanks() {
if (banks == null) {
banks = new HashMap<>();
banks.put("main", mainMemory);
banks.put("lc", languageCard);
banks.put("lc2", languageCard2);
banks.put("//e rom (80-col)", cPageRom);
banks.put("//e rom", rom);
banks.put("blank", blank);
banks.put("aux", getAuxMemory());
banks.put("aux lc", getAuxLanguageCard());
banks.put("aux lc2", getAuxLanguageCard2());
cards[1].ifPresent(c -> banks.put("card1a", c.getCxRom()));
cards[1].ifPresent(c -> banks.put("card1b", c.getC8Rom()));
cards[2].ifPresent(c -> banks.put("card2a", c.getCxRom()));
cards[2].ifPresent(c -> banks.put("card2b", c.getC8Rom()));
cards[3].ifPresent(c -> banks.put("card3a", c.getCxRom()));
cards[3].ifPresent(c -> banks.put("card3b", c.getC8Rom()));
cards[4].ifPresent(c -> banks.put("card4a", c.getCxRom()));
cards[4].ifPresent(c -> banks.put("card4b", c.getC8Rom()));
cards[5].ifPresent(c -> banks.put("card5a", c.getCxRom()));
cards[5].ifPresent(c -> banks.put("card5b", c.getC8Rom()));
cards[6].ifPresent(c -> banks.put("card6a", c.getCxRom()));
cards[6].ifPresent(c -> banks.put("card6b", c.getC8Rom()));
cards[7].ifPresent(c -> banks.put("card7a", c.getCxRom()));
cards[7].ifPresent(c -> banks.put("card7b", c.getC8Rom()));
}
return banks;
}
@Override
public void performExtendedCommand(int param) {
switch (param) {
case 0xda:
// 64 da : Dump all memory mappings
System.out.println("Active banks");
for (int i = 0; i < 256; i++) {
byte[] read = activeRead.get(i);
byte[] write = activeWrite.get(i);
String readBank = getBanks().keySet().stream().filter(bank->{
PagedMemory mem = getBanks().get(bank);
for (byte[] page : mem.getMemory()) {
if (page == read) {
return true;
}
}
return false;
}).findFirst().orElse("unknown");
String writeBank = getBanks().keySet().stream().filter(bank->{
PagedMemory mem = getBanks().get(bank);
for (byte[] page : mem.getMemory()) {
if (page == write) {
return true;
}
}
return false;
}).findFirst().orElse("unknown");
LOG.log(Level.INFO,"Bank {0}\t{1}\t{2}", new Object[]{Integer.toHexString(i), readBank, writeBank});
}
default:
}
}
@Stateful
public PagedMemory mainMemory;
@ -90,7 +160,7 @@ abstract public class RAM128k extends RAM {
// First off, set up read/write for main memory (might get changed later on)
activeRead.fillBanks(SoftSwitches.RAMRD.getState() ? getAuxMemory() : mainMemory);
activeWrite.fillBanks(SoftSwitches.RAMWRT.getState() ? getAuxMemory() : mainMemory);
// Handle language card softswitches
activeRead.fillBanks(rom);
//activeRead.fillBanks(cPageRom);
@ -110,7 +180,7 @@ abstract public class RAM128k extends RAM {
}
}
}
if (SoftSwitches.LCWRITE.isOn()) {
if (SoftSwitches.AUXZP.isOff()) {
activeWrite.fillBanks(languageCard);
@ -129,7 +199,7 @@ abstract public class RAM128k extends RAM {
activeWrite.set(i, null);
}
}
// Handle 80STORE logic for bankswitching video ram
if (SoftSwitches._80STORE.isOn()) {
activeRead.setBanks(0x04, 0x04, 0x04,
@ -143,7 +213,7 @@ abstract public class RAM128k extends RAM {
SoftSwitches.PAGE2.isOn() ? getAuxMemory() : mainMemory);
}
}
// Handle zero-page bankswitching
if (SoftSwitches.AUXZP.getState()) {
// Aux pages 0 and 1
@ -154,13 +224,13 @@ abstract public class RAM128k extends RAM {
activeRead.setBanks(0, 2, 0, mainMemory);
activeWrite.setBanks(0, 2, 0, mainMemory);
}
/*
INTCXROM SLOTC3ROM C1,C2,C4-CF C3
0 0 slot rom
0 1 slot slot
1 - rom rom
*/
*/
if (SoftSwitches.CXROM.getState()) {
// Enable C1-CF to point to rom
activeRead.setBanks(0, 0x0F, 0x0C1, cPageRom);

View File

@ -335,4 +335,6 @@ public abstract class RAM implements Reconfigurable {
abstract public void attach();
abstract public void detach();
abstract public void performExtendedCommand(int i);
}

View File

@ -156,18 +156,18 @@ public abstract class Video extends Device {
@Override
public void tick() {
setScannerLocation(currentWriter.getYOffset(y));
setFloatingBus(computer.getMemory().readRaw(scannerAddress + x));
if (hPeriod > 0) {
hPeriod--;
if (hPeriod <= 1) {
if (hPeriod == 0) {
x = -1;
setScannerLocation(currentWriter.getYOffset(y));
}
} else {
if (!isVblank && x < (APPLE_CYCLES_PER_LINE)) {
if (!isVblank && x < (APPLE_CYCLES_PER_LINE-1)) {
draw();
}
if (x >= APPLE_CYCLES_PER_LINE) {
if (x >= APPLE_CYCLES_PER_LINE - 1) {
int yy = y + hblankOffsetY;
if (yy < 0) {
yy += APPLE_SCREEN_LINES;
@ -175,8 +175,7 @@ public abstract class Video extends Device {
if (yy >= APPLE_SCREEN_LINES) {
yy -= (TOTAL_LINES - APPLE_SCREEN_LINES);
}
setScannerLocation(currentWriter.getYOffset(yy) + hblankOffsetX + (yy < 64 ? 128 : 0));
x = -1;
x = hblankOffsetX - 1;
if (!isVblank) {
if (lineDirty) {
screenDirty = true;