From a30a2cf1c72339c752496d632205a0f684de602f Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Wed, 7 Sep 2016 20:13:27 -0400 Subject: [PATCH] Make room for family basic This is a long way from functional, but at least now the game will boot. It needs the keyboard to do anything (so it's in a similar state to compumate on A2600) --- .../Consoles/Nintendo/NES/NES.Core.cs | 186 ++++++++++++------ 1 file changed, 129 insertions(+), 57 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs index b0a9d05c0f..ccc5a7196c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs @@ -26,14 +26,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES int sprdma_countdown; bool _irq_apu; //various irq signals that get merged to the cpu irq pin - /// clock speed of the main cpu in hz + /// clock speed of the main cpu in hz public int cpuclockrate { get; private set; } //irq state management public bool irq_apu { get { return _irq_apu; } set { _irq_apu = value; } } //user configuration - int[] palette_compiled = new int[64*8]; + int[] palette_compiled = new int[64 * 8]; + + //variable to change controller read/write behaviour when keyboard is attached + public bool _iskeyboard = false; // new input system NESControlSettings ControllerSettings; // this is stored internally so that a new change of settings won't replace @@ -157,7 +160,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES ppu = new PPU(this); ram = new byte[0x800]; CIRAM = new byte[0x800]; - + // wire controllers // todo: allow changing this ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback); @@ -222,7 +225,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES // apu has some specific power up bahaviour that we will emulate here apu.NESHardReset(); - + if (SyncSettings.InitialWRamStatePattern != null && SyncSettings.InitialWRamStatePattern.Any()) { for (int i = 0; i < 0x800; i++) @@ -280,7 +283,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES Frame++; //if (resetSignal) - //Controller.UnpressButton("Reset"); TODO fix this + //Controller.UnpressButton("Reset"); TODO fix this resetSignal = Controller["Reset"]; hardResetSignal = Controller["Power"]; @@ -309,19 +312,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES //PAL: //0 15 30 45 60 -> 12 27 42 57 -> 9 24 39 54 -> 6 21 36 51 -> 3 18 33 48 -> 0 //sequence of ppu clocks per cpu clock: 3,3,3,3,4 - //at least it should be, but something is off with that (start up time?) so it is 3,3,3,4,3 for now + //at least it should be, but something is off with that (start up time?) so it is 3,3,3,4,3 for now //NTSC: //sequence of ppu clocks per cpu clock: 3 ByteBuffer cpu_sequence; - static ByteBuffer cpu_sequence_NTSC = new ByteBuffer(new byte[]{3,3,3,3,3}); - static ByteBuffer cpu_sequence_PAL = new ByteBuffer(new byte[]{3,3,3,4,3}); + static ByteBuffer cpu_sequence_NTSC = new ByteBuffer(new byte[] { 3, 3, 3, 3, 3 }); + static ByteBuffer cpu_sequence_PAL = new ByteBuffer(new byte[] { 3, 3, 3, 4, 3 }); public int cpu_step, cpu_stepcounter, cpu_deadcounter; public int oam_dma_index; - public bool oam_dma_exec=false; + public bool oam_dma_exec = false; public ushort oam_dma_addr; public byte oam_dma_byte; - public bool dmc_dma_exec=false; + public bool dmc_dma_exec = false; public bool dmc_realign; public bool IRQ_delay; public bool special_case_delay; // very ugly but the only option @@ -336,7 +339,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES if (cpu_stepcounter == cpu_sequence[cpu_step]) { cpu_step++; - if(cpu_step == 5) cpu_step=0; + if (cpu_step == 5) cpu_step = 0; cpu_stepcounter = 0; @@ -350,10 +353,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES sprdma_countdown--; if (sprdma_countdown == 0) { - if (cpu.TotalExecutedCycles%2==0) + if (cpu.TotalExecutedCycles % 2 == 0) { cpu_deadcounter = 2; - } else + } + else { cpu_deadcounter = 1; } @@ -364,29 +368,34 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES } } - if (oam_dma_exec && apu.dmc_dma_countdown !=1 && !dmc_realign) + if (oam_dma_exec && apu.dmc_dma_countdown != 1 && !dmc_realign) { - if (cpu_deadcounter==0) + if (cpu_deadcounter == 0) { - - if (oam_dma_index%2==0) { + + if (oam_dma_index % 2 == 0) + { oam_dma_byte = ReadMemory(oam_dma_addr); oam_dma_addr++; - } else + } + else { WriteMemory(0x2004, oam_dma_byte); } oam_dma_index++; if (oam_dma_index == 512) oam_dma_exec = false; - } else + } + else { cpu_deadcounter--; } - } else if (apu.dmc_dma_countdown==1) + } + else if (apu.dmc_dma_countdown == 1) { dmc_realign = true; - } else if (dmc_realign) + } + else if (dmc_realign) { dmc_realign = false; } @@ -394,17 +403,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES // OAM DMA end ///////////////////////////// - + ///////////////////////////// // dmc dma start ///////////////////////////// - if (apu.dmc_dma_countdown>0) + if (apu.dmc_dma_countdown > 0) { cpu.RDY = false; dmc_dma_exec = true; apu.dmc_dma_countdown--; - if (apu.dmc_dma_countdown==0) + if (apu.dmc_dma_countdown == 0) { apu.RunDMCFetch(); dmc_dma_exec = false; @@ -421,14 +430,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES if (cpu.RDY && !IRQ_delay) { cpu.IRQ = _irq_apu || Board.IRQSignal; - } else if (special_case_delay || apu.dmc_dma_countdown==3) + } + else if (special_case_delay || apu.dmc_dma_countdown == 3) { cpu.IRQ = _irq_apu || Board.IRQSignal; special_case_delay = false; } - - cpu.ExecuteOne(); + + cpu.ExecuteOne(); apu.RunOne(false); if (ppu.double_2007_read > 0) @@ -445,11 +455,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES cpu.RDY = true; IRQ_delay = true; } - + ppu.ppu_open_bus_decay(0); - + Board.ClockCPU(); ppu.PostCpuInstructionOne(); } @@ -463,15 +473,30 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES byte ret_spec; switch (addr) { - case 0x4000: case 0x4001: case 0x4002: case 0x4003: - case 0x4004: case 0x4005: case 0x4006: case 0x4007: - case 0x4008: case 0x4009: case 0x400A: case 0x400B: - case 0x400C: case 0x400D: case 0x400E: case 0x400F: - case 0x4010: case 0x4011: case 0x4012: case 0x4013: + case 0x4000: + case 0x4001: + case 0x4002: + case 0x4003: + case 0x4004: + case 0x4005: + case 0x4006: + case 0x4007: + case 0x4008: + case 0x4009: + case 0x400A: + case 0x400B: + case 0x400C: + case 0x400D: + case 0x400E: + case 0x400F: + case 0x4010: + case 0x4011: + case 0x4012: + case 0x4013: return DB; - //return apu.ReadReg(addr); + //return apu.ReadReg(addr); case 0x4014: /*OAM DMA*/ break; - case 0x4015: return (byte)((byte)(apu.ReadReg(addr) & 0xDF) + (byte)(DB&0x20)); + case 0x4015: return (byte)((byte)(apu.ReadReg(addr) & 0xDF) + (byte)(DB & 0x20)); case 0x4016: { // special hardware glitch case @@ -481,11 +506,21 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES ret_spec = read_joyport(addr); do_the_reread = false; } - return ret_spec; + return ret_spec; } case 0x4017: - return read_joyport(addr); + { + if (_iskeyboard) + { + // eventually this will be the keyboard function, but for now it is a place holder (no keys pressed) + return 0x1E; + } + else + { + return read_joyport(addr); + } + } default: //Console.WriteLine("read register: {0:x4}", addr); break; @@ -498,14 +533,29 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { switch (addr) { - case 0x4000: case 0x4001: case 0x4002: case 0x4003: - case 0x4004: case 0x4005: case 0x4006: case 0x4007: - case 0x4008: case 0x4009: case 0x400A: case 0x400B: - case 0x400C: case 0x400D: case 0x400E: case 0x400F: - case 0x4010: case 0x4011: case 0x4012: case 0x4013: + case 0x4000: + case 0x4001: + case 0x4002: + case 0x4003: + case 0x4004: + case 0x4005: + case 0x4006: + case 0x4007: + case 0x4008: + case 0x4009: + case 0x400A: + case 0x400B: + case 0x400C: + case 0x400D: + case 0x400E: + case 0x400F: + case 0x4010: + case 0x4011: + case 0x4012: + case 0x4013: return apu.PeekReg(addr); case 0x4014: /*OAM DMA*/ break; - case 0x4015: return apu.PeekReg(addr); + case 0x4015: return apu.PeekReg(addr); case 0x4016: case 0x4017: return peek_joyport(addr); @@ -521,17 +571,39 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { switch (addr) { - case 0x4000: case 0x4001: case 0x4002: case 0x4003: - case 0x4004: case 0x4005: case 0x4006: case 0x4007: - case 0x4008: case 0x4009: case 0x400A: case 0x400B: - case 0x400C: case 0x400D: case 0x400E: case 0x400F: - case 0x4010: case 0x4011: case 0x4012: case 0x4013: + case 0x4000: + case 0x4001: + case 0x4002: + case 0x4003: + case 0x4004: + case 0x4005: + case 0x4006: + case 0x4007: + case 0x4008: + case 0x4009: + case 0x400A: + case 0x400B: + case 0x400C: + case 0x400D: + case 0x400E: + case 0x400F: + case 0x4010: + case 0x4011: + case 0x4012: + case 0x4013: apu.WriteReg(addr, val); break; case 0x4014: Exec_OAMDma(val); break; case 0x4015: apu.WriteReg(addr, val); break; case 0x4016: - write_joyport(val); + if (_iskeyboard) + { + // eventually keyboard emulation will go here + } + else + { + write_joyport(val); + } break; case 0x4017: apu.WriteReg(addr, val); break; default: @@ -551,10 +623,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { InputCallbacks.Call(); lagged = false; - byte ret = addr == 0x4016 ? ControllerDeck.ReadA(Controller) : ControllerDeck.ReadB(Controller); - ret &= 0x1f; - ret |= (byte)(0xe0 & DB); - return ret; + byte ret = addr == 0x4016 ? ControllerDeck.ReadA(Controller) : ControllerDeck.ReadB(Controller); + ret &= 0x1f; + ret |= (byte)(0xe0 & DB); + return ret; } byte peek_joyport(int addr) @@ -682,7 +754,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public byte ReadMemory(ushort addr) { byte ret; - + if (addr >= 0x8000) { ret = Board.ReadPRG(addr - 0x8000); //easy optimization, since rom reads are so common, move this up (reordering the rest of these elseifs is not easy) @@ -711,7 +783,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { ret = Board.ReadWRAM(addr - 0x6000); } - + //handle breakpoints and stuff. //the idea is that each core can implement its own watch class on an address which will track all the different kinds of monitors and breakpoints and etc. //but since freeze is a common case, it was implemented through its own mechanisms @@ -755,7 +827,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES } else if (addr < 0x4000) { - Board.WriteReg2xxx(addr,value); + Board.WriteReg2xxx(addr, value); } else if (addr < 0x4020) {