GBHawk: finsih mappers start integration
This commit is contained in:
parent
03b83a1043
commit
b8233666ac
|
@ -52,6 +52,14 @@ namespace GBHawk
|
|||
psg.is_GBC = &MemMap.is_GBC;
|
||||
psg.double_speed = &MemMap.double_speed;
|
||||
psg.timer_div_reg = &timer.divider_reg;
|
||||
|
||||
mapper.addr_access = &MemMap.addr_access;
|
||||
mapper.Acc_X_state = &MemMap.Acc_X_state;
|
||||
mapper.Acc_Y_state = &MemMap.Acc_Y_state;
|
||||
mapper.ROM_Length = &MemMap.ROM_Length;
|
||||
mapper.Cart_RAM_Length = &MemMap.Cart_RAM_Length;
|
||||
mapper.ROM = &MemMap.ROM[0];
|
||||
mapper.Cart_RAM = &MemMap.Cart_RAM[0];
|
||||
};
|
||||
|
||||
PPU ppu;
|
||||
|
|
|
@ -22,8 +22,7 @@ GBHawk_EXPORT GBCore* GB_create()
|
|||
GBHawk_EXPORT void GB_destroy(GBCore* p)
|
||||
{
|
||||
delete p->MemMap.bios_rom;
|
||||
delete p->MemMap.rom_1;
|
||||
delete p->MemMap.rom_2;
|
||||
delete p->MemMap.ROM;
|
||||
std::free(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,10 +18,13 @@ namespace GBHawk
|
|||
|
||||
}
|
||||
|
||||
uint8_t* ROM = nullptr;
|
||||
uint8_t* Cart_RAM = nullptr;
|
||||
uint32_t* ROM_Length = nullptr;
|
||||
uint32_t* Cart_RAM_Length = nullptr;
|
||||
uint32_t* ROM = nullptr;
|
||||
uint32_t* Cart_RAM = nullptr;
|
||||
uint32_t* addr_access = nullptr;
|
||||
uint32_t* Acc_X_state = nullptr;
|
||||
uint32_t* Acc_Y_state = nullptr;
|
||||
|
||||
// Generic Mapper Variables
|
||||
bool RAM_enable;
|
||||
|
@ -51,7 +54,16 @@ namespace GBHawk
|
|||
bool RTC_regs_latch_wr;
|
||||
uint32_t RTC_offset;
|
||||
|
||||
// camera
|
||||
bool regs_enable;
|
||||
uint8_t regs_cam[0x80] = {};
|
||||
|
||||
// sachen
|
||||
bool locked, locked_GBC, finished, reg_access;
|
||||
uint32_t ROM_bank_mask;
|
||||
uint32_t BASE_ROM_Bank;
|
||||
uint32_t addr_last;
|
||||
uint32_t counter;
|
||||
|
||||
// TAMA5
|
||||
uint8_t RTC_regs_TAMA[10] = {};
|
||||
|
@ -63,6 +75,30 @@ namespace GBHawk
|
|||
uint8_t Chip_return_low;
|
||||
uint8_t Chip_return_high;
|
||||
|
||||
// MBC7
|
||||
bool RAM_enable_1, RAM_enable_2, is_erased;
|
||||
uint8_t acc_x_low;
|
||||
uint8_t acc_x_high;
|
||||
uint8_t acc_y_low;
|
||||
uint8_t acc_y_high;
|
||||
// EEPROM related
|
||||
bool CS_prev;
|
||||
bool CLK_prev;
|
||||
bool DI_prev;
|
||||
bool DO;
|
||||
bool instr_read;
|
||||
bool perf_instr;
|
||||
bool WR_EN;
|
||||
bool countdown_start;
|
||||
uint32_t instr_bit_counter;
|
||||
uint32_t instr;
|
||||
uint32_t EE_addr;
|
||||
uint32_t instr_case;
|
||||
uint32_t instr_clocks;
|
||||
uint32_t EE_value;
|
||||
uint32_t countdown;
|
||||
|
||||
|
||||
|
||||
virtual uint8_t ReadMemory(uint32_t addr)
|
||||
{
|
||||
|
@ -142,6 +178,18 @@ namespace GBHawk
|
|||
saver = bool_saver(RTC_regs_latch_wr, saver);
|
||||
saver = int_saver(RTC_offset, saver);
|
||||
|
||||
saver = bool_saver(regs_enable, saver);
|
||||
for (int i = 0; i < 5; i++) { saver = byte_saver(regs_cam[i], saver); }
|
||||
|
||||
saver = bool_saver(locked, saver);
|
||||
saver = bool_saver(locked_GBC, saver);
|
||||
saver = bool_saver(finished, saver);
|
||||
saver = bool_saver(reg_access, saver);
|
||||
saver = int_saver(ROM_bank_mask, saver);
|
||||
saver = int_saver(BASE_ROM_Bank, saver);
|
||||
saver = int_saver(addr_last, saver);
|
||||
saver = int_saver(counter, saver);
|
||||
|
||||
for (int i = 0; i < 10; i++) { saver = byte_saver(RTC_regs_TAMA[i], saver); }
|
||||
saver = byte_saver(Chip_return_low, saver);
|
||||
saver = byte_saver(Chip_return_high, saver);
|
||||
|
@ -151,11 +199,103 @@ namespace GBHawk
|
|||
saver = int_saver(RAM_val_low, saver);
|
||||
saver = int_saver(RAM_val_high, saver);
|
||||
|
||||
saver = bool_saver(RAM_enable_1, saver);
|
||||
saver = bool_saver(RAM_enable_2, saver);
|
||||
saver = bool_saver(is_erased, saver);
|
||||
saver = byte_saver(acc_x_low, saver);
|
||||
saver = byte_saver(acc_x_high, saver);
|
||||
saver = byte_saver(acc_y_low, saver);
|
||||
saver = byte_saver(acc_y_high, saver);
|
||||
// EEPROM related
|
||||
saver = bool_saver(CS_prev, saver);
|
||||
saver = bool_saver(CLK_prev, saver);
|
||||
saver = bool_saver(DI_prev, saver);
|
||||
saver = bool_saver(DO, saver);
|
||||
saver = bool_saver(instr_read, saver);
|
||||
saver = bool_saver(perf_instr, saver);
|
||||
saver = bool_saver(WR_EN, saver);
|
||||
saver = bool_saver(countdown_start, saver);
|
||||
saver = int_saver(instr_bit_counter, saver);
|
||||
saver = int_saver(instr, saver);
|
||||
saver = int_saver(EE_addr, saver);
|
||||
saver = int_saver(instr_case, saver);
|
||||
saver = int_saver(instr_clocks, saver);
|
||||
saver = int_saver(EE_value, saver);
|
||||
saver = int_saver(countdown, saver);
|
||||
|
||||
return saver;
|
||||
}
|
||||
|
||||
uint8_t* LoadState(uint8_t* loader)
|
||||
{
|
||||
loader = bool_loader(&RAM_enable, loader);
|
||||
loader = bool_loader(&sel_mode, loader);
|
||||
loader = bool_loader(&IR_signal, loader);
|
||||
loader = int_loader(&ROM_bank, loader);
|
||||
loader = int_loader(&RAM_bank, loader);
|
||||
loader = int_loader(&ROM_mask, loader);
|
||||
loader = int_loader(&RAM_mask, loader);
|
||||
|
||||
loader = bool_loader(&halt, loader);
|
||||
loader = int_loader(&RTC_timer, loader);
|
||||
loader = int_loader(&RTC_low_clock, loader);
|
||||
|
||||
loader = bool_loader(&timer_read, loader);
|
||||
loader = byte_loader(&control, loader);
|
||||
loader = byte_loader(&chip_read, loader);
|
||||
loader = int_loader(&time_val_shift, loader);
|
||||
loader = int_loader(&time, loader);
|
||||
loader = int_loader(&RTC_seconds, loader);
|
||||
|
||||
for (int i = 0; i < 5; i++) { loader = byte_loader(&RTC_regs[i], loader); }
|
||||
for (int i = 0; i < 5; i++) { loader = byte_loader(&RTC_regs_latch[i], loader); }
|
||||
loader = bool_loader(&RTC_regs_latch_wr, loader);
|
||||
loader = int_loader(&RTC_offset, loader);
|
||||
|
||||
loader = bool_loader(®s_enable, loader);
|
||||
for (int i = 0; i < 5; i++) { loader = byte_loader(®s_cam[i], loader); }
|
||||
|
||||
loader = bool_loader(&locked, loader);
|
||||
loader = bool_loader(&locked_GBC, loader);
|
||||
loader = bool_loader(&finished, loader);
|
||||
loader = bool_loader(®_access, loader);
|
||||
loader = int_loader(&ROM_bank_mask, loader);
|
||||
loader = int_loader(&BASE_ROM_Bank, loader);
|
||||
loader = int_loader(&addr_last, loader);
|
||||
loader = int_loader(&counter, loader);
|
||||
|
||||
for (int i = 0; i < 10; i++) { loader = byte_loader(&RTC_regs_TAMA[i], loader); }
|
||||
loader = byte_loader(&Chip_return_low, loader);
|
||||
loader = byte_loader(&Chip_return_high, loader);
|
||||
loader = int_loader(&ctrl, loader);
|
||||
loader = int_loader(&RAM_addr_low, loader);
|
||||
loader = int_loader(&RAM_addr_high, loader);
|
||||
loader = int_loader(&RAM_val_low, loader);
|
||||
loader = int_loader(&RAM_val_high, loader);
|
||||
|
||||
loader = bool_loader(&RAM_enable_1, loader);
|
||||
loader = bool_loader(&RAM_enable_2, loader);
|
||||
loader = bool_loader(&is_erased, loader);
|
||||
loader = byte_loader(&acc_x_low, loader);
|
||||
loader = byte_loader(&acc_x_high, loader);
|
||||
loader = byte_loader(&acc_y_low, loader);
|
||||
loader = byte_loader(&acc_y_high, loader);
|
||||
// EEPROM related
|
||||
loader = bool_loader(&CS_prev, loader);
|
||||
loader = bool_loader(&CLK_prev, loader);
|
||||
loader = bool_loader(&DI_prev, loader);
|
||||
loader = bool_loader(&DO, loader);
|
||||
loader = bool_loader(&instr_read, loader);
|
||||
loader = bool_loader(&perf_instr, loader);
|
||||
loader = bool_loader(&WR_EN, loader);
|
||||
loader = bool_loader(&countdown_start, loader);
|
||||
loader = int_loader(&instr_bit_counter, loader);
|
||||
loader = int_loader(&instr, loader);
|
||||
loader = int_loader(&EE_addr, loader);
|
||||
loader = int_loader(&instr_case, loader);
|
||||
loader = int_loader(&instr_clocks, loader);
|
||||
loader = int_loader(&EE_value, loader);
|
||||
loader = int_loader(&countdown, loader);
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
|
|
@ -14,10 +14,6 @@ namespace GBHawk
|
|||
{
|
||||
public:
|
||||
|
||||
|
||||
bool regs_enable;
|
||||
uint8_t regs[0x80] = {};
|
||||
|
||||
void Reset()
|
||||
{
|
||||
ROM_bank = 1;
|
||||
|
@ -132,7 +128,7 @@ namespace GBHawk
|
|||
{
|
||||
if (regs_enable)
|
||||
{
|
||||
regs[(addr & 0x7F)] = (uint8_t)(value & 0x7);
|
||||
regs_cam[(addr & 0x7F)] = (uint8_t)(value & 0x7);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -14,31 +14,6 @@ namespace GBHawk
|
|||
{
|
||||
public:
|
||||
|
||||
bool RAM_enable_1, RAM_enable_2;
|
||||
uint8_t acc_x_low;
|
||||
uint8_t acc_x_high;
|
||||
uint8_t acc_y_low;
|
||||
uint8_t acc_y_high;
|
||||
bool is_erased;
|
||||
|
||||
// EEPROM related
|
||||
bool CS_prev;
|
||||
bool CLK_prev;
|
||||
bool DI_prev;
|
||||
bool DO;
|
||||
bool instr_read;
|
||||
bool perf_instr;
|
||||
uint32_t instr_bit_counter;
|
||||
uint32_t instr;
|
||||
bool WR_EN;
|
||||
uint32_t EE_addr;
|
||||
uint32_t instr_case;
|
||||
uint32_t instr_clocks;
|
||||
uint32_t EE_value;
|
||||
uint32_t countdown;
|
||||
bool countdown_start;
|
||||
|
||||
|
||||
void Reset()
|
||||
{
|
||||
ROM_bank = 1;
|
||||
|
@ -236,10 +211,10 @@ namespace GBHawk
|
|||
{
|
||||
// latch new accelerometer values
|
||||
//Console.WriteLine("Latching ACC");
|
||||
acc_x_low = (uint8_t)(Core.Acc_X_state & 0xFF);
|
||||
acc_x_high = (uint8_t)((Core.Acc_X_state & 0xFF00) >> 8);
|
||||
acc_y_low = (uint8_t)(Core.Acc_Y_state & 0xFF);
|
||||
acc_y_high = (uint8_t)((Core.Acc_Y_state & 0xFF00) >> 8);
|
||||
acc_x_low = (uint8_t)(Acc_X_state[0] & 0xFF);
|
||||
acc_x_high = (uint8_t)((Acc_X_state[0] & 0xFF00) >> 8);
|
||||
acc_y_low = (uint8_t)(Acc_Y_state[0] & 0xFF);
|
||||
acc_y_high = (uint8_t)((Acc_Y_state[0] & 0xFF00) >> 8);
|
||||
}
|
||||
}
|
||||
else if ((addr & 0xA0F0) == 0xA080)
|
||||
|
@ -251,9 +226,9 @@ namespace GBHawk
|
|||
|
||||
void EEPROM_write(uint8_t value)
|
||||
{
|
||||
bool CS = value.Bit(7);
|
||||
bool CLK = value.Bit(6);
|
||||
bool DI = value.Bit(1);
|
||||
bool CS = (value & 0x80) > 0;
|
||||
bool CLK = (value & 0x40) > 0;
|
||||
bool DI = (value & 0x2) > 0;
|
||||
|
||||
// if we deselect the chip, complete instructions or countdown and stop
|
||||
if (!CS)
|
||||
|
|
|
@ -14,13 +14,6 @@ namespace GBHawk
|
|||
{
|
||||
public:
|
||||
|
||||
bool locked;
|
||||
uint32_t ROM_bank_mask;
|
||||
uint32_t BASE_ROM_Bank;
|
||||
bool reg_access;
|
||||
uint32_t addr_last;
|
||||
uint32_t counter;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
ROM_bank = 1;
|
||||
|
@ -154,21 +147,19 @@ namespace GBHawk
|
|||
{
|
||||
if (locked)
|
||||
{
|
||||
if (((Core.addr_access & 0x8000) == 0) && ((addr_last & 0x8000) > 0) && (Core.addr_access >= 0x100))
|
||||
if (((addr_access[0] & 0x8000) == 0) && ((addr_last & 0x8000) > 0) && (addr_access[0] >= 0x100))
|
||||
{
|
||||
counter++;
|
||||
Console.WriteLine(Core.cpu.TotalExecutedCycles);
|
||||
}
|
||||
|
||||
if (Core.addr_access >= 0x100)
|
||||
if (addr_access[0] >= 0x100)
|
||||
{
|
||||
addr_last = Core.addr_access;
|
||||
addr_last = addr_access[0];
|
||||
}
|
||||
|
||||
if (counter == 0x30)
|
||||
{
|
||||
locked = false;
|
||||
Console.WriteLine("Unlocked");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,6 @@ namespace GBHawk
|
|||
{
|
||||
public:
|
||||
|
||||
bool locked, locked_GBC, finished;
|
||||
uint32_t ROM_bank_mask;
|
||||
uint32_t BASE_ROM_Bank;
|
||||
bool reg_access;
|
||||
uint32_t addr_last;
|
||||
uint32_t counter;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
ROM_bank = 1;
|
||||
|
@ -158,14 +151,14 @@ namespace GBHawk
|
|||
{
|
||||
if (locked)
|
||||
{
|
||||
if (((Core.addr_access & 0x8000) == 0) && ((addr_last & 0x8000) > 0) && (Core.addr_access >= 0x100))
|
||||
if (((addr_access[0] & 0x8000) == 0) && ((addr_last & 0x8000) > 0) && (addr_access[0] >= 0x100))
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
|
||||
if (Core.addr_access >= 0x100)
|
||||
if (addr_access[0] >= 0x100)
|
||||
{
|
||||
addr_last = Core.addr_access;
|
||||
addr_last = addr_access[0];
|
||||
}
|
||||
|
||||
if (counter == 0x30)
|
||||
|
@ -177,14 +170,14 @@ namespace GBHawk
|
|||
}
|
||||
else if (locked_GBC)
|
||||
{
|
||||
if (((Core.addr_access & 0x8000) == 0) && ((addr_last & 0x8000) > 0) && (Core.addr_access >= 0x100))
|
||||
if (((addr_access[0] & 0x8000) == 0) && ((addr_last & 0x8000) > 0) && (addr_access[0] >= 0x100))
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
|
||||
if (Core.addr_access >= 0x100)
|
||||
if (addr_access[0] >= 0x100)
|
||||
{
|
||||
addr_last = Core.addr_access;
|
||||
addr_last = addr_access[0];
|
||||
}
|
||||
|
||||
if (counter == 0x30)
|
||||
|
@ -196,7 +189,7 @@ namespace GBHawk
|
|||
// The above condition seems to never be reached as described in the mapper notes
|
||||
// so for now add this one
|
||||
|
||||
if ((Core.addr_access == 0x133) && (counter == 1))
|
||||
if ((addr_access[0] == 0x133) && (counter == 1))
|
||||
{
|
||||
locked_GBC = false;
|
||||
finished = true;
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include "LR35902.h"
|
||||
#include "PPU_Base.h"
|
||||
#include "GBAudio.h"
|
||||
#include "Mapper_Base.h"
|
||||
#include "SerialPort.h"
|
||||
#include "Timer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -59,7 +62,7 @@ namespace GBHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
return mapper_pntr->ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if ((addr >= 0xE000) && (addr < 0xF000))
|
||||
|
@ -70,7 +73,7 @@ namespace GBHawk
|
|||
{
|
||||
return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)];
|
||||
}
|
||||
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu.DMA_OAM_access)
|
||||
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu_pntr->DMA_OAM_access)
|
||||
{
|
||||
return OAM[addr - 0xFE00];
|
||||
}
|
||||
|
@ -97,7 +100,7 @@ namespace GBHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
return mapper_pntr->ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if (addr >= 0x200)
|
||||
|
@ -109,17 +112,17 @@ namespace GBHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
return mapper_pntr->ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
return mapper_pntr->ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
return mapper_pntr->ReadMemory(addr);
|
||||
}
|
||||
else if (addr < 0xA000)
|
||||
{
|
||||
|
@ -128,7 +131,7 @@ namespace GBHawk
|
|||
}
|
||||
else if (addr < 0xC000)
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
return mapper_pntr->ReadMemory(addr);
|
||||
}
|
||||
else if (addr < 0xD000)
|
||||
{
|
||||
|
@ -188,7 +191,7 @@ namespace GBHawk
|
|||
{
|
||||
RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)] = value;
|
||||
}
|
||||
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu.DMA_OAM_access)
|
||||
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu_pntr->DMA_OAM_access)
|
||||
{
|
||||
OAM[addr - 0xFE00] = value;
|
||||
}
|
||||
|
@ -213,7 +216,7 @@ namespace GBHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
mapper.WriteMemory(addr, value);
|
||||
mapper_pntr->WriteMemory(addr, value);
|
||||
}
|
||||
}
|
||||
else if (addr >= 0x200)
|
||||
|
@ -224,17 +227,17 @@ namespace GBHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
mapper.WriteMemory(addr, value);
|
||||
mapper_pntr->WriteMemory(addr, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.WriteMemory(addr, value);
|
||||
mapper_pntr->WriteMemory(addr, value);
|
||||
}
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
mapper.WriteMemory(addr, value);
|
||||
mapper_pntr->WriteMemory(addr, value);
|
||||
}
|
||||
else if (addr < 0xA000)
|
||||
{
|
||||
|
@ -242,7 +245,7 @@ namespace GBHawk
|
|||
}
|
||||
else if (addr < 0xC000)
|
||||
{
|
||||
mapper.WriteMemory(addr, value);
|
||||
mapper_pntr->WriteMemory(addr, value);
|
||||
}
|
||||
else if (addr < 0xD000)
|
||||
{
|
||||
|
@ -295,7 +298,7 @@ namespace GBHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
return mapper_pntr->ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if ((addr >= 0xE000) && (addr < 0xF000))
|
||||
|
@ -306,7 +309,7 @@ namespace GBHawk
|
|||
{
|
||||
return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)];
|
||||
}
|
||||
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu.DMA_OAM_access)
|
||||
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu_pntr->DMA_OAM_access)
|
||||
{
|
||||
return OAM[addr - 0xFE00];
|
||||
}
|
||||
|
@ -333,7 +336,7 @@ namespace GBHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
return mapper_pntr->ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if (addr >= 0x200)
|
||||
|
@ -345,17 +348,17 @@ namespace GBHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
return mapper_pntr->ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
return mapper_pntr->ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
return mapper.PeekMemory(addr);
|
||||
return mapper_pntr->PeekMemory(addr);
|
||||
}
|
||||
else if (addr < 0xA000)
|
||||
{
|
||||
|
@ -364,7 +367,7 @@ namespace GBHawk
|
|||
}
|
||||
else if (addr < 0xC000)
|
||||
{
|
||||
return mapper.PeekMemory(addr);
|
||||
return mapper_pntr->PeekMemory(addr);
|
||||
}
|
||||
else if (addr < 0xD000)
|
||||
{
|
||||
|
@ -405,4 +408,507 @@ namespace GBHawk
|
|||
return Read_Registers(addr);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t MemoryManager::Read_Registers(uint32_t addr)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
// Read Input
|
||||
case 0xFF00:
|
||||
_islag = false;
|
||||
ret = input_register;
|
||||
break;
|
||||
|
||||
// Serial data port
|
||||
case 0xFF01:
|
||||
ret = serialport_pntr->ReadReg(addr);
|
||||
break;
|
||||
|
||||
// Serial port control
|
||||
case 0xFF02:
|
||||
ret = serialport_pntr->ReadReg(addr);
|
||||
break;
|
||||
|
||||
// Timer Registers
|
||||
case 0xFF04:
|
||||
case 0xFF05:
|
||||
case 0xFF06:
|
||||
case 0xFF07:
|
||||
ret = timer_pntr->ReadReg(addr);
|
||||
break;
|
||||
|
||||
// Interrupt flags
|
||||
case 0xFF0F:
|
||||
ret = REG_FF0F_OLD;
|
||||
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 = psg_pntr->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_pntr->ReadReg(addr);
|
||||
break;
|
||||
|
||||
// Speed Control for GBC
|
||||
case 0xFF4D:
|
||||
if (GBC_compat)
|
||||
{
|
||||
ret = (uint8_t)(((double_speed ? 1 : 0) << 7) + ((speed_switch ? 1 : 0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF4F: // VBK
|
||||
if (GBC_compat)
|
||||
{
|
||||
ret = (uint8_t)(0xFE | VRAM_Bank);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
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:
|
||||
if (GBC_compat)
|
||||
{
|
||||
ret = ppu_pntr->ReadReg(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF56:
|
||||
if (GBC_compat)
|
||||
{
|
||||
// can receive data
|
||||
if ((IR_reg & 0xC0) == 0xC0)
|
||||
{
|
||||
ret = IR_reg;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = (uint8_t)(IR_reg | 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF68:
|
||||
case 0xFF69:
|
||||
case 0xFF6A:
|
||||
case 0xFF6B:
|
||||
if (GBC_compat)
|
||||
{
|
||||
ret = ppu_pntr->ReadReg(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
break;
|
||||
|
||||
// Speed Control for GBC
|
||||
case 0xFF70:
|
||||
if (GBC_compat)
|
||||
{
|
||||
ret = (uint8_t)RAM_Bank;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF6C:
|
||||
if (GBC_compat) { ret = undoc_6C; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF72:
|
||||
if (is_GBC) { ret = undoc_72; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF73:
|
||||
if (is_GBC) { ret = undoc_73; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF74:
|
||||
if (GBC_compat) { ret = undoc_74; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF75:
|
||||
if (is_GBC) { ret = undoc_75; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF76:
|
||||
if (is_GBC) { ret = undoc_76; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF77:
|
||||
if (is_GBC) { ret = undoc_77; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
// interrupt control register
|
||||
case 0xFFFF:
|
||||
ret = REG_FFFF;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = 0xFF;
|
||||
break;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MemoryManager::Write_Registers(uint32_t addr, uint8_t value)
|
||||
{
|
||||
// check for high to low transitions that trigger IRQs
|
||||
uint8_t contr_prev = input_register;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
// select input
|
||||
case 0xFF00:
|
||||
input_register &= 0xCF;
|
||||
input_register |= (uint8_t)(value & 0x30); // top 2 bits always 1
|
||||
|
||||
input_register &= 0xF0;
|
||||
if ((input_register & 0x30) == 0x20)
|
||||
{
|
||||
input_register |= (uint8_t)(controller_state & 0xF);
|
||||
}
|
||||
else if ((input_register & 0x30) == 0x10)
|
||||
{
|
||||
input_register |= (uint8_t)((controller_state & 0xF0) >> 4);
|
||||
}
|
||||
else if ((input_register & 0x30) == 0x00)
|
||||
{
|
||||
// if both polls are set, then a bit is zero if either or both pins are zero
|
||||
uint8_t temp = (uint8_t)((controller_state & 0xF) & ((controller_state & 0xF0) >> 4));
|
||||
input_register |= temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
input_register |= 0xF;
|
||||
}
|
||||
|
||||
// check for interrupts
|
||||
if (((contr_prev & 8) > 0) && ((input_register & 8) == 0) ||
|
||||
((contr_prev & 4) > 0) && ((input_register & 4) == 0) ||
|
||||
((contr_prev & 2) > 0) && ((input_register & 2) == 0) ||
|
||||
((contr_prev & 1) > 0) && ((input_register & 1) == 0))
|
||||
{
|
||||
if (((REG_FFFF & 0x10) > 0)) { cpu_pntr->FlagI = true; }
|
||||
REG_FF0F |= 0x10;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Serial data port
|
||||
case 0xFF01:
|
||||
serialport_pntr->WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
// Serial port control
|
||||
case 0xFF02:
|
||||
serialport_pntr->WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
// Timer Registers
|
||||
case 0xFF04:
|
||||
case 0xFF05:
|
||||
case 0xFF06:
|
||||
case 0xFF07:
|
||||
timer_pntr->WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
// Interrupt flags
|
||||
case 0xFF0F:
|
||||
REG_FF0F = (uint8_t)(0xE0 | value);
|
||||
|
||||
// check if enabling any of the bits triggered an IRQ
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (((REG_FFFF & (1 << i)) > 0) && ((REG_FF0F & (1 << i)) > 0))
|
||||
{
|
||||
cpu_pntr->FlagI = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if no bits are in common between flags and enables, de-assert the IRQ
|
||||
if (((REG_FF0F & 0x1F) & REG_FFFF) == 0) { cpu_pntr->FlagI = false; }
|
||||
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:
|
||||
psg_pntr->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_pntr->WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
// GBC compatibility register (I think)
|
||||
case 0xFF4C:
|
||||
if ((value != 0xC0) && (value != 0x80))// && (value != 0xFF) && (value != 0x04))
|
||||
{
|
||||
GBC_compat = false;
|
||||
|
||||
// cpu operation is a function of hardware only
|
||||
//cpu.is_GBC = GBC_compat;
|
||||
}
|
||||
break;
|
||||
|
||||
// Speed Control for GBC
|
||||
case 0xFF4D:
|
||||
if (GBC_compat)
|
||||
{
|
||||
speed_switch = (value & 1) > 0;
|
||||
}
|
||||
break;
|
||||
|
||||
// VBK
|
||||
case 0xFF4F:
|
||||
if (GBC_compat && !ppu_pntr->HDMA_active)
|
||||
{
|
||||
VRAM_Bank = (uint8_t)(value & 1);
|
||||
}
|
||||
break;
|
||||
|
||||
// Bios control register. Writing 1 permanently disables BIOS until a power cycle occurs
|
||||
case 0xFF50:
|
||||
// Console.WriteLine(value);
|
||||
if (GB_bios_register == 0)
|
||||
{
|
||||
GB_bios_register = value;
|
||||
}
|
||||
break;
|
||||
|
||||
// PPU Regs for GBC
|
||||
case 0xFF51:
|
||||
case 0xFF52:
|
||||
case 0xFF53:
|
||||
case 0xFF54:
|
||||
case 0xFF55:
|
||||
if (GBC_compat)
|
||||
{
|
||||
ppu_pntr->WriteReg(addr, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF56:
|
||||
if (is_GBC)
|
||||
{
|
||||
IR_reg = (uint8_t)((value & 0xC1) | (IR_reg & 0x3E));
|
||||
|
||||
// send IR signal out
|
||||
if ((IR_reg & 0x1) == 0x1) { IR_signal = (uint8_t)(0 | IR_mask); }
|
||||
else { IR_signal = 2; }
|
||||
|
||||
// receive own signal if IR on and receive on
|
||||
if ((IR_reg & 0xC1) == 0xC1) { IR_self = (uint8_t)(0 | IR_mask); }
|
||||
else { IR_self = 2; }
|
||||
|
||||
IR_write = 8;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF68:
|
||||
case 0xFF69:
|
||||
case 0xFF6A:
|
||||
case 0xFF6B:
|
||||
//if (GBC_compat)
|
||||
//{
|
||||
ppu_pntr->WriteReg(addr, value);
|
||||
//}
|
||||
break;
|
||||
|
||||
// RAM Bank in GBC mode
|
||||
case 0xFF70:
|
||||
//Console.WriteLine(value);
|
||||
if (GBC_compat)
|
||||
{
|
||||
RAM_Bank = value & 7;
|
||||
if (RAM_Bank == 0) { RAM_Bank = 1; }
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF6C:
|
||||
if (GBC_compat) { undoc_6C |= (uint8_t)(value & 1); }
|
||||
break;
|
||||
|
||||
case 0xFF72:
|
||||
if (is_GBC) { undoc_72 = value; }
|
||||
break;
|
||||
|
||||
case 0xFF73:
|
||||
if (is_GBC) { undoc_73 = value; }
|
||||
break;
|
||||
|
||||
case 0xFF74:
|
||||
if (GBC_compat) { undoc_74 = value; }
|
||||
break;
|
||||
|
||||
case 0xFF75:
|
||||
if (is_GBC) { undoc_75 |= (uint8_t)(value & 0x70); }
|
||||
break;
|
||||
|
||||
case 0xFF76:
|
||||
// read only
|
||||
break;
|
||||
|
||||
case 0xFF77:
|
||||
// read only
|
||||
break;
|
||||
|
||||
// interrupt control register
|
||||
case 0xFFFF:
|
||||
REG_FFFF = value;
|
||||
|
||||
// check if enabling any of the bits triggered an IRQ
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (((REG_FFFF & (1 << i)) > 0) && ((REG_FF0F & (1 << i)) > 0))
|
||||
{
|
||||
cpu_pntr->FlagI = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if no bits are in common between flags and enables, de-assert the IRQ
|
||||
if (((REG_FF0F & 0x1F) & REG_FFFF) == 0) { cpu_pntr->FlagI = false; }
|
||||
break;
|
||||
|
||||
default:
|
||||
//Console.Write(addr);
|
||||
//Console.Write(" ");
|
||||
//Console.WriteLine(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,8 @@ namespace GBHawk
|
|||
uint8_t ReadMemory(uint32_t addr);
|
||||
uint8_t PeekMemory(uint32_t addr);
|
||||
void WriteMemory(uint32_t addr, uint8_t value);
|
||||
uint8_t Read_Registers(uint32_t addr);
|
||||
void Write_Registers(uint32_t addr, uint8_t value);
|
||||
|
||||
#pragma region Declarations
|
||||
|
||||
|
@ -35,15 +37,14 @@ namespace GBHawk
|
|||
Timer* timer_pntr = nullptr;
|
||||
SerialPort* serialport_pntr = nullptr;
|
||||
Mapper* mapper_pntr = nullptr;
|
||||
uint8_t* rom_1 = nullptr;
|
||||
uint8_t* rom_2 = nullptr;
|
||||
uint8_t* ROM = nullptr;
|
||||
uint8_t* Cart_RAM = nullptr;
|
||||
uint8_t* bios_rom = nullptr;
|
||||
|
||||
// initialized by core loading, not savestated
|
||||
uint32_t rom_size_1;
|
||||
uint32_t rom_mapper_1;
|
||||
uint32_t rom_size_2;
|
||||
uint32_t rom_mapper_2;
|
||||
uint32_t ROM_Length;
|
||||
uint32_t ROM_Mapper;
|
||||
uint32_t Cart_RAM_Length;
|
||||
|
||||
// controls are not stated
|
||||
uint8_t controller_byte_1, controller_byte_2;
|
||||
|
@ -60,7 +61,7 @@ namespace GBHawk
|
|||
bool GB_bios_register;
|
||||
bool HDMA_transfer;
|
||||
bool _islag;
|
||||
uint8_t addr_access;
|
||||
|
||||
uint8_t REG_FFFF, REG_FF0F, REG_FF0F_OLD;
|
||||
uint8_t _scanlineCallbackLine;
|
||||
uint8_t input_register;
|
||||
|
@ -69,6 +70,9 @@ namespace GBHawk
|
|||
|
||||
uint8_t IR_reg, IR_mask, IR_signal, IR_receive, IR_self;
|
||||
uint32_t IR_write;
|
||||
uint32_t addr_access;
|
||||
uint32_t Acc_X_state;
|
||||
uint32_t Acc_Y_state;
|
||||
|
||||
// several undocumented GBC Registers
|
||||
uint8_t undoc_6C, undoc_72, undoc_73, undoc_74, undoc_75, undoc_76, undoc_77;
|
||||
|
@ -106,17 +110,12 @@ namespace GBHawk
|
|||
|
||||
void Load_ROM(uint8_t* ext_rom_1, uint32_t ext_rom_size_1, uint32_t ext_rom_mapper_1, uint8_t* ext_rom_2, uint32_t ext_rom_size_2, uint32_t ext_rom_mapper_2)
|
||||
{
|
||||
rom_1 = new uint8_t[ext_rom_size_1];
|
||||
rom_2 = new uint8_t[ext_rom_size_2];
|
||||
ROM = new uint8_t[ext_rom_size_1];
|
||||
|
||||
memcpy(rom_1, ext_rom_1, ext_rom_size_1);
|
||||
memcpy(rom_2, ext_rom_2, ext_rom_size_2);
|
||||
memcpy(ROM, ext_rom_1, ext_rom_size_1);
|
||||
|
||||
rom_size_1 = ext_rom_size_1 / 0x4000;
|
||||
rom_mapper_1 = ext_rom_mapper_1;
|
||||
|
||||
rom_size_2 = ext_rom_size_2 / 0x4000;
|
||||
rom_mapper_2 = ext_rom_mapper_2;
|
||||
ROM_Length = ext_rom_size_1;
|
||||
ROM_Mapper = ext_rom_mapper_1;
|
||||
}
|
||||
|
||||
// Switch Speed (GBC only)
|
||||
|
@ -140,509 +139,6 @@ namespace GBHawk
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint8_t Read_Registers(uint32_t addr)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
// Read Input
|
||||
case 0xFF00:
|
||||
_islag = false;
|
||||
ret = input_register;
|
||||
break;
|
||||
|
||||
// Serial data port
|
||||
case 0xFF01:
|
||||
ret = serialport_pntr->ReadReg(addr);
|
||||
break;
|
||||
|
||||
// Serial port control
|
||||
case 0xFF02:
|
||||
ret = serialport_pntr->ReadReg(addr);
|
||||
break;
|
||||
|
||||
// Timer Registers
|
||||
case 0xFF04:
|
||||
case 0xFF05:
|
||||
case 0xFF06:
|
||||
case 0xFF07:
|
||||
ret = timer_pntr->ReadReg(addr);
|
||||
break;
|
||||
|
||||
// Interrupt flags
|
||||
case 0xFF0F:
|
||||
ret = REG_FF0F_OLD;
|
||||
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 = psg_pntr->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_pntr->ReadReg(addr);
|
||||
break;
|
||||
|
||||
// Speed Control for GBC
|
||||
case 0xFF4D:
|
||||
if (GBC_compat)
|
||||
{
|
||||
ret = (uint8_t)(((double_speed ? 1 : 0) << 7) + ((speed_switch ? 1 : 0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF4F: // VBK
|
||||
if (GBC_compat)
|
||||
{
|
||||
ret = (uint8_t)(0xFE | VRAM_Bank);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
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:
|
||||
if (GBC_compat)
|
||||
{
|
||||
ret = ppu_pntr->ReadReg(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF56:
|
||||
if (GBC_compat)
|
||||
{
|
||||
// can receive data
|
||||
if ((IR_reg & 0xC0) == 0xC0)
|
||||
{
|
||||
ret = IR_reg;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = (uint8_t)(IR_reg | 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF68:
|
||||
case 0xFF69:
|
||||
case 0xFF6A:
|
||||
case 0xFF6B:
|
||||
if (GBC_compat)
|
||||
{
|
||||
ret = ppu_pntr->ReadReg(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
break;
|
||||
|
||||
// Speed Control for GBC
|
||||
case 0xFF70:
|
||||
if (GBC_compat)
|
||||
{
|
||||
ret = (uint8_t)RAM_Bank;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0xFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF6C:
|
||||
if (GBC_compat) { ret = undoc_6C; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF72:
|
||||
if (is_GBC) { ret = undoc_72; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF73:
|
||||
if (is_GBC) { ret = undoc_73; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF74:
|
||||
if (GBC_compat) { ret = undoc_74; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF75:
|
||||
if (is_GBC) { ret = undoc_75; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF76:
|
||||
if (is_GBC) { ret = undoc_76; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
case 0xFF77:
|
||||
if (is_GBC) { ret = undoc_77; }
|
||||
else { ret = 0xFF; }
|
||||
break;
|
||||
|
||||
// interrupt control register
|
||||
case 0xFFFF:
|
||||
ret = REG_FFFF;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = 0xFF;
|
||||
break;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Write_Registers(int addr, uint8_t value)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
// select input
|
||||
case 0xFF00:
|
||||
input_register &= 0xCF;
|
||||
input_register |= (uint8_t)(value & 0x30); // top 2 bits always 1
|
||||
|
||||
// check for high to low transitions that trigger IRQs
|
||||
uint8_t contr_prev = input_register;
|
||||
|
||||
input_register &= 0xF0;
|
||||
if ((input_register & 0x30) == 0x20)
|
||||
{
|
||||
input_register |= (uint8_t)(controller_state & 0xF);
|
||||
}
|
||||
else if ((input_register & 0x30) == 0x10)
|
||||
{
|
||||
input_register |= (uint8_t)((controller_state & 0xF0) >> 4);
|
||||
}
|
||||
else if ((input_register & 0x30) == 0x00)
|
||||
{
|
||||
// if both polls are set, then a bit is zero if either or both pins are zero
|
||||
uint8_t temp = (uint8_t)((controller_state & 0xF) & ((controller_state & 0xF0) >> 4));
|
||||
input_register |= temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
input_register |= 0xF;
|
||||
}
|
||||
|
||||
// check for interrupts
|
||||
if (((contr_prev & 8) > 0) && ((input_register & 8) == 0) ||
|
||||
((contr_prev & 4) > 0) && ((input_register & 4) == 0) ||
|
||||
((contr_prev & 2) > 0) && ((input_register & 2) == 0) ||
|
||||
((contr_prev & 1) > 0) && ((input_register & 1) == 0))
|
||||
{
|
||||
if (((REG_FFFF & 0x10) > 0)) { cpu_pntr->FlagI = true; }
|
||||
REG_FF0F |= 0x10;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Serial data port
|
||||
case 0xFF01:
|
||||
serialport_pntr->WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
// Serial port control
|
||||
case 0xFF02:
|
||||
serialport_pntr->WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
// Timer Registers
|
||||
case 0xFF04:
|
||||
case 0xFF05:
|
||||
case 0xFF06:
|
||||
case 0xFF07:
|
||||
timer_pntr->WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
// Interrupt flags
|
||||
case 0xFF0F:
|
||||
REG_FF0F = (uint8_t)(0xE0 | value);
|
||||
|
||||
// check if enabling any of the bits triggered an IRQ
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (((REG_FFFF & (1 <<i)) > 0) && ((REG_FF0F & (1 << i)) > 0))
|
||||
{
|
||||
cpu_pntr->FlagI = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if no bits are in common between flags and enables, de-assert the IRQ
|
||||
if (((REG_FF0F & 0x1F) & REG_FFFF) == 0) { cpu_pntr->FlagI = false; }
|
||||
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:
|
||||
psg_pntr->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_pntr->WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
// GBC compatibility register (I think)
|
||||
case 0xFF4C:
|
||||
if ((value != 0xC0) && (value != 0x80))// && (value != 0xFF) && (value != 0x04))
|
||||
{
|
||||
GBC_compat = false;
|
||||
|
||||
// cpu operation is a function of hardware only
|
||||
//cpu.is_GBC = GBC_compat;
|
||||
}
|
||||
break;
|
||||
|
||||
// Speed Control for GBC
|
||||
case 0xFF4D:
|
||||
if (GBC_compat)
|
||||
{
|
||||
speed_switch = (value & 1) > 0;
|
||||
}
|
||||
break;
|
||||
|
||||
// VBK
|
||||
case 0xFF4F:
|
||||
if (GBC_compat && !ppu_pntr->HDMA_active)
|
||||
{
|
||||
VRAM_Bank = (uint8_t)(value & 1);
|
||||
}
|
||||
break;
|
||||
|
||||
// Bios control register. Writing 1 permanently disables BIOS until a power cycle occurs
|
||||
case 0xFF50:
|
||||
// Console.WriteLine(value);
|
||||
if (GB_bios_register == 0)
|
||||
{
|
||||
GB_bios_register = value;
|
||||
}
|
||||
break;
|
||||
|
||||
// PPU Regs for GBC
|
||||
case 0xFF51:
|
||||
case 0xFF52:
|
||||
case 0xFF53:
|
||||
case 0xFF54:
|
||||
case 0xFF55:
|
||||
if (GBC_compat)
|
||||
{
|
||||
ppu_pntr->WriteReg(addr, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF56:
|
||||
if (is_GBC)
|
||||
{
|
||||
IR_reg = (uint8_t)((value & 0xC1) | (IR_reg & 0x3E));
|
||||
|
||||
// send IR signal out
|
||||
if ((IR_reg & 0x1) == 0x1) { IR_signal = (uint8_t)(0 | IR_mask); }
|
||||
else { IR_signal = 2; }
|
||||
|
||||
// receive own signal if IR on and receive on
|
||||
if ((IR_reg & 0xC1) == 0xC1) { IR_self = (uint8_t)(0 | IR_mask); }
|
||||
else { IR_self = 2; }
|
||||
|
||||
IR_write = 8;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF68:
|
||||
case 0xFF69:
|
||||
case 0xFF6A:
|
||||
case 0xFF6B:
|
||||
//if (GBC_compat)
|
||||
//{
|
||||
ppu_pntr->WriteReg(addr, value);
|
||||
//}
|
||||
break;
|
||||
|
||||
// RAM Bank in GBC mode
|
||||
case 0xFF70:
|
||||
//Console.WriteLine(value);
|
||||
if (GBC_compat)
|
||||
{
|
||||
RAM_Bank = value & 7;
|
||||
if (RAM_Bank == 0) { RAM_Bank = 1; }
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF6C:
|
||||
if (GBC_compat) { undoc_6C |= (uint8_t)(value & 1); }
|
||||
break;
|
||||
|
||||
case 0xFF72:
|
||||
if (is_GBC) { undoc_72 = value; }
|
||||
break;
|
||||
|
||||
case 0xFF73:
|
||||
if (is_GBC) { undoc_73 = value; }
|
||||
break;
|
||||
|
||||
case 0xFF74:
|
||||
if (GBC_compat) { undoc_74 = value; }
|
||||
break;
|
||||
|
||||
case 0xFF75:
|
||||
if (is_GBC) { undoc_75 |= (uint8_t)(value & 0x70); }
|
||||
break;
|
||||
|
||||
case 0xFF76:
|
||||
// read only
|
||||
break;
|
||||
|
||||
case 0xFF77:
|
||||
// read only
|
||||
break;
|
||||
|
||||
// interrupt control register
|
||||
case 0xFFFF:
|
||||
REG_FFFF = value;
|
||||
|
||||
// check if enabling any of the bits triggered an IRQ
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (((REG_FFFF & (1 << i)) > 0) && ((REG_FF0F & (1 << i)) > 0))
|
||||
{
|
||||
cpu_pntr->FlagI = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if no bits are in common between flags and enables, de-assert the IRQ
|
||||
if (((REG_FF0F & 0x1F) & REG_FFFF) == 0) { cpu_pntr->FlagI = false; }
|
||||
break;
|
||||
|
||||
default:
|
||||
//Console.Write(addr);
|
||||
//Console.Write(" ");
|
||||
//Console.WriteLine(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Register_Reset()
|
||||
{
|
||||
input_register = 0xCF; // not reading any input
|
||||
|
|
Loading…
Reference in New Issue