diff --git a/.gitignore b/.gitignore index 422c5a3..5b7d156 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea target +nes cmake-build-debug \ No newline at end of file diff --git a/app/src/main/java/cn/navclub/nes4j/app/view/GameHall.java b/app/src/main/java/cn/navclub/nes4j/app/view/GameHall.java index 9c070b2..358f73b 100644 --- a/app/src/main/java/cn/navclub/nes4j/app/view/GameHall.java +++ b/app/src/main/java/cn/navclub/nes4j/app/view/GameHall.java @@ -108,7 +108,10 @@ protected List call() { if (!file.exists() || file.listFiles() == null) { return List.of(); } - return Arrays.stream(file.listFiles()).filter(File::isFile).toList(); + return Arrays + .stream(file.listFiles()).filter(File::isFile) + .filter(it -> it.getName().endsWith(".nes")) + .toList(); } }; } diff --git a/app/src/main/java/cn/navclub/nes4j/app/view/GameWorld.java b/app/src/main/java/cn/navclub/nes4j/app/view/GameWorld.java index d99d905..4ee1fef 100644 --- a/app/src/main/java/cn/navclub/nes4j/app/view/GameWorld.java +++ b/app/src/main/java/cn/navclub/nes4j/app/view/GameWorld.java @@ -155,6 +155,14 @@ public void handle() { }); } + @FXML + public void reset() { + if (this.instance == null) { + return; + } + this.instance.reset(); + } + private void gameLoopCallback(Frame frame, JoyPad joyPad, JoyPad joyPad1) { var w = Frame.width; diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/fxml/GameWorld.fxml b/app/src/main/resources/cn/navclub/nes4j/app/assets/fxml/GameWorld.fxml index c1beaea..4395146 100644 --- a/app/src/main/resources/cn/navclub/nes4j/app/assets/fxml/GameWorld.fxml +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/fxml/GameWorld.fxml @@ -10,7 +10,7 @@ - + diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/NES.java b/bin/src/main/java/cn/navclub/nes4j/bin/NES.java index 1bb3037..8fc1290 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/NES.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/NES.java @@ -81,15 +81,10 @@ public void execute() { } else { //fire ppu or apu interrupt cycles += this.cpu.interrupt(this.getInterrupt()); - var programCounter = this.cpu.getPc(); if (this.debugger != null && this.debugger.hack(this)) { //lock current program process LockSupport.park(); } - //Check program counter whether in legal memory area - if (programCounter < 0x8000 || programCounter >= 0x10000) { - throw new RuntimeException("Text memory area except in 0x8000 to 0xffff current 0x" + Integer.toHexString(programCounter)); - } cycles += this.cpu.next(); this.instructions++; } diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/config/CPUInterrupt.java b/bin/src/main/java/cn/navclub/nes4j/bin/config/CPUInterrupt.java index 3319194..4c1648a 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/config/CPUInterrupt.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/config/CPUInterrupt.java @@ -8,11 +8,11 @@ @Getter public enum CPUInterrupt { //PPU - NMI(2, 0xfffa), + NMI(7, 0xfffa), //APU - IRQ(2, 0xfffe), + IRQ(7, 0xfffe), //CPU - BRK(1, 0xfffe); + BRK(7, 0xfffe); private final int cycle; private final int vector; diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/config/ICPUStatus.java b/bin/src/main/java/cn/navclub/nes4j/bin/config/ICPUStatus.java index 8816674..0ea20f6 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/config/ICPUStatus.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/config/ICPUStatus.java @@ -2,19 +2,19 @@ public enum ICPUStatus { //Carry flag - CF, + CARRY, //Zero flag - ZF, + ZERO, //Interrupt disable - ID, + INTERRUPT_DISABLE, //Decimal mode - DM, + DECIMAL_MODE, //Break command - BK, + BREAK_COMMAND, //Empty - BK2, + EMPTY, //Overflow flag - OF, + OVERFLOW, //Negative flag - NF + NEGATIVE } diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/config/Instruction.java b/bin/src/main/java/cn/navclub/nes4j/bin/config/Instruction.java index aaa982b..581a96e 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/config/Instruction.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/config/Instruction.java @@ -9,7 +9,7 @@ /** - * 6502 指令集 + * 6502 instructions * * @author GZYangKui */ @@ -22,8 +22,8 @@ public enum Instruction { InstructionWrap.create(int8(0x69), 2, 2, Immediate), InstructionWrap.create(int8(0x65), 2, 3, ZeroPage), InstructionWrap.create(int8(0x75), 2, 4, ZeroPage_X), - InstructionWrap.create(int8(0x6D), 3, 4, Absolute), - InstructionWrap.create(int8(0x7D), 3, 4, Absolute_X), + InstructionWrap.create(int8(0x6d), 3, 4, Absolute), + InstructionWrap.create(int8(0x7d), 3, 4, Absolute_X), InstructionWrap.create(int8(0x79), 3, 4, Absolute_Y), InstructionWrap.create(int8(0x61), 2, 6, Indirect_X), InstructionWrap.create(int8(0x71), 2, 5, Indirect_Y), @@ -34,14 +34,14 @@ public enum Instruction { * 相关文档 */ LDA(new InstructionWrap[]{ - InstructionWrap.create(int8(0xA9), 2, 2, Immediate), - InstructionWrap.create(int8(0xA5), 2, 3, ZeroPage), - InstructionWrap.create(int8(0xB5), 2, 4, ZeroPage_X), - InstructionWrap.create(int8(0xAD), 3, 4, Absolute), - InstructionWrap.create(int8(0xBD), 3, 4, Absolute_X), - InstructionWrap.create(int8(0xB9), 3, 4, Absolute_Y), - InstructionWrap.create(int8(0xA1), 2, 6, Indirect_X), - InstructionWrap.create(int8(0xB1), 2, 5, Indirect_Y), + InstructionWrap.create(int8(0xa9), 2, 2, Immediate), + InstructionWrap.create(int8(0xa5), 2, 3, ZeroPage), + InstructionWrap.create(int8(0xb5), 2, 4, ZeroPage_X), + InstructionWrap.create(int8(0xad), 3, 4, Absolute), + InstructionWrap.create(int8(0xbd), 3, 4, Absolute_X), + InstructionWrap.create(int8(0xb9), 3, 4, Absolute_Y), + InstructionWrap.create(int8(0xa1), 2, 6, Indirect_X), + InstructionWrap.create(int8(0xb1), 2, 5, Indirect_Y), }), /** * 将累加器中的值写入内存中 @@ -50,8 +50,8 @@ public enum Instruction { STA(new InstructionWrap[]{ InstructionWrap.create(int8(0x85), 2, 3, ZeroPage), InstructionWrap.create(int8(0x95), 2, 4, ZeroPage_X), - InstructionWrap.create(int8(0x8D), 3, 4, Absolute), - InstructionWrap.create(int8(0x9D), 3, 5, Absolute_X), + InstructionWrap.create(int8(0x8d), 3, 4, Absolute), + InstructionWrap.create(int8(0x9d), 3, 5, Absolute_X), InstructionWrap.create(int8(0x99), 3, 5, Absolute_Y), InstructionWrap.create(int8(0x81), 2, 6, Indirect_X), InstructionWrap.create(int8(0x91), 2, 6, Indirect_Y) @@ -63,7 +63,7 @@ public enum Instruction { STX(new InstructionWrap[]{ InstructionWrap.create(int8(0x86), 2, 3, ZeroPage), InstructionWrap.create(int8(0x96), 2, 4, ZeroPage_Y), - InstructionWrap.create(int8(0x8E), 3, 4, Absolute), + InstructionWrap.create(int8(0x8e), 3, 4, Absolute), }), /** @@ -74,7 +74,7 @@ public enum Instruction { STY(new InstructionWrap[]{ InstructionWrap.create(int8(0x84), 2, 3, ZeroPage), InstructionWrap.create(int8(0x94), 2, 4, ZeroPage_X), - InstructionWrap.create(int8(0X8C), 3, 4, Absolute) + InstructionWrap.create(int8(0X8c), 3, 4, Absolute) }), /** @@ -86,8 +86,8 @@ public enum Instruction { InstructionWrap.create(int8(0x29), 2, 2, Immediate), InstructionWrap.create(int8(0x25), 2, 3, ZeroPage), InstructionWrap.create(int8(0x35), 2, 4, ZeroPage_X), - InstructionWrap.create(int8(0x2D), 3, 4, Absolute), - InstructionWrap.create(int8(0x3D), 3, 4, Absolute_X), + InstructionWrap.create(int8(0x2d), 3, 4, Absolute), + InstructionWrap.create(int8(0x3d), 3, 4, Absolute_X), InstructionWrap.create(int8(0x39), 3, 4, Absolute_Y), InstructionWrap.create(int8(0x21), 2, 6, Indirect_X), InstructionWrap.create(int8(0x31), 2, 5, Indirect_Y), @@ -100,8 +100,8 @@ public enum Instruction { InstructionWrap.create(int8(0x09), 2, 2, Immediate), InstructionWrap.create(int8(0x05), 2, 3, ZeroPage), InstructionWrap.create(int8(0x15), 2, 4, ZeroPage_X), - InstructionWrap.create(int8(0x0D), 3, 4, Absolute), - InstructionWrap.create(int8(0x1D), 3, 4, Absolute_X), + InstructionWrap.create(int8(0x0d), 3, 4, Absolute), + InstructionWrap.create(int8(0x1d), 3, 4, Absolute_X), InstructionWrap.create(int8(0x19), 3, 4, Absolute_Y), InstructionWrap.create(int8(0x01), 2, 6, Indirect_X), InstructionWrap.create(int8(0x11), 2, 5, Indirect_Y) @@ -115,8 +115,8 @@ public enum Instruction { InstructionWrap.create(int8(0x49), 2, 2, Immediate), InstructionWrap.create(int8(0x45), 2, 3, ZeroPage), InstructionWrap.create(int8(0x55), 2, 4, ZeroPage_X), - InstructionWrap.create(int8(0x4D), 3, 4, Absolute), - InstructionWrap.create(int8(0x5D), 3, 4, Absolute_X), + InstructionWrap.create(int8(0x4d), 3, 4, Absolute), + InstructionWrap.create(int8(0x5d), 3, 4, Absolute_X), InstructionWrap.create(int8(0x59), 3, 4, Absolute_Y), InstructionWrap.create(int8(0x41), 2, 6, Indirect_X), InstructionWrap.create(int8(0x51), 2, 5, Indirect_Y) @@ -135,7 +135,7 @@ public enum Instruction { * * 相关文档 */ - PHP(int8(0X08), 1, 3), + PHP(int8(0x08), 1, 3), /** * 从系统栈中获取值并更新累加寄存器 @@ -156,22 +156,22 @@ public enum Instruction { * 相关文档 */ ASL(new InstructionWrap[]{ - InstructionWrap.create(int8(0x0A), 1, 2, Accumulator), + InstructionWrap.create(int8(0x0a), 1, 2, Accumulator), InstructionWrap.create(int8(0x06), 2, 5, ZeroPage), InstructionWrap.create(int8(0x16), 2, 6, ZeroPage_X), - InstructionWrap.create(int8(0x0E), 3, 6, Absolute), - InstructionWrap.create(int8(0x1E), 3, 7, Absolute_X) + InstructionWrap.create(int8(0x0e), 3, 6, Absolute), + InstructionWrap.create(int8(0x1e), 3, 7, Absolute_X) }), /** * 相关文档 */ LSR(new InstructionWrap[]{ - InstructionWrap.create(int8(0x4A), 1, 2, Accumulator), + InstructionWrap.create(int8(0x4a), 1, 2, Accumulator), InstructionWrap.create(int8(0x46), 2, 5, ZeroPage), InstructionWrap.create(int8(0x56), 2, 6, ZeroPage_X), - InstructionWrap.create(int8(0x4E), 3, 6, Absolute), - InstructionWrap.create(int8(0x5E), 3, 7, Absolute_X) + InstructionWrap.create(int8(0x4e), 3, 6, Absolute), + InstructionWrap.create(int8(0x5e), 3, 7, Absolute_X) }), /** @@ -179,14 +179,14 @@ public enum Instruction { * 相关文档 */ CMP(new InstructionWrap[]{ - InstructionWrap.create(int8(0xC9), 2, 2, Immediate), - InstructionWrap.create(int8(0xC5), 2, 3, ZeroPage), - InstructionWrap.create(int8(0xD5), 2, 4, ZeroPage_X), - InstructionWrap.create(int8(0xCD), 3, 4, Absolute), - InstructionWrap.create(int8(0xDD), 3, 4, Absolute_X), - InstructionWrap.create(int8(0xD9), 3, 4, Absolute_Y), - InstructionWrap.create(int8(0xC1), 2, 6, Indirect_X), - InstructionWrap.create(int8(0xD1), 2, 5, Indirect_Y) + InstructionWrap.create(int8(0xc9), 2, 2, Immediate), + InstructionWrap.create(int8(0xc5), 2, 3, ZeroPage), + InstructionWrap.create(int8(0xd5), 2, 4, ZeroPage_X), + InstructionWrap.create(int8(0xcd), 3, 4, Absolute), + InstructionWrap.create(int8(0xdd), 3, 4, Absolute_X), + InstructionWrap.create(int8(0xd9), 3, 4, Absolute_Y), + InstructionWrap.create(int8(0xc1), 2, 6, Indirect_X), + InstructionWrap.create(int8(0xd1), 2, 5, Indirect_Y) }), /** @@ -195,9 +195,9 @@ public enum Instruction { * 相关文档 */ CPX(new InstructionWrap[]{ - InstructionWrap.create(int8(0xE0), 2, 2, Immediate), - InstructionWrap.create(int8(0xE4), 2, 3, ZeroPage), - InstructionWrap.create(int8(0xEC), 2, 4, Absolute), + InstructionWrap.create(int8(0xe0), 2, 2, Immediate), + InstructionWrap.create(int8(0xe4), 2, 3, ZeroPage), + InstructionWrap.create(int8(0xec), 3, 4, Absolute), }), /** @@ -206,9 +206,9 @@ public enum Instruction { * 相关文档 */ CPY(new InstructionWrap[]{ - InstructionWrap.create(int8(0xC0), 2, 2, Immediate), - InstructionWrap.create(int8(0xC4), 2, 3, ZeroPage), - InstructionWrap.create(int8(0xCC), 2, 4, Absolute), + InstructionWrap.create(int8(0xc0), 2, 2, Immediate), + InstructionWrap.create(int8(0xc4), 2, 3, ZeroPage), + InstructionWrap.create(int8(0xcc), 3, 4, Absolute), } ), @@ -216,11 +216,11 @@ public enum Instruction { * 相关文档 */ LDX(new InstructionWrap[]{ - InstructionWrap.create(int8(0xA2), 2, 2, Immediate), - InstructionWrap.create(int8(0xA6), 2, 3, ZeroPage), - InstructionWrap.create(int8(0xB6), 2, 4, ZeroPage_Y), - InstructionWrap.create(int8(0xAE), 3, 4, Absolute), - InstructionWrap.create(int8(0xBE), 3, 4, Absolute_Y) + InstructionWrap.create(int8(0xa2), 2, 2, Immediate), + InstructionWrap.create(int8(0xa6), 2, 3, ZeroPage), + InstructionWrap.create(int8(0xb6), 2, 4, ZeroPage_Y), + InstructionWrap.create(int8(0xae), 3, 4, Absolute), + InstructionWrap.create(int8(0xbe), 3, 4, Absolute_Y) } ), @@ -228,11 +228,11 @@ public enum Instruction { * 相关文档 */ LDY(new InstructionWrap[]{ - InstructionWrap.create(int8(0xA0), 2, 2, Immediate), - InstructionWrap.create(int8(0xA4), 2, 3, ZeroPage), + InstructionWrap.create(int8(0xa0), 2, 2, Immediate), + InstructionWrap.create(int8(0xa4), 2, 3, ZeroPage), InstructionWrap.create(int8(0xb4), 2, 4, ZeroPage_X), - InstructionWrap.create(int8(0xAC), 3, 4, Absolute), - InstructionWrap.create(int8(0xBC), 3, 4, Absolute_X) + InstructionWrap.create(int8(0xac), 3, 4, Absolute), + InstructionWrap.create(int8(0xbc), 3, 4, Absolute_X) } ), @@ -240,10 +240,10 @@ public enum Instruction { * 相关文档 */ INC(new InstructionWrap[]{ - InstructionWrap.create(int8(0xE6), 2, 5, ZeroPage), - InstructionWrap.create(int8(0xF6), 2, 6, ZeroPage_X), - InstructionWrap.create(int8(0xEE), 3, 6, Absolute), - InstructionWrap.create(int8(0xFE), 3, 7, Absolute_X), + InstructionWrap.create(int8(0xe6), 2, 5, ZeroPage), + InstructionWrap.create(int8(0xf6), 2, 6, ZeroPage_X), + InstructionWrap.create(int8(0xee), 3, 6, Absolute), + InstructionWrap.create(int8(0xfe), 3, 7, Absolute_X), } ), @@ -259,17 +259,17 @@ public enum Instruction { */ BIT(new InstructionWrap[]{ InstructionWrap.create(int8(0x24), 2, 3, ZeroPage), - InstructionWrap.create(int8(0X2C), 3, 4, Absolute) + InstructionWrap.create(int8(0X2c), 3, 4, Absolute) }), /** * 相关文档 */ DEC(new InstructionWrap[]{ - InstructionWrap.create(int8(0xC6), 2, 5, ZeroPage), - InstructionWrap.create(int8(0xD6), 2, 6, ZeroPage_X), - InstructionWrap.create(int8(0xCE), 3, 6, Absolute), - InstructionWrap.create(int8(0xDE), 3, 7, Absolute_X) + InstructionWrap.create(int8(0xc6), 2, 5, ZeroPage), + InstructionWrap.create(int8(0xd6), 2, 6, ZeroPage_X), + InstructionWrap.create(int8(0xce), 3, 6, Absolute), + InstructionWrap.create(int8(0xde), 3, 7, Absolute_X) }), /** @@ -284,22 +284,22 @@ public enum Instruction { * 相关文档 */ ROR(new InstructionWrap[]{ - InstructionWrap.create(int8(0x6A), 1, 2, Accumulator), + InstructionWrap.create(int8(0x6a), 1, 2, Accumulator), InstructionWrap.create(int8(0x66), 2, 5, ZeroPage), InstructionWrap.create(int8(0x76), 2, 6, ZeroPage_X), - InstructionWrap.create(int8(0x6E), 3, 6, Absolute), - InstructionWrap.create(int8(0x7E), 3, 7, Absolute_X), + InstructionWrap.create(int8(0x6e), 3, 6, Absolute), + InstructionWrap.create(int8(0x7e), 3, 7, Absolute_X), }), /** * 相关文档 */ ROL(new InstructionWrap[]{ - InstructionWrap.create(int8(0x2A), 1, 2, Accumulator), + InstructionWrap.create(int8(0x2a), 1, 2, Accumulator), InstructionWrap.create(int8(0x26), 2, 5, ZeroPage), InstructionWrap.create(int8(0x36), 2, 6, ZeroPage_X), - InstructionWrap.create(int8(0x2E), 3, 6, Absolute), - InstructionWrap.create(int8(0x3E), 3, 7, Absolute_X), + InstructionWrap.create(int8(0x2e), 3, 6, Absolute), + InstructionWrap.create(int8(0x3e), 3, 7, Absolute_X), }), /** @@ -315,13 +315,13 @@ public enum Instruction { InstructionWrap.create(int8(0xe1), 2, 6, Indirect_X), InstructionWrap.create(int8(0xf1), 2, 5, Indirect_Y), //un-office sbc+NOP - InstructionWrap.create((byte) 0xeb, 2, 2, Immediate) + InstructionWrap.create(int8(0xeb), 2, 2, Immediate) }), /** * 相关文档 */ - DEX(int8(0xCA), 1, 2), + DEX(int8(0xca), 1, 2), /** * 相关文档 @@ -331,7 +331,7 @@ public enum Instruction { /** * 相关文档 */ - RTS(int8(0X60), 1, 6), + RTS(int8(0x60), 1, 6), /** * 清除进位标识 @@ -343,7 +343,7 @@ public enum Instruction { * 清除数字标识 * 相关文档 */ - CLD(int8(0xD8), 1, 2), + CLD(int8(0xd8), 1, 2), /** * 清除中断标识 @@ -357,20 +357,20 @@ public enum Instruction { * * 相关文档 */ - CLV(int8(0xB8), 1, 2), + CLV(int8(0xb8), 1, 2), /** * 自增X寄存器 * * 相关文档 */ - INX(int8(0XE8), 1, 2), + INX(int8(0xe8), 1, 2), /** * 自增Y寄存器 * 相关文档 */ - INY(int8(0xC8), 1, 2), + INY(int8(0xc8), 1, 2), /** * 相关文档 @@ -385,7 +385,7 @@ public enum Instruction { /** * 相关文档 */ - BCS(int8(0xB0), 2, 2, Relative), + BCS(int8(0xb0), 2, 2, Relative), /** * 相关文档 @@ -395,12 +395,12 @@ public enum Instruction { /** * 相关文档 */ - BNE(int8(0XD0), 2, 2, Relative), + BNE(int8(0xd0), 2, 2, Relative), /** * 相关文档 */ - BPL(int8(0X10), 2, 2, Relative), + BPL(int8(0x10), 2, 2, Relative), /** * 相关文档 @@ -430,7 +430,7 @@ public enum Instruction { /** * 相关文档 */ - SED(int8(0xF8), 1, 2), + SED(int8(0xf8), 1, 2), /** * 相关文档 @@ -440,27 +440,27 @@ public enum Instruction { /** * 相关文档 */ - TAX(int8(0xAA), 1, 2), + TAX(int8(0xaa), 1, 2), /** * 相关文档 */ - TAY(int8(0xA8), 1, 2), + TAY(int8(0xa8), 1, 2), /** * 相关文档 */ - TSX(int8(0xBA), 1, 2), + TSX(int8(0xba), 1, 2), /** * 相关文档 */ - TXA(int8(0x8A), 1, 2), + TXA(int8(0x8a), 1, 2), /** * 相关文档 */ - TXS(int8(0x9A), 1, 2), + TXS(int8(0x9a), 1, 2), /** * 相关文档 diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/core/Bus.java b/bin/src/main/java/cn/navclub/nes4j/bin/core/Bus.java index 4625c96..d13f204 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/core/Bus.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/core/Bus.java @@ -125,7 +125,6 @@ else if (address >= RPG_ROM && address <= RPG_ROM_END) { public void write(int address, byte b) { address = this.map(address); - if (address >= 0 && address <= RAM_MIRROR_END) { this.ram[address] = b; } diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/core/CPU.java b/bin/src/main/java/cn/navclub/nes4j/bin/core/CPU.java index 993c38c..6c4efad 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/core/CPU.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/core/CPU.java @@ -3,6 +3,9 @@ import cn.navclub.nes4j.bin.NES; import cn.navclub.nes4j.bin.config.*; import cn.navclub.nes4j.bin.core.register.CPUStatus; +import cn.navclub.nes4j.bin.debug.OpenCodeFormat; +import cn.navclub.nes4j.bin.ppu.PPU; +import cn.navclub.nes4j.bin.util.BinUtil; import lombok.Data; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -61,7 +64,7 @@ public void reset() { this.ra = 0; this.sp = STACK_RESET; this.pc = this.bus.readInt(PC_RESET); - this.status.setBits(int8(0b100100)); + this.status.setBits(int8(0b000100)); } @@ -111,8 +114,8 @@ private void raUpdate(int value) { */ private void NZUpdate(int result) { var b = (result & 0xff); - this.status.update(ICPUStatus.ZF, (b == 0)); - this.status.update(ICPUStatus.NF, (b >> 7) == 1); + this.status.update(ICPUStatus.ZERO, (b == 0)); + this.status.update(ICPUStatus.NEGATIVE, (b >> 7) == 1); } /** @@ -137,7 +140,7 @@ private void lsr(AddressMode mode) { ? this.ra : this.bus.ReadU8(addr = this.modeProvider.getAbsAddr(mode)); - this.status.update(ICPUStatus.CF, (operand & 1) == 1); + this.status.update(ICPUStatus.CARRY, (operand & 1) == 1); operand >>= 1; if (mode == AddressMode.Accumulator) { this.raUpdate(operand); @@ -160,8 +163,8 @@ private void rol(AddressMode mode) { } bit = value >> 7; value <<= 1; - value |= this.status.get(ICPUStatus.CF); - this.status.update(ICPUStatus.CF, bit == 1); + value |= this.status.get(ICPUStatus.CARRY); + this.status.update(ICPUStatus.CARRY, bit == 1); if (updateRA) { this.raUpdate(value); } else { @@ -180,8 +183,8 @@ private void ror(AddressMode mode) { } var oBit = value & 1; value >>= 1; - value |= (this.status.get(ICPUStatus.CF) << 7); - this.status.update(ICPUStatus.CF, oBit == 1); + value |= (this.status.get(ICPUStatus.CARRY) << 7); + this.status.update(ICPUStatus.CARRY, oBit == 1); if (rora) { this.raUpdate(value); } else { @@ -201,7 +204,7 @@ private void asl(InstructionWrap instruction6502) { b = this.bus.ReadU8(address); } //更新进位标识 - this.status.update(ICPUStatus.CF, (b >> 7) == 1); + this.status.update(ICPUStatus.CARRY, (b >> 7) == 1); //左移1位 b = b << 1; if (a) { @@ -218,7 +221,7 @@ private void push(InstructionWrap instruction6502) { this.push((byte) this.ra); } else { var flags = this.status.copy(); - flags.set(ICPUStatus.BK, ICPUStatus.BK2); + flags.set(ICPUStatus.BREAK_COMMAND, ICPUStatus.EMPTY); this.push(flags.getBits()); } } @@ -230,8 +233,8 @@ private void pull(InstructionWrap instruction6502) { this.raUpdate(value); } else { this.status.setBits(value); - this.status.set(ICPUStatus.BK2); - this.status.clear(ICPUStatus.BK); + this.status.set(ICPUStatus.EMPTY); + this.status.clear(ICPUStatus.BREAK_COMMAND); } } @@ -248,7 +251,7 @@ private void cmp(InstructionWrap instruction6502) { var address = this.modeProvider.getAbsAddr(instruction6502.getAddressMode()); var m = this.bus.ReadU8(address); //设置Carry Flag - this.status.update(ICPUStatus.CF, a >= m); + this.status.update(ICPUStatus.CARRY, a >= m); //更新cpu状态 this.NZUpdate(u8sbc(a, m)); } @@ -276,10 +279,10 @@ private void adc(AddressMode mode, boolean sbc) { b = (byte) (-b - 1); } var value = b & 0xff; - var sum = this.ra + value + this.status.get(ICPUStatus.CF); - this.status.update(ICPUStatus.CF, sum > 0xff); + var sum = this.ra + value + this.status.get(ICPUStatus.CARRY); + this.status.update(ICPUStatus.CARRY, sum > 0xff); var result = sum & 0xff; - this.status.update(ICPUStatus.OF, (((b & 0xff ^ result) & (result ^ this.ra)) & 0x80) != 0); + this.status.update(ICPUStatus.OVERFLOW, (((b & 0xff ^ result) & (result ^ this.ra)) & 0x80) != 0); this.raUpdate(result); } @@ -319,9 +322,9 @@ private void branch(boolean condition) { private void bit(InstructionWrap instruction6502) { var address = this.modeProvider.getAbsAddr(instruction6502.getAddressMode()); var value = this.bus.ReadU8(address); - this.status.update(ICPUStatus.ZF, (this.ra & value) == 0); - this.status.update(ICPUStatus.NF, (value >> 7) == 1); - this.status.update(ICPUStatus.OF, (value >> 6) == 1); + this.status.update(ICPUStatus.ZERO, (this.ra & value) == 0); + this.status.update(ICPUStatus.NEGATIVE, (value >> 7) == 1); + this.status.update(ICPUStatus.OVERFLOW, (value >> 6) == 1); } private void dec(InstructionWrap instruction6502) { @@ -346,7 +349,9 @@ private void dec(InstructionWrap instruction6502) { } public int interrupt(CPUInterrupt interrupt) { - if (interrupt == null || (interrupt != CPUInterrupt.NMI && this.status.contain(ICPUStatus.ID))) { + if (interrupt == null + //When set, all interrupts except the NMI are inhibited. + || (this.status.contain(ICPUStatus.INTERRUPT_DISABLE) && interrupt != CPUInterrupt.NMI)) { return 0; } @@ -355,12 +360,16 @@ public int interrupt(CPUInterrupt interrupt) { var flag = this.status.copy(); //https://www.nesdev.org/wiki/Status_flags#The_B_flag - flag.set(ICPUStatus.BK2); - flag.update(ICPUStatus.BK, interrupt == CPUInterrupt.BRK); + flag.set(ICPUStatus.EMPTY); + flag.update(ICPUStatus.BREAK_COMMAND, interrupt == CPUInterrupt.BRK); this.push(flag.getBits()); - this.status.set(ICPUStatus.ID); + //Automatically set by the CPU when an IRQ is triggered, and restored to its previous state by RTI. + if (interrupt == CPUInterrupt.IRQ) { + this.status.set(ICPUStatus.INTERRUPT_DISABLE); + } + this.pc = this.bus.readInt(interrupt.getVector()); return interrupt.getCycle(); @@ -379,6 +388,7 @@ public int next() { var mode = instruction6502.getAddressMode(); var instruction = instruction6502.getInstruction(); +// System.out.println(Integer.toHexString(this.pc - 1) + ":" + instruction + "(" + BinUtil.toHexStr(instruction6502.getOpenCode()) + ")"); if (instruction == Instruction.JMP) { this.pc = this.modeProvider.getAbsAddr(mode); @@ -387,8 +397,8 @@ public int next() { if (instruction == Instruction.RTI) { this.status.setBits(this.pop()); - this.status.set(ICPUStatus.BK2); - this.status.clear(ICPUStatus.BK); + this.status.set(ICPUStatus.EMPTY); + this.status.clear(ICPUStatus.BREAK_COMMAND); this.pc = this.popInt(); } @@ -447,6 +457,9 @@ public int next() { //刷新累加寄存器值到内存 if (instruction == Instruction.STA) { var addr = this.modeProvider.getAbsAddr(mode); + if (this.pc - 1 == 0xe992) { + var str = "555"; + } this.bus.WriteU8(addr, this.ra); } @@ -462,21 +475,21 @@ public int next() { //清除进位标识 if (instruction == Instruction.CLC) { - this.status.clear(ICPUStatus.CF); + this.status.clear(ICPUStatus.CARRY); } //清除Decimal model if (instruction == Instruction.CLD) { - this.status.clear(ICPUStatus.DM); + this.status.clear(ICPUStatus.DECIMAL_MODE); } //清除中断标识 if (instruction == Instruction.CLI) { - this.status.clear(ICPUStatus.ID); + this.status.clear(ICPUStatus.INTERRUPT_DISABLE); } if (instruction == Instruction.CLV) { - this.status.clear(ICPUStatus.OF); + this.status.clear(ICPUStatus.OVERFLOW); } if (instruction == Instruction.CMP @@ -502,21 +515,21 @@ public int next() { //By negative flag to jump if (instruction == Instruction.BPL || instruction == Instruction.BMI) { - this.branch((instruction == Instruction.BMI) == this.status.contain(ICPUStatus.NF)); + this.branch((instruction == Instruction.BMI) == this.status.contain(ICPUStatus.NEGATIVE)); } //By zero flag to jump if (instruction == Instruction.BEQ || instruction == Instruction.BNE) { - this.branch((instruction == Instruction.BEQ) == this.status.contain(ICPUStatus.ZF)); + this.branch((instruction == Instruction.BEQ) == this.status.contain(ICPUStatus.ZERO)); } //By overflow flag to jump if (instruction == Instruction.BVC || instruction == Instruction.BVS) { - this.branch((instruction == Instruction.BVS) == this.status.contain(ICPUStatus.OF)); + this.branch((instruction == Instruction.BVS) == this.status.contain(ICPUStatus.OVERFLOW)); } if (instruction == Instruction.BCS || instruction == Instruction.BCC) { - this.branch((instruction == Instruction.BCS) == this.status.contain(ICPUStatus.CF)); + this.branch((instruction == Instruction.BCS) == this.status.contain(ICPUStatus.CARRY)); } if (instruction == Instruction.DEC @@ -527,15 +540,15 @@ public int next() { if (instruction == Instruction.SEC) { - this.status.set(ICPUStatus.CF); + this.status.set(ICPUStatus.CARRY); } if (instruction == Instruction.SED) { - this.status.set(ICPUStatus.DM); + this.status.set(ICPUStatus.DECIMAL_MODE); } if (instruction == Instruction.SEI) { - this.status.set(ICPUStatus.ID); + this.status.set(ICPUStatus.INTERRUPT_DISABLE); } if (instruction == Instruction.TAX) { @@ -584,7 +597,7 @@ public int next() { if (instruction == Instruction.ANC) { this.adc(mode, false); - this.status.update(ICPUStatus.CF, this.status.contain(ICPUStatus.NF)); + this.status.update(ICPUStatus.CARRY, this.status.contain(ICPUStatus.NEGATIVE)); } if (instruction == Instruction.XAA) { @@ -602,8 +615,8 @@ public int next() { var result = this.ra; var b5 = (result >> 5 & 1); var b6 = (result >> 6 & 1); - this.status.update(ICPUStatus.CF, b6 == 1); - this.status.update(ICPUStatus.OF, (b5 ^ b6) == 1); + this.status.update(ICPUStatus.CARRY, b6 == 1); + this.status.update(ICPUStatus.OVERFLOW, (b5 ^ b6) == 1); this.NZUpdate(result); } @@ -613,7 +626,7 @@ public int next() { value = u8sbc(value, 1); this.bus.WriteU8(addr, value); if (value <= this.ra) { - this.status.set(ICPUStatus.CF); + this.status.set(ICPUStatus.CARRY); } this.NZUpdate(u8sbc(this.ra, value)); } diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/ppu/PPU.java b/bin/src/main/java/cn/navclub/nes4j/bin/ppu/PPU.java index af9c39a..6f93d36 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/ppu/PPU.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/ppu/PPU.java @@ -114,7 +114,7 @@ public byte readOam() { } public void OAMAddrWrite(byte b) { - this.oamAddr = (b & 0xff); + this.oamAddr = uint8(b); } public void AddrWrite(byte b) { @@ -221,6 +221,12 @@ public byte readStatus() { return b; } + /** + * The PPU uses the current VRAM address for both reading and writing PPU memory thru $2007, and for fetching nametable data to draw the background. As it's drawing the background, it updates the address to point to the nametable data currently being drawn. Bits 10-11 hold the base address of the nametable minus $2000. Bits 12-14 are the Y offset of a scanline within a tile. + * + * @param addr PPU address + * @return Current nametable data address + */ private int ramMirror(int addr) { var mirrorRam = addr & 0x2fff; var ramIndex = mirrorRam - 0x2000; @@ -289,6 +295,9 @@ public int pixel() { * Output one frame video sign. */ protected void fireNMI() { + if (!this.ctr.generateVBlankNMI()) { + return; + } this.status.set(PStatus.V_BLANK_OCCUR); this.context.interrupt(CPUInterrupt.NMI); } diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/ppu/register/PPUStatus.java b/bin/src/main/java/cn/navclub/nes4j/bin/ppu/register/PPUStatus.java index 0843c54..8d7b3f5 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/ppu/register/PPUStatus.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/ppu/register/PPUStatus.java @@ -16,7 +16,7 @@ * ---- ---- * VSO. .... * |||| |||| - * |||+-++++- PPU open bus. Returns stale PPU bus contents. + * |||+-++++- PPU open bus. Returns stale PPU bus contents. * ||+------- Sprite overflow. The intent was for this flag to be set * || whenever more than eight sprites appear on a scanline, but a * || hardware bug causes the actual behavior to be more complicated @@ -32,6 +32,7 @@ * line); cleared after reading $2002 and at dot 1 of the * pre-render line. * + * * @author GZYangKui */ public class PPUStatus extends Register {