diff --git a/gameboy/CMakeLists.txt b/gameboy/CMakeLists.txt index 1455bddb2489832d90af8ea22825d9decaca34e4..bab7fa2a07592e44f72fd08c9aa8da54c069d3dd 100644 --- a/gameboy/CMakeLists.txt +++ b/gameboy/CMakeLists.txt @@ -4,8 +4,7 @@ project (test C ASM) set(CMAKE_C_COMPILER arm-none-eabi-gcc) set(CMAKE_ASM_COMPILER arm-none-eabi-gcc) -# -O2 bricks the screen! -set(CMAKE_C_FLAGS "-g3 -O1 -mcpu=cortex-m0plus --specs=nosys.specs -Wl,--wrap,malloc -Wl,--wrap,calloc -Wl,--wrap,free -Wl,--wrap,vprintf -Wl,--wrap,vscanf") +set(CMAKE_C_FLAGS "-g3 -O2 -mcpu=cortex-m0plus --specs=nosys.specs -Wl,--wrap,malloc -Wl,--wrap,calloc -Wl,--wrap,free -Wl,--wrap,vprintf -Wl,--wrap,vscanf") SET(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp") file (GLOB srcs diff --git a/gameboy/CPU.c b/gameboy/CPU.c index 93f52f27bd7b1d42faca489c748f265b2accbad2..0ccfcf3198e8c361ec9dd6d3e9a3f120ba6fbe13 100644 --- a/gameboy/CPU.c +++ b/gameboy/CPU.c @@ -20,7 +20,7 @@ const uint8_t ClocksPerInstruction[] = { 12, 12, 8, 4, 0, 16, 8, 16, 12, 8, 16, 4, 0, 0, 8, 16 // F }; -uint32_t ClockCount = 0; +uint32_t cpu_clock_count = 0; uint32_t InstructionCount = 0; uint8_t Debugging = 0; @@ -58,7 +58,7 @@ uint8_t Stopped = 0; uint8_t EnableInterruptsFlag = 0; uint8_t InterruptsEnabled = 0; -void InitCPU() { +void cpu_init() { // Simulate Boot ROM reg_AF = 0x11B0; reg_BC = 0x0013; @@ -68,7 +68,6 @@ void InitCPU() { PC = 0x0100; // Setup I/O - SetByteAt (0xFF00, 0xFF); SetByteAt (0xFF04, 0xAB); SetByteAt (0xFF10, 0x80); SetByteAt (0xFF11, 0xBF); @@ -112,16 +111,16 @@ void Interrupt (uint8_t ID) { */ uint8_t reg_IF = 0; - SetBit (®_IF, ID, 1); + set_bit(®_IF, ID, 1); if (InterruptsEnabled) { uint8_t reg_IE = GetByteAt(0xFFFF); - if (GetBit (reg_IE, ID)) { // Interrupt Enabled in IE - ClockCount += 20; + if (get_bit(reg_IE, ID)) { // Interrupt Enabled in IE + cpu_clock_count += 20; InterruptsEnabled = 0; if (Halt) - ClockCount += 4; + cpu_clock_count += 4; Halt = 0; StackPush (PC); PC = 0x0040 + (ID << 3); // Jump to interrupt handler @@ -216,7 +215,7 @@ void Clock () { */ if (Halt) { - ClockCount += ClocksPerInstruction [0x00]; // Execute NOP + cpu_clock_count += ClocksPerInstruction [0x00]; // Execute NOP InstructionCount++; return; } @@ -226,15 +225,15 @@ void Clock () { } void Execute (uint8_t Instruction) { - ClockCount += ClocksPerInstruction [Instruction]; + cpu_clock_count += ClocksPerInstruction [Instruction]; InstructionCount++; //printf("0x%04x: Executing 0x%02x\n", PC - 1, Instruction); - flag_Z = GetBit (*reg_F, 7); - flag_N = GetBit (*reg_F, 6); - flag_H = GetBit (*reg_F, 5); - flag_C = GetBit (*reg_F, 4); + flag_Z = get_bit(*reg_F, 7); + flag_N = get_bit(*reg_F, 6); + flag_H = get_bit(*reg_F, 5); + flag_C = get_bit(*reg_F, 4); if (EnableInterruptsFlag) { InterruptsEnabled = 1; @@ -249,7 +248,7 @@ void Execute (uint8_t Instruction) { case 0xF3: InterruptsEnabled = 0; break; // DI case 0xFB: EnableInterruptsFlag = 1; break; // EI - Delay of one instruction case 0xCB: u8 = GetByteAt(PC++); // CB - ClockCount += 8; + cpu_clock_count += 8; switch (u8) { case 0x00: SetN (0); SetH (0); u8 = *reg_B >> 7; *reg_B <<= 1; *reg_B |= u8; SetC (u8); SetZ (*reg_B == 0); break; // RLC case 0x01: SetN (0); SetH (0); u8 = *reg_C >> 7; *reg_C <<= 1; *reg_C |= u8; SetC (u8); SetZ (*reg_C == 0); break; // RLC @@ -257,7 +256,7 @@ void Execute (uint8_t Instruction) { case 0x03: SetN (0); SetH (0); u8 = *reg_E >> 7; *reg_E <<= 1; *reg_E |= u8; SetC (u8); SetZ (*reg_E == 0); break; // RLC case 0x04: SetN (0); SetH (0); u8 = *reg_H >> 7; *reg_H <<= 1; *reg_H |= u8; SetC (u8); SetZ (*reg_H == 0); break; // RLC case 0x05: SetN (0); SetH (0); u8 = *reg_L >> 7; *reg_L <<= 1; *reg_L |= u8; SetC (u8); SetZ (*reg_L == 0); break; // RLC - case 0x06: SetN (0); SetH (0); u8 = GetM () >> 7; SetM ((GetM () << 1) | u8); SetC (u8); SetZ (GetM () == 0); ClockCount += 8; break; // RLC + case 0x06: SetN (0); SetH (0); u8 = GetM () >> 7; SetM ((GetM () << 1) | u8); SetC (u8); SetZ (GetM () == 0); cpu_clock_count += 8; break; // RLC case 0x07: SetN (0); SetH (0); u8 = *reg_A >> 7; *reg_A <<= 1; *reg_A |= u8; SetC (u8); SetZ (*reg_A == 0); break; // RLC case 0x08: SetN (0); SetH (0); u8 = *reg_B & 1; *reg_B >>= 1; *reg_B |= u8 << 7; SetC (u8); SetZ (*reg_B == 0); break; // RRC @@ -266,7 +265,7 @@ void Execute (uint8_t Instruction) { case 0x0B: SetN (0); SetH (0); u8 = *reg_E & 1; *reg_E >>= 1; *reg_E |= u8 << 7; SetC (u8); SetZ (*reg_E == 0); break; // RRC case 0x0C: SetN (0); SetH (0); u8 = *reg_H & 1; *reg_H >>= 1; *reg_H |= u8 << 7; SetC (u8); SetZ (*reg_H == 0); break; // RRC case 0x0D: SetN (0); SetH (0); u8 = *reg_L & 1; *reg_L >>= 1; *reg_L |= u8 << 7; SetC (u8); SetZ (*reg_L == 0); break; // RRC - case 0x0E: SetN (0); SetH (0); u8 = GetM () & 1; SetM ((GetM () >> 1) | (u8 << 7)); SetC (u8); SetZ (GetM () == 0); ClockCount += 8; break; // RRC + case 0x0E: SetN (0); SetH (0); u8 = GetM () & 1; SetM ((GetM () >> 1) | (u8 << 7)); SetC (u8); SetZ (GetM () == 0); cpu_clock_count += 8; break; // RRC case 0x0F: SetN (0); SetH (0); u8 = *reg_A & 1; *reg_A >>= 1; *reg_A |= u8 << 7; SetC (u8); SetZ (*reg_A == 0); break; // RRC case 0x10: SetN (0); SetH (0); u8 = *reg_B >> 7; *reg_B <<= 1; *reg_B |= flag_C; SetC (u8); SetZ (*reg_B == 0); break; // RL @@ -275,7 +274,7 @@ void Execute (uint8_t Instruction) { case 0x13: SetN (0); SetH (0); u8 = *reg_E >> 7; *reg_E <<= 1; *reg_E |= flag_C; SetC (u8); SetZ (*reg_E == 0); break; // RL case 0x14: SetN (0); SetH (0); u8 = *reg_H >> 7; *reg_H <<= 1; *reg_H |= flag_C; SetC (u8); SetZ (*reg_H == 0); break; // RL case 0x15: SetN (0); SetH (0); u8 = *reg_L >> 7; *reg_L <<= 1; *reg_L |= flag_C; SetC (u8); SetZ (*reg_L == 0); break; // RL - case 0x16: SetN (0); SetH (0); u8 = GetM () >> 7; SetM ((GetM () << 1) | flag_C); SetC (u8); SetZ (GetM () == 0); ClockCount += 8; break; // RL + case 0x16: SetN (0); SetH (0); u8 = GetM () >> 7; SetM ((GetM () << 1) | flag_C); SetC (u8); SetZ (GetM () == 0); cpu_clock_count += 8; break; // RL case 0x17: SetN (0); SetH (0); u8 = *reg_A >> 7; *reg_A <<= 1; *reg_A |= flag_C; SetC (u8); SetZ (*reg_A == 0); break; // RL case 0x18: SetN (0); SetH (0); u8 = *reg_B & 1; *reg_B >>= 1; *reg_B |= flag_C << 7; SetC (u8); SetZ (*reg_B == 0); break; // RR @@ -284,7 +283,7 @@ void Execute (uint8_t Instruction) { case 0x1B: SetN (0); SetH (0); u8 = *reg_E & 1; *reg_E >>= 1; *reg_E |= flag_C << 7; SetC (u8); SetZ (*reg_E == 0); break; // RR case 0x1C: SetN (0); SetH (0); u8 = *reg_H & 1; *reg_H >>= 1; *reg_H |= flag_C << 7; SetC (u8); SetZ (*reg_H == 0); break; // RR case 0x1D: SetN (0); SetH (0); u8 = *reg_L & 1; *reg_L >>= 1; *reg_L |= flag_C << 7; SetC (u8); SetZ (*reg_L == 0); break; // RR - case 0x1E: SetN (0); SetH (0); u8 = GetM () & 1; SetM ((GetM () >> 1) | (flag_C << 7)); SetC (u8); SetZ (GetM () == 0); ClockCount += 8; break; // RR + case 0x1E: SetN (0); SetH (0); u8 = GetM () & 1; SetM ((GetM () >> 1) | (flag_C << 7)); SetC (u8); SetZ (GetM () == 0); cpu_clock_count += 8; break; // RR case 0x1F: SetN (0); SetH (0); u8 = *reg_A & 1; *reg_A >>= 1; *reg_A |= flag_C << 7; SetC (u8); SetZ (*reg_A == 0); break; // RR case 0x20: SetN (0); SetH (0); SetC (*reg_B >> 7); *reg_B <<= 1; SetZ (*reg_B == 0); break; // SLA @@ -293,7 +292,7 @@ void Execute (uint8_t Instruction) { case 0x23: SetN (0); SetH (0); SetC (*reg_E >> 7); *reg_E <<= 1; SetZ (*reg_E == 0); break; // SLA case 0x24: SetN (0); SetH (0); SetC (*reg_H >> 7); *reg_H <<= 1; SetZ (*reg_H == 0); break; // SLA case 0x25: SetN (0); SetH (0); SetC (*reg_L >> 7); *reg_L <<= 1; SetZ (*reg_L == 0); break; // SLA - case 0x26: SetN (0); SetH (0); SetC (GetM () >> 7); SetM (GetM () << 1); SetZ (GetM () == 0); ClockCount += 8; break; // SLA + case 0x26: SetN (0); SetH (0); SetC (GetM () >> 7); SetM (GetM () << 1); SetZ (GetM () == 0); cpu_clock_count += 8; break; // SLA case 0x27: SetN (0); SetH (0); SetC (*reg_A >> 7); *reg_A <<= 1; SetZ (*reg_A == 0); break; // SLA case 0x28: SetN (0); SetH (0); u8 = *reg_B >> 7; SetC (*reg_B & 1); *reg_B >>= 1; *reg_B |= u8 << 7; SetZ (*reg_B == 0); break; // SRA @@ -302,7 +301,7 @@ void Execute (uint8_t Instruction) { case 0x2B: SetN (0); SetH (0); u8 = *reg_E >> 7; SetC (*reg_E & 1); *reg_E >>= 1; *reg_E |= u8 << 7; SetZ (*reg_E == 0); break; // SRA case 0x2C: SetN (0); SetH (0); u8 = *reg_H >> 7; SetC (*reg_H & 1); *reg_H >>= 1; *reg_H |= u8 << 7; SetZ (*reg_H == 0); break; // SRA case 0x2D: SetN (0); SetH (0); u8 = *reg_L >> 7; SetC (*reg_L & 1); *reg_L >>= 1; *reg_L |= u8 << 7; SetZ (*reg_L == 0); break; // SRA - case 0x2E: SetN (0); SetH (0); u8 = GetM () >> 7; SetC (GetM () & 1); SetM ((GetM () >> 1) | (u8 << 7)); SetZ (GetM () == 0); ClockCount += 8; break; // SRA + case 0x2E: SetN (0); SetH (0); u8 = GetM () >> 7; SetC (GetM () & 1); SetM ((GetM () >> 1) | (u8 << 7)); SetZ (GetM () == 0); cpu_clock_count += 8; break; // SRA case 0x2F: SetN (0); SetH (0); u8 = *reg_A >> 7; SetC (*reg_A & 1); *reg_A >>= 1; *reg_A |= u8 << 7; SetZ (*reg_A == 0); break; // SRA case 0x30: SetN (0); SetH (0); SetC (0); SetZ (*reg_B == 0); *reg_B = (*reg_B << 4) | (*reg_B >> 4); break; // SWAP @@ -311,7 +310,7 @@ void Execute (uint8_t Instruction) { case 0x33: SetN (0); SetH (0); SetC (0); SetZ (*reg_E == 0); *reg_E = (*reg_E << 4) | (*reg_E >> 4); break; // SWAP case 0x34: SetN (0); SetH (0); SetC (0); SetZ (*reg_H == 0); *reg_H = (*reg_H << 4) | (*reg_H >> 4); break; // SWAP case 0x35: SetN (0); SetH (0); SetC (0); SetZ (*reg_L == 0); *reg_L = (*reg_L << 4) | (*reg_L >> 4); break; // SWAP - case 0x36: SetN (0); SetH (0); SetC (0); SetZ (GetM () == 0); SetM ((GetM () << 4) | (GetM () >> 4)); ClockCount += 8; break; // SWAP + case 0x36: SetN (0); SetH (0); SetC (0); SetZ (GetM () == 0); SetM ((GetM () << 4) | (GetM () >> 4)); cpu_clock_count += 8; break; // SWAP case 0x37: SetN (0); SetH (0); SetC (0); SetZ (*reg_A == 0); *reg_A = (*reg_A << 4) | (*reg_A >> 4); break; // SWAP case 0x38: SetN (0); SetH (0); u8 = *reg_B & 1; *reg_B >>= 1; SetC (u8); SetZ (*reg_B == 0); break; // SRL @@ -320,7 +319,7 @@ void Execute (uint8_t Instruction) { case 0x3B: SetN (0); SetH (0); u8 = *reg_E & 1; *reg_E >>= 1; SetC (u8); SetZ (*reg_E == 0); break; // SRL case 0x3C: SetN (0); SetH (0); u8 = *reg_H & 1; *reg_H >>= 1; SetC (u8); SetZ (*reg_H == 0); break; // SRL case 0x3D: SetN (0); SetH (0); u8 = *reg_L & 1; *reg_L >>= 1; SetC (u8); SetZ (*reg_L == 0); break; // SRL - case 0x3E: SetN (0); SetH (0); u8 = GetM () & 1; SetM (GetM () >> 1); SetC (u8); SetZ (GetM () == 0); ClockCount += 8; break; // SRL + case 0x3E: SetN (0); SetH (0); u8 = GetM () & 1; SetM (GetM () >> 1); SetC (u8); SetZ (GetM () == 0); cpu_clock_count += 8; break; // SRL case 0x3F: SetN (0); SetH (0); u8 = *reg_A & 1; *reg_A >>= 1; SetC (u8); SetZ (*reg_A == 0); break; // SRL case 0x40: SetZ ((*reg_B & (1 << 0)) == 0); SetN (0); SetH (1); break; // BIT @@ -329,7 +328,7 @@ void Execute (uint8_t Instruction) { case 0x43: SetZ ((*reg_E & (1 << 0)) == 0); SetN (0); SetH (1); break; // BIT case 0x44: SetZ ((*reg_H & (1 << 0)) == 0); SetN (0); SetH (1); break; // BIT case 0x45: SetZ ((*reg_L & (1 << 0)) == 0); SetN (0); SetH (1); break; // BIT - case 0x46: SetZ ((GetM () & (1 << 0)) == 0); SetN (0); SetH (1); ClockCount += 8; break; // BIT + case 0x46: SetZ ((GetM () & (1 << 0)) == 0); SetN (0); SetH (1); cpu_clock_count += 8; break; // BIT case 0x47: SetZ ((*reg_A & (1 << 0)) == 0); SetN (0); SetH (1); break; // BIT case 0x48: SetZ ((*reg_B & (1 << 1)) == 0); SetN (0); SetH (1); break; // BIT @@ -338,7 +337,7 @@ void Execute (uint8_t Instruction) { case 0x4B: SetZ ((*reg_E & (1 << 1)) == 0); SetN (0); SetH (1); break; // BIT case 0x4C: SetZ ((*reg_H & (1 << 1)) == 0); SetN (0); SetH (1); break; // BIT case 0x4D: SetZ ((*reg_L & (1 << 1)) == 0); SetN (0); SetH (1); break; // BIT - case 0x4E: SetZ ((GetM () & (1 << 1)) == 0); SetN (0); SetH (1); ClockCount += 8; break; // BIT + case 0x4E: SetZ ((GetM () & (1 << 1)) == 0); SetN (0); SetH (1); cpu_clock_count += 8; break; // BIT case 0x4F: SetZ ((*reg_A & (1 << 1)) == 0); SetN (0); SetH (1); break; // BIT case 0x50: SetZ ((*reg_B & (1 << 2)) == 0); SetN (0); SetH (1); break; // BIT @@ -347,7 +346,7 @@ void Execute (uint8_t Instruction) { case 0x53: SetZ ((*reg_E & (1 << 2)) == 0); SetN (0); SetH (1); break; // BIT case 0x54: SetZ ((*reg_H & (1 << 2)) == 0); SetN (0); SetH (1); break; // BIT case 0x55: SetZ ((*reg_L & (1 << 2)) == 0); SetN (0); SetH (1); break; // BIT - case 0x56: SetZ ((GetM () & (1 << 2)) == 0); SetN (0); SetH (1); ClockCount += 8; break; // BIT + case 0x56: SetZ ((GetM () & (1 << 2)) == 0); SetN (0); SetH (1); cpu_clock_count += 8; break; // BIT case 0x57: SetZ ((*reg_A & (1 << 2)) == 0); SetN (0); SetH (1); break; // BIT case 0x58: SetZ ((*reg_B & (1 << 3)) == 0); SetN (0); SetH (1); break; // BIT @@ -356,7 +355,7 @@ void Execute (uint8_t Instruction) { case 0x5B: SetZ ((*reg_E & (1 << 3)) == 0); SetN (0); SetH (1); break; // BIT case 0x5C: SetZ ((*reg_H & (1 << 3)) == 0); SetN (0); SetH (1); break; // BIT case 0x5D: SetZ ((*reg_L & (1 << 3)) == 0); SetN (0); SetH (1); break; // BIT - case 0x5E: SetZ ((GetM () & (1 << 3)) == 0); SetN (0); SetH (1); ClockCount += 8; break; // BIT + case 0x5E: SetZ ((GetM () & (1 << 3)) == 0); SetN (0); SetH (1); cpu_clock_count += 8; break; // BIT case 0x5F: SetZ ((*reg_A & (1 << 3)) == 0); SetN (0); SetH (1); break; // BIT case 0x60: SetZ ((*reg_B & (1 << 4)) == 0); SetN (0); SetH (1); break; // BIT @@ -365,7 +364,7 @@ void Execute (uint8_t Instruction) { case 0x63: SetZ ((*reg_E & (1 << 4)) == 0); SetN (0); SetH (1); break; // BIT case 0x64: SetZ ((*reg_H & (1 << 4)) == 0); SetN (0); SetH (1); break; // BIT case 0x65: SetZ ((*reg_L & (1 << 4)) == 0); SetN (0); SetH (1); break; // BIT - case 0x66: SetZ ((GetM () & (1 << 4)) == 0); SetN (0); SetH (1); ClockCount += 8; break; // BIT + case 0x66: SetZ ((GetM () & (1 << 4)) == 0); SetN (0); SetH (1); cpu_clock_count += 8; break; // BIT case 0x67: SetZ ((*reg_A & (1 << 4)) == 0); SetN (0); SetH (1); break; // BIT case 0x68: SetZ ((*reg_B & (1 << 5)) == 0); SetN (0); SetH (1); break; // BIT @@ -374,7 +373,7 @@ void Execute (uint8_t Instruction) { case 0x6B: SetZ ((*reg_E & (1 << 5)) == 0); SetN (0); SetH (1); break; // BIT case 0x6C: SetZ ((*reg_H & (1 << 5)) == 0); SetN (0); SetH (1); break; // BIT case 0x6D: SetZ ((*reg_L & (1 << 5)) == 0); SetN (0); SetH (1); break; // BIT - case 0x6E: SetZ ((GetM () & (1 << 5)) == 0); SetN (0); SetH (1); ClockCount += 8; break; // BIT + case 0x6E: SetZ ((GetM () & (1 << 5)) == 0); SetN (0); SetH (1); cpu_clock_count += 8; break; // BIT case 0x6F: SetZ ((*reg_A & (1 << 5)) == 0); SetN (0); SetH (1); break; // BIT case 0x70: SetZ ((*reg_B & (1 << 6)) == 0); SetN (0); SetH (1); break; // BIT @@ -383,7 +382,7 @@ void Execute (uint8_t Instruction) { case 0x73: SetZ ((*reg_E & (1 << 6)) == 0); SetN (0); SetH (1); break; // BIT case 0x74: SetZ ((*reg_H & (1 << 6)) == 0); SetN (0); SetH (1); break; // BIT case 0x75: SetZ ((*reg_L & (1 << 6)) == 0); SetN (0); SetH (1); break; // BIT - case 0x76: SetZ ((GetM () & (1 << 6)) == 0); SetN (0); SetH (1); ClockCount += 8; break; // BIT + case 0x76: SetZ ((GetM () & (1 << 6)) == 0); SetN (0); SetH (1); cpu_clock_count += 8; break; // BIT case 0x77: SetZ ((*reg_A & (1 << 6)) == 0); SetN (0); SetH (1); break; // BIT case 0x78: SetZ ((*reg_B & (1 << 7)) == 0); SetN (0); SetH (1); break; // BIT @@ -392,7 +391,7 @@ void Execute (uint8_t Instruction) { case 0x7B: SetZ ((*reg_E & (1 << 7)) == 0); SetN (0); SetH (1); break; // BIT case 0x7C: SetZ ((*reg_H & (1 << 7)) == 0); SetN (0); SetH (1); break; // BIT case 0x7D: SetZ ((*reg_L & (1 << 7)) == 0); SetN (0); SetH (1); break; // BIT - case 0x7E: SetZ ((GetM () & (1 << 7)) == 0); SetN (0); SetH (1); ClockCount += 8; break; // BIT + case 0x7E: SetZ ((GetM () & (1 << 7)) == 0); SetN (0); SetH (1); cpu_clock_count += 8; break; // BIT case 0x7F: SetZ ((*reg_A & (1 << 7)) == 0); SetN (0); SetH (1); break; // BIT case 0x80: *reg_B &= 0xFF ^ (1 << 0); break; // RES @@ -401,7 +400,7 @@ void Execute (uint8_t Instruction) { case 0x83: *reg_E &= 0xFF ^ (1 << 0); break; // RES case 0x84: *reg_H &= 0xFF ^ (1 << 0); break; // RES case 0x85: *reg_L &= 0xFF ^ (1 << 0); break; // RES - case 0x86: SetM (GetM () & (0xFF ^ (1 << 0))); ClockCount += 8; break; // RES + case 0x86: SetM (GetM () & (0xFF ^ (1 << 0))); cpu_clock_count += 8; break; // RES case 0x87: *reg_A &= 0xFF ^ (1 << 0); break; // RES case 0x88: *reg_B &= 0xFF ^ (1 << 1); break; // RES @@ -410,7 +409,7 @@ void Execute (uint8_t Instruction) { case 0x8B: *reg_E &= 0xFF ^ (1 << 1); break; // RES case 0x8C: *reg_H &= 0xFF ^ (1 << 1); break; // RES case 0x8D: *reg_L &= 0xFF ^ (1 << 1); break; // RES - case 0x8E: SetM (GetM () & (0xFF ^ (1 << 1))); ClockCount += 8; break; // RES + case 0x8E: SetM (GetM () & (0xFF ^ (1 << 1))); cpu_clock_count += 8; break; // RES case 0x8F: *reg_A &= 0xFF ^ (1 << 1); break; // RES case 0x90: *reg_B &= 0xFF ^ (1 << 2); break; // RES @@ -419,7 +418,7 @@ void Execute (uint8_t Instruction) { case 0x93: *reg_E &= 0xFF ^ (1 << 2); break; // RES case 0x94: *reg_H &= 0xFF ^ (1 << 2); break; // RES case 0x95: *reg_L &= 0xFF ^ (1 << 2); break; // RES - case 0x96: SetM (GetM () & (0xFF ^ (1 << 2))); ClockCount += 8; break; // RES + case 0x96: SetM (GetM () & (0xFF ^ (1 << 2))); cpu_clock_count += 8; break; // RES case 0x97: *reg_A &= 0xFF ^ (1 << 2); break; // RES case 0x98: *reg_B &= 0xFF ^ (1 << 3); break; // RES @@ -428,7 +427,7 @@ void Execute (uint8_t Instruction) { case 0x9B: *reg_E &= 0xFF ^ (1 << 3); break; // RES case 0x9C: *reg_H &= 0xFF ^ (1 << 3); break; // RES case 0x9D: *reg_L &= 0xFF ^ (1 << 3); break; // RES - case 0x9E: SetM (GetM () & (0xFF ^ (1 << 3))); ClockCount += 8; break; // RES + case 0x9E: SetM (GetM () & (0xFF ^ (1 << 3))); cpu_clock_count += 8; break; // RES case 0x9F: *reg_A &= 0xFF ^ (1 << 3); break; // RES case 0xA0: *reg_B &= 0xFF ^ (1 << 4); break; // RES @@ -437,7 +436,7 @@ void Execute (uint8_t Instruction) { case 0xA3: *reg_E &= 0xFF ^ (1 << 4); break; // RES case 0xA4: *reg_H &= 0xFF ^ (1 << 4); break; // RES case 0xA5: *reg_L &= 0xFF ^ (1 << 4); break; // RES - case 0xA6: SetM (GetM () & (0xFF ^ (1 << 4))); ClockCount += 8; break; // RES + case 0xA6: SetM (GetM () & (0xFF ^ (1 << 4))); cpu_clock_count += 8; break; // RES case 0xA7: *reg_A &= 0xFF ^ (1 << 4); break; // RES case 0xA8: *reg_B &= 0xFF ^ (1 << 5); break; // RES @@ -446,7 +445,7 @@ void Execute (uint8_t Instruction) { case 0xAB: *reg_E &= 0xFF ^ (1 << 5); break; // RES case 0xAC: *reg_H &= 0xFF ^ (1 << 5); break; // RES case 0xAD: *reg_L &= 0xFF ^ (1 << 5); break; // RES - case 0xAE: SetM (GetM () & (0xFF ^ (1 << 5))); ClockCount += 8; break; // RES + case 0xAE: SetM (GetM () & (0xFF ^ (1 << 5))); cpu_clock_count += 8; break; // RES case 0xAF: *reg_A &= 0xFF ^ (1 << 5); break; // RES case 0xB0: *reg_B &= 0xFF ^ (1 << 6); break; // RES @@ -455,7 +454,7 @@ void Execute (uint8_t Instruction) { case 0xB3: *reg_E &= 0xFF ^ (1 << 6); break; // RES case 0xB4: *reg_H &= 0xFF ^ (1 << 6); break; // RES case 0xB5: *reg_L &= 0xFF ^ (1 << 6); break; // RES - case 0xB6: SetM (GetM () & (0xFF ^ (1 << 6))); ClockCount += 8; break; // RES + case 0xB6: SetM (GetM () & (0xFF ^ (1 << 6))); cpu_clock_count += 8; break; // RES case 0xB7: *reg_A &= 0xFF ^ (1 << 6); break; // RES case 0xB8: *reg_B &= 0xFF ^ (1 << 7); break; // RES @@ -464,7 +463,7 @@ void Execute (uint8_t Instruction) { case 0xBB: *reg_E &= 0xFF ^ (1 << 7); break; // RES case 0xBC: *reg_H &= 0xFF ^ (1 << 7); break; // RES case 0xBD: *reg_L &= 0xFF ^ (1 << 7); break; // RES - case 0xBE: SetM (GetM () & (0xFF ^ (1 << 7))); ClockCount += 8; break; // RES + case 0xBE: SetM (GetM () & (0xFF ^ (1 << 7))); cpu_clock_count += 8; break; // RES case 0xBF: *reg_A &= 0xFF ^ (1 << 7); break; // RES case 0xC0: *reg_B |= 1 << 0; break; // SET @@ -473,7 +472,7 @@ void Execute (uint8_t Instruction) { case 0xC3: *reg_E |= 1 << 0; break; // SET case 0xC4: *reg_H |= 1 << 0; break; // SET case 0xC5: *reg_L |= 1 << 0; break; // SET - case 0xC6: SetM (GetM () | (1 << 0)); ClockCount += 8; break; // SET + case 0xC6: SetM (GetM () | (1 << 0)); cpu_clock_count += 8; break; // SET case 0xC7: *reg_A |= 1 << 0; break; // SET case 0xC8: *reg_B |= 1 << 1; break; // SET @@ -482,7 +481,7 @@ void Execute (uint8_t Instruction) { case 0xCB: *reg_E |= 1 << 1; break; // SET case 0xCC: *reg_H |= 1 << 1; break; // SET case 0xCD: *reg_L |= 1 << 1; break; // SET - case 0xCE: SetM (GetM () | (1 << 1)); ClockCount += 8; break; // SET + case 0xCE: SetM (GetM () | (1 << 1)); cpu_clock_count += 8; break; // SET case 0xCF: *reg_A |= 1 << 1; break; // SET case 0xD0: *reg_B |= 1 << 2; break; // SET @@ -491,7 +490,7 @@ void Execute (uint8_t Instruction) { case 0xD3: *reg_E |= 1 << 2; break; // SET case 0xD4: *reg_H |= 1 << 2; break; // SET case 0xD5: *reg_L |= 1 << 2; break; // SET - case 0xD6: SetM (GetM () | (1 << 2)); ClockCount += 8; break; // SET + case 0xD6: SetM (GetM () | (1 << 2)); cpu_clock_count += 8; break; // SET case 0xD7: *reg_A |= 1 << 2; break; // SET case 0xD8: *reg_B |= 1 << 3; break; // SET @@ -500,7 +499,7 @@ void Execute (uint8_t Instruction) { case 0xDB: *reg_E |= 1 << 3; break; // SET case 0xDC: *reg_H |= 1 << 3; break; // SET case 0xDD: *reg_L |= 1 << 3; break; // SET - case 0xDE: SetM (GetM () | (1 << 3)); ClockCount += 8; break; // SET + case 0xDE: SetM (GetM () | (1 << 3)); cpu_clock_count += 8; break; // SET case 0xDF: *reg_A |= 1 << 3; break; // SET case 0xE0: *reg_B |= 1 << 4; break; // SET @@ -509,7 +508,7 @@ void Execute (uint8_t Instruction) { case 0xE3: *reg_E |= 1 << 4; break; // SET case 0xE4: *reg_H |= 1 << 4; break; // SET case 0xE5: *reg_L |= 1 << 4; break; // SET - case 0xE6: SetM (GetM () | (1 << 4)); ClockCount += 8; break; // SET + case 0xE6: SetM (GetM () | (1 << 4)); cpu_clock_count += 8; break; // SET case 0xE7: *reg_A |= 1 << 4; break; // SET case 0xE8: *reg_B |= 1 << 5; break; // SET @@ -518,7 +517,7 @@ void Execute (uint8_t Instruction) { case 0xEB: *reg_E |= 1 << 5; break; // SET case 0xEC: *reg_H |= 1 << 5; break; // SET case 0xED: *reg_L |= 1 << 5; break; // SET - case 0xEE: SetM (GetM () | (1 << 5)); ClockCount += 8; break; // SET + case 0xEE: SetM (GetM () | (1 << 5)); cpu_clock_count += 8; break; // SET case 0xEF: *reg_A |= 1 << 5; break; // SET case 0xF0: *reg_B |= 1 << 6; break; // SET @@ -527,7 +526,7 @@ void Execute (uint8_t Instruction) { case 0xF3: *reg_E |= 1 << 6; break; // SET case 0xF4: *reg_H |= 1 << 6; break; // SET case 0xF5: *reg_L |= 1 << 6; break; // SET - case 0xF6: SetM (GetM () | (1 << 6)); ClockCount += 8; break; // SET + case 0xF6: SetM (GetM () | (1 << 6)); cpu_clock_count += 8; break; // SET case 0xF7: *reg_A |= 1 << 6; break; // SET case 0xF8: *reg_B |= 1 << 7; break; // SET @@ -536,7 +535,7 @@ void Execute (uint8_t Instruction) { case 0xFB: *reg_E |= 1 << 7; break; // SET case 0xFC: *reg_H |= 1 << 7; break; // SET case 0xFD: *reg_L |= 1 << 7; break; // SET - case 0xFE: SetM (GetM () | (1 << 7)); ClockCount += 8; break; // SET + case 0xFE: SetM (GetM () | (1 << 7)); cpu_clock_count += 8; break; // SET case 0xFF: *reg_A |= 1 << 7; break; // SET } break; @@ -544,29 +543,29 @@ void Execute (uint8_t Instruction) { // Jumps / Calls case 0xC3: PC = GetWordAt(PC); break; // JP a16 case 0xE9: PC = reg_HL; break; // JP HL - case 0xC2: u16 = GetWordAt(PC); PC += 2; if (!flag_Z) {PC = u16; ClockCount += 4;} break; // JP NZ a16 - case 0xD2: u16 = GetWordAt(PC); PC += 2; if (!flag_C) {PC = u16; ClockCount += 4;} break; // JP NC a16 - case 0xCA: u16 = GetWordAt(PC); PC += 2; if (flag_Z) {PC = u16; ClockCount += 4;} break; // JP Z a16 - case 0xDA: u16 = GetWordAt(PC); PC += 2; if (flag_C) {PC = u16; ClockCount += 4;} break; // JP C a16 + case 0xC2: u16 = GetWordAt(PC); PC += 2; if (!flag_Z) {PC = u16; cpu_clock_count += 4;} break; // JP NZ a16 + case 0xD2: u16 = GetWordAt(PC); PC += 2; if (!flag_C) {PC = u16; cpu_clock_count += 4;} break; // JP NC a16 + case 0xCA: u16 = GetWordAt(PC); PC += 2; if (flag_Z) {PC = u16; cpu_clock_count += 4;} break; // JP Z a16 + case 0xDA: u16 = GetWordAt(PC); PC += 2; if (flag_C) {PC = u16; cpu_clock_count += 4;} break; // JP C a16 case 0x18: i8 = GetByteAt(PC++); PC += i8; break; // JR - case 0x28: i8 = GetByteAt(PC++); if (flag_Z) {PC += i8; ClockCount += 4;} break; // JR Z - case 0x38: i8 = GetByteAt(PC++); if (flag_C) {PC += i8; ClockCount += 4;} break; // JR C - case 0x20: i8 = GetByteAt(PC++); if (!flag_Z) {PC += i8; ClockCount += 4;} break; // JR NZ - case 0x30: i8 = GetByteAt(PC++); if (!flag_C) {PC += i8; ClockCount += 4;} break; // JR NC + case 0x28: i8 = GetByteAt(PC++); if (flag_Z) {PC += i8; cpu_clock_count += 4;} break; // JR Z + case 0x38: i8 = GetByteAt(PC++); if (flag_C) {PC += i8; cpu_clock_count += 4;} break; // JR C + case 0x20: i8 = GetByteAt(PC++); if (!flag_Z) {PC += i8; cpu_clock_count += 4;} break; // JR NZ + case 0x30: i8 = GetByteAt(PC++); if (!flag_C) {PC += i8; cpu_clock_count += 4;} break; // JR NC case 0xCD: u16 = GetWordAt(PC); PC += 2; StackPush (PC); PC = u16; break; // CALL - case 0xC4: u16 = GetWordAt(PC); PC += 2; if (!flag_Z) {StackPush (PC); PC = u16; ClockCount += 12;} break; // CALL NZ, a16 - case 0xD4: u16 = GetWordAt(PC); PC += 2; if (!flag_C) {StackPush (PC); PC = u16; ClockCount += 12;} break; // CALL NC, a16 - case 0xCC: u16 = GetWordAt(PC); PC += 2; if (flag_Z) {StackPush (PC); PC = u16; ClockCount += 12;} break; // CALL Z, a16 - case 0xDC: u16 = GetWordAt(PC); PC += 2; if (flag_C) {StackPush (PC); PC = u16; ClockCount += 12;} break; // CALL C, a16 + case 0xC4: u16 = GetWordAt(PC); PC += 2; if (!flag_Z) {StackPush (PC); PC = u16; cpu_clock_count += 12;} break; // CALL NZ, a16 + case 0xD4: u16 = GetWordAt(PC); PC += 2; if (!flag_C) {StackPush (PC); PC = u16; cpu_clock_count += 12;} break; // CALL NC, a16 + case 0xCC: u16 = GetWordAt(PC); PC += 2; if (flag_Z) {StackPush (PC); PC = u16; cpu_clock_count += 12;} break; // CALL Z, a16 + case 0xDC: u16 = GetWordAt(PC); PC += 2; if (flag_C) {StackPush (PC); PC = u16; cpu_clock_count += 12;} break; // CALL C, a16 case 0xC9: PC = StackPop(); break; // RET case 0xD9: PC = StackPop(); InterruptsEnabled = 1; break; // RETI - case 0xC0: if (!flag_Z) {PC = StackPop(); ClockCount += 12;} break; // RET NZ - case 0xD0: if (!flag_C) {PC = StackPop(); ClockCount += 12;} break; // RET NC - case 0xC8: if (flag_Z) {PC = StackPop(); ClockCount += 12;} break; // RET Z - case 0xD8: if (flag_C) {PC = StackPop(); ClockCount += 12;} break; // RET C + case 0xC0: if (!flag_Z) {PC = StackPop(); cpu_clock_count += 12;} break; // RET NZ + case 0xD0: if (!flag_C) {PC = StackPop(); cpu_clock_count += 12;} break; // RET NC + case 0xC8: if (flag_Z) {PC = StackPop(); cpu_clock_count += 12;} break; // RET Z + case 0xD8: if (flag_C) {PC = StackPop(); cpu_clock_count += 12;} break; // RET C case 0xC7: StackPush (PC); PC = 0x00; break; // RST case 0xCF: StackPush (PC); PC = 0x08; break; // RST diff --git a/gameboy/CPU.h b/gameboy/CPU.h index bb42ad5578a32e81dcbf89bede7a710ba41a11fc..4ac25f088341372df02006836d32bc67988c6570 100644 --- a/gameboy/CPU.h +++ b/gameboy/CPU.h @@ -5,12 +5,12 @@ #ifndef CPU_H #define CPU_H -void InitCPU(); +void cpu_init(); void Clock (); void Debug (); void Interrupt (uint8_t ID); -extern uint32_t ClockCount; +extern uint32_t cpu_clock_count; extern uint32_t InstructionCount; extern uint8_t Debugging; diff --git a/gameboy/MMU.c b/gameboy/MMU.c index 95a82e1c78280a709f40715a0e231dae588a38c1..46715b5274d29f2a1e0c98acd3d6581200d57fa0 100644 --- a/gameboy/MMU.c +++ b/gameboy/MMU.c @@ -1,11 +1,9 @@ #include "MMU.h" -#include "enums.h" -#include "consts.h" // TODO - Move to flash later on, intended to be 16 * uint8_t ExternalRAM[4 * 0x2000]; // 16 RAM Banks Max -enum RomType rom_type; +ROMType rom_type; uint8_t rom_has_battery; uint8_t rom_has_external_ram; @@ -17,17 +15,12 @@ uint8_t SelectRAMBank = 0; uint8_t RTCRegister [0x0D]; uint8_t ExternalRAMSize = 0; -// VRAM Status -uint8_t CurrentPPUMode = 1; - -// Convenience Pointers - uint8_t* rom = &__rom_lol_start_cursed_section; -uint8_t Memory[0x10000]; -uint8_t* IOMap = Memory + 0xFF00; +uint8_t ram[0x10000]; +uint8_t* io_map = ram + 0xFF00; void mmu_init() { - memset(Memory, 0, sizeof(Memory)); + memset(ram, 0, sizeof(ram)); parse_rom(); } @@ -73,7 +66,6 @@ void parse_rom() { } printf("\n"); printf("ROM Size: %d KB\n", 32 << GetByteAt(0x0148)); - printf("ORIGINAL1 get_byte: rom_type: %d | MBC3: %d\n", rom_type, MBC3); uint8_t external_ram_size = 0; @@ -87,23 +79,15 @@ void parse_rom() { default: break; } - printf("ORIGINAL2 get_byte: rom_type: %d | MBC3: %d\n", rom_type, MBC3); - rom_has_battery = 1; - rom_has_external_ram = 1; - printf("ORIGINAL3 get_byte: rom_type: %d | MBC3: %d\n", rom_type, MBC3); + rom_has_battery = ROM_INDEX_HAS_BATTERY[rom_index]; + rom_has_external_ram = ROM_INDEX_HAS_RAM[rom_index]; printf("\n"); printf("ROM has Battery: %d\n", rom_has_battery); printf("ROM has External RAM: %d\n", rom_has_external_ram); - - printf("ORIGINAL4 get_byte: rom_type: %d | MBC3: %d\n", rom_type, MBC3); - printf("addr1: %x (rom_type)\naddr2: %x (rom_has_battery)\n", &rom_type, &rom_has_battery); } uint8_t GetByteAt(uint16_t Address) { - printf("get_byte: rom_type: %d | MBC3: %d\n", rom_type, MBC3); - sleep_ms(250); - if (Address < 0x4000) return rom [Address]; // ROM Bank 0 else if (Address < 0x8000) @@ -113,7 +97,7 @@ uint8_t GetByteAt(uint16_t Address) { Address -= 0x2000; if (Address >= 0xFE00 && Address < 0xFEA0) { // OAM - if (CurrentPPUMode >= 2) { // Inaccessible + if (ppu_mode >= 2) { // Inaccessible printf("[WARN] Blocked OAM Read\n"); return 0xFF; } @@ -134,14 +118,14 @@ uint8_t GetByteAt(uint16_t Address) { } } - return Memory [Address]; + return ram [Address]; } void SetByteAt (uint16_t Address, uint8_t Value) { switch (Address) { case 0xFF01: printf("%c", Value); fflush (stdout); return; // SB case 0xFF04: Value = 0; return; // DIV Register, Always write 0 - case 0xFF46: if (CurrentPPUMode < 2) memcpy (Memory + 0xFE00, Memory + (Value << 8), 0xA0); return; // DMA + case 0xFF46: if (ppu_mode < 2) memcpy (ram + 0xFE00, ram + (Value << 8), 0xA0); return; // DMA default: break; } @@ -149,20 +133,20 @@ void SetByteAt (uint16_t Address, uint8_t Value) { Address -= 0x2000; if (Address >= 0xFE00 && Address < 0xFEA0) { // OAM - if (CurrentPPUMode >= 2) { // Inaccessible + if (ppu_mode >= 2) { // Inaccessible printf("[WARN] Blocked OAM Write\n"); return; } } if (Address >= 0x8000 && Address < 0xA000) { // VRAM - if (CurrentPPUMode >= 3) { // Inaccessible + if (ppu_mode >= 3) { // Inaccessible printf("[WARN] Blocked VRAM Write\n"); return; } } - if (Address >= 0xFEA0 && Address < 0xFF00) // Unused Memory Area, Ignore write + if (Address >= 0xFEA0 && Address < 0xFF00) // Unused ram Area, Ignore write return; if (rom_type == ROM_ONLY) { @@ -235,7 +219,7 @@ void SetByteAt (uint16_t Address, uint8_t Value) { } } - Memory [Address] = Value; + ram [Address] = Value; } uint16_t GetWordAt (uint16_t Address) { diff --git a/gameboy/MMU.h b/gameboy/MMU.h index c067ab041dba483042d06348d17a4ba100e9429b..3b4ebc68cb78eabaec7b37dd6203202e5d2058f2 100644 --- a/gameboy/MMU.h +++ b/gameboy/MMU.h @@ -5,6 +5,9 @@ #include "pico/stdlib.h" #include <stdio.h> #include <string.h> +#include "enums.h" +#include "consts.h" +#include "PPU.h" void mmu_init(); void parse_rom(); @@ -34,7 +37,7 @@ void SetWordAt(uint16_t Address, uint16_t Value); extern char __rom_lol_start_cursed_section; extern uint8_t* rom; extern uint8_t ExternalRAM[]; -extern enum RomType rom_type; +extern ROMType rom_type; extern uint8_t rom_has_battery; extern uint8_t rom_has_external_ram; @@ -46,11 +49,8 @@ extern uint8_t SelectRAMBank; extern uint8_t RTCRegister[]; extern uint8_t ExternalRAMSize; -// VRAM Status -extern uint8_t CurrentPPUMode; - // Convenience Pointers -extern uint8_t Memory[]; -extern uint8_t* IOMap; +extern uint8_t ram[]; +extern uint8_t* io_map; #endif \ No newline at end of file diff --git a/gameboy/PPU.c b/gameboy/PPU.c index b93a68ce7838ca3282dd60ea7eb0824e8e1fd4f7..06a5c59d1ed2f2f7e76dc7f463fa8a6cf95a8c2d 100644 --- a/gameboy/PPU.c +++ b/gameboy/PPU.c @@ -6,7 +6,7 @@ uint8_t BGPalette [4]; uint8_t SpritePalette0 [4]; uint8_t SpritePalette1 [4]; -uint8_t SpriteCount = 0; +uint8_t num_sprites_on_current_line = 0; uint16_t PixelSize; uint8_t CurrentY = 0; @@ -17,8 +17,17 @@ uint16_t PixelsReady [160 * 144]; // When rendering, use these uint8_t OAMQueue [10 * 4]; // 10 Sprites, 4 Bytes each uint8_t ppu_display_y_offset = 0; +PPUMode ppu_mode = VBLANK; -void InitPPU() { +void ppu_init() { +} + +void set_ppu_mode(PPUMode _ppu_mode) { + ppu_mode = _ppu_mode; + + // Update PPU mode register + set_bit(io_map + 0x41, 0, ppu_mode & 1); + set_bit(io_map + 0x41, 1, ppu_mode & 2); } void add_to_ppu_y_offset(uint8_t increment) { @@ -45,55 +54,55 @@ inline void SetPixel (uint32_t CoordX, uint32_t CoordY, uint32_t Color) { Pixels [PixelNo] = Color; } -void OAMSearch (uint8_t* Memory, uint8_t* IOMap) { - uint8_t SpriteSize = 8 + (GetBit (IOMap [0x40], 2) << 3); // 8x8 or 8x16 +void OAMSearch() { + uint8_t SpriteSize = 8 + (get_bit(io_map[0x40], 2) << 3); // 8x8 or 8x16 uint8_t QueueNumber = 0; for (int i = 0xFE00; i <= 0xFE9F; i += 4) { - if (CurrentY + 16 >= Memory[i] && CurrentY + 16 < Memory[i] + SpriteSize) { // Y Position + if (CurrentY + 16 >= ram[i] && CurrentY + 16 < ram[i] + SpriteSize) { // Y Position //printf("%d: Load sprite at %d\n", QueueNumber, CurrentY); - memcpy (OAMQueue + (QueueNumber << 2), Memory + i, 4); + memcpy (OAMQueue + (QueueNumber << 2), ram + i, 4); QueueNumber++; if (QueueNumber == 10) // Max 10 sprites per line break; } } - SpriteCount = QueueNumber; + num_sprites_on_current_line = QueueNumber; } -void Render () { +void render_to_screen() { ST7735_DrawImage(0, 0, 80, 160, (uint8_t*) PixelsReady); } -void Update (uint8_t* Memory, uint8_t* IOMap) { +void render_line() { uint16_t BGTable = 0x9800; uint16_t WindowTable = 0x9800; - if (GetBit (IOMap [0x40], 3)) + if (get_bit(io_map[0x40], 3)) BGTable = 0x9C00; - if (GetBit (IOMap [0x40], 6)) + if (get_bit(io_map[0x40], 6)) WindowTable = 0x9C00; - uint8_t BGAddressingMode = GetBit (IOMap [0x40], 4); // 0 - Signed (0x8000), 1 - Unsigned (0x9000) + uint8_t BGAddressingMode = get_bit(io_map[0x40], 4); // 0 - Signed (0x8000), 1 - Unsigned (0x9000) - if (GetBit (IOMap [0x40], 0)) { // BG Enabled + if (get_bit(io_map[0x40], 0)) { // BG Enabled // Set BG Palette - BGPalette [0] = GetBit (IOMap [0x47], 0) | (GetBit (IOMap [0x47], 1) << 1); - BGPalette [1] = GetBit (IOMap [0x47], 2) | (GetBit (IOMap [0x47], 3) << 1); - BGPalette [2] = GetBit (IOMap [0x47], 4) | (GetBit (IOMap [0x47], 5) << 1); - BGPalette [3] = GetBit (IOMap [0x47], 6) | (GetBit (IOMap [0x47], 7) << 1); + BGPalette [0] = get_bit(io_map[0x47], 0) | (get_bit(io_map[0x47], 1) << 1); + BGPalette [1] = get_bit(io_map[0x47], 2) | (get_bit(io_map[0x47], 3) << 1); + BGPalette [2] = get_bit(io_map[0x47], 4) | (get_bit(io_map[0x47], 5) << 1); + BGPalette [3] = get_bit(io_map[0x47], 6) | (get_bit(io_map[0x47], 7) << 1); } - if (GetBit (IOMap [0x40], 1)) { // Sprites Enabled + if (get_bit(io_map[0x40], 1)) { // Sprites Enabled // Set Sprite Palettes - SpritePalette0 [1] = GetBit (IOMap [0x48], 2) | (GetBit (IOMap [0x48], 3) << 1); - SpritePalette0 [2] = GetBit (IOMap [0x48], 4) | (GetBit (IOMap [0x48], 5) << 1); - SpritePalette0 [3] = GetBit (IOMap [0x48], 6) | (GetBit (IOMap [0x48], 7) << 1); + SpritePalette0 [1] = get_bit(io_map[0x48], 2) | (get_bit(io_map[0x48], 3) << 1); + SpritePalette0 [2] = get_bit(io_map[0x48], 4) | (get_bit(io_map[0x48], 5) << 1); + SpritePalette0 [3] = get_bit(io_map[0x48], 6) | (get_bit(io_map[0x48], 7) << 1); - SpritePalette1 [1] = GetBit (IOMap [0x49], 2) | (GetBit (IOMap [0x49], 3) << 1); - SpritePalette1 [2] = GetBit (IOMap [0x49], 4) | (GetBit (IOMap [0x49], 5) << 1); - SpritePalette1 [3] = GetBit (IOMap [0x49], 6) | (GetBit (IOMap [0x49], 7) << 1); + SpritePalette1 [1] = get_bit(io_map[0x49], 2) | (get_bit(io_map[0x49], 3) << 1); + SpritePalette1 [2] = get_bit(io_map[0x49], 4) | (get_bit(io_map[0x49], 5) << 1); + SpritePalette1 [3] = get_bit(io_map[0x49], 6) | (get_bit(io_map[0x49], 7) << 1); } if (CurrentY < Height) { @@ -101,59 +110,59 @@ void Update (uint8_t* Memory, uint8_t* IOMap) { uint32_t ColorToDraw = Colors [BGPalette [0]]; uint8_t BGColor = 0; - if (GetBit (IOMap [0x40], 0)) { // BG Display + Window Display (DMG Only) - uint8_t BGX = CurrentX + IOMap[0x43]; - uint8_t BGY = CurrentY + IOMap[0x42]; + if (get_bit(io_map[0x40], 0)) { // BG Display + Window Display (DMG Only) + uint8_t BGX = CurrentX + io_map[0x43]; + uint8_t BGY = CurrentY + io_map[0x42]; - uint8_t BGTile = Memory [BGTable + ((BGY >> 3) << 5) + (BGX >> 3)]; + uint8_t BGTile = ram [BGTable + ((BGY >> 3) << 5) + (BGX >> 3)]; uint8_t PixelX = BGX & 0x7; uint8_t PixelY = BGY & 0x7; uint8_t* BGTileData; if (BGAddressingMode) - BGTileData = Memory + (0x8000 + (BGTile << 4)); + BGTileData = ram + (0x8000 + (BGTile << 4)); else - BGTileData = Memory + (0x9000 + (int8_t) BGTile * 16); + BGTileData = ram + (0x9000 + (int8_t) BGTile * 16); // First Byte: LSB of Color for Pixel (PixelX, PixelY) // Second Byte: MSB ~~~ - uint8_t Color = (GetBit (BGTileData [PixelY * 2 + 1], 7 - PixelX) << 1) | GetBit (BGTileData [PixelY * 2], 7 - PixelX); + uint8_t Color = (get_bit(BGTileData [PixelY * 2 + 1], 7 - PixelX) << 1) | get_bit(BGTileData [PixelY * 2], 7 - PixelX); BGColor = Color; ColorToDraw = Colors [BGPalette [Color]]; } - if (GetBit (IOMap [0x40], 0) && GetBit (IOMap [0x40], 5)) { // Window Display - uint8_t CoordX = IOMap[0x4B]; - uint8_t CoordY = IOMap[0x4A]; + if (get_bit(io_map[0x40], 0) && get_bit(io_map[0x40], 5)) { // Window Display + uint8_t CoordX = io_map[0x4B]; + uint8_t CoordY = io_map[0x4A]; if (CoordX - 7 <= CurrentX && CoordY <= CurrentY) { uint8_t WindowX = CurrentX + 7 - CoordX; uint8_t WindowY = CurrentY - CoordY; - uint8_t WindowTile = Memory [WindowTable + ((WindowY >> 3) << 5) + (WindowX >> 3)]; + uint8_t WindowTile = ram [WindowTable + ((WindowY >> 3) << 5) + (WindowX >> 3)]; uint8_t PixelX = WindowX & 0x7; uint8_t PixelY = WindowY & 0x7; uint8_t* WindowTileData; if (BGAddressingMode) - WindowTileData = Memory + (0x8000 + (WindowTile << 4)); + WindowTileData = ram + (0x8000 + (WindowTile << 4)); else - WindowTileData = Memory + (0x9000 + (int8_t) WindowTile * 16); + WindowTileData = ram + (0x9000 + (int8_t) WindowTile * 16); // First Byte: LSB of Color for Pixel (PixelX, PixelY) // Second Byte: MSB ~~~ - uint8_t Color = (GetBit (WindowTileData [PixelY * 2 + 1], 7 - PixelX) << 1) | GetBit (WindowTileData [PixelY * 2], 7 - PixelX); + uint8_t Color = (get_bit(WindowTileData [PixelY * 2 + 1], 7 - PixelX) << 1) | get_bit(WindowTileData [PixelY * 2], 7 - PixelX); ColorToDraw = Colors [BGPalette [Color]]; // Shared with BG } } - if (GetBit (IOMap [0x40], 1)) { // Sprite Display + if (get_bit(io_map[0x40], 1)) { // Sprite Display uint16_t MinX = 256; // Just greater than max (SpriteX) - for (int i = 0; i < (SpriteCount << 2); i += 4) { + for (int i = 0; i < (num_sprites_on_current_line << 2); i += 4) { uint8_t CoordY = OAMQueue [i]; uint8_t CoordX = OAMQueue [i + 1]; @@ -162,35 +171,35 @@ void Update (uint8_t* Memory, uint8_t* IOMap) { uint8_t PixelY = (CurrentY + 16) - CoordY; uint8_t SpriteTile = OAMQueue [i + 2]; - if (GetBit (IOMap [0x40], 2)) // Ignore bit 0 if 8x16 - SetBit (&SpriteTile, 0, 0); + if (get_bit(io_map[0x40], 2)) // Ignore bit 0 if 8x16 + set_bit(&SpriteTile, 0, 0); - uint8_t* SpriteTileData = Memory + (0x8000 + (SpriteTile << 4)); + uint8_t* SpriteTileData = ram + (0x8000 + (SpriteTile << 4)); uint8_t Color = 0; - if (GetBit (OAMQueue [i + 3], 5)) // Flip X + if (get_bit(OAMQueue [i + 3], 5)) // Flip X PixelX = 7 - PixelX; // Y flipping is done differently for 8x16 - if (GetBit (IOMap [0x40], 2)) { // 0 - 8x8, 1 - 8x16 - if (GetBit (OAMQueue [i + 3], 6)) // Flip Y + if (get_bit(io_map[0x40], 2)) { // 0 - 8x8, 1 - 8x16 + if (get_bit(OAMQueue [i + 3], 6)) // Flip Y PixelY = 15 - PixelY; } else { - if (GetBit (OAMQueue [i + 3], 6)) // Flip Y + if (get_bit(OAMQueue [i + 3], 6)) // Flip Y PixelY = 7 - PixelY; } - Color = (GetBit (SpriteTileData [PixelY * 2 + 1], PixelX) << 1) | GetBit (SpriteTileData [PixelY * 2], PixelX); + Color = (get_bit(SpriteTileData [PixelY * 2 + 1], PixelX) << 1) | get_bit(SpriteTileData [PixelY * 2], PixelX); if (Color != 0) { // Not Transparent - if (GetBit (OAMQueue [i + 3], 4)) // Choose sprite palette + if (get_bit(OAMQueue [i + 3], 4)) // Choose sprite palette Color = SpritePalette1 [Color]; else Color = SpritePalette0 [Color]; if (CoordX < MinX) { // Only draw over the sprite if our X coord is < MinX = CoordX; - if (GetBit (OAMQueue [i + 3], 7)) { // Above only if BG Color is 0 + if (get_bit(OAMQueue [i + 3], 7)) { // Above only if BG Color is 0 if (BGColor == 0) ColorToDraw = Colors [Color]; } else @@ -206,7 +215,7 @@ void Update (uint8_t* Memory, uint8_t* IOMap) { } CurrentY = (CurrentY + 1) % 154; - IOMap [0x44] = CurrentY; // Update current line that's being scanned + io_map[0x44] = CurrentY; // Update current line that's being scanned if (CurrentY == 0) // End of Frame, Save the good pixels to be drawn at 60 Hz afterwards memcpy (PixelsReady, Pixels, sizeof (Pixels)); diff --git a/gameboy/PPU.h b/gameboy/PPU.h index a5587b19f0a477ac8f9ea1c17b9654b6f3cdc9da..21a3fb94356c7f70a0c75b1c7174460076817877 100644 --- a/gameboy/PPU.h +++ b/gameboy/PPU.h @@ -4,20 +4,23 @@ #include <string.h> #include "utils.h" #include "pico/pico4ml/screen.h" +#include "enums.h" +#include "enums.h" +#include "MMU.h" #ifndef PPU_H #define PPU_H -void InitPPU(); +void ppu_init(); void add_to_ppu_y_offset(uint8_t increment); void sub_from_ppu_y_offset(uint8_t decrement); -void OAMSearch (uint8_t* Memory, uint8_t* IOMap); -void Update (uint8_t* Memory, uint8_t* IOMap); -void Render (); +void OAMSearch(); +void render_line(); +void render_to_screen(); -extern uint8_t SpriteCount; +extern uint8_t num_sprites_on_current_line; extern uint16_t PixelSize; extern uint8_t CurrentY; @@ -27,6 +30,10 @@ extern uint16_t Pixels[]; extern uint16_t PixelsReady []; // When rendering, use these extern uint8_t OAMQueue[]; // 10 Sprites, 4 Bytes each +extern PPUMode ppu_mode; + +void set_ppu_mode(PPUMode _ppu_mode); + // Drawing Functions void SetPixel (uint32_t CoordX, uint32_t CoordY, uint32_t Color); diff --git a/gameboy/consts.c b/gameboy/consts.c index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7b6c28cacd9575c24831e42cbe11b12934e11667 100644 --- a/gameboy/consts.c +++ b/gameboy/consts.c @@ -0,0 +1,39 @@ +#include "consts.h" + +const uint8_t VALID_ROM_BYTES[24] = {0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x08, 0x09, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x20, 0x22}; + +const ROMType ROM_INDEX_TO_ROMTYPE[] = { + ROM_ONLY, + MBC1, MBC1, MBC1, + MBC2, MBC2, + ROM_ONLY, ROM_ONLY, + MMM01, MMM01, MMM01, + MBC3, MBC3, MBC3, MBC3, MBC3, + MBC5, MBC5, MBC5, MBC5, MBC5, MBC5, + MBC6, + MBC7 +}; + +const uint8_t ROM_INDEX_HAS_RAM[] = { + false, + false, true, true, + false, false, + true, true, + false, true, true, + false, true, false, true, true, + false, true, true, false, true, true, + false, + true +}; + +const uint8_t ROM_INDEX_HAS_BATTERY[] = { + false, + false, false, true, + false, true, + false, true, + false, false, true, + true, true, false, false, true, + false, false, true, false, false, true, + false, + true +}; \ No newline at end of file diff --git a/gameboy/consts.h b/gameboy/consts.h index 65870b3740ec39d890c7c973997db0f661b5dd5d..65817359167f18050959f3ebc32d85b7db98c526 100644 --- a/gameboy/consts.h +++ b/gameboy/consts.h @@ -4,41 +4,9 @@ #include "pico/stdlib.h" #include "enums.h" -const uint8_t VALID_ROM_BYTES[24] = {0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x08, 0x09, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x20, 0x22}; +const extern uint8_t VALID_ROM_BYTES[24]; +const extern ROMType ROM_INDEX_TO_ROMTYPE[]; +const extern uint8_t ROM_INDEX_HAS_RAM[]; +const extern uint8_t ROM_INDEX_HAS_BATTERY[]; -const enum RomType ROM_INDEX_TO_ROMTYPE[] = { - ROM_ONLY, - MBC1, MBC1, MBC1, - MBC2, MBC2, - ROM_ONLY, ROM_ONLY, - MMM01, MMM01, MMM01, - MBC3, MBC3, MBC3, MBC3, MBC3, - MBC5, MBC5, MBC5, MBC5, MBC5, MBC5, - MBC6, - MBC7 -}; - -const uint8_t ROM_INDEX_HAS_RAM[] = { - false, - false, true, true, - false, false, - true, true, - false, true, true, - false, true, false, true, true, - false, true, true, false, true, true, - false, - true -}; - -const uint8_t ROM_INDEX_HAS_BATTERY[] = { - false, - false, false, true, - false, true, - false, true, - false, false, true, - true, true, false, false, true, - false, false, true, false, false, true, - false, - true -}; #endif diff --git a/gameboy/enums.h b/gameboy/enums.h index dad413df5ad0a9cac7c418a9e8e9209e054367b7..2457135317a61a509f1b07ef5497ca3b0c04934e 100644 --- a/gameboy/enums.h +++ b/gameboy/enums.h @@ -1,7 +1,7 @@ #ifndef ENUMS_H #define ENUMS_H -enum RomType{ +typedef enum{ ROM_ONLY, MBC1, MBC2, @@ -10,6 +10,13 @@ enum RomType{ MBC5, MBC6, MBC7 -}; +} ROMType; + +typedef enum{ + HBLANK = 0, + VBLANK = 1, + OAM_SEARCH = 2, + DATA_TRANSFER = 3 +} PPUMode; #endif diff --git a/gameboy/lol.uf2 b/gameboy/lol.uf2 new file mode 100644 index 0000000000000000000000000000000000000000..898ebe17b405a0e89f6080a3ee8d7ba06d6957fd Binary files /dev/null and b/gameboy/lol.uf2 differ diff --git a/gameboy/lol2.uf2 b/gameboy/lol2.uf2 new file mode 100644 index 0000000000000000000000000000000000000000..a5b942025f4613d7a2dab5b66a57ff1424e69eae Binary files /dev/null and b/gameboy/lol2.uf2 differ diff --git a/gameboy/main.c b/gameboy/main.c index 814bce22ca6cd85e899400a4a8a5779050f3cf34..cad27c5e8e82de4edc45ec0160bfb2eb34c27103 100644 --- a/gameboy/main.c +++ b/gameboy/main.c @@ -1,3 +1,4 @@ +#include "enums.h" #include "pico/stdlib.h" #include "pico/stdio.h" #include <stdbool.h> @@ -9,17 +10,11 @@ #include "CPU.h" #include "utils.h" -void cpu_loop(); +void emu_loop(); +void get_button_from_fifo_nonblocking(); +void core1_entry(); -void core1_entry() { - char c; - - while(1) { - c = getchar(); - multicore_fifo_push_blocking(c); - //printf("sent to the other core: %d\n", c); - } -} +uint8_t sticky_button_input = 0; int main() { stdio_init_all(); @@ -34,169 +29,104 @@ int main() { printf("Gameboy emulator booting up!\n"); mmu_init(); - InitCPU(); - InitPPU(); + cpu_init(); + ppu_init(); - /* - for (int i = 0; i < 100; i++) { - printf("INCOMING! %08x\n", rom); - sleep_ms(100); - } - - while(1) { - for (int i = 0; i < 20; i++) { - for (int k = 0; k < 16; k++) - printf("%x ", rom[i * 16 + k]); - printf("\n"); - } - - sleep_ms(1000); - }*/ - - cpu_loop(); + emu_loop(); printf("\n\n[INFO] CPU Stopped.\n"); } -uint8_t sticky_buttons = 0; - -void get_button_from_fifo_nonblocking() { - if (multicore_fifo_rvalid()) { - char c = multicore_fifo_pop_blocking(); - //printf("got from the other core: %d\n", c); - - if (c == ',') { - sub_from_ppu_y_offset(2); - } - - if (c == '.') { - add_to_ppu_y_offset(2); - } - - if (c == 'w') sticky_buttons |= 1 << 0; - if (c == 'a') sticky_buttons |= 1 << 1; - if (c == 's') sticky_buttons |= 1 << 2; - if (c == 'd') sticky_buttons |= 1 << 3; - - if (c == 'o') sticky_buttons |= 1 << 4; - if (c == 'p') sticky_buttons |= 1 << 5; - if (c == ' ') sticky_buttons |= 1 << 6; - if (c == 13) sticky_buttons |= 1 << 7; - } -} +void emu_loop() { + uint32_t clock_of_last_line = 0; -void cpu_loop() { - // Input status - uint8_t PressDebug = 0; - uint8_t PressControlR = 0; - uint8_t Quit = 0; - - // Timing - uint32_t LastRenderClock = 0; - uint32_t LastLineDrawClock = 0; uint32_t PixelTransferDuration = 0; - uint32_t ClocksPerSec = 4194304; - uint32_t ClocksPerMS = ClocksPerSec / 1000; - uint32_t LastMSClock = 0; + uint32_t LastRenderClock = 0; uint32_t LastTimerClock = 0; uint32_t LastDivClock = 0; - uint32_t LastDebugClock = 0; - uint32_t LastDebugInstructionCount = 0; - - // Main Loop - while (!Quit) { - // Input - SDL - - // IOMap 0x40 - LCDC - // IOMap 0x41 - LCD STAT + + while (1) { + // io_map 0x40 - LCDC + // io_map 0x41 - LCD STAT // Rendering - if (GetBit (IOMap [0x40], 7)) { // LCD Operation - uint32_t CurrentLineClock = ClockCount - LastLineDrawClock; - - if (IOMap [0x44] < 144) { // Current line being drawn - if (CurrentLineClock <= 80) { // OAM Period - if (CurrentPPUMode == 0 || CurrentPPUMode == 1) { // Came from HBlank or VBlank - CurrentPPUMode = 2; - OAMSearch (Memory, IOMap); - PixelTransferDuration = 168 + (SpriteCount * (291 - 168)) / 10; // 10 Sprites should cause maximum duration = 291 Clocks + if (get_bit(io_map[0x40], 7)) { // LCD Display is enabled + uint32_t clock_of_current_line = cpu_clock_count - clock_of_last_line; + + // Apparently the dot clock runs 4x slower than the gameboy cpu? + // So 80 dots = 20 cpu cycles - SetBit (IOMap + 0x41, 0, 0); // Set them now so that the CPU can service the INT correctly - SetBit (IOMap + 0x41, 1, 1); - - if (GetBit (IOMap [0x41], 5)) + if (io_map[0x44] < 144) { // The line being drawn is on the display + if (clock_of_current_line <= 80) { // OAM Period + if (ppu_mode == HBLANK || ppu_mode == VBLANK) { + OAMSearch(); + set_ppu_mode(OAM_SEARCH); + PixelTransferDuration = 168 + (num_sprites_on_current_line * (291 - 168)) / 10; // 10 Sprites should cause maximum duration = 291 Clocks + + if (get_bit(io_map[0x41], 5)) Interrupt (1); } - } else if (CurrentLineClock <= 80 + PixelTransferDuration) { // Pixel Transfer - if (CurrentPPUMode == 2) { - CurrentPPUMode = 3; - - SetBit (IOMap + 0x41, 0, 1); - SetBit (IOMap + 0x41, 1, 1); + } else if (clock_of_current_line <= 80 + PixelTransferDuration) { // Pixel Transfer + if (ppu_mode == OAM_SEARCH) { + set_ppu_mode(DATA_TRANSFER); } } else { // HBlank - if (CurrentPPUMode == 3) { - CurrentPPUMode = 0; - - SetBit (IOMap + 0x41, 0, 0); - SetBit (IOMap + 0x41, 1, 0); - - if (GetBit (IOMap [0x41], 3)) + if (ppu_mode == DATA_TRANSFER) { + set_ppu_mode(HBLANK); + + if (get_bit(io_map[0x41], 3)) Interrupt (1); } } } else { - if (CurrentPPUMode == 0) { // VBlank - CurrentPPUMode = 1; - - SetBit (IOMap + 0x41, 0, 1); - SetBit (IOMap + 0x41, 1, 0); - - Interrupt (0); + if (ppu_mode == HBLANK) { // VBlank + set_ppu_mode(VBLANK); + + Interrupt(0); - if (ClockCount - LastRenderClock >= 103800) { // 83800 - LastRenderClock = ClockCount; - Render (); // Actual rendering on the screen + if (cpu_clock_count - LastRenderClock >= 103800) { // 83800 + LastRenderClock = cpu_clock_count; + render_to_screen(); // Actual rendering on the screen } - if (GetBit (IOMap [0x41], 4)) + if (get_bit(io_map[0x41], 4)) Interrupt (1); } } - if (CurrentLineClock >= (114 << 2)) { // Passed On a New Line - LastLineDrawClock = ClockCount; - Update (Memory, IOMap); + if (clock_of_current_line >= 456) { // Passed On a New Line + clock_of_last_line = cpu_clock_count; + render_line(); - if (IOMap [0x44] == IOMap [0x45]) { // Coincidence LY, LYC - SetBit (IOMap + 0x41, 2, 1); - if (GetBit (IOMap [0x41], 6)) + if (io_map[0x44] == io_map[0x45]) { // Coincidence LY, LYC + set_bit(io_map + 0x41, 2, 1); + if (get_bit(io_map[0x41], 6)) Interrupt (1); } else - SetBit (IOMap + 0x41, 2, 0); + set_bit(io_map + 0x41, 2, 0); } } // Timer // TODO Timer Obscure Behaviour - if (GetBit (IOMap [0x07], 2)) { // TIMCONT + if (get_bit(io_map[0x07], 2)) { // TIMCONT uint32_t TimerDelay = 0; - if (GetBit (IOMap [0x07], 0)) { - if (GetBit (IOMap [0x07], 1)) + if (get_bit(io_map[0x07], 0)) { + if (get_bit(io_map[0x07], 1)) TimerDelay = 256; else TimerDelay = 16; - } else if (GetBit (IOMap [0x07], 1)) + } else if (get_bit(io_map[0x07], 1)) TimerDelay = 64; else TimerDelay = 1024; - if (ClockCount - LastTimerClock >= TimerDelay) { - LastTimerClock = ClockCount; - IOMap [0x05]++; // TIMECNT + if (cpu_clock_count - LastTimerClock >= TimerDelay) { + LastTimerClock = cpu_clock_count; + io_map[0x05]++; // TIMECNT - if (IOMap [0x05] == 0) { - IOMap [0x05] = IOMap [0x06]; // TIMEMOD + if (io_map[0x05] == 0) { + io_map[0x05] = io_map[0x06]; // TIMEMOD Interrupt (2); } } @@ -204,68 +134,103 @@ void cpu_loop() { get_button_from_fifo_nonblocking(); - if (GetBit (IOMap [0x00], 4) == 0) { // Direction Pad - IOMap [0x00] |= 0xF; // 1 - Not Pressed + if (get_bit(io_map[0x00], 4) == 0) { // Direction Pad + io_map[0x00] |= 0xF; // 1 - Not Pressed - if (GetBit(sticky_buttons, 3)) { - SetBit (IOMap + 0x00, 0, 0); + if (get_bit(sticky_button_input, 3)) { + set_bit(io_map + 0x00, 0, 0); } - if (GetBit(sticky_buttons, 1)) { - SetBit (IOMap + 0x00, 1, 0); + if (get_bit(sticky_button_input, 1)) { + set_bit(io_map + 0x00, 1, 0); } - if (GetBit(sticky_buttons, 0)) { - SetBit (IOMap + 0x00, 2, 0); + if (get_bit(sticky_button_input, 0)) { + set_bit(io_map + 0x00, 2, 0); } - if (GetBit(sticky_buttons, 2)) { - SetBit (IOMap + 0x00, 3, 0); + if (get_bit(sticky_button_input, 2)) { + set_bit(io_map + 0x00, 3, 0); } - if ((IOMap [0x00] & 0xF) != 0xF) { // Something was pressed - sticky_buttons &= 0xF0; - //printf("Firing interrupt: %x\n", IOMap[0]); + if ((io_map[0x00] & 0xF) != 0xF) { // Something was pressed + sticky_button_input &= 0xF0; + //printf("Firing interrupt: %x\n", io_map[0]); Interrupt (4); - SetBit (IOMap + 0, 4, 1); + set_bit(io_map + 0, 4, 1); } } - if (GetBit (IOMap [0x00], 5) == 0) { // Buttons - IOMap [0x00] |= 0xF; // 1 - Not Pressed + if (get_bit(io_map[0x00], 5) == 0) { // Buttons + io_map[0x00] |= 0xF; // 1 - Not Pressed - if (GetBit(sticky_buttons, 5)) // A - SetBit (IOMap + 0x00, 0, 0); + if (get_bit(sticky_button_input, 5)) // A + set_bit(io_map + 0x00, 0, 0); - if (GetBit(sticky_buttons, 4)) // B - SetBit (IOMap + 0x00, 1, 0); + if (get_bit(sticky_button_input, 4)) // B + set_bit(io_map + 0x00, 1, 0); - if (GetBit(sticky_buttons, 6)) // SELECT - SetBit (IOMap + 0x00, 2, 0); + if (get_bit(sticky_button_input, 6)) // SELECT + set_bit(io_map + 0x00, 2, 0); - if (GetBit(sticky_buttons, 7)) // START - SetBit (IOMap + 0x00, 3, 0); + if (get_bit(sticky_button_input, 7)) // START + set_bit(io_map + 0x00, 3, 0); - if ((IOMap [0x00] & 0xF) != 0xF) {// Something was pressed - sticky_buttons &= 0x0F; - //printf("Firing interrupt: %x\n", IOMap[0]); + if ((io_map[0x00] & 0xF) != 0xF) {// Something was pressed + sticky_button_input &= 0x0F; + //printf("Firing interrupt: %x\n", io_map[0]); Interrupt (4); - SetBit (IOMap + 0, 5, 1); + set_bit(io_map + 0, 5, 1); } } // DIV Register - if (ClockCount - LastDivClock >= 256) { // DIV increases every 256 clocks - LastDivClock = ClockCount; - IOMap [0x04]++; + if (cpu_clock_count - LastDivClock >= 256) { // DIV increases every 256 clocks + LastDivClock = cpu_clock_count; + io_map[0x04]++; } if (!Debugging) { - uint8_t OldDMA = IOMap [0x46]; + uint8_t OldDMA = io_map[0x46]; Clock (); - if (IOMap [0x46] != OldDMA) // DMA Write - ClockCount += (160 << 2) + 4; + if (io_map[0x46] != OldDMA) // DMA Write + cpu_clock_count += (160 << 2) + 4; } } -} \ No newline at end of file +} + +void core1_entry() { + char c; + + while(1) { + c = getchar(); + multicore_fifo_push_blocking(c); + //printf("sent to the other core: %d\n", c); + } +} + +void get_button_from_fifo_nonblocking() { + if (multicore_fifo_rvalid()) { + char c = multicore_fifo_pop_blocking(); + //printf("got from the other core: %d\n", c); + + if (c == ',') { + sub_from_ppu_y_offset(2); + } + + if (c == '.') { + add_to_ppu_y_offset(2); + } + + if (c == 'w') sticky_button_input |= 1 << 0; + if (c == 'a') sticky_button_input |= 1 << 1; + if (c == 's') sticky_button_input |= 1 << 2; + if (c == 'd') sticky_button_input |= 1 << 3; + + if (c == 'o') sticky_button_input |= 1 << 4; + if (c == 'p') sticky_button_input |= 1 << 5; + if (c == ' ') sticky_button_input |= 1 << 6; + if (c == 13) sticky_button_input |= 1 << 7; + } +} diff --git a/gameboy/pico/pico4ml/screen.c b/gameboy/pico/pico4ml/screen.c index 7603b8d86a334bd701a67c34e027d2f6ad95f886..17c51ba3f71f3c1cecb17d5fcd3890ad21995cbd 100644 --- a/gameboy/pico/pico4ml/screen.c +++ b/gameboy/pico/pico4ml/screen.c @@ -92,7 +92,7 @@ static void ST7735_Select() { gpio_put(EPD_CS_PIN, 0); } -void ST7735_Unselect() { +static void ST7735_Unselect() { //HAL_GPIO_WritePin(ST7735_CS_GPIO_Port, ST7735_CS_Pin, GPIO_PIN_SET); gpio_put(EPD_CS_PIN, 1); } @@ -159,7 +159,7 @@ static void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t ST7735_WriteCommand(ST7735_RAMWR); } -void ST7735_Init() { +void __attribute__((optimize("O1"))) ST7735_Init() { spi_init(spi1, 12000 * 1000); gpio_set_function(EPD_CLK_PIN, GPIO_FUNC_SPI); gpio_set_function(EPD_MOSI_PIN, GPIO_FUNC_SPI); diff --git a/gameboy/pico/pico4ml/screen.h b/gameboy/pico/pico4ml/screen.h index 62878171bd68ee27d8a30f46754d33210e2b59c2..24fed2eb8f99895fc871a8c92a5c637c06d7f7fd 100644 --- a/gameboy/pico/pico4ml/screen.h +++ b/gameboy/pico/pico4ml/screen.h @@ -116,8 +116,6 @@ extern int EPD_MOSI_PIN; #ifdef __cplusplus extern "C" { #endif -// call before initializing any SPI devices -void ST7735_Unselect(); void ST7735_Init(void); void ST7735_DrawPixel(uint16_t x, uint16_t y, uint16_t color); diff --git a/gameboy/utils.c b/gameboy/utils.c index c57dc5d32ee1a71dd4554b1b05f36c5a7677cfca..bf1b8349e930971b9479903fb41ec3f1d170ec6b 100644 --- a/gameboy/utils.c +++ b/gameboy/utils.c @@ -1,10 +1,10 @@ #include "utils.h" -inline uint8_t GetBit (uint8_t Value, uint8_t BitNo) { +inline uint8_t get_bit(uint8_t Value, uint8_t BitNo) { return (Value & (1 << BitNo)) != 0; } -inline void SetBit (uint8_t* Value, uint8_t BitNo, uint8_t Set) { +inline void set_bit(uint8_t* Value, uint8_t BitNo, uint8_t Set) { if (Set) *Value |= 1 << BitNo; else diff --git a/gameboy/utils.h b/gameboy/utils.h index e6469a940fdf7ca24d5d85af6971799f16f3a9fb..3d5c61bc874b806628db321ab1050b1d45232767 100644 --- a/gameboy/utils.h +++ b/gameboy/utils.h @@ -5,10 +5,10 @@ #ifndef UTILS_H #define UTILS_H -//#define GetBit(Value, BitNo) (((Value >> BitNo) & 1) != 0) +//#define get_bit(Value, BitNo) (((Value >> BitNo) & 1) != 0) -uint8_t GetBit (uint8_t Value, uint8_t BitNo); -void SetBit (uint8_t *Value, uint8_t BitNo, uint8_t Set); +uint8_t get_bit(uint8_t Value, uint8_t BitNo); +void set_bit(uint8_t *Value, uint8_t BitNo, uint8_t Set); /* using namespace std::chrono;