GBHawk: finish PPU ports
This commit is contained in:
parent
6ee8d6d312
commit
37e8b29056
|
@ -28,9 +28,12 @@ namespace GBHawk
|
|||
ppu._scanlineCallbackLine = &MemMap._scanlineCallbackLine;
|
||||
ppu.OAM = &MemMap.OAM[0];
|
||||
ppu.VRAM = &MemMap.VRAM[0];
|
||||
ppu.VRAM_Bank = &MemMap.VRAM_Bank;
|
||||
ppu.cpu_halted = &cpu.halted;
|
||||
ppu._vidbuffer = &MemMap._vidbuffer[0];
|
||||
ppu.color_palette = &MemMap.color_palette[0];
|
||||
ppu.HDMA_transfer = &MemMap.HDMA_transfer;
|
||||
ppu.GBC_compat = &MemMap.GBC_compat;
|
||||
|
||||
sl_case = 0;
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -153,6 +153,8 @@
|
|||
<ItemGroup>
|
||||
<ClInclude Include="GBAudio.h" />
|
||||
<ClInclude Include="Core.h" />
|
||||
<ClInclude Include="GBC_GB_PPU.h" />
|
||||
<ClInclude Include="GBC_PPU.h" />
|
||||
<ClInclude Include="GBHawk.h" />
|
||||
<ClInclude Include="GB_PPU.h" />
|
||||
<ClInclude Include="Memory.h" />
|
||||
|
|
|
@ -13,8 +13,6 @@ namespace GBHawk
|
|||
class GB_PPU : public PPU
|
||||
{
|
||||
public:
|
||||
#pragma region PPU
|
||||
|
||||
uint8_t ReadReg(uint32_t addr)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
|
@ -559,8 +557,8 @@ namespace GBHawk
|
|||
if (render_counter >= (render_offset + 8))
|
||||
{
|
||||
|
||||
pixel = tile_data_latch[0] & (1 << (7 - (render_counter % 8))) > 0 ? 1 : 0;
|
||||
pixel |= tile_data_latch[1] & (1 << (7 - (render_counter % 8))) > 0 ? 2 : 0;
|
||||
pixel = (tile_data_latch[0] & (1 << (7 - (render_counter % 8))) > 0) ? 1 : 0;
|
||||
pixel |= (tile_data_latch[1] & (1 << (7 - (render_counter % 8))) > 0) ? 2 : 0;
|
||||
|
||||
uint32_t ref_pixel = pixel;
|
||||
if (((LCDC & 0x1) > 0))
|
||||
|
@ -665,7 +663,7 @@ namespace GBHawk
|
|||
if ((internal_cycle % 2) == 1)
|
||||
{
|
||||
// calculate the row number of the tiles to be fetched
|
||||
y_tile = ((uint32_t)floor((float)(scroll_y + LY) / 8.0)) % 32;
|
||||
y_tile = ((uint32_t)floor((float)((uint32_t)scroll_y + LY) / 8.0)) % 32;
|
||||
|
||||
temp_fetch = y_tile * 32 + (x_tile + tile_inc) % 32;
|
||||
tile_byte = VRAM[0x1800 + (((LCDC & 0x8) > 0) ? 1 : 0) * 0x400 + temp_fetch];
|
||||
|
@ -945,7 +943,7 @@ namespace GBHawk
|
|||
else if (((last_eval + render_offset) % 8) == 6) { sprite_fetch_counter += 0; }
|
||||
else if (((last_eval + render_offset) % 8) == 7) { sprite_fetch_counter += 0; }
|
||||
|
||||
consecutive_sprite = (uint32_t)floor((double)(last_eval + render_offset) / 8.0) * 8 + 8 - render_offset;
|
||||
consecutive_sprite = (uint32_t)floor((double)((uint32_t)last_eval + render_offset) / 8.0) * 8 + 8 - render_offset;
|
||||
|
||||
// special case exists here for sprites at zero with non-zero x-scroll. Not sure exactly the reason for it.
|
||||
if (last_eval == 0 && render_offset != 0)
|
||||
|
@ -1043,12 +1041,12 @@ namespace GBHawk
|
|||
// So transfers nominally from higher memory areas are actually still from there (i.e. FF -> DF)
|
||||
uint8_t DMA_actual = DMA_addr;
|
||||
if (DMA_addr > 0xDF) { DMA_actual &= 0xDF; }
|
||||
DMA_uint8_t = ReadMemory((uint32_t)((DMA_actual << 8) + DMA_inc));
|
||||
DMA_byte = ReadMemory((uint32_t)((DMA_actual << 8) + DMA_inc));
|
||||
DMA_start = true;
|
||||
}
|
||||
else if ((DMA_clock % 4) == 3)
|
||||
{
|
||||
OAM[DMA_inc] = DMA_uint8_t;
|
||||
OAM[DMA_inc] = DMA_byte;
|
||||
|
||||
if (DMA_inc < (0xA0 - 1)) { DMA_inc++; }
|
||||
}
|
||||
|
|
|
@ -11,21 +11,21 @@ namespace GBHawk
|
|||
{
|
||||
void LR35902::WriteMemory(uint32_t addr, uint8_t value)
|
||||
{
|
||||
mem_ctrl->MemoryWrite(addr, value);
|
||||
mem_ctrl->WriteMemory(addr, value);
|
||||
}
|
||||
|
||||
uint8_t LR35902::ReadMemory(uint32_t addr)
|
||||
{
|
||||
return mem_ctrl->HardwareRead(addr);
|
||||
return mem_ctrl->ReadMemory(addr);
|
||||
}
|
||||
|
||||
uint8_t LR35902::PeekMemory(uint32_t addr)
|
||||
{
|
||||
return mem_ctrl->HardwareRead(addr);
|
||||
return mem_ctrl->PeekMemory(addr);
|
||||
}
|
||||
|
||||
uint8_t LR35902::SpeedFunc(uint32_t addr)
|
||||
uint8_t LR35902::SpeedFunc(uint32_t val)
|
||||
{
|
||||
return mem_ctrl->HardwareRead(addr);
|
||||
return mem_ctrl->SpeedFunc(val);
|
||||
}
|
||||
}
|
|
@ -12,14 +12,397 @@ using namespace std;
|
|||
|
||||
namespace GBHawk
|
||||
{
|
||||
uint8_t MemoryManager::HardwareRead(uint32_t port)
|
||||
{
|
||||
/*
|
||||
$FFFF Interrupt Enable Flag
|
||||
$FF80-$FFFE Zero Page - 127 bytes
|
||||
$FF00-$FF7F Hardware I/O Registers
|
||||
$FEA0-$FEFF Unusable Memory
|
||||
$FE00-$FE9F OAM - Object Attribute Memory
|
||||
$E000-$FDFF Echo RAM - Reserved, Do Not Use
|
||||
$D000-$DFFF Internal RAM - Bank 1-7 (switchable - CGB only)
|
||||
$C000-$CFFF Internal RAM - Bank 0 (fixed)
|
||||
$A000-$BFFF Cartridge RAM (If Available)
|
||||
$9C00-$9FFF BG Map Data 2
|
||||
$9800-$9BFF BG Map Data 1
|
||||
$8000-$97FF Character RAM
|
||||
$4000-$7FFF Cartridge ROM - Switchable Banks 1-xx
|
||||
$0150-$3FFF Cartridge ROM - Bank 0 (fixed)
|
||||
$0100-$014F Cartridge Header Area
|
||||
$0000-$00FF Restart and Interrupt Vectors
|
||||
*/
|
||||
|
||||
/*
|
||||
* VRAM is arranged as:
|
||||
* 0x1800 Tiles
|
||||
* 0x400 BG Map 1
|
||||
* 0x400 BG Map 2
|
||||
* 0x1800 Tiles
|
||||
* 0x400 CA Map 1
|
||||
* 0x400 CA Map 2
|
||||
* Only the top set is available in GB (i.e. VRAM_Bank = 0)
|
||||
*/
|
||||
|
||||
uint8_t MemoryManager::ReadMemory(uint32_t addr)
|
||||
{
|
||||
//uint flags = (uint)(MemoryCallbackFlags.AccessRead);
|
||||
//MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus");
|
||||
addr_access = addr;
|
||||
|
||||
if (ppu_pntr->DMA_start)
|
||||
{
|
||||
// some of gekkio's tests require these to be accessible during DMA
|
||||
if (addr < 0x8000)
|
||||
{
|
||||
if (ppu_pntr->DMA_addr < 0x80)
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if ((addr >= 0xE000) && (addr < 0xF000))
|
||||
{
|
||||
return RAM[addr - 0xE000];
|
||||
}
|
||||
else if ((addr >= 0xF000) && (addr < 0xFE00))
|
||||
{
|
||||
return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)];
|
||||
}
|
||||
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu.DMA_OAM_access)
|
||||
{
|
||||
return OAM[addr - 0xFE00];
|
||||
}
|
||||
else if ((addr >= 0xFF00) && (addr < 0xFF80)) // The game GOAL! Requires Hardware Regs to be accessible
|
||||
{
|
||||
return Read_Registers(addr);
|
||||
}
|
||||
else if ((addr >= 0xFF80))
|
||||
{
|
||||
return ZP_RAM[addr - 0xFF80];
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
if (addr < 0x900)
|
||||
{
|
||||
if (addr < 0x100)
|
||||
{
|
||||
// return Either BIOS ROM or Game ROM
|
||||
if ((GB_bios_register & 0x1) == 0)
|
||||
{
|
||||
return bios_rom[addr]; // Return BIOS
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if (addr >= 0x200)
|
||||
{
|
||||
// return Either BIOS ROM or Game ROM
|
||||
if (((GB_bios_register & 0x1) == 0) && is_GBC)
|
||||
{
|
||||
return bios_rom[addr]; // Return BIOS
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
else if (addr < 0xA000)
|
||||
{
|
||||
if (ppu_pntr->VRAM_access_read) { return VRAM[(VRAM_Bank * 0x2000) + (addr - 0x8000)]; }
|
||||
else { return 0xFF; }
|
||||
}
|
||||
else if (addr < 0xC000)
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
else if (addr < 0xD000)
|
||||
{
|
||||
return RAM[addr - 0xC000];
|
||||
}
|
||||
else if (addr < 0xE000)
|
||||
{
|
||||
return RAM[(RAM_Bank * 0x1000) + (addr - 0xD000)];
|
||||
}
|
||||
else if (addr < 0xF000)
|
||||
{
|
||||
return RAM[addr - 0xE000];
|
||||
}
|
||||
else if (addr < 0xFE00)
|
||||
{
|
||||
return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)];
|
||||
}
|
||||
else if (addr < 0xFEA0)
|
||||
{
|
||||
if (ppu_pntr->OAM_access_read) { return OAM[addr - 0xFE00]; }
|
||||
else { return 0xFF; }
|
||||
}
|
||||
else if (addr < 0xFF00)
|
||||
{
|
||||
// unmapped memory, returns 0xFF
|
||||
return 0xFF;
|
||||
}
|
||||
else if (addr < 0xFF80)
|
||||
{
|
||||
return Read_Registers(addr);
|
||||
}
|
||||
else if (addr < 0xFFFF)
|
||||
{
|
||||
return ZP_RAM[addr - 0xFF80];
|
||||
}
|
||||
else
|
||||
{
|
||||
return Read_Registers(addr);
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void MemoryManager::HardwareWrite(uint32_t port, uint8_t value)
|
||||
void MemoryManager::WriteMemory(uint32_t addr, uint8_t value)
|
||||
{
|
||||
//uint flags = (uint)(MemoryCallbackFlags.AccessWrite);
|
||||
//MemoryCallbacks.CallMemoryCallbacks(addr, value, flags, "System Bus");
|
||||
addr_access = addr;
|
||||
|
||||
if (ppu_pntr->DMA_start)
|
||||
{
|
||||
// some of gekkio's tests require this to be accessible during DMA
|
||||
if ((addr >= 0xE000) && (addr < 0xF000))
|
||||
{
|
||||
RAM[addr - 0xE000] = value;
|
||||
}
|
||||
else if ((addr >= 0xF000) && (addr < 0xFE00))
|
||||
{
|
||||
RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)] = value;
|
||||
}
|
||||
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu.DMA_OAM_access)
|
||||
{
|
||||
OAM[addr - 0xFE00] = value;
|
||||
}
|
||||
else if ((addr >= 0xFF00) && (addr < 0xFF80)) // The game GOAL! Requires Hardware Regs to be accessible
|
||||
{
|
||||
Write_Registers(addr, value);
|
||||
}
|
||||
else if ((addr >= 0xFF80))
|
||||
{
|
||||
ZP_RAM[addr - 0xFF80] = value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (addr < 0x900)
|
||||
{
|
||||
if (addr < 0x100)
|
||||
{
|
||||
if ((GB_bios_register & 0x1) == 0)
|
||||
{
|
||||
// No Writing to BIOS
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.WriteMemory(addr, value);
|
||||
}
|
||||
}
|
||||
else if (addr >= 0x200)
|
||||
{
|
||||
if (((GB_bios_register & 0x1) == 0) && is_GBC)
|
||||
{
|
||||
// No Writing to BIOS
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.WriteMemory(addr, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.WriteMemory(addr, value);
|
||||
}
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
mapper.WriteMemory(addr, value);
|
||||
}
|
||||
else if (addr < 0xA000)
|
||||
{
|
||||
if (ppu_pntr->VRAM_access_write) { VRAM[(VRAM_Bank * 0x2000) + (addr - 0x8000)] = value; }
|
||||
}
|
||||
else if (addr < 0xC000)
|
||||
{
|
||||
mapper.WriteMemory(addr, value);
|
||||
}
|
||||
else if (addr < 0xD000)
|
||||
{
|
||||
RAM[addr - 0xC000] = value;
|
||||
}
|
||||
else if (addr < 0xE000)
|
||||
{
|
||||
RAM[(RAM_Bank * 0x1000) + (addr - 0xD000)] = value;
|
||||
}
|
||||
else if (addr < 0xF000)
|
||||
{
|
||||
RAM[addr - 0xE000] = value;
|
||||
}
|
||||
else if (addr < 0xFE00)
|
||||
{
|
||||
RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)] = value;
|
||||
}
|
||||
else if (addr < 0xFEA0)
|
||||
{
|
||||
if (ppu_pntr->OAM_access_write) { OAM[addr - 0xFE00] = value; }
|
||||
}
|
||||
else if (addr < 0xFF00)
|
||||
{
|
||||
// unmapped, writing has no effect
|
||||
}
|
||||
else if (addr < 0xFF80)
|
||||
{
|
||||
Write_Registers(addr, value);
|
||||
}
|
||||
else if (addr < 0xFFFF)
|
||||
{
|
||||
ZP_RAM[addr - 0xFF80] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Write_Registers(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t MemoryManager::PeekMemory(uint32_t addr)
|
||||
{
|
||||
if (ppu_pntr->DMA_start)
|
||||
{
|
||||
// some of gekkio's tests require these to be accessible during DMA
|
||||
if (addr < 0x8000)
|
||||
{
|
||||
if (ppu.DMA_addr < 0x80)
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if ((addr >= 0xE000) && (addr < 0xF000))
|
||||
{
|
||||
return RAM[addr - 0xE000];
|
||||
}
|
||||
else if ((addr >= 0xF000) && (addr < 0xFE00))
|
||||
{
|
||||
return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)];
|
||||
}
|
||||
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu.DMA_OAM_access)
|
||||
{
|
||||
return OAM[addr - 0xFE00];
|
||||
}
|
||||
else if ((addr >= 0xFF00) && (addr < 0xFF80)) // The game GOAL! Requires Hardware Regs to be accessible
|
||||
{
|
||||
return Read_Registers(addr);
|
||||
}
|
||||
else if ((addr >= 0xFF80))
|
||||
{
|
||||
return ZP_RAM[addr - 0xFF80];
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
if (addr < 0x900)
|
||||
{
|
||||
if (addr < 0x100)
|
||||
{
|
||||
// return Either BIOS ROM or Game ROM
|
||||
if ((GB_bios_register & 0x1) == 0)
|
||||
{
|
||||
return bios_rom[addr]; // Return BIOS
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if (addr >= 0x200)
|
||||
{
|
||||
// return Either BIOS ROM or Game ROM
|
||||
if (((GB_bios_register & 0x1) == 0) && is_GBC)
|
||||
{
|
||||
return bios_rom[addr]; // Return BIOS
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
return mapper.PeekMemory(addr);
|
||||
}
|
||||
else if (addr < 0xA000)
|
||||
{
|
||||
if (ppu_pntr->VRAM_access_read) { return VRAM[(VRAM_Bank * 0x2000) + (addr - 0x8000)]; }
|
||||
else { return 0xFF; }
|
||||
}
|
||||
else if (addr < 0xC000)
|
||||
{
|
||||
return mapper.PeekMemory(addr);
|
||||
}
|
||||
else if (addr < 0xD000)
|
||||
{
|
||||
return RAM[addr - 0xC000];
|
||||
}
|
||||
else if (addr < 0xE000)
|
||||
{
|
||||
return RAM[(RAM_Bank * 0x1000) + (addr - 0xD000)];
|
||||
}
|
||||
else if (addr < 0xF000)
|
||||
{
|
||||
return RAM[addr - 0xE000];
|
||||
}
|
||||
else if (addr < 0xFE00)
|
||||
{
|
||||
return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)];
|
||||
}
|
||||
else if (addr < 0xFEA0)
|
||||
{
|
||||
if (ppu_pntr->OAM_access_read) { return OAM[addr - 0xFE00]; }
|
||||
else { return 0xFF; }
|
||||
}
|
||||
else if (addr < 0xFF00)
|
||||
{
|
||||
// unmapped memory, returns 0xFF
|
||||
return 0xFF;
|
||||
}
|
||||
else if (addr < 0xFF80)
|
||||
{
|
||||
return Read_Registers(addr);
|
||||
}
|
||||
else if (addr < 0xFFFF)
|
||||
{
|
||||
return ZP_RAM[addr - 0xFF80];
|
||||
}
|
||||
else
|
||||
{
|
||||
return Read_Registers(addr);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,17 @@ namespace GBHawk
|
|||
{
|
||||
public:
|
||||
|
||||
MemoryManager()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
uint8_t ReadMemory(uint32_t addr);
|
||||
uint8_t PeekMemory(uint32_t addr);
|
||||
void WriteMemory(uint32_t addr, uint8_t value);
|
||||
|
||||
#pragma region Declarations
|
||||
|
||||
PPU* ppu_pntr = nullptr;
|
||||
GBAudio* psg_pntr = nullptr;
|
||||
LR35902* cpu_pntr = nullptr;
|
||||
|
@ -36,11 +47,20 @@ namespace GBHawk
|
|||
bool PortDEEnabled = false;
|
||||
bool lagged;
|
||||
bool start_pressed;
|
||||
bool is_GBC;
|
||||
bool GBC_compat;
|
||||
bool speed_switch, double_speed;
|
||||
bool in_vblank;
|
||||
bool GB_bios_register;
|
||||
bool HDMA_transfer;
|
||||
uint8_t addr_access;
|
||||
uint8_t REG_FFFF, REG_FF0F;
|
||||
uint8_t _scanlineCallbackLine;
|
||||
uint32_t RAM_Bank;
|
||||
uint32_t VRAM_Bank;
|
||||
|
||||
uint8_t kb_rows_sel;
|
||||
uint8_t PortA8 = 0x00;
|
||||
uint8_t reg_FFFC, reg_FFFD, reg_FFFE, reg_FFFF;
|
||||
uint8_t RAM[0x10000] = {};
|
||||
uint8_t ZP_RAM[0x80] = {};
|
||||
uint8_t RAM[0x8000] = {};
|
||||
uint8_t VRAM[0x10000] = {};
|
||||
uint8_t OAM[0x10000] = {};
|
||||
uint8_t cart_ram[0x8000] = {};
|
||||
|
@ -48,39 +68,24 @@ namespace GBHawk
|
|||
uint32_t _vidbuffer[160 * 144] = {};
|
||||
uint32_t color_palette[4] = { 0xFFFFFFFF , 0xFFAAAAAA, 0xFF555555, 0xFF000000 };
|
||||
|
||||
uint32_t FrameBuffer[0x400] = {};
|
||||
uint32_t FrameBuffer[160 * 144] = {};
|
||||
|
||||
// state shared amongst different components
|
||||
bool in_vblank;
|
||||
uint8_t REG_FFFF, REG_FF0F;
|
||||
uint8_t _scanlineCallbackLine;
|
||||
#pragma endregion
|
||||
|
||||
|
||||
MemoryManager()
|
||||
#pragma region Functions
|
||||
// NOTE: only called when checks pass that the files are correct
|
||||
void Load_BIOS(uint8_t* bios, bool GBC_console)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
uint8_t HardwareRead(uint32_t value);
|
||||
|
||||
void HardwareWrite(uint32_t addr, uint8_t value);
|
||||
|
||||
// NOTE: only called from source when both are available and of correct size (0x4000)
|
||||
void Load_BIOS(uint8_t* bios, bool GBC_console)
|
||||
{
|
||||
if (GBC_console)
|
||||
if (GBC_console)
|
||||
{
|
||||
bios_rom = new uint8_t[2304];
|
||||
memcpy(bios_rom, bios, 2304);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
bios_rom = new uint8_t[256];
|
||||
memcpy(bios_rom, bios, 256);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -96,16 +101,33 @@ namespace GBHawk
|
|||
|
||||
rom_size_2 = ext_rom_size_2 / 0x4000;
|
||||
rom_mapper_2 = ext_rom_mapper_2;
|
||||
|
||||
// default memory map setup
|
||||
PortA8 = 0;
|
||||
}
|
||||
|
||||
void MemoryWrite(uint32_t addr, uint8_t value)
|
||||
// Switch Speed (GBC only)
|
||||
uint32_t SpeedFunc(uint32_t temp)
|
||||
{
|
||||
if (is_GBC)
|
||||
{
|
||||
if (speed_switch)
|
||||
{
|
||||
speed_switch = false;
|
||||
uint32_t ret = double_speed ? 70224 * 2 : 70224 * 2; // actual time needs checking
|
||||
double_speed = !double_speed;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// if we are not switching speed, return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if we are in GB mode, return 0 indicating not switching speed
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region State Save / Load
|
||||
|
||||
uint8_t* SaveState(uint8_t* saver)
|
||||
|
@ -114,13 +136,6 @@ namespace GBHawk
|
|||
*saver = (uint8_t)(lagged ? 1 : 0); saver++;
|
||||
*saver = (uint8_t)(start_pressed ? 1 : 0); saver++;
|
||||
|
||||
*saver = kb_rows_sel; saver++;
|
||||
*saver = PortA8; saver++;
|
||||
*saver = reg_FFFC; saver++;
|
||||
*saver = reg_FFFD; saver++;
|
||||
*saver = reg_FFFE; saver++;
|
||||
*saver = reg_FFFF; saver++;
|
||||
|
||||
std::memcpy(saver, &RAM, 0x10000); saver += 0x10000;
|
||||
std::memcpy(saver, &cart_ram, 0x8000); saver += 0x8000;
|
||||
|
||||
|
@ -133,13 +148,6 @@ namespace GBHawk
|
|||
lagged = *loader == 1; loader++;
|
||||
start_pressed = *loader == 1; loader++;
|
||||
|
||||
kb_rows_sel = *loader; loader++;
|
||||
PortA8 = *loader; loader++;
|
||||
reg_FFFC = *loader; loader++;
|
||||
reg_FFFD = *loader; loader++;
|
||||
reg_FFFE = *loader; loader++;
|
||||
reg_FFFF = *loader; loader++;
|
||||
|
||||
std::memcpy(&RAM, loader, 0x10000); loader += 0x10000;
|
||||
std::memcpy(&cart_ram, loader, 0x8000); loader += 0x8000;
|
||||
|
||||
|
|
|
@ -11,6 +11,6 @@ namespace GBHawk
|
|||
{
|
||||
uint8_t PPU::ReadMemory(uint32_t addr)
|
||||
{
|
||||
return mem_ctrl->HardwareRead(addr);
|
||||
return mem_ctrl->ReadMemory(addr);
|
||||
}
|
||||
}
|
|
@ -19,21 +19,26 @@ namespace GBHawk
|
|||
|
||||
}
|
||||
|
||||
uint8_t ReadMemory(uint32_t);
|
||||
|
||||
MemoryManager* mem_ctrl;
|
||||
|
||||
// pointers not stated
|
||||
bool* FlagI = nullptr;
|
||||
bool* in_vblank = nullptr;
|
||||
bool* cpu_halted = nullptr;
|
||||
bool* HDMA_transfer = nullptr;
|
||||
bool* GBC_compat = nullptr;
|
||||
|
||||
uint8_t* cpu_LY = nullptr;
|
||||
uint8_t* REG_FFFF = nullptr;
|
||||
uint8_t* REG_FF0F = nullptr;
|
||||
uint8_t* _scanlineCallbackLine = nullptr;
|
||||
uint8_t* OAM = nullptr;
|
||||
uint8_t* VRAM = nullptr;
|
||||
uint32_t* VRAM_Bank = nullptr;
|
||||
uint32_t* _vidbuffer = nullptr;
|
||||
uint32_t* color_palette = nullptr;
|
||||
|
||||
|
||||
uint32_t BG_palette[32] = {};
|
||||
uint32_t OBJ_palette[32] = {};
|
||||
|
@ -59,7 +64,7 @@ namespace GBHawk
|
|||
bool DMA_start;
|
||||
uint32_t DMA_clock;
|
||||
uint32_t DMA_inc;
|
||||
uint8_t DMA_uint8_t;
|
||||
uint8_t DMA_byte;
|
||||
|
||||
// state variables
|
||||
uint32_t cycle;
|
||||
|
@ -136,14 +141,54 @@ namespace GBHawk
|
|||
|
||||
uint32_t hbl_countdown;
|
||||
|
||||
uint8_t ReadMemory(uint32_t);
|
||||
// The following are GBC specific variables
|
||||
// individual uint8_t used in palette colors
|
||||
uint8_t BG_bytes[64] = {};
|
||||
uint8_t OBJ_bytes[64] = {};
|
||||
bool BG_bytes_inc;
|
||||
bool OBJ_bytes_inc;
|
||||
uint8_t BG_bytes_index;
|
||||
uint8_t OBJ_bytes_index;
|
||||
uint8_t BG_transfer_byte;
|
||||
uint8_t OBJ_transfer_byte;
|
||||
|
||||
virtual uint8_t ReadReg(int addr)
|
||||
// HDMA is unique to GBC, do it as part of the PPU tick
|
||||
uint8_t HDMA_src_hi;
|
||||
uint8_t HDMA_src_lo;
|
||||
uint8_t HDMA_dest_hi;
|
||||
uint8_t HDMA_dest_lo;
|
||||
uint32_t HDMA_tick;
|
||||
uint8_t HDMA_byte;
|
||||
|
||||
// controls for tile attributes
|
||||
uint32_t VRAM_sel;
|
||||
bool BG_V_flip;
|
||||
bool HDMA_mode;
|
||||
bool HDMA_run_once;
|
||||
uint32_t cur_DMA_src;
|
||||
uint32_t cur_DMA_dest;
|
||||
uint32_t HDMA_length;
|
||||
uint32_t HDMA_countdown;
|
||||
uint32_t HBL_HDMA_count;
|
||||
uint32_t last_HBL;
|
||||
bool HBL_HDMA_go;
|
||||
bool HBL_test;
|
||||
uint8_t LYC_t;
|
||||
uint32_t LYC_cd;
|
||||
|
||||
// accessors for derived values (GBC only)
|
||||
uint8_t BG_pal_ret() { return (uint8_t)(((BG_bytes_inc ? 1 : 0) << 7) | (BG_bytes_index & 0x3F)); }
|
||||
|
||||
uint8_t OBJ_pal_ret() { return (uint8_t)(((OBJ_bytes_inc ? 1 : 0) << 7) | (OBJ_bytes_index & 0x3F)); }
|
||||
|
||||
uint8_t HDMA_ctrl() { return (uint8_t)(((HDMA_active ? 0 : 1) << 7) | ((HDMA_length >> 4) - 1)); }
|
||||
|
||||
virtual uint8_t ReadReg(uint32_t addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void WriteReg(int addr, uint8_t value)
|
||||
virtual void WriteReg(uint32_t addr, uint8_t value)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -159,7 +204,7 @@ namespace GBHawk
|
|||
|
||||
}
|
||||
|
||||
virtual void render(int render_cycle)
|
||||
virtual void render(uint32_t render_cycle)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -176,7 +221,7 @@ namespace GBHawk
|
|||
|
||||
}
|
||||
|
||||
virtual void OAM_scan(int OAM_cycle)
|
||||
virtual void OAM_scan(uint32_t OAM_cycle)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -193,6 +238,16 @@ namespace GBHawk
|
|||
|
||||
}
|
||||
|
||||
virtual void color_compute_BG()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void color_compute_OBJ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region State Save / Load
|
||||
|
@ -232,7 +287,7 @@ namespace GBHawk
|
|||
saver = bool_saver(DMA_start, saver);
|
||||
saver = int_saver(DMA_clock, saver);
|
||||
saver = int_saver(DMA_inc, saver);
|
||||
saver = byte_saver(DMA_uint8_t, saver);
|
||||
saver = byte_saver(DMA_byte, saver);
|
||||
|
||||
saver = int_saver(cycle, saver);
|
||||
saver = bool_saver(LYC_INT, saver);
|
||||
|
@ -298,6 +353,40 @@ namespace GBHawk
|
|||
|
||||
saver = int_saver(hbl_countdown, saver);
|
||||
|
||||
// The following are GBC specific variables
|
||||
for (int i = 0; i < 64; i++) { saver = byte_saver(BG_bytes[i], saver); }
|
||||
for (int i = 0; i < 64; i++) { saver = byte_saver(OBJ_bytes[i], saver); }
|
||||
|
||||
saver = byte_saver(BG_transfer_byte, saver);
|
||||
saver = byte_saver(OBJ_transfer_byte, saver);
|
||||
saver = byte_saver(HDMA_src_hi, saver);
|
||||
saver = byte_saver(HDMA_src_lo, saver);
|
||||
saver = byte_saver(HDMA_dest_hi, saver);
|
||||
saver = byte_saver(HDMA_dest_lo, saver);
|
||||
saver = int_saver(HDMA_tick, saver);
|
||||
saver = byte_saver(HDMA_byte, saver);
|
||||
|
||||
saver = int_saver(VRAM_sel, saver);
|
||||
saver = bool_saver(BG_V_flip, saver);
|
||||
saver = bool_saver(HDMA_mode, saver);
|
||||
saver = bool_saver(HDMA_run_once, saver);
|
||||
saver = int_saver(cur_DMA_src, saver);
|
||||
saver = int_saver(cur_DMA_dest, saver);
|
||||
saver = int_saver(HDMA_length, saver);
|
||||
saver = int_saver(HDMA_countdown, saver);
|
||||
saver = int_saver(HBL_HDMA_count, saver);
|
||||
saver = int_saver(last_HBL, saver);
|
||||
saver = bool_saver(HBL_HDMA_go, saver);
|
||||
saver = bool_saver(HBL_test, saver);
|
||||
|
||||
saver = bool_saver(BG_bytes_inc, saver);
|
||||
saver = bool_saver(OBJ_bytes_inc, saver);
|
||||
saver = byte_saver(BG_bytes_index, saver);
|
||||
saver = byte_saver(OBJ_bytes_index, saver);
|
||||
|
||||
saver = byte_saver(LYC_t, saver);
|
||||
saver = int_saver(LYC_cd, saver);
|
||||
|
||||
return saver;
|
||||
}
|
||||
|
||||
|
@ -336,7 +425,7 @@ namespace GBHawk
|
|||
loader = bool_loader(&DMA_start, loader);
|
||||
loader = int_loader(&DMA_clock, loader);
|
||||
loader = int_loader(&DMA_inc, loader);
|
||||
loader = byte_loader(&DMA_uint8_t, loader);
|
||||
loader = byte_loader(&DMA_byte, loader);
|
||||
|
||||
loader = int_loader(&cycle, loader);
|
||||
loader = bool_loader(&LYC_INT, loader);
|
||||
|
@ -401,6 +490,40 @@ namespace GBHawk
|
|||
loader = int_loader(&window_y_latch, loader);
|
||||
|
||||
loader = int_loader(&hbl_countdown, loader);
|
||||
|
||||
// The following are GBC specific variables
|
||||
for (int i = 0; i < 64; i++) { loader = byte_loader(&BG_bytes[i], loader); }
|
||||
for (int i = 0; i < 64; i++) { loader = byte_loader(&OBJ_bytes[i], loader); }
|
||||
|
||||
loader = byte_loader(&BG_transfer_byte, loader);
|
||||
loader = byte_loader(&OBJ_transfer_byte, loader);
|
||||
loader = byte_loader(&HDMA_src_hi, loader);
|
||||
loader = byte_loader(&HDMA_src_lo, loader);
|
||||
loader = byte_loader(&HDMA_dest_hi, loader);
|
||||
loader = byte_loader(&HDMA_dest_lo, loader);
|
||||
loader = int_loader(&HDMA_tick, loader);
|
||||
loader = byte_loader(&HDMA_byte, loader);
|
||||
|
||||
loader = int_loader(&VRAM_sel, loader);
|
||||
loader = bool_loader(&BG_V_flip, loader);
|
||||
loader = bool_loader(&HDMA_mode, loader);
|
||||
loader = bool_loader(&HDMA_run_once, loader);
|
||||
loader = int_loader(&cur_DMA_src, loader);
|
||||
loader = int_loader(&cur_DMA_dest, loader);
|
||||
loader = int_loader(&HDMA_length, loader);
|
||||
loader = int_loader(&HDMA_countdown, loader);
|
||||
loader = int_loader(&HBL_HDMA_count, loader);
|
||||
loader = int_loader(&last_HBL, loader);
|
||||
loader = bool_loader(&HBL_HDMA_go, loader);
|
||||
loader = bool_loader(&HBL_test, loader);
|
||||
|
||||
loader = bool_loader(&BG_bytes_inc, loader);
|
||||
loader = bool_loader(&OBJ_bytes_inc, loader);
|
||||
loader = byte_loader(&BG_bytes_index, loader);
|
||||
loader = byte_loader(&OBJ_bytes_index, loader);
|
||||
|
||||
loader = byte_loader(&LYC_t, loader);
|
||||
loader = int_loader(&LYC_cd, loader);
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue