mirror of
https://github.com/badvision/jace.git
synced 2025-04-06 18:37:22 +00:00
Added debugging NOP opcode support.
This commit is contained in:
parent
9f838d11f1
commit
893052b004
@ -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:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -335,4 +335,6 @@ public abstract class RAM implements Reconfigurable {
|
||||
abstract public void attach();
|
||||
|
||||
abstract public void detach();
|
||||
|
||||
abstract public void performExtendedCommand(int i);
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user