GBHawk: more clean up and optimizing

This commit is contained in:
alyosha-tas 2020-03-31 20:49:49 -04:00
parent 7797689c53
commit 00471ac530
6 changed files with 172 additions and 171 deletions

View File

@ -76,24 +76,26 @@ namespace GBHawk
MemMap.serialport_pntr = &serialport;
cpu.mem_ctrl = &MemMap;
MemMap.ppu_pntr->FlagI = &cpu.FlagI;
MemMap.ppu_pntr->in_vblank = &MemMap.in_vblank;
MemMap.ppu_pntr->cpu_LY = &cpu.LY;
MemMap.ppu_pntr->REG_FFFF = &MemMap.REG_FFFF;
MemMap.ppu_pntr->REG_FF0F = &MemMap.REG_FF0F;
MemMap.ppu_pntr->_scanlineCallbackLine = &MemMap._scanlineCallbackLine;
MemMap.ppu_pntr->OAM = &MemMap.OAM[0];
MemMap.ppu_pntr->VRAM = &MemMap.VRAM[0];
MemMap.ppu_pntr->VRAM_Bank = &MemMap.VRAM_Bank;
MemMap.ppu_pntr->cpu_halted = &cpu.halted;
MemMap.ppu_pntr->_vidbuffer = &MemMap.vidbuffer[0];
MemMap.ppu_pntr->color_palette = &MemMap.color_palette[0];
MemMap.ppu_pntr->HDMA_transfer = &MemMap.HDMA_transfer;
MemMap.ppu_pntr->GBC_compat = &MemMap.GBC_compat;
ppu->FlagI = &cpu.FlagI;
ppu->in_vblank = &MemMap.in_vblank;
ppu->vblank_rise = &MemMap.vblank_rise;
ppu->cpu_LY = &cpu.LY;
ppu->REG_FFFF = &MemMap.REG_FFFF;
ppu->REG_FF0F = &MemMap.REG_FF0F;
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;
timer.FlagI = &cpu.FlagI;
timer.REG_FFFF = &MemMap.REG_FFFF;
timer.REG_FF0F = &MemMap.REG_FF0F;
timer.CPU_cycle_pntr = &cpu.TotalExecutedCycles;
serialport.GBC_compat = &MemMap.GBC_compat;
serialport.FlagI = &cpu.FlagI;
@ -146,6 +148,9 @@ namespace GBHawk
temp_check = 5;
}
*/
MemMap.new_controller_1 = new_controller_1;
MemMap.new_accx = new_accx;
MemMap.new_accy = new_accy;
temp_check = 70224;
@ -160,57 +165,30 @@ namespace GBHawk
{
// These things all tick twice as fast in GBC double speed mode
if (ppu->DMA_start && !cpu.halted) { ppu->DMA_tick(); }
timer.tick_1();
serialport.serial_transfer_tick();
cpu.ExecuteOne(&MemMap.REG_FF0F, &MemMap.REG_FFFF);
timer.tick_2();
timer.tick();
if (MemMap.double_speed)
{
if (ppu->DMA_start && !cpu.halted) { ppu->DMA_tick(); }
timer.tick_1();
serialport.serial_transfer_tick();
cpu.ExecuteOne(&MemMap.REG_FF0F, &MemMap.REG_FFFF);
timer.tick_2();
timer.tick();
}
}
else
{
timer.tick_1();
timer.tick_2();
timer.tick();
cpu.TotalExecutedCycles++;
if (MemMap.double_speed)
{
timer.tick_1();
timer.tick_2();
timer.tick();
cpu.TotalExecutedCycles++;
}
}
if (MemMap.in_vblank && !MemMap.in_vblank_old)
{
MemMap.lagged = false;
// update the controller state on VBlank
MemMap.controller_state = new_controller_1;
MemMap.Acc_X_state = new_accx;
MemMap.Acc_Y_state = new_accy;
// check if controller state caused interrupt
do_controller_check();
// send the image on VBlank
SendVideoBuffer();
if ((ppu->scanlineCallback) && (MemMap._scanlineCallbackLine == -1))
{
ppu->scanlineCallback();
}
}
MemMap.REG_FF0F_OLD = MemMap.REG_FF0F;
MemMap.in_vblank_old = MemMap.in_vblank;
}
// turn off the screen so the image doesnt persist
@ -238,29 +216,25 @@ namespace GBHawk
// These things all tick twice as fast in GBC double speed mode
// Note that DMA is halted when the CPU is halted
if (ppu->DMA_start && !cpu.halted) { ppu->DMA_tick(); }
timer.tick_1();
serialport.serial_transfer_tick();
cpu.ExecuteOne(&MemMap.REG_FF0F, &MemMap.REG_FFFF);
timer.tick_2();
timer.tick();
if (MemMap.double_speed)
{
if (ppu->DMA_start && !cpu.halted) { ppu->DMA_tick(); }
timer.tick_1();
serialport.serial_transfer_tick();
cpu.ExecuteOne(&MemMap.REG_FF0F, &MemMap.REG_FFFF);
timer.tick_2();
timer.tick();
}
}
else
{
timer.tick_1();
timer.tick_2();
timer.tick();
cpu.TotalExecutedCycles++;
if (MemMap.double_speed)
{
timer.tick_1();
timer.tick_2();
timer.tick();
cpu.TotalExecutedCycles++;
}
}
@ -274,69 +248,6 @@ namespace GBHawk
MemMap.REG_FF0F_OLD = MemMap.REG_FF0F;
}
void do_controller_check()
{
// check if new input changed the input register and triggered IRQ
uint8_t contr_prev = MemMap.input_register;
MemMap.input_register &= 0xF0;
if ((MemMap.input_register & 0x30) == 0x20)
{
MemMap.input_register |= (uint8_t)(MemMap.controller_state & 0xF);
}
else if ((MemMap.input_register & 0x30) == 0x10)
{
MemMap.input_register |= (uint8_t)((MemMap.controller_state & 0xF0) >> 4);
}
else if ((MemMap.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)((MemMap.controller_state & 0xF) & ((MemMap.controller_state & 0xF0) >> 4));
MemMap.input_register |= temp;
}
else
{
MemMap.input_register |= 0xF;
}
// check for interrupts
if (((contr_prev & 8) > 0) && ((MemMap.input_register & 8) == 0) ||
((contr_prev & 4) > 0) && ((MemMap.input_register & 4) == 0) ||
((contr_prev & 2) > 0) && ((MemMap.input_register & 2) == 0) ||
((contr_prev & 1) > 0) && ((MemMap.input_register & 1) == 0))
{
if ((MemMap.REG_FFFF & 0x10) > 0) { cpu.FlagI = true; }
MemMap.REG_FF0F |= 0x10;
}
}
void SendVideoBuffer()
{
if (MemMap.GBC_compat)
{
if (!ppu->blank_frame)
{
for (int j = 0; j < (160 * 144); j++) { MemMap.frame_buffer[j] = MemMap.vidbuffer[j]; }
}
ppu->blank_frame = false;
}
else
{
if (ppu->blank_frame)
{
for (int i = 0; i < (160 * 144); i++)
{
MemMap.vidbuffer[i] = (int)MemMap.color_palette[0];
}
}
for (int j = 0; j < (160 * 144); j++) { MemMap.frame_buffer[j] = MemMap.vidbuffer[j]; }
ppu->blank_frame = false;
}
}
void GetVideo(uint32_t* dest)
{
uint32_t* src = MemMap.frame_buffer;

View File

@ -926,4 +926,74 @@ namespace GBHawk
color_palette_BG[i] = color_palette[(ppu_pntr->BGP >> (i * 2)) & 3];
}
}
void MemoryManager::do_controller_check()
{
lagged = false;
// update the controller state on VBlank
controller_state = new_controller_1;
Acc_X_state = new_accx;
Acc_Y_state = new_accy;
// check if new input changed the input register and triggered IRQ
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;
}
}
void MemoryManager::SendVideoBuffer()
{
if (GBC_compat)
{
if (!ppu_pntr->blank_frame)
{
for (int j = 0; j < (160 * 144); j++) { frame_buffer[j] = vidbuffer[j]; }
}
ppu_pntr->blank_frame = false;
}
else
{
if (ppu_pntr->blank_frame)
{
for (int i = 0; i < (160 * 144); i++)
{
vidbuffer[i] = color_palette[0];
}
}
for (int j = 0; j < (160 * 144); j++) { frame_buffer[j] = vidbuffer[j]; }
ppu_pntr->blank_frame = false;
}
}
}

View File

@ -29,6 +29,8 @@ namespace GBHawk
uint8_t Read_Registers(uint32_t addr);
void Write_Registers(uint32_t addr, uint8_t value);
void compute_palettes();
void do_controller_check();
void SendVideoBuffer();
#pragma region Declarations
@ -47,6 +49,11 @@ namespace GBHawk
uint32_t ROM_Mapper;
uint32_t Cart_RAM_Length;
// passed in on frame advace, not stated
uint8_t new_controller_1;
uint32_t new_accx;
uint32_t new_accy;
// State
bool lagged;
bool is_GBC;

View File

@ -13,4 +13,20 @@ namespace GBHawk
{
return mem_ctrl->ReadMemory(addr);
}
void PPU::vblank_process()
{
in_vblank[0] = true;
vblank_rise[0] = true;
if (scanlineCallback && (_scanlineCallbackLine[0] == -1))
{
scanlineCallback();
}
mem_ctrl->do_controller_check();
// send the image on VBlank
mem_ctrl->SendVideoBuffer();
}
}

View File

@ -23,6 +23,7 @@ namespace GBHawk
// pointers not stated
bool* FlagI = nullptr;
bool* in_vblank = nullptr;
bool* vblank_rise = nullptr;
bool* cpu_halted = nullptr;
bool* HDMA_transfer = nullptr;
bool* GBC_compat = nullptr;
@ -198,6 +199,8 @@ namespace GBHawk
virtual void reorder_and_assemble_sprites() { }
void vblank_process();
uint8_t BG_PAL_read()
{
if (VRAM_access_read)
@ -850,7 +853,7 @@ namespace GBHawk
if (LY == 144)
{
in_vblank[0] = true;
vblank_process();
}
}
@ -1787,7 +1790,7 @@ namespace GBHawk
{
if (OAM_scan_index < 40)
{
uint32_t temp = DMA_OAM_access ? OAM[OAM_scan_index * 4] : (uint32_t)0xFF;
int32_t temp = DMA_OAM_access ? OAM[OAM_scan_index * 4] : (int32_t)0xFF;
// (sprite Y - 16) equals LY, we have a sprite
if ((temp - 16) <= LY &&
((temp - 16) + 8 + (((LCDC & 0x4) > 0) ? 8 : 0)) > LY)
@ -2220,7 +2223,7 @@ namespace GBHawk
if (LY == 144)
{
in_vblank[0] = true;
vblank_process();
}
}
@ -3221,7 +3224,7 @@ namespace GBHawk
{
if (OAM_scan_index < 40)
{
uint32_t temp = DMA_OAM_access ? OAM[OAM_scan_index * 4] : (uint32_t)0xFF;
int32_t temp = DMA_OAM_access ? OAM[OAM_scan_index * 4] : (int32_t)0xFF;
// (sprite Y - 16) equals LY, we have a sprite
if ((temp - 16) <= LY &&
((temp - 16) + 8 + (((LCDC & 0x4) > 0) ? 8 : 0)) > LY)
@ -3680,7 +3683,7 @@ namespace GBHawk
if (LY == 144)
{
in_vblank[0] = true;
vblank_process();
}
}
@ -4738,7 +4741,7 @@ namespace GBHawk
{
if (OAM_scan_index < 40)
{
uint32_t temp = DMA_OAM_access ? OAM[OAM_scan_index * 4] : (uint32_t)0xFF;
int32_t temp = DMA_OAM_access ? OAM[OAM_scan_index * 4] : (int32_t)0xFF;
// (sprite Y - 16) equals LY, we have a sprite
if ((temp - 16) <= LY &&
((temp - 16) + 8 + (((LCDC & 0x4) > 0) ? 8 : 0)) > LY)

View File

@ -19,20 +19,21 @@ namespace GBHawk
bool* FlagI = nullptr;
uint8_t* REG_FFFF = nullptr;
uint8_t* REG_FF0F = nullptr;
uint64_t* CPU_cycle_pntr = nullptr;
bool old_state;
bool state;
bool reload_block;
bool TMA_coincidence;
bool old_state = false;
bool state = false;
bool reload_block = false;
uint8_t timer_reload = 0;
uint8_t timer = 0;
uint8_t timer_old = 0;
uint8_t timer_control = 0;
uint8_t pending_reload = 0;
uint8_t timer_reload;
uint8_t timer;
uint8_t timer_old;
uint8_t timer_control;
uint8_t pending_reload;
uint8_t write_ignore;
uint32_t divider_reg;
uint32_t divider_reg = 0;
uint64_t next_free_cycle = 0;
uint8_t ReadReg(uint32_t addr)
{
@ -60,7 +61,7 @@ namespace GBHawk
// TIMA (Timer Counter)
case 0xFF05:
if (write_ignore == 0)
if (CPU_cycle_pntr[0] >= next_free_cycle)
{
timer_old = timer;
timer = value;
@ -71,7 +72,7 @@ namespace GBHawk
// TMA (Timer Modulo)
case 0xFF06:
timer_reload = value;
if (TMA_coincidence)
if (CPU_cycle_pntr[0] < next_free_cycle)
{
timer = timer_reload;
timer_old = timer;
@ -85,35 +86,7 @@ namespace GBHawk
}
}
void tick_1()
{
if (write_ignore > 0)
{
write_ignore--;
if (write_ignore == 0)
{
TMA_coincidence = false;
}
}
if (pending_reload > 0)
{
pending_reload--;
if (pending_reload == 0 && !reload_block)
{
timer = timer_reload;
timer_old = timer;
write_ignore = 4;
TMA_coincidence = true;
// set interrupts
if ((REG_FFFF[0] & 0x4) > 0) { FlagI[0] = true; }
REG_FF0F[0] |= 0x04;
}
}
}
void tick_2()
void tick()
{
divider_reg++;
@ -162,6 +135,22 @@ namespace GBHawk
}
old_state = state;
if (pending_reload > 0)
{
pending_reload--;
if (pending_reload == 0 && !reload_block)
{
timer = timer_reload;
timer_old = timer;
next_free_cycle = 4 + CPU_cycle_pntr[0];
// set interrupts
if ((REG_FFFF[0] & 0x4) > 0) { FlagI[0] = true; }
REG_FF0F[0] |= 0x04;
}
}
}
void Reset()
@ -172,11 +161,10 @@ namespace GBHawk
timer_old = 0;
timer_control = 0xF8;
pending_reload = 0;
write_ignore = 0;
old_state = false;
state = false;
reload_block = false;
TMA_coincidence = false;
next_free_cycle = 0;
}
#pragma region State Save / Load
@ -187,18 +175,21 @@ namespace GBHawk
*saver = (uint8_t)(old_state ? 1 : 0); saver++;
*saver = (uint8_t)(state ? 1 : 0); saver++;
*saver = (uint8_t)(reload_block ? 1 : 0); saver++;
*saver = (uint8_t)(TMA_coincidence ? 1 : 0); saver++;
*saver = timer_reload; saver++;
*saver = timer; saver++;
*saver = timer_old; saver++;
*saver = timer_control; saver++;
*saver = pending_reload; saver++;
*saver = write_ignore; saver++;
*saver = (uint8_t)(divider_reg & 0xFF); saver++; *saver = (uint8_t)((divider_reg >> 8) & 0xFF); saver++;
*saver = (uint8_t)((divider_reg >> 16) & 0xFF); saver++; *saver = (uint8_t)((divider_reg >> 24) & 0xFF); saver++;
*saver = (uint8_t)(next_free_cycle & 0xFF); saver++; *saver = (uint8_t)((next_free_cycle >> 8) & 0xFF); saver++;
*saver = (uint8_t)((next_free_cycle >> 16) & 0xFF); saver++; *saver = (uint8_t)((next_free_cycle >> 24) & 0xFF); saver++;
*saver = (uint8_t)((next_free_cycle >> 32) & 0xFF); saver++; *saver = (uint8_t)((next_free_cycle >> 40) & 0xFF); saver++;
*saver = (uint8_t)((next_free_cycle >> 48) & 0xFF); saver++; *saver = (uint8_t)((next_free_cycle >> 56) & 0xFF); saver++;
return saver;
}
@ -207,18 +198,21 @@ namespace GBHawk
old_state = *loader == 1; loader++;
state = *loader == 1; loader++;
reload_block = *loader == 1; loader++;
TMA_coincidence = *loader == 1; loader++;
timer_reload = *loader; loader++;
timer = *loader; loader++;
timer_old = *loader; loader++;
timer_control = *loader; loader++;
pending_reload = *loader; loader++;
write_ignore = *loader; loader++;
divider_reg = *loader; loader++; divider_reg |= (*loader << 8); loader++;
divider_reg |= (*loader << 16); loader++; divider_reg |= (*loader << 24); loader++;
next_free_cycle = *loader; loader++; next_free_cycle |= ((uint64_t)*loader << 8); loader++;
next_free_cycle |= ((uint64_t)*loader << 16); loader++; next_free_cycle |= ((uint64_t)*loader << 24); loader++;
next_free_cycle |= ((uint64_t)*loader << 32); loader++; next_free_cycle |= ((uint64_t)*loader << 40); loader++;
next_free_cycle |= ((uint64_t)*loader << 48); loader++; next_free_cycle |= ((uint64_t)*loader << 56); loader++;
return loader;
}