/** * Performs a CPU address space write. Maps all of the relevant object into the right parts of * memory. */ public final void addressWrite(int addr, int data) { switch (addr & 0xF000) { case 0x0000: case 0x1000: case 0x2000: case 0x3000: case 0x4000: case 0x5000: case 0x6000: case 0x7000: if (!running) { cartridge.debuggerAddressWrite(addr, data); } else { cartridge.addressWrite(addr, data); } break; case 0x8000: case 0x9000: graphicsChip.addressWrite(addr - 0x8000, (byte) data); break; case 0xA000: case 0xB000: cartridge.addressWrite(addr, data); break; case 0xC000: mainRam[addr - 0xC000] = (byte) data; break; case 0xD000: mainRam[addr - 0xD000 + (gbcRamBank * 0x1000)] = (byte) data; break; case 0xE000: mainRam[addr - 0xE000] = (byte) data; break; case 0xF000: if (addr < 0xFE00) { try { mainRam[addr - 0xE000] = (byte) data; } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Address error: " + addr + " pc = " + JavaBoy.hexWord(pc)); } } else if (addr < 0xFF00) { oam[addr - 0xFE00] = (byte) data; } else { ioHandler.ioWrite(addr - 0xFF00, (short) data); } break; } }
/** Execute the specified number of Gameboy instructions. Use '-1' to execute forever */ public final void execute(int numInstr) { terminate = false; running = true; graphicsChip.startTime = System.currentTimeMillis(); int b1, b2, b3, offset; long t; for (int r = 0; (r != numInstr) && (!terminate); r++) { t = System.currentTimeMillis(); instrCount++; b1 = JavaBoy.unsign(addressRead(pc)); offset = addressRead(pc + 1); b3 = JavaBoy.unsign(addressRead(pc + 2)); b2 = JavaBoy.unsign((short) offset); // stats.addExecution(b1); instructionManager.execute(b1, b2, b3, offset); if (ieDelay != -1) { if (ieDelay > 0) { ieDelay--; } else { interruptsEnabled = true; ieDelay = -1; } } if (interruptsEnabled) { checkInterrupts(); } cartridge.update(); initiateInterrupts(); if ((t - initialTime) > checkpointTime) { initialTime = t; saveCheckpointInterrupt = true; } if (saveInterrupt) { saveState(".stsv"); saveInterrupt = false; } if (loadStateInterrupt) { loadState(".stsv"); loadStateInterrupt = false; } if (saveCheckpointInterrupt) { saveState(".cksv"); saveCheckpointInterrupt = false; } if (loadCheckpointInterrupt) { loadState(".cksv"); loadCheckpointInterrupt = false; } } running = false; terminate = false; }
/** Resets the CPU to it's power on state. Memory contents are not cleared. */ public void reset() { checkEnableGbc(); setDoubleSpeedCpu(false); graphicsChip.dispose(); cartridge.reset(); interruptsEnabled = false; ieDelay = -1; pc = 0x0100; sp = 0xFFFE; f = 0xB0; gbcRamBank = 1; instrCount = 0; if (gbcFeatures) { registers[a] = 0x11; } else { registers[a] = 0x01; } for (int r = 0; r < 0x8000; r++) { mainRam[r] = 0; } setBC(0x0013); setDE(0x00D8); setHL(0x014D); JavaBoy.debugLog("CPU reset"); ioHandler.reset(); }
public void saveState(String extension) { String directory = (cartridge.romFileName + extension); try { FileOutputStream fl = new FileOutputStream(directory); DataOutputStream sv = new DataOutputStream(fl); saveData(sv, directory); // write battery ram cartridge.saveData(sv, directory); // write graphic memory graphicsChip.saveData(sv, directory); // write io state ioHandler.saveData(sv, directory); // stats.printStats(); sv.close(); fl.close(); } catch (FileNotFoundException e) { System.out.println("Dmgcpu.saveState: Could not open file " + directory); System.out.println("Error Message: " + e.getMessage()); System.exit(-1); } catch (IOException e) { System.out.println("Dmgcpu.saveState: Could not write to file " + directory); System.out.println("Error Message: " + e.getMessage()); System.exit(-1); } System.out.println("Saved stage!"); }
/** * Perform a CPU address space read. This maps all the relevant objects into the correct parts of * the memory */ public final short addressRead(int addr) { addr = addr & 0xFFFF; switch ((addr & 0xF000)) { case 0x0000: case 0x1000: case 0x2000: case 0x3000: case 0x4000: case 0x5000: case 0x6000: case 0x7000: return cartridge.addressRead(addr); case 0x8000: case 0x9000: return graphicsChip.addressRead(addr - 0x8000); case 0xA000: case 0xB000: return cartridge.addressRead(addr); case 0xC000: return (mainRam[addr - 0xC000]); case 0xD000: return (mainRam[addr - 0xD000 + (gbcRamBank * 0x1000)]); case 0xE000: return mainRam[addr - 0xE000]; case 0xF000: if (addr < 0xFE00) { return mainRam[addr - 0xE000]; } else if (addr < 0xFF00) { return (short) (oam[addr - 0xFE00] & 0x00FF); } else { return ioHandler.ioRead(addr - 0xFF00); } default: System.out.println("Tried to read address " + addr + ". pc = " + JavaBoy.hexWord(pc)); return 0xFF; } }
public void loadState(String extension) { String directory = cartridge.romFileName + extension; try { reset(); FileInputStream fl = new FileInputStream(directory); DataInputStream sv = new DataInputStream(fl); // write cpu data loadData(sv, directory); // write battery ram cartridge.loadData(sv, directory); // write graphic memory graphicsChip.loadData(sv, directory); // writes io state ioHandler.loadData(sv, directory); sv.close(); fl.close(); } catch (FileNotFoundException ex) { System.out.println("Dmgcpu.loadState: Could not open file " + directory); System.out.println("Error Message: " + ex.getMessage()); System.exit(-1); } catch (IOException ex) { System.out.println("Dmgcpu.loadState: Could not read file " + directory); System.out.println("Error Message: " + ex.getMessage()); System.exit(-1); } System.out.println("Loaded stage!"); }