From 8b9968da601d7d99db1a25b3e471d16d253591ba Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sun, 17 Nov 2019 22:29:17 -0500 Subject: [PATCH] O2Hawk: more groundwork --- .../BizHawk.Emulation.Cores.csproj | 1 - .../CPUs/Intel8048/Execute.cs | 36 +-- .../CPUs/Intel8048/I8048.cs | 146 +++++---- .../CPUs/Intel8048/OP_Tables.cs | 82 +++-- .../CPUs/Intel8048/Registers.cs | 4 + .../Consoles/Magnavox/Odyssey2/Audio.cs | 160 ++++------ .../Magnavox/Odyssey2/HW_Registers.cs | 291 ------------------ .../Magnavox/Odyssey2/O2Hawk.IEmulator.cs | 26 +- .../Magnavox/Odyssey2/O2Hawk.ISettable.cs | 27 -- .../Magnavox/Odyssey2/O2Hawk.IStatable.cs | 2 - .../Consoles/Magnavox/Odyssey2/O2Hawk.cs | 3 +- .../Magnavox/Odyssey2/O2HawkControllerDeck.cs | 23 +- .../Magnavox/Odyssey2/O2HawkControllers.cs | 127 +------- .../Consoles/Magnavox/Odyssey2/PPU.cs | 229 +++++--------- 14 files changed, 310 insertions(+), 847 deletions(-) delete mode 100644 BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/HW_Registers.cs diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 0e551be12f..b12cbd8090 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -735,7 +735,6 @@ - diff --git a/BizHawk.Emulation.Cores/CPUs/Intel8048/Execute.cs b/BizHawk.Emulation.Cores/CPUs/Intel8048/Execute.cs index 5b8c2c56a3..4cddf8f0a3 100644 --- a/BizHawk.Emulation.Cores/CPUs/Intel8048/Execute.cs +++ b/BizHawk.Emulation.Cores/CPUs/Intel8048/Execute.cs @@ -39,8 +39,8 @@ namespace BizHawk.Emulation.Common.Components.I8048 case 0x0D: MOV_A_P4(5); break; // MOV A,P5 case 0x0E: MOV_A_P4(6); break; // MOV A,P6 case 0x0F: MOV_A_P4(7); break; // MOV A,P7 - case 0x10: OP_A_R(INC_RAM, R0); break; // INC #,@R0 - case 0x11: OP_A_R(INC_RAM, R1); break; // INC #,@R1 + case 0x10: OP_IR(INC_RAM, R0); break; // INC @R0 + case 0x11: OP_IR(INC_RAM, R1); break; // INC @R1 case 0x12: JPB(0); break; // JPB 0 case 0x13: OP_A_DIR(ADC8); break; // ADC A,# case 0x14: CALL(0); break; // CALL @@ -55,8 +55,8 @@ namespace BizHawk.Emulation.Common.Components.I8048 case 0x1D: OP_R_IMP(INC8, R5); break; // INC R5 case 0x1E: OP_R_IMP(INC8, R6); break; // INC R6 case 0x1F: OP_R_IMP(INC8, R7); break; // INC R7 - case 0x20: OP_A_R(XCH_RAM, R0); break; // XCH A,@R0 - case 0x21: OP_A_R(XCH_RAM, R1); break; // XCH A,@R1 + case 0x20: OP_IR(XCH_RAM, R0); break; // XCH A,@R0 + case 0x21: OP_IR(XCH_RAM, R1); break; // XCH A,@R1 case 0x22: ILLEGAL(); break; // ILLEGAL case 0x23: OP_A_DIR(MOV); break; // MOV A,# case 0x24: JP_2k(1); break; // JP 2K 1 @@ -71,8 +71,8 @@ namespace BizHawk.Emulation.Common.Components.I8048 case 0x2D: OP_A_R(XCH, R5); break; // XCH A,R5 case 0x2E: OP_A_R(XCH, R6); break; // XCH A,R6 case 0x2F: OP_A_R(XCH, R7); break; // XCH A,R7 - case 0x30: OP_A_R(XCHD_RAM, R0); break; // XCHD A,@R0 - case 0x31: OP_A_R(XCHD_RAM, R1); break; // XCHD A,@R1 + case 0x30: OP_IR(XCHD_RAM, R0); break; // XCHD A,@R0 + case 0x31: OP_IR(XCHD_RAM, R1); break; // XCHD A,@R1 case 0x32: JPB(1); break; // JPB 1 case 0x33: ILLEGAL(); break; // ILLEGAL case 0x34: CALL(1); break; // CALL @@ -87,8 +87,8 @@ namespace BizHawk.Emulation.Common.Components.I8048 case 0x3D: MOV_P4_A(5); break; // MOV P5,A case 0x3E: MOV_P4_A(6); break; // MOV P6,A case 0x3F: MOV_P4_A(7); break; // MOV P7,A - case 0x40: OP_A_R(OR8RAM, R0); break; // OR A,@R0 - case 0x41: OP_A_R(OR8RAM, R1); break; // OR A,@R1 + case 0x40: OP_A_IR(OR8, R0); break; // OR A,@R0 + case 0x41: OP_A_IR(OR8, R1); break; // OR A,@R1 case 0x42: MOV_R(A, TIM); break; // MOV A,TIM case 0x43: OP_A_DIR(OR8); break; // OR A,# case 0x44: JP_2k(2); break; // JP 2K 2 @@ -103,8 +103,8 @@ namespace BizHawk.Emulation.Common.Components.I8048 case 0x4D: OP_A_R(OR8, R5); break; // OR A,R5 case 0x4E: OP_A_R(OR8, R6); break; // OR A,R6 case 0x4F: OP_A_R(OR8, R7); break; // OR A,R7 - case 0x50: OP_A_R(AND8RAM, R0); break; // AND A,@R0 - case 0x51: OP_A_R(AND8RAM, R1); break; // AND A,@R1 + case 0x50: OP_A_IR(AND8, R0); break; // AND A,@R0 + case 0x51: OP_A_IR(AND8, R1); break; // AND A,@R1 case 0x52: JPB(2); break; // JPB 2 case 0x53: OP_A_DIR(AND8); break; // AND A,# case 0x54: CALL(2); break; // CALL @@ -119,8 +119,8 @@ namespace BizHawk.Emulation.Common.Components.I8048 case 0x5D: OP_A_R(AND8, R5); break; // AND A,R5 case 0x5E: OP_A_R(AND8, R6); break; // AND A,R6 case 0x5F: OP_A_R(AND8, R7); break; // AND A,R7 - case 0x60: OP_A_R(ADD8RAM, R0); break; // ADD A,@R0 - case 0x61: OP_A_R(ADD8RAM, R1); break; // ADD A,@R1 + case 0x60: OP_A_IR(ADD8, R0); break; // ADD A,@R0 + case 0x61: OP_A_IR(ADD8, R1); break; // ADD A,@R1 case 0x62: MOV_R(TIM, A); break; // MOV TIM,A case 0x63: ILLEGAL(); break; // ILLEGAL case 0x64: JP_2k(3); break; // JP 2K 3 @@ -135,8 +135,8 @@ namespace BizHawk.Emulation.Common.Components.I8048 case 0x6D: OP_A_R(ADD8, R5); break; // ADD A,R5 case 0x6E: OP_A_R(ADD8, R6); break; // ADD A,R6 case 0x6F: OP_A_R(ADD8, R7); break; // ADD A,R7 - case 0x70: OP_A_R(ADC8RAM, R0); break; // ADC A,@R0 - case 0x71: OP_A_R(ADC8RAM, R1); break; // ADC A,@R1 + case 0x70: OP_A_IR(ADC8, R0); break; // ADC A,@R0 + case 0x71: OP_A_IR(ADC8, R1); break; // ADC A,@R1 case 0x72: JPB(3); break; // JPB 3 case 0x73: ILLEGAL(); break; // ILLEGAL case 0x74: CALL(3); break; // CALL @@ -231,8 +231,8 @@ namespace BizHawk.Emulation.Common.Components.I8048 case 0xCD: OP_R_IMP(DEC8, R5); break; // DEC R5 case 0xCE: OP_R_IMP(DEC8, R6); break; // DEC R6 case 0xCF: OP_R_IMP(DEC8, R7); break; // DEC R7 - case 0xD0: OP_A_R(XOR8RAM, R0); break; // XOR A,@R0 - case 0xD1: OP_A_R(XOR8RAM, R1); break; // XOR A,@R1 + case 0xD0: OP_A_IR(XOR8, R0); break; // XOR A,@R0 + case 0xD1: OP_A_IR(XOR8, R1); break; // XOR A,@R1 case 0xD2: JPB(6); break; // JPB 6 case 0xD3: OP_A_DIR(XOR8); break; // XOR A,# case 0xD4: CALL(6); break; // CALL @@ -263,8 +263,8 @@ namespace BizHawk.Emulation.Common.Components.I8048 case 0xED: DJNZ(R5); break; // DJNZ R5 case 0xEE: DJNZ(R6); break; // DJNZ R6 case 0xEF: DJNZ(R7); break; // DJNZ R7 - case 0xF0: OP_A_R(MOV_RAM, R0); break; // MOV A,@R0 - case 0xF1: OP_A_R(MOV_RAM, R1); break; // MOV A,@R1 + case 0xF0: OP_A_IR(MOV, R0); break; // MOV A,@R0 + case 0xF1: OP_A_IR(MOV, R1); break; // MOV A,@R1 case 0xF2: JPB(7); break; // JPB 7 case 0xF3: ILLEGAL(); break; // ILLEGAL case 0xF4: CALL(7); break; // CALL diff --git a/BizHawk.Emulation.Cores/CPUs/Intel8048/I8048.cs b/BizHawk.Emulation.Cores/CPUs/Intel8048/I8048.cs index 5c2be40a23..092dd3c63e 100644 --- a/BizHawk.Emulation.Cores/CPUs/Intel8048/I8048.cs +++ b/BizHawk.Emulation.Cores/CPUs/Intel8048/I8048.cs @@ -13,11 +13,10 @@ namespace BizHawk.Emulation.Common.Components.I8048 public const ushort RD = 2; public const ushort WR = 3; public const ushort TR = 4; - public const ushort ADD16BR = 5; + public const ushort INC11 = 5; public const ushort ADD8 = 6; - public const ushort ADD8RAM = 7; + public const ushort CMP8 = 7; public const ushort ADC8 = 8; - public const ushort ADC8RAM = 9; public const ushort INC16 = 10; public const ushort INC8 = 11; public const ushort INCA = 12; @@ -35,55 +34,51 @@ namespace BizHawk.Emulation.Common.Components.I8048 public const ushort CM1 = 24; public const ushort DA = 25; public const ushort AND8 = 26; - public const ushort AND8RAM = 27; - public const ushort XOR8 = 28; - public const ushort XOR8RAM = 29; - public const ushort OR8 = 30; - public const ushort OR8RAM = 31; - public const ushort ASL = 32; - public const ushort ASR = 33; - public const ushort LSR = 34; - public const ushort BIT = 35; - public const ushort RD_INC = 36; - public const ushort SET_ADDR = 37; - public const ushort NEG = 38; - public const ushort TST = 39; - public const ushort CLRA = 40; - public const ushort CLC = 41; - public const ushort CL0 = 42; - public const ushort CL1 = 43; - public const ushort EI = 44; - public const ushort EN = 45; - public const ushort DI = 46; - public const ushort DN = 47; - public const ushort ADD8BR = 49; - public const ushort ABX = 50; - public const ushort JPE = 51; - public const ushort MSK = 52; - public const ushort CMP8 = 53; - public const ushort SUB16 = 54; - public const ushort ADD16 = 55; - public const ushort CMP16 = 56; - public const ushort CMP16D = 57; - public const ushort CLK_OUT = 64; - public const ushort IN = 65; - public const ushort OUT = 66; - public const ushort XCH = 67; - public const ushort XCH_RAM = 68; - public const ushort XCHD_RAM = 69; - public const ushort SEL_MB0 = 70; - public const ushort SEL_MB1 = 71; - public const ushort SEL_RB0 = 72; - public const ushort SEL_RB1 = 73; - public const ushort INC_RAM = 74; - public const ushort RES_TF = 75; - public const ushort MOV = 76; - public const ushort MOV_RAM = 77; - public const ushort MOVT = 78; - public const ushort MOVT_RAM = 79; - public const ushort ST_CNT = 80; - public const ushort STP_CNT = 81; - public const ushort ST_T = 82; + public const ushort XOR8 = 27; + public const ushort OR8 = 28; + public const ushort ASL = 29; + public const ushort ASR = 30; + public const ushort LSR = 31; + public const ushort BIT = 32; + public const ushort RD_INC = 33; + public const ushort SET_ADDR = 34; + public const ushort TST = 35; + public const ushort CLRA = 36; + public const ushort CLC = 37; + public const ushort CL0 = 38; + public const ushort CL1 = 39; + public const ushort EI = 40; + public const ushort EN = 41; + public const ushort DI = 42; + public const ushort DN = 43; + public const ushort ADD8BR = 44; + public const ushort ABX = 45; + public const ushort JPE = 46; + public const ushort MSK = 47; + public const ushort SUB16 = 48; + public const ushort ADD16 = 49; + public const ushort CMP16 = 50; + public const ushort CMP16D = 51; + public const ushort CLK_OUT = 52; + public const ushort IN = 53; + public const ushort OUT = 54; + public const ushort XCH = 55; + public const ushort XCH_RAM = 56; + public const ushort XCHD_RAM = 57; + public const ushort SEL_MB0 = 58; + public const ushort SEL_MB1 = 59; + public const ushort SEL_RB0 = 60; + public const ushort SEL_RB1 = 61; + public const ushort INC_RAM = 62; + public const ushort RES_TF = 63; + public const ushort MOV = 64; + public const ushort MOVT = 65; + public const ushort MOVT_RAM = 66; + public const ushort ST_CNT = 67; + public const ushort STP_CNT = 68; + public const ushort ST_T = 69; + public const ushort SET_ADDR_8 = 70; + public const ushort MEM_ALU = 71; public I8048() { @@ -188,13 +183,10 @@ namespace BizHawk.Emulation.Common.Components.I8048 break; case SET_ADDR: reg_d_ad = cur_instr[instr_pntr++]; - reg_h_ad = cur_instr[instr_pntr++]; reg_l_ad = cur_instr[instr_pntr++]; + reg_h_ad = cur_instr[instr_pntr++]; // direct value - // Console.WriteLine(reg_d_ad + " " + reg_h_ad + " " + reg_l_ad); - // Console.WriteLine(Regs[reg_d_ad] + " " + Regs[reg_h_ad] + " " + Regs[reg_l_ad]); - - Regs[reg_d_ad] = (ushort)((Regs[reg_h_ad] << 8) | Regs[reg_l_ad]); + Regs[reg_d_ad] = (ushort)(MB | reg_h_ad | Regs[reg_l_ad]); break; case TST: TST_Func(cur_instr[instr_pntr++]); @@ -211,9 +203,6 @@ namespace BizHawk.Emulation.Common.Components.I8048 case CL1: F1 = false; break; - case ADD16BR: - ADD16BR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); - break; case ADD8BR: ADD8BR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; @@ -226,6 +215,10 @@ namespace BizHawk.Emulation.Common.Components.I8048 case CMP8: CMP8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; + case INC11: + reg_d_ad = cur_instr[instr_pntr++]; + Regs[reg_d_ad] = (ushort)(((Regs[reg_d_ad] + 1) & 0x7FF) | MB); + break; case INC16: INC16_Func(cur_instr[instr_pntr++]); break; @@ -298,16 +291,27 @@ namespace BizHawk.Emulation.Common.Components.I8048 Regs[cur_instr[instr_pntr++]] = Regs[ALU]; break; case XCH_RAM: + reg_d_ad = cur_instr[instr_pntr++]; + reg_d_ad = (ushort)(Regs[reg_d_ad] & 0x3F); + Regs[ALU] = Regs[reg_d_ad]; + Regs[reg_d_ad] = Regs[A]; + Regs[A] = Regs[ALU]; break; case XCHD_RAM: + reg_d_ad = cur_instr[instr_pntr++]; + reg_d_ad = (ushort)(Regs[reg_d_ad] & 0x3F); + + Regs[ALU] = Regs[reg_d_ad]; + Regs[reg_d_ad] = (ushort)((Regs[reg_d_ad] & 0xF0) | (Regs[A] & 0xF)); + Regs[A] = (ushort)((Regs[A] & 0xF0) | (Regs[ALU] & 0xF)); break; case SEL_MB0: - + MB = 0; break; case SEL_MB1: - + MB = 1 << 11; break; case SEL_RB0: RB = 0; @@ -316,16 +320,15 @@ namespace BizHawk.Emulation.Common.Components.I8048 RB = 24; break; case INC_RAM: - + reg_d_ad = cur_instr[instr_pntr++]; + reg_d_ad = (ushort)(Regs[reg_d_ad] & 0x3F); + Regs[reg_d_ad] = (ushort)((Regs[reg_d_ad] + 1) & 0xFF); break; case RES_TF: break; case MOV: Regs[cur_instr[instr_pntr++]] = Regs[cur_instr[instr_pntr++]]; - break; - case MOV_RAM: - break; case MOVT: @@ -354,7 +357,14 @@ namespace BizHawk.Emulation.Common.Components.I8048 case DECA: DEC8_Func(A); break; - + case SET_ADDR_8: + reg_d_ad = cur_instr[instr_pntr++]; + Regs[reg_d_ad] &= 0xFF00; + Regs[reg_d_ad] |= Regs[cur_instr[instr_pntr++]]; + break; + case MEM_ALU: + Regs[ALU] = Regs[(ushort)(Regs[cur_instr[instr_pntr++]] & 0x3F)]; + break; } if (++irq_pntr == IRQS) @@ -466,7 +476,7 @@ namespace BizHawk.Emulation.Common.Components.I8048 ser.Sync(nameof(RB), ref RB); ser.Sync(nameof(RAM_ptr), ref RAM_ptr); - + ser.Sync(nameof(MB), ref MB); ser.Sync(nameof(Regs), ref Regs, false); ser.Sync(nameof(F1), ref F1); diff --git a/BizHawk.Emulation.Cores/CPUs/Intel8048/OP_Tables.cs b/BizHawk.Emulation.Cores/CPUs/Intel8048/OP_Tables.cs index 84f2469304..2e443e1180 100644 --- a/BizHawk.Emulation.Cores/CPUs/Intel8048/OP_Tables.cs +++ b/BizHawk.Emulation.Cores/CPUs/Intel8048/OP_Tables.cs @@ -48,6 +48,26 @@ namespace BizHawk.Emulation.Common.Components.I8048 IRQS = 4; } + public void OP_IR(ushort oper, ushort reg) + { + PopulateCURINSTR(IDLE, + IDLE, + IDLE, + oper, (ushort)(reg + RB)); + + IRQS = 4; + } + + public void OP_A_IR(ushort oper, ushort reg) + { + PopulateCURINSTR(IDLE, + IDLE, + MEM_ALU, (ushort)(reg + RB), + oper, A, ALU); + + IRQS = 4; + } + public void IN_OUT_A(ushort oper, ushort port) { PopulateCURINSTR(IDLE, @@ -68,21 +88,6 @@ namespace BizHawk.Emulation.Common.Components.I8048 IRQS = 4; } - public void JP_A() - { - PopulateCURINSTR(IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - IDLE); - - IRQS = 9; - } - public void IN_OUT_BUS(ushort oper) { PopulateCURINSTR(IDLE, @@ -239,7 +244,7 @@ namespace BizHawk.Emulation.Common.Components.I8048 IDLE, IDLE, RD, ALU, PC, - INC16, PC, + INC11, PC, IDLE, IDLE, IDLE, @@ -254,7 +259,7 @@ namespace BizHawk.Emulation.Common.Components.I8048 IDLE, IDLE, RD, ALU, PC, - INC16, PC, + INC11, PC, IDLE, IDLE, IDLE, @@ -269,7 +274,7 @@ namespace BizHawk.Emulation.Common.Components.I8048 IDLE, IDLE, RD, ALU, PC, - INC16, PC, + INC11, PC, IDLE, IDLE, IDLE, @@ -340,6 +345,21 @@ namespace BizHawk.Emulation.Common.Components.I8048 IRQS = 9; } + public void JP_A() + { + PopulateCURINSTR(IDLE, + IDLE, + IDLE, + MEM_ALU, A, + IDLE, + IDLE, + IDLE, + IDLE, + SET_ADDR_8, PC, ALU); + + IRQS = 9; + } + public void JPB(ushort Tebit) { if (Regs[A].Bit(Tebit)) @@ -347,20 +367,20 @@ namespace BizHawk.Emulation.Common.Components.I8048 PopulateCURINSTR(IDLE, IDLE, IDLE, + RD, ALU, PC, + INC11, PC, IDLE, IDLE, IDLE, - IDLE, - IDLE, - IDLE); + SET_ADDR_8, PC, ALU); } else { PopulateCURINSTR(IDLE, IDLE, IDLE, - IDLE, - IDLE, + RD, ALU, PC, + INC11, PC, IDLE, IDLE, IDLE, @@ -377,20 +397,20 @@ namespace BizHawk.Emulation.Common.Components.I8048 PopulateCURINSTR(IDLE, IDLE, IDLE, + RD, ALU, PC, + INC11, PC, IDLE, IDLE, IDLE, - IDLE, - IDLE, - IDLE); + SET_ADDR_8, PC, ALU); } else { PopulateCURINSTR(IDLE, IDLE, IDLE, - IDLE, - IDLE, + RD, ALU, PC, + INC11, PC, SPEC, IDLE, IDLE, @@ -405,12 +425,12 @@ namespace BizHawk.Emulation.Common.Components.I8048 PopulateCURINSTR(IDLE, IDLE, IDLE, + RD, ALU, PC, + INC11, PC, IDLE, IDLE, IDLE, - IDLE, - IDLE, - IDLE); + SET_ADDR, PC, ALU, high_addr); IRQS = 9; } diff --git a/BizHawk.Emulation.Cores/CPUs/Intel8048/Registers.cs b/BizHawk.Emulation.Cores/CPUs/Intel8048/Registers.cs index abd4a81dc8..07772bb6ad 100644 --- a/BizHawk.Emulation.Cores/CPUs/Intel8048/Registers.cs +++ b/BizHawk.Emulation.Cores/CPUs/Intel8048/Registers.cs @@ -32,6 +32,10 @@ namespace BizHawk.Emulation.Common.Components.I8048 public ushort RB = 0; public ushort RAM_ptr = 0; + // high PC address bit is controlled by instruction bank + // only hanges on JMP and CALL instructions + public ushort MB = 0; + //RAM occupies registers 0-63 public const ushort PC = 64; public const ushort PSW = 65; diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/Audio.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/Audio.cs index 9a459bf8f5..e9025fb0fd 100644 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/Audio.cs +++ b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/Audio.cs @@ -7,59 +7,22 @@ using BizHawk.Common.NumberExtensions; namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk { - // Audio Emulation + // Audio Emulation (a 24 bit shift register plus a control register) public class Audio : ISoundProvider { public O2Hawk Core { get; set; } - private BlipBuffer _blip_L = new BlipBuffer(15000); - private BlipBuffer _blip_R = new BlipBuffer(15000); - - public const int NR10 = 0; - public const int NR11 = 1; - public const int NR12 = 2; - public const int NR13 = 3; - public const int NR14 = 4; - public const int NR21 = 5; - public const int NR22 = 6; - public const int NR23 = 7; - public const int NR24 = 8; - public const int NR30 = 9; - public const int NR31 = 10; - public const int NR32 = 11; - public const int NR33 = 12; - public const int NR34 = 13; - public const int NR41 = 14; - public const int NR42 = 15; - public const int NR43 = 16; - public const int NR44 = 17; - public const int NR50 = 18; - public const int NR51 = 19; - public const int NR52 = 20; - - - public byte[] Audio_Regs = new byte[21]; - - // Contol Variables - public bool AUD_CTRL_vin_L_en; - public bool AUD_CTRL_vin_R_en; - public bool AUD_CTRL_sq1_L_en; - public bool AUD_CTRL_sq2_L_en; - public bool AUD_CTRL_wave_L_en; - public bool AUD_CTRL_noise_L_en; - public bool AUD_CTRL_sq1_R_en; - public bool AUD_CTRL_sq2_R_en; - public bool AUD_CTRL_wave_R_en; - public bool AUD_CTRL_noise_R_en; - public bool AUD_CTRL_power; - public byte AUD_CTRL_vol_L; - public byte AUD_CTRL_vol_R; + private BlipBuffer _blip_C = new BlipBuffer(15000); public byte sample; + public byte shift_0, shift_1, shift_2, aud_ctrl; + public uint master_audio_clock; - public int latched_sample_L, latched_sample_R; + public int tick_cnt, output_bit; + + public int latched_sample_C; public byte ReadReg(int addr) { @@ -67,10 +30,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk switch (addr) { - case 0xFF10: ret = (byte)(Audio_Regs[NR10]); break; // NR10 (sweep) - case 0xFF11: ret = (byte)(Audio_Regs[NR11]); break; // NR11 (sound length / wave pattern duty %) - case 0xFF12: ret = (byte)(Audio_Regs[NR12]); break; // NR12 (envelope) - case 0xFF13: ret = (byte)(Audio_Regs[NR13]); break; // NR13 (freq low) + case 0xA7: ret = shift_0; break; + case 0xA8: ret = shift_1; break; + case 0xA9: ret = shift_2; break; + case 0xAA: ret = aud_ctrl; break; } return ret; @@ -78,34 +41,50 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk public void WriteReg(int addr, byte value) { + switch (addr) + { + case 0xA7: shift_0 = value; break; + case 0xA8: shift_1 = value; break; + case 0xA9: shift_2 = value; break; + case 0xAA: aud_ctrl = value; break; + } } public void tick() { + int C_final = 0; - // add up components to each channel - int L_final = 0; - int R_final = 0; - - if (AUD_CTRL_sq1_L_en) { L_final += 0; } - - - if (AUD_CTRL_sq1_R_en) { R_final += 0; } - - L_final *= (AUD_CTRL_vol_L + 1) * 40; - R_final *= (AUD_CTRL_vol_R + 1) * 40; - - if (L_final != latched_sample_L) + if (aud_ctrl.Bit(7)) { - _blip_L.AddDelta(master_audio_clock, L_final - latched_sample_L); - latched_sample_L = L_final; + tick_cnt++; + if (tick_cnt > (aud_ctrl.Bit(5) ? 455 : 1820)) + { + tick_cnt = 0; + + output_bit = (shift_0 >> 1) & 1; + + shift_0 = (byte)((shift_0 >> 1) | ((shift_1 & 1) << 3)); + shift_1 = (byte)((shift_1 >> 1) | ((shift_2 & 1) << 3)); + + if (aud_ctrl.Bit(6)) + { + shift_2 = (byte)((shift_2 >> 1) | ((output_bit) << 3)); + } + else + { + shift_0 = (byte)(shift_2 >> 1); + } + } + + C_final = output_bit; + C_final *= ((aud_ctrl & 0xF) + 1) * 40; } - if (R_final != latched_sample_R) + if (C_final != latched_sample_C) { - _blip_R.AddDelta(master_audio_clock, R_final - latched_sample_R); - latched_sample_R = R_final; + _blip_C.AddDelta(master_audio_clock, C_final - latched_sample_C); + latched_sample_C = C_final; } master_audio_clock++; @@ -121,39 +100,26 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk public void Reset() { - Audio_Regs = new byte[21]; - master_audio_clock = 0; sample = 0; - _blip_L.SetRates(4194304, 44100); - _blip_R.SetRates(4194304, 44100); + _blip_C.SetRates(4194304, 44100); } public void SyncState(Serializer ser) { - ser.Sync(nameof(Audio_Regs), ref Audio_Regs, false); - ser.Sync(nameof(master_audio_clock), ref master_audio_clock); ser.Sync(nameof(sample), ref sample); - ser.Sync(nameof(latched_sample_L), ref latched_sample_L); - ser.Sync(nameof(latched_sample_R), ref latched_sample_R); + ser.Sync(nameof(latched_sample_C), ref latched_sample_C); - ser.Sync(nameof(AUD_CTRL_vin_L_en), ref AUD_CTRL_vin_L_en); - ser.Sync(nameof(AUD_CTRL_vin_R_en), ref AUD_CTRL_vin_R_en); - ser.Sync(nameof(AUD_CTRL_sq1_L_en), ref AUD_CTRL_sq1_L_en); - ser.Sync(nameof(AUD_CTRL_sq2_L_en), ref AUD_CTRL_sq2_L_en); - ser.Sync(nameof(AUD_CTRL_wave_L_en), ref AUD_CTRL_wave_L_en); - ser.Sync(nameof(AUD_CTRL_noise_L_en), ref AUD_CTRL_noise_L_en); - ser.Sync(nameof(AUD_CTRL_sq1_R_en), ref AUD_CTRL_sq1_R_en); - ser.Sync(nameof(AUD_CTRL_sq2_R_en), ref AUD_CTRL_sq2_R_en); - ser.Sync(nameof(AUD_CTRL_wave_R_en), ref AUD_CTRL_wave_R_en); - ser.Sync(nameof(AUD_CTRL_noise_R_en), ref AUD_CTRL_noise_R_en); - ser.Sync(nameof(AUD_CTRL_power), ref AUD_CTRL_power); - ser.Sync(nameof(AUD_CTRL_vol_L), ref AUD_CTRL_vol_L); - ser.Sync(nameof(AUD_CTRL_vol_R), ref AUD_CTRL_vol_R); + ser.Sync(nameof(aud_ctrl), ref aud_ctrl); + ser.Sync(nameof(shift_0), ref shift_0); + ser.Sync(nameof(shift_1), ref shift_1); + ser.Sync(nameof(shift_2), ref shift_2); + ser.Sync(nameof(tick_cnt), ref tick_cnt); + ser.Sync(nameof(output_bit), ref output_bit); } #region audio @@ -172,17 +138,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk public void GetSamplesSync(out short[] samples, out int nsamp) { - _blip_L.EndFrame(master_audio_clock); - _blip_R.EndFrame(master_audio_clock); + _blip_C.EndFrame(master_audio_clock); - nsamp = _blip_L.SamplesAvailable(); + nsamp = _blip_C.SamplesAvailable(); samples = new short[nsamp * 2]; if (nsamp != 0) { - _blip_L.ReadSamplesLeft(samples, nsamp); - _blip_R.ReadSamplesRight(samples, nsamp); + _blip_C.ReadSamples(samples, nsamp, false); } master_audio_clock = 0; @@ -195,8 +159,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk public void DiscardSamples() { - _blip_L.Clear(); - _blip_R.Clear(); + _blip_C.Clear(); master_audio_clock = 0; } @@ -207,12 +170,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk public void DisposeSound() { - _blip_L.Clear(); - _blip_R.Clear(); - _blip_L.Dispose(); - _blip_R.Dispose(); - _blip_L = null; - _blip_R = null; + _blip_C.Clear(); + _blip_C.Dispose(); + _blip_C = null; } #endregion diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/HW_Registers.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/HW_Registers.cs deleted file mode 100644 index 3181a60936..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/HW_Registers.cs +++ /dev/null @@ -1,291 +0,0 @@ -using System; -using BizHawk.Common.NumberExtensions; - -namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk -{ - public partial class O2Hawk - { - public byte Read_Registers(int addr) - { - byte ret = 0; - - switch (addr) - { - // Read Input - case 0xFF00: - _islag = false; - ret = input_register; - break; - - // Serial data port - case 0xFF01: - ret = serialport.ReadReg(addr); - break; - - // Serial port control - case 0xFF02: - ret = serialport.ReadReg(addr); - break; - - // Interrupt flags - case 0xFF0F: - - break; - - // audio regs - case 0xFF10: - case 0xFF11: - case 0xFF12: - case 0xFF13: - case 0xFF14: - case 0xFF16: - case 0xFF17: - case 0xFF18: - case 0xFF19: - case 0xFF1A: - case 0xFF1B: - case 0xFF1C: - case 0xFF1D: - case 0xFF1E: - case 0xFF20: - case 0xFF21: - case 0xFF22: - case 0xFF23: - case 0xFF24: - case 0xFF25: - case 0xFF26: - case 0xFF30: - case 0xFF31: - case 0xFF32: - case 0xFF33: - case 0xFF34: - case 0xFF35: - case 0xFF36: - case 0xFF37: - case 0xFF38: - case 0xFF39: - case 0xFF3A: - case 0xFF3B: - case 0xFF3C: - case 0xFF3D: - case 0xFF3E: - case 0xFF3F: - ret = audio.ReadReg(addr); - break; - - // PPU Regs - case 0xFF40: - case 0xFF41: - case 0xFF42: - case 0xFF43: - case 0xFF44: - case 0xFF45: - case 0xFF46: - case 0xFF47: - case 0xFF48: - case 0xFF49: - case 0xFF4A: - case 0xFF4B: - ret = ppu.ReadReg(addr); - break; - - // Speed Control for GBC - case 0xFF4D: - - break; - - case 0xFF4F: // VBK - - break; - - // Bios control register. Not sure if it is readable - case 0xFF50: - ret = 0xFF; - break; - - // PPU Regs for GBC - case 0xFF51: - case 0xFF52: - case 0xFF53: - case 0xFF54: - case 0xFF55: - - break; - - case 0xFF56: - - break; - - case 0xFF68: - case 0xFF69: - case 0xFF6A: - case 0xFF6B: - - break; - - // Speed Control for GBC - case 0xFF70: - - break; - - case 0xFF6C: - case 0xFF72: - case 0xFF73: - case 0xFF74: - case 0xFF75: - case 0xFF76: - case 0xFF77: - - break; - - // interrupt control register - case 0xFFFF: - - break; - - default: - ret = 0xFF; - break; - - } - return ret; - } - - public void Write_Registers(int addr, byte value) - { - switch (addr) - { - // select input - case 0xFF00: - - break; - - // Serial data port - case 0xFF01: - serialport.WriteReg(addr, value); - break; - - // Serial port control - case 0xFF02: - serialport.WriteReg(addr, value); - break; - - // Interrupt flags - case 0xFF0F: - - break; - - // audio regs - case 0xFF10: - case 0xFF11: - case 0xFF12: - case 0xFF13: - case 0xFF14: - case 0xFF16: - case 0xFF17: - case 0xFF18: - case 0xFF19: - case 0xFF1A: - case 0xFF1B: - case 0xFF1C: - case 0xFF1D: - case 0xFF1E: - case 0xFF20: - case 0xFF21: - case 0xFF22: - case 0xFF23: - case 0xFF24: - case 0xFF25: - case 0xFF26: - case 0xFF30: - case 0xFF31: - case 0xFF32: - case 0xFF33: - case 0xFF34: - case 0xFF35: - case 0xFF36: - case 0xFF37: - case 0xFF38: - case 0xFF39: - case 0xFF3A: - case 0xFF3B: - case 0xFF3C: - case 0xFF3D: - case 0xFF3E: - case 0xFF3F: - audio.WriteReg(addr, value); - break; - - // PPU Regs - case 0xFF40: - case 0xFF41: - case 0xFF42: - case 0xFF43: - case 0xFF44: - case 0xFF45: - case 0xFF46: - case 0xFF47: - case 0xFF48: - case 0xFF49: - case 0xFF4A: - case 0xFF4B: - ppu.WriteReg(addr, value); - break; - - // GBC compatibility register (I think) - case 0xFF4C: - - break; - - // Speed Control for GBC - case 0xFF4D: - - break; - - // VBK - case 0xFF4F: - - break; - - // Bios control register. Writing 1 permanently disables BIOS until a power cycle occurs - case 0xFF50: - - break; - - // PPU Regs for GBC - case 0xFF51: - case 0xFF52: - case 0xFF53: - case 0xFF54: - case 0xFF55: - - break; - - case 0xFF56: - - break; - - case 0xFF68: - case 0xFF69: - case 0xFF6A: - case 0xFF6B: - //if (GBC_compat) - //{ - ppu.WriteReg(addr, value); - //} - break; - - default: - Console.Write(addr); - Console.Write(" "); - Console.WriteLine(value); - break; - } - } - - public void Register_Reset() - { - input_register = 0xCF; // not reading any input - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IEmulator.cs index c9452702a4..71c1e5d677 100644 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IEmulator.cs @@ -1,8 +1,7 @@ -using BizHawk.Common.NumberExtensions; +using System; + +using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk { @@ -13,8 +12,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; public byte controller_state; - public ushort Acc_X_state; - public ushort Acc_Y_state; public bool in_vblank_old; public bool in_vblank; public bool vblank_rise; @@ -76,10 +73,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk in_vblank_old = in_vblank; } - // turn off the screen so the image doesnt persist - // but dont turn off blank_frame yet, it still needs to be true until the next VBL - // this doesn't run for GBC, some games, ex MIB the series 2, rely on the screens persistence while off to make video look smooth. - // But some GB gams, ex Battletoads, turn off the screen for a long time from the middle of the frame, so need to be cleared. if (ppu.clear_screen) { for (int j = 0; j < frame_buffer.Length; j++) { frame_buffer[j] = (int)color_palette[0]; } @@ -126,9 +119,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk { InputCallbacks.Call(); controller_state = _controllerDeck.ReadPort1(controller); - - Acc_X_state = _controllerDeck.ReadAccX1(controller); - Acc_Y_state = _controllerDeck.ReadAccY1(controller); } public int Frame => _frame; @@ -166,17 +156,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk public void SendVideoBuffer() { - if (ppu.blank_frame) - { - for (int i = 0; i < _vidbuffer.Length; i++) - { - _vidbuffer[i] = (int)color_palette[0]; - } - } - for (int j = 0; j < frame_buffer.Length; j++) { frame_buffer[j] = _vidbuffer[j]; } - - ppu.blank_frame = false; } public int VirtualWidth => 160; diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISettable.cs index 11025b254a..36ac0802eb 100644 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISettable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISettable.cs @@ -46,33 +46,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk public class O2SyncSettings { - [JsonIgnore] - public string Port1 = O2HawkControllerDeck.DefaultControllerName; - - public enum ControllerType - { - Default, - Tilt - } - - [JsonIgnore] - private ControllerType _O2Controller; - - [DisplayName("Controller")] - [Description("Select Controller Type")] - [DefaultValue(ControllerType.Default)] - public ControllerType O2Controller - { - get { return _O2Controller; } - set - { - if (value == ControllerType.Default) { Port1 = O2HawkControllerDeck.DefaultControllerName; } - else { Port1 = "Gameboy Controller + Tilt"; } - - _O2Controller = value; - } - } - [DisplayName("Use Existing SaveRAM")] [Description("When true, existing SaveRAM will be loaded at boot up")] [DefaultValue(false)] diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IStatable.cs index 5d1f0b840f..97fdb77aa0 100644 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IStatable.cs @@ -61,8 +61,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk _controllerDeck.SyncState(ser); ser.Sync(nameof(controller_state), ref controller_state); - ser.Sync(nameof(Acc_X_state), ref Acc_X_state); - ser.Sync(nameof(Acc_Y_state), ref Acc_Y_state); ser.Sync(nameof(in_vblank), ref in_vblank); ser.Sync(nameof(in_vblank_old), ref in_vblank_old); ser.Sync(nameof(vblank_rise), ref vblank_rise); diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs index 6a3ca6b7de..0f017efd0f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs @@ -69,7 +69,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk _settings = (O2Settings)settings ?? new O2Settings(); _syncSettings = (O2SyncSettings)syncSettings ?? new O2SyncSettings(); - _controllerDeck = new O2HawkControllerDeck(_syncSettings.Port1); + _controllerDeck = new O2HawkControllerDeck("O2 Controller", "O2 Controller"); byte[] Bios = null; @@ -121,7 +121,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk RAM_Bank = 1; // RAM bank always starts as 1 (even writing zero still sets 1) - Register_Reset(); ppu.Reset(); audio.Reset(); serialport.Reset(); diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllerDeck.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllerDeck.cs index 83c92a6f2c..eb6a4bede0 100644 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllerDeck.cs +++ b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllerDeck.cs @@ -10,19 +10,26 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk { public class O2HawkControllerDeck { - public O2HawkControllerDeck(string controller1Name) + public O2HawkControllerDeck(string controller1Name, string controller2Name) { if (!ValidControllerTypes.ContainsKey(controller1Name)) { throw new InvalidOperationException("Invalid controller type: " + controller1Name); } + if (!ValidControllerTypes.ContainsKey(controller2Name)) + { + throw new InvalidOperationException("Invalid controller type: " + controller2Name); + } + Port1 = (IPort)Activator.CreateInstance(ValidControllerTypes[controller1Name], 1); + Port2 = (IPort)Activator.CreateInstance(ValidControllerTypes[controller2Name], 2); Definition = new ControllerDefinition { Name = Port1.Definition.Name, BoolButtons = Port1.Definition.BoolButtons + .Concat(Port2.Definition.BoolButtons) .ToList() }; @@ -36,14 +43,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk return Port1.Read(c); } - public ushort ReadAccX1(IController c) + public byte ReadPort2(IController c) { - return Port1.ReadAccX(c); - } - - public ushort ReadAccY1(IController c) - { - return Port1.ReadAccY(c); + return Port2.Read(c); } public ControllerDefinition Definition { get; } @@ -53,9 +55,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk ser.BeginSection(nameof(Port1)); Port1.SyncState(ser); ser.EndSection(); + ser.BeginSection(nameof(Port2)); + Port2.SyncState(ser); + ser.EndSection(); } - private readonly IPort Port1; + private readonly IPort Port1, Port2; private static Dictionary _controllerTypes; diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllers.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllers.cs index 8af8abcdd9..68c5759d8e 100644 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllers.cs +++ b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllers.cs @@ -15,10 +15,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk { byte Read(IController c); - ushort ReadAccX(IController c); - - ushort ReadAccY(IController c); - ControllerDefinition Definition { get; } void SyncState(Serializer ser); @@ -26,7 +22,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk int PortNum { get; } } - [DisplayName("Gameboy Controller")] + [DisplayName("O2 Controller")] public class StandardControls : IPort { public StandardControls(int portNum) @@ -34,7 +30,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk PortNum = portNum; Definition = new ControllerDefinition { - Name = "Gameboy Controller H", + Name = "O2 Joystick", BoolButtons = BaseDefinition .Select(b => "P" + PortNum + " " + b) .ToList() @@ -85,16 +81,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk return result; } - public ushort ReadAccX(IController c) - { - return 0; - } - - public ushort ReadAccY(IController c) - { - return 0; - } - private static readonly string[] BaseDefinition = { "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "Power" @@ -105,113 +91,4 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk //nothing } } - - [DisplayName("Gameboy Controller + Tilt")] - public class StandardTilt : IPort - { - public StandardTilt(int portNum) - { - PortNum = portNum; - Definition = new ControllerDefinition - { - Name = "Gameboy Controller + Tilt", - BoolButtons = BaseDefinition - .Select(b => "P" + PortNum + " " + b) - .ToList(), - FloatControls = { "P" + PortNum + " Tilt X", "P" + PortNum + " Tilt Y" }, - FloatRanges = { new[] { -45.0f, 0, 45.0f }, new[] { -45.0f, 0, 45.0f } } - }; - } - - public int PortNum { get; } - - public float theta, phi, theta_prev, phi_prev; - - public ControllerDefinition Definition { get; } - - public byte Read(IController c) - { - byte result = 0xFF; - - if (c.IsPressed(Definition.BoolButtons[0])) - { - result -= 4; - } - if (c.IsPressed(Definition.BoolButtons[1])) - { - result -= 8; - } - if (c.IsPressed(Definition.BoolButtons[2])) - { - result -= 2; - } - if (c.IsPressed(Definition.BoolButtons[3])) - { - result -= 1; - } - if (c.IsPressed(Definition.BoolButtons[4])) - { - result -= 128; - } - if (c.IsPressed(Definition.BoolButtons[5])) - { - result -= 64; - } - if (c.IsPressed(Definition.BoolButtons[6])) - { - result -= 32; - } - if (c.IsPressed(Definition.BoolButtons[7])) - { - result -= 16; - } - - return result; - } - - // acc x is the result of rotating around body y AFTER rotating around body x - // therefore this control scheme gives decreasing sensitivity in X as Y rotation inscreases - public ushort ReadAccX(IController c) - { - theta_prev = theta; - phi_prev = phi; - - theta = (float)(c.GetFloat(Definition.FloatControls[1]) * Math.PI / 180.0); - phi = (float)(c.GetFloat(Definition.FloatControls[0]) * Math.PI / 180.0); - - float temp = (float)(Math.Cos(theta) * Math.Sin(phi)); - - // here we add in rates of change parameters. - // a typical rate of change for a fast rotation is guessed at 0.5 rad / frame - // since rotations about X have less of a moment arm compared to by, we take 1/5 of the effect as a baseline - float temp2 = (float)((phi - phi_prev) / 0.5 * 25); - - return (ushort)(0x81D0 - Math.Floor(temp * 125) - temp2); - } - - // acc y is just the sine of the angle - // we assume that ReadAccX is called first, which updates the the states - public ushort ReadAccY(IController c) - { - float temp = (float)Math.Sin(theta); - - // here we add in rates of change parameters. - // a typical rate of change for a fast rotation is guessed at 0.5 rad / frame - // further it will be assumed that the resulting acceleration is roughly eqvuivalent to gravity - float temp2 = (float)((theta - theta_prev)/0.5 * 125); - - return (ushort)(0x81D0 - Math.Floor(temp * 125) + temp2); - } - - private static readonly string[] BaseDefinition = - { - "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "Power" - }; - - public void SyncState(Serializer ser) - { - // since we need rate of change of angle, need to savestate them - ser.Sync(nameof(theta), ref theta); - } - } } \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs index 9fd91d3c11..3b3d6ad2cd 100644 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs +++ b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs @@ -7,6 +7,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk { public O2Hawk Core { get; set; } + public byte[] Sprites = new byte[16]; + public byte[] Sprite_Shapes = new byte[32]; + public byte[] Foreground = new byte[48]; + public byte[] Quad_Chars = new byte[64]; + + public byte VDC_ctrl, VDC_status, VDC_collision, VDC_color; + public uint[] BG_palette = new uint[32]; public uint[] OBJ_palette = new uint[32]; @@ -33,88 +40,41 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk public int DMA_inc; public byte DMA_byte; - // state variables - public int cycle; - public bool LYC_INT; - public bool HBL_INT; - public bool VBL_INT; - public bool OAM_INT; - public bool LCD_was_off; - public bool stat_line; - public bool stat_line_old; - // OAM scan - public bool DMA_OAM_access; - public bool OAM_access_read; - public bool OAM_access_write; - public int OAM_scan_index; - public int SL_sprites_index; - public int[] SL_sprites = new int[40]; - public int write_sprite; - public bool no_scan; - // render - public bool VRAM_access_read; - public bool VRAM_access_write; - public int read_case; - public int internal_cycle; - public int y_tile; - public int y_scroll_offset; - public int x_tile; - public int x_scroll_offset; - public int tile_byte; - public int sprite_fetch_cycles; - public bool fetch_sprite; - public bool going_to_fetch; - public bool first_fetch; - public int sprite_fetch_counter; - public byte[] sprite_attr_list = new byte[160]; - public byte[] sprite_pixel_list = new byte[160]; - public byte[] sprite_present_list = new byte[160]; - public int temp_fetch; - public int tile_inc; - public bool pre_render; - public bool pre_render_2; - public byte[] tile_data = new byte[3]; - public byte[] tile_data_latch = new byte[3]; - public int latch_counter; - public bool latch_new_data; - public int render_counter; - public int render_offset; - public int pixel_counter; - public int pixel; - public byte[] sprite_data = new byte[2]; - public byte[] sprite_sel = new byte[2]; - public int sl_use_index; - public bool no_sprites; - public int[] SL_sprites_ordered = new int[40]; // (x_end, data_low, data_high, attr) - public int evaled_sprites; - public int sprite_ordered_index; - public bool blank_frame; - public bool window_latch; - public int consecutive_sprite; - public int last_eval; - - public int total_counter; - // windowing state - public int window_counter; - public bool window_pre_render; - public bool window_started; - public bool window_is_reset; - public int window_tile_inc; - public int window_y_tile; - public int window_x_tile; - public int window_y_tile_inc; - public int window_x_latch; - public int window_y_latch; - - public int hbl_countdown; - public byte ReadReg(int addr) { byte ret = 0; - switch (addr) + if (addr < 0x10) { - + ret = Sprites[addr]; + } + else if (addr < 0x40) + { + ret = Foreground[addr - 0x10]; + } + else if (addr < 0x80) + { + ret = Quad_Chars[addr - 0x40]; + } + else if (addr < 0xA0) + { + ret = Sprite_Shapes[addr - 0x80]; + } + else if (addr == 0xA0) + { + ret = VDC_ctrl; + } + else if (addr == 0xA1) + { + ret = VDC_status; + } + else if (addr == 0xA2) + { + ret = VDC_collision; + } + else + { + ret = VDC_color; } return ret; @@ -122,7 +82,38 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk public void WriteReg(int addr, byte value) { - + if (addr < 0x10) + { + Sprites[addr] = value; + } + else if (addr < 0x40) + { + Foreground[addr - 0x10] = value; + } + else if (addr < 0x80) + { + Quad_Chars[addr - 0x40] = value; + } + else if (addr < 0xA0) + { + Sprite_Shapes[addr - 0x80] = value; + } + else if (addr == 0xA0) + { + VDC_ctrl = value; + } + else if (addr == 0xA1) + { + VDC_status = value; + } + else if (addr == 0xA2) + { + VDC_collision = value; + } + else + { + VDC_color = value; + } } public void tick() @@ -238,6 +229,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk public void SyncState(Serializer ser) { + ser.Sync(nameof(Sprites), ref Sprites, false); + ser.Sync(nameof(Sprite_Shapes), ref Sprite_Shapes, false); + ser.Sync(nameof(Foreground), ref Foreground, false); + ser.Sync(nameof(Quad_Chars), ref Quad_Chars, false); + + ser.Sync(nameof(VDC_ctrl), ref VDC_ctrl); + ser.Sync(nameof(VDC_status), ref VDC_status); + ser.Sync(nameof(VDC_collision), ref VDC_collision); + ser.Sync(nameof(VDC_color), ref VDC_color); + ser.Sync(nameof(BG_palette), ref BG_palette, false); ser.Sync(nameof(OBJ_palette), ref OBJ_palette, false); ser.Sync(nameof(HDMA_active), ref HDMA_active); @@ -261,78 +262,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.O2Hawk ser.Sync(nameof(DMA_clock), ref DMA_clock); ser.Sync(nameof(DMA_inc), ref DMA_inc); ser.Sync(nameof(DMA_byte), ref DMA_byte); - - ser.Sync(nameof(cycle), ref cycle); - ser.Sync(nameof(LYC_INT), ref LYC_INT); - ser.Sync(nameof(HBL_INT), ref HBL_INT); - ser.Sync(nameof(VBL_INT), ref VBL_INT); - ser.Sync(nameof(OAM_INT), ref OAM_INT); - ser.Sync(nameof(stat_line), ref stat_line); - ser.Sync(nameof(stat_line_old), ref stat_line_old); - ser.Sync(nameof(LCD_was_off), ref LCD_was_off); - ser.Sync(nameof(OAM_scan_index), ref OAM_scan_index); - ser.Sync(nameof(SL_sprites_index), ref SL_sprites_index); - ser.Sync(nameof(SL_sprites), ref SL_sprites, false); - ser.Sync(nameof(write_sprite), ref write_sprite); - ser.Sync(nameof(no_scan), ref no_scan); - - ser.Sync(nameof(DMA_OAM_access), ref DMA_OAM_access); - ser.Sync(nameof(OAM_access_read), ref OAM_access_read); - ser.Sync(nameof(OAM_access_write), ref OAM_access_write); - ser.Sync(nameof(VRAM_access_read), ref VRAM_access_read); - ser.Sync(nameof(VRAM_access_write), ref VRAM_access_write); - - ser.Sync(nameof(read_case), ref read_case); - ser.Sync(nameof(internal_cycle), ref internal_cycle); - ser.Sync(nameof(y_tile), ref y_tile); - ser.Sync(nameof(y_scroll_offset), ref y_scroll_offset); - ser.Sync(nameof(x_tile), ref x_tile); - ser.Sync(nameof(x_scroll_offset), ref x_scroll_offset); - ser.Sync(nameof(tile_byte), ref tile_byte); - ser.Sync(nameof(sprite_fetch_cycles), ref sprite_fetch_cycles); - ser.Sync(nameof(fetch_sprite), ref fetch_sprite); - ser.Sync(nameof(going_to_fetch), ref going_to_fetch); - ser.Sync(nameof(first_fetch), ref first_fetch); - ser.Sync(nameof(sprite_fetch_counter), ref sprite_fetch_counter); - ser.Sync(nameof(sprite_attr_list), ref sprite_attr_list, false); - ser.Sync(nameof(sprite_pixel_list), ref sprite_pixel_list, false); - ser.Sync(nameof(sprite_present_list), ref sprite_present_list, false); - ser.Sync(nameof(temp_fetch), ref temp_fetch); - ser.Sync(nameof(tile_inc), ref tile_inc); - ser.Sync(nameof(pre_render), ref pre_render); - ser.Sync(nameof(pre_render_2), ref pre_render_2); - ser.Sync(nameof(tile_data), ref tile_data, false); - ser.Sync(nameof(tile_data_latch), ref tile_data_latch, false); - ser.Sync(nameof(latch_counter), ref latch_counter); - ser.Sync(nameof(latch_new_data), ref latch_new_data); - ser.Sync(nameof(render_counter), ref render_counter); - ser.Sync(nameof(render_offset), ref render_offset); - ser.Sync(nameof(pixel_counter), ref pixel_counter); - ser.Sync(nameof(pixel), ref pixel); - ser.Sync(nameof(sprite_data), ref sprite_data, false); - ser.Sync(nameof(sl_use_index), ref sl_use_index); - ser.Sync(nameof(sprite_sel), ref sprite_sel, false); - ser.Sync(nameof(no_sprites), ref no_sprites); - ser.Sync(nameof(evaled_sprites), ref evaled_sprites); - ser.Sync(nameof(SL_sprites_ordered), ref SL_sprites_ordered, false); - ser.Sync(nameof(sprite_ordered_index), ref sprite_ordered_index); - ser.Sync(nameof(blank_frame), ref blank_frame); - ser.Sync(nameof(window_latch), ref window_latch); - ser.Sync(nameof(consecutive_sprite), ref consecutive_sprite); - ser.Sync(nameof(last_eval), ref last_eval); - - ser.Sync(nameof(window_counter), ref window_counter); - ser.Sync(nameof(window_pre_render), ref window_pre_render); - ser.Sync(nameof(window_started), ref window_started); - ser.Sync(nameof(window_is_reset), ref window_is_reset); - ser.Sync(nameof(window_tile_inc), ref window_tile_inc); - ser.Sync(nameof(window_y_tile), ref window_y_tile); - ser.Sync(nameof(window_x_tile), ref window_x_tile); - ser.Sync(nameof(window_y_tile_inc), ref window_y_tile_inc); - ser.Sync(nameof(window_x_latch), ref window_x_latch); - ser.Sync(nameof(window_y_latch), ref window_y_latch); - - ser.Sync(nameof(hbl_countdown), ref hbl_countdown); } } }