Unroll some loops in PPU code, more efficient timer handling
This commit is contained in:
parent
612cd07fb3
commit
af0430dbc5
@ -27,6 +27,7 @@ static GB_fifo_item_t *fifo_pop(GB_fifo_t *fifo)
|
|||||||
static void fifo_push_bg_row(GB_fifo_t *fifo, uint8_t lower, uint8_t upper, uint8_t palette, bool bg_priority, bool flip_x)
|
static void fifo_push_bg_row(GB_fifo_t *fifo, uint8_t lower, uint8_t upper, uint8_t palette, bool bg_priority, bool flip_x)
|
||||||
{
|
{
|
||||||
if (!flip_x) {
|
if (!flip_x) {
|
||||||
|
#pragma unroll
|
||||||
for (unsigned i = 8; i--;) {
|
for (unsigned i = 8; i--;) {
|
||||||
fifo->fifo[fifo->write_end] = (GB_fifo_item_t) {
|
fifo->fifo[fifo->write_end] = (GB_fifo_item_t) {
|
||||||
(lower >> 7) | ((upper >> 7) << 1),
|
(lower >> 7) | ((upper >> 7) << 1),
|
||||||
@ -42,6 +43,7 @@ static void fifo_push_bg_row(GB_fifo_t *fifo, uint8_t lower, uint8_t upper, uint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#pragma unroll
|
||||||
for (unsigned i = 8; i--;) {
|
for (unsigned i = 8; i--;) {
|
||||||
fifo->fifo[fifo->write_end] = (GB_fifo_item_t) {
|
fifo->fifo[fifo->write_end] = (GB_fifo_item_t) {
|
||||||
(lower & 1) | ((upper & 1) << 1),
|
(lower & 1) | ((upper & 1) << 1),
|
||||||
@ -68,6 +70,7 @@ static void fifo_overlay_object_row(GB_fifo_t *fifo, uint8_t lower, uint8_t uppe
|
|||||||
|
|
||||||
uint8_t flip_xor = flip_x? 0: 0x7;
|
uint8_t flip_xor = flip_x? 0: 0x7;
|
||||||
|
|
||||||
|
#pragma unroll
|
||||||
for (unsigned i = 8; i--;) {
|
for (unsigned i = 8; i--;) {
|
||||||
uint8_t pixel = (lower >> 7) | ((upper >> 7) << 1);
|
uint8_t pixel = (lower >> 7) | ((upper >> 7) << 1);
|
||||||
GB_fifo_item_t *target = &fifo->fifo[(fifo->read_end + (i ^ flip_xor)) & (GB_FIFO_LENGTH - 1)];
|
GB_fifo_item_t *target = &fifo->fifo[(fifo->read_end + (i ^ flip_xor)) & (GB_FIFO_LENGTH - 1)];
|
||||||
@ -1063,6 +1066,7 @@ uint8_t GB_get_oam_info(GB_gameboy_t *gb, GB_oam_info_t *dest, uint8_t *sprite_h
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned y = 0; y < *sprite_height; y++) {
|
for (unsigned y = 0; y < *sprite_height; y++) {
|
||||||
|
#pragma unroll
|
||||||
for (unsigned x = 0; x < 8; x++) {
|
for (unsigned x = 0; x < 8; x++) {
|
||||||
uint8_t color = (((gb->vram[vram_address ] >> ((~x)&7)) & 1 ) |
|
uint8_t color = (((gb->vram[vram_address ] >> ((~x)&7)) & 1 ) |
|
||||||
((gb->vram[vram_address + 1] >> ((~x)&7)) & 1) << 1 );
|
((gb->vram[vram_address + 1] >> ((~x)&7)) & 1) << 1 );
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const unsigned int GB_TAC_RATIOS[] = {1024, 16, 64, 256};
|
static const unsigned int GB_TAC_TRIGGER_BITS[] = {512, 8, 32, 128};
|
||||||
|
|
||||||
#ifndef DISABLE_TIMEKEEPING
|
#ifndef DISABLE_TIMEKEEPING
|
||||||
static int64_t get_nanoseconds(void)
|
static int64_t get_nanoseconds(void)
|
||||||
@ -108,11 +108,6 @@ static void advance_tima_state_machine(GB_gameboy_t *gb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool counter_overflow_check(uint32_t old, uint32_t new, uint32_t max)
|
|
||||||
{
|
|
||||||
return (old & (max >> 1)) && !(new & (max >> 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void increase_tima(GB_gameboy_t *gb)
|
static void increase_tima(GB_gameboy_t *gb)
|
||||||
{
|
{
|
||||||
gb->io_registers[GB_IO_TIMA]++;
|
gb->io_registers[GB_IO_TIMA]++;
|
||||||
@ -126,13 +121,13 @@ static void GB_set_internal_div_counter(GB_gameboy_t *gb, uint32_t value)
|
|||||||
{
|
{
|
||||||
/* TIMA increases when a specific high-bit becomes a low-bit. */
|
/* TIMA increases when a specific high-bit becomes a low-bit. */
|
||||||
value &= INTERNAL_DIV_CYCLES - 1;
|
value &= INTERNAL_DIV_CYCLES - 1;
|
||||||
if ((gb->io_registers[GB_IO_TAC] & 4) &&
|
uint32_t triggers = gb->div_counter & ~value;
|
||||||
counter_overflow_check(gb->div_counter, value, GB_TAC_RATIOS[gb->io_registers[GB_IO_TAC] & 3])) {
|
if ((gb->io_registers[GB_IO_TAC] & 4) && (triggers & GB_TAC_TRIGGER_BITS[gb->io_registers[GB_IO_TAC] & 3])) {
|
||||||
increase_tima(gb);
|
increase_tima(gb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Can switching to double speed mode trigger an event? */
|
/* TODO: Can switching to double speed mode trigger an event? */
|
||||||
if (counter_overflow_check(gb->div_counter, value, gb->cgb_double_speed? 0x4000 : 0x2000)) {
|
if (triggers & (gb->cgb_double_speed? 0x2000 : 0x1000)) {
|
||||||
GB_apu_run(gb);
|
GB_apu_run(gb);
|
||||||
GB_apu_div_event(gb);
|
GB_apu_div_event(gb);
|
||||||
}
|
}
|
||||||
@ -221,13 +216,13 @@ void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac)
|
|||||||
/* Glitch only happens when old_tac is enabled. */
|
/* Glitch only happens when old_tac is enabled. */
|
||||||
if (!(old_tac & 4)) return;
|
if (!(old_tac & 4)) return;
|
||||||
|
|
||||||
unsigned int old_clocks = GB_TAC_RATIOS[old_tac & 3];
|
unsigned int old_clocks = GB_TAC_TRIGGER_BITS[old_tac & 3];
|
||||||
unsigned int new_clocks = GB_TAC_RATIOS[new_tac & 3];
|
unsigned int new_clocks = GB_TAC_TRIGGER_BITS[new_tac & 3];
|
||||||
|
|
||||||
/* The bit used for overflow testing must have been 1 */
|
/* The bit used for overflow testing must have been 1 */
|
||||||
if (gb->div_counter & (old_clocks >> 1)) {
|
if (gb->div_counter & old_clocks) {
|
||||||
/* And now either the timer must be disabled, or the new bit used for overflow testing be 0. */
|
/* And now either the timer must be disabled, or the new bit used for overflow testing be 0. */
|
||||||
if (!(new_tac & 4) || gb->div_counter & (new_clocks >> 1)) {
|
if (!(new_tac & 4) || gb->div_counter & new_clocks) {
|
||||||
increase_tima(gb);
|
increase_tima(gb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user