mirror of https://github.com/bsnes-emu/bsnes.git
Redo TPP1 saving, fix RTC and HUC3 in BESS
This commit is contained in:
parent
f0a6488546
commit
87a2d48675
84
Core/gb.c
84
Core/gb.c
|
@ -572,6 +572,15 @@ typedef struct {
|
|||
uint8_t padding5[3];
|
||||
} GB_vba_rtc_time_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t magic;
|
||||
uint16_t version;
|
||||
uint8_t mr4;
|
||||
uint8_t reserved;
|
||||
uint64_t last_rtc_second;
|
||||
uint8_t rtc_data[4];
|
||||
} GB_tpp1_rtc_save_t;
|
||||
|
||||
typedef union {
|
||||
struct __attribute__((packed)) {
|
||||
GB_rtc_time_t rtc_real;
|
||||
|
@ -589,6 +598,18 @@ typedef union {
|
|||
} vba64;
|
||||
} GB_rtc_save_t;
|
||||
|
||||
static void GB_fill_tpp1_save_data(GB_gameboy_t *gb, GB_tpp1_rtc_save_t *data)
|
||||
{
|
||||
data->magic = BE32('TPP1');
|
||||
data->version = BE16(0x100);
|
||||
data->mr4 = gb->tpp1_mr4;
|
||||
data->reserved = 0;
|
||||
data->last_rtc_second = LE64(time(NULL));
|
||||
unrolled for (unsigned i = 4; i--;) {
|
||||
data->rtc_data[i] = gb->rtc_real.data[i ^ 3];
|
||||
}
|
||||
}
|
||||
|
||||
int GB_save_battery_size(GB_gameboy_t *gb)
|
||||
{
|
||||
if (!gb->cartridge_type->has_battery) return 0; // Nothing to save.
|
||||
|
@ -599,6 +620,11 @@ int GB_save_battery_size(GB_gameboy_t *gb)
|
|||
if (gb->cartridge_type->mbc_type == GB_HUC3) {
|
||||
return gb->mbc_ram_size + sizeof(GB_huc3_rtc_time_t);
|
||||
}
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
return gb->mbc_ram_size + sizeof(GB_tpp1_rtc_save_t);
|
||||
}
|
||||
|
||||
GB_rtc_save_t rtc_save_size;
|
||||
return gb->mbc_ram_size + (gb->cartridge_type->has_rtc ? sizeof(rtc_save_size.vba64) : 0);
|
||||
}
|
||||
|
@ -613,7 +639,13 @@ int GB_save_battery_to_buffer(GB_gameboy_t *gb, uint8_t *buffer, size_t size)
|
|||
|
||||
memcpy(buffer, gb->mbc_ram, gb->mbc_ram_size);
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_HUC3) {
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
buffer += gb->mbc_ram_size;
|
||||
GB_tpp1_rtc_save_t rtc_save;
|
||||
GB_fill_tpp1_save_data(gb, &rtc_save);
|
||||
memcpy(buffer, &rtc_save, sizeof(rtc_save));
|
||||
}
|
||||
else if (gb->cartridge_type->mbc_type == GB_HUC3) {
|
||||
buffer += gb->mbc_ram_size;
|
||||
|
||||
#ifdef GB_BIG_ENDIAN
|
||||
|
@ -676,7 +708,16 @@ int GB_save_battery(GB_gameboy_t *gb, const char *path)
|
|||
fclose(f);
|
||||
return EIO;
|
||||
}
|
||||
if (gb->cartridge_type->mbc_type == GB_HUC3) {
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
GB_tpp1_rtc_save_t rtc_save;
|
||||
GB_fill_tpp1_save_data(gb, &rtc_save);
|
||||
|
||||
if (fwrite(&rtc_save, sizeof(rtc_save), 1, f) != 1) {
|
||||
fclose(f);
|
||||
return EIO;
|
||||
}
|
||||
}
|
||||
else if (gb->cartridge_type->mbc_type == GB_HUC3) {
|
||||
#ifdef GB_BIG_ENDIAN
|
||||
GB_huc3_rtc_time_t rtc_save = {
|
||||
__builtin_bswap64(gb->last_rtc_second),
|
||||
|
@ -731,6 +772,14 @@ int GB_save_battery(GB_gameboy_t *gb, const char *path)
|
|||
return errno;
|
||||
}
|
||||
|
||||
static void GB_load_tpp1_save_data(GB_gameboy_t *gb, const GB_tpp1_rtc_save_t *data)
|
||||
{
|
||||
gb->last_rtc_second = LE64(data->last_rtc_second);
|
||||
unrolled for (unsigned i = 4; i--;) {
|
||||
gb->rtc_real.data[i ^ 3] = data->rtc_data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void GB_load_battery_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t size)
|
||||
{
|
||||
memcpy(gb->mbc_ram, buffer, MIN(gb->mbc_ram_size, size));
|
||||
|
@ -738,6 +787,22 @@ void GB_load_battery_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t
|
|||
goto reset_rtc;
|
||||
}
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
GB_tpp1_rtc_save_t rtc_save;
|
||||
if (size - gb->mbc_ram_size < sizeof(rtc_save)) {
|
||||
goto reset_rtc;
|
||||
}
|
||||
memcpy(&rtc_save, buffer + gb->mbc_ram_size, sizeof(rtc_save));
|
||||
|
||||
GB_load_tpp1_save_data(gb, &rtc_save);
|
||||
|
||||
if (gb->last_rtc_second > time(NULL)) {
|
||||
/* We must reset RTC here, or it will not advance. */
|
||||
goto reset_rtc;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_HUC3) {
|
||||
GB_huc3_rtc_time_t rtc_save;
|
||||
if (size - gb->mbc_ram_size < sizeof(rtc_save)) {
|
||||
|
@ -847,6 +912,21 @@ void GB_load_battery(GB_gameboy_t *gb, const char *path)
|
|||
goto reset_rtc;
|
||||
}
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
GB_tpp1_rtc_save_t rtc_save;
|
||||
if (fread(&rtc_save, sizeof(rtc_save), 1, f) != 1) {
|
||||
goto reset_rtc;
|
||||
}
|
||||
|
||||
GB_load_tpp1_save_data(gb, &rtc_save);
|
||||
|
||||
if (gb->last_rtc_second > time(NULL)) {
|
||||
/* We must reset RTC here, or it will not advance. */
|
||||
goto reset_rtc;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_HUC3) {
|
||||
GB_huc3_rtc_time_t rtc_save;
|
||||
if (fread(&rtc_save, sizeof(rtc_save), 1, f) != 1) {
|
||||
|
|
12
Core/gb.h
12
Core/gb.h
|
@ -98,6 +98,13 @@ typedef union {
|
|||
uint8_t days;
|
||||
uint8_t high;
|
||||
};
|
||||
struct {
|
||||
uint8_t seconds;
|
||||
uint8_t minutes;
|
||||
uint8_t hours:5;
|
||||
uint8_t weekday:3;
|
||||
uint8_t weeks;
|
||||
} tpp1;
|
||||
uint8_t data[5];
|
||||
} GB_rtc_time_t;
|
||||
|
||||
|
@ -515,6 +522,7 @@ struct GB_gameboy_internal_s {
|
|||
uint64_t last_rtc_second;
|
||||
bool rtc_latch;
|
||||
uint32_t rtc_cycles;
|
||||
uint8_t tpp1_mr4;
|
||||
);
|
||||
|
||||
/* Video Display */
|
||||
|
@ -781,8 +789,6 @@ void *GB_get_direct_access(GB_gameboy_t *gb, GB_direct_access_t access, size_t *
|
|||
void *GB_get_user_data(GB_gameboy_t *gb);
|
||||
void GB_set_user_data(GB_gameboy_t *gb, void *data);
|
||||
|
||||
|
||||
|
||||
int GB_load_boot_rom(GB_gameboy_t *gb, const char *path);
|
||||
void GB_load_boot_rom_from_buffer(GB_gameboy_t *gb, const unsigned char *buffer, size_t size);
|
||||
int GB_load_rom(GB_gameboy_t *gb, const char *path);
|
||||
|
@ -850,5 +856,5 @@ unsigned GB_get_screen_width(GB_gameboy_t *gb);
|
|||
unsigned GB_get_screen_height(GB_gameboy_t *gb);
|
||||
double GB_get_usual_frame_rate(GB_gameboy_t *gb);
|
||||
unsigned GB_get_player_count(GB_gameboy_t *gb);
|
||||
|
||||
|
||||
#endif /* GB_h */
|
||||
|
|
|
@ -185,30 +185,13 @@ static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr)
|
|||
case 0: return gb->tpp1_rom_bank;
|
||||
case 1: return gb->tpp1_rom_bank >> 8;
|
||||
case 2: return gb->tpp1_ram_bank;
|
||||
case 3: return gb->rumble_strength | (((gb->rtc_real.high & 0xC0) ^ 0x40) >> 4);
|
||||
case 3: return gb->rumble_strength | gb->tpp1_mr4;
|
||||
}
|
||||
case 2:
|
||||
case 3:
|
||||
break; // Read RAM
|
||||
case 5:
|
||||
switch (addr & 3) {
|
||||
case 0: { // Week count
|
||||
unsigned total_days = (((gb->rtc_latched.high & 7) << 8) + gb->rtc_latched.days);
|
||||
if (gb->rtc_latched.high & 0x20) {
|
||||
return total_days / 7 - 1;
|
||||
}
|
||||
return total_days / 7;
|
||||
}
|
||||
case 1: { // Week count
|
||||
unsigned total_days = (((gb->rtc_latched.high & 7) << 8) + gb->rtc_latched.days);
|
||||
if (gb->rtc_latched.high & 0x20) {
|
||||
return gb->rtc_latched.hours | 0xe0; // Hours and weekday
|
||||
}
|
||||
return gb->rtc_latched.hours | ((total_days % 7) << 5); // Hours and weekday
|
||||
}
|
||||
case 2: return gb->rtc_latched.minutes;
|
||||
case 3: return gb->rtc_latched.seconds;
|
||||
}
|
||||
return gb->rtc_latched.data[(addr & 3) ^ 3];
|
||||
default:
|
||||
return 0xFF;
|
||||
}
|
||||
|
@ -625,20 +608,17 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
memcpy(&gb->rtc_latched, &gb->rtc_real, sizeof(gb->rtc_real));
|
||||
break;
|
||||
case 0x11: {
|
||||
uint8_t flags = gb->rtc_real.high & 0xc0;
|
||||
memcpy(&gb->rtc_real, &gb->rtc_latched, sizeof(gb->rtc_real));
|
||||
gb->rtc_real.high &= ~0xe0;
|
||||
gb->rtc_real.high |= flags;
|
||||
break;
|
||||
}
|
||||
case 0x14:
|
||||
gb->rtc_real.high &= ~0x80;
|
||||
gb->tpp1_mr4 &= ~0x8;
|
||||
break;
|
||||
case 0x18:
|
||||
gb->rtc_real.high |= 0x40;
|
||||
gb->tpp1_mr4 &= ~0x4;
|
||||
break;
|
||||
case 0x19:
|
||||
gb->rtc_real.high &= ~0x40;
|
||||
gb->tpp1_mr4 |= 0x4;
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
|
@ -776,32 +756,7 @@ static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
case 3:
|
||||
break;
|
||||
case 5:
|
||||
switch (addr & 3) {
|
||||
case 0: {
|
||||
unsigned total_days = (((gb->rtc_latched.high & 7) << 8) + gb->rtc_latched.days);
|
||||
total_days = total_days % 7 + value * 7;
|
||||
bool had_illegal_weekday = gb->rtc_latched.high & 0x20;
|
||||
gb->rtc_latched.days = total_days;
|
||||
gb->rtc_latched.high = total_days >> 8;
|
||||
if (had_illegal_weekday) {
|
||||
gb->rtc_latched.high |= 0x20;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 1: {
|
||||
unsigned total_days = (((gb->rtc_latched.high & 7) << 8) + gb->rtc_latched.days);
|
||||
total_days = total_days / 7 * 7 + (value >> 5);
|
||||
gb->rtc_latched.hours = value & 0x1F;
|
||||
gb->rtc_latched.days = total_days;
|
||||
gb->rtc_latched.high = total_days >> 8;
|
||||
if ((value & 0xE0) == 0xE0) { // Illegal weekday
|
||||
gb->rtc_latched.high |= 0x20;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 2: gb->rtc_latched.minutes = value; return;
|
||||
case 3: gb->rtc_latched.seconds = value; return;
|
||||
}
|
||||
gb->rtc_latched.data[(addr & 3) ^ 3] = value;
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
|
|
|
@ -112,6 +112,14 @@ typedef struct __attribute__((packed)){
|
|||
GB_huc3_rtc_time_t data;
|
||||
} BESS_HUC3_t;
|
||||
|
||||
typedef struct __attribute__((packed)){
|
||||
BESS_block_t header;
|
||||
uint64_t last_rtc_second;
|
||||
uint8_t real_rtc_data[4];
|
||||
uint8_t latched_rtc_data[4];
|
||||
uint8_t mr4;
|
||||
} BESS_TPP1_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t address;
|
||||
uint8_t value;
|
||||
|
@ -222,7 +230,7 @@ static size_t bess_size_for_cartridge(const GB_cartridge_t *cart)
|
|||
case GB_HUC3:
|
||||
return sizeof(BESS_block_t) + 3 * sizeof(BESS_MBC_pair_t) + sizeof(BESS_HUC3_t);
|
||||
case GB_TPP1:
|
||||
return sizeof(BESS_block_t) + 4 * sizeof(BESS_MBC_pair_t) + sizeof(BESS_RTC_t);
|
||||
return sizeof(BESS_block_t) + 4 * sizeof(BESS_MBC_pair_t) + sizeof(BESS_TPP1_t);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,7 +261,7 @@ size_t GB_get_save_state_size(GB_gameboy_t *gb)
|
|||
+ sizeof(BESS_CORE_t)
|
||||
+ sizeof(BESS_XOAM_t)
|
||||
+ (gb->sgb? sizeof(BESS_SGB_t) : 0)
|
||||
+ bess_size_for_cartridge(gb->cartridge_type) // MBC & RTC/HUC3 block
|
||||
+ bess_size_for_cartridge(gb->cartridge_type) // MBC & RTC/HUC3/TPP1 block
|
||||
+ sizeof(BESS_block_t) // END block
|
||||
+ sizeof(BESS_footer_t);
|
||||
}
|
||||
|
@ -630,7 +638,22 @@ static int save_state_internal(GB_gameboy_t *gb, virtual_file_t *file, bool appe
|
|||
|
||||
save_bess_mbc_block(gb, file);
|
||||
if (gb->cartridge_type->has_rtc) {
|
||||
if (gb->cartridge_type ->mbc_type != GB_HUC3) {
|
||||
if (gb->cartridge_type ->mbc_type == GB_TPP1) {
|
||||
BESS_TPP1_t bess_tpp1 = {0,};
|
||||
bess_tpp1.header = (BESS_block_t){BE32('TPP1'), LE32(sizeof(bess_tpp1) - sizeof(bess_tpp1.header))};
|
||||
|
||||
bess_tpp1.last_rtc_second = LE64(gb->last_rtc_second);
|
||||
unrolled for (unsigned i = 4; i--;) {
|
||||
bess_tpp1.real_rtc_data[i] = gb->rtc_real.data[i ^ 3];
|
||||
bess_tpp1.latched_rtc_data[i] = gb->rtc_latched.data[i ^ 3];
|
||||
}
|
||||
bess_tpp1.mr4 = gb->tpp1_mr4;
|
||||
|
||||
if (file->write(file, &bess_tpp1, sizeof(bess_tpp1)) != sizeof(bess_tpp1)) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (gb->cartridge_type ->mbc_type != GB_HUC3) {
|
||||
BESS_RTC_t bess_rtc = {0,};
|
||||
bess_rtc.header = (BESS_block_t){BE32('RTC '), LE32(sizeof(bess_rtc) - sizeof(bess_rtc.header))};
|
||||
bess_rtc.real.seconds = gb->rtc_real.seconds;
|
||||
|
@ -997,33 +1020,51 @@ static int load_bess_save(GB_gameboy_t *gb, virtual_file_t *file, bool is_samebo
|
|||
BESS_RTC_t bess_rtc;
|
||||
if (LE32(block.size) != sizeof(bess_rtc) - sizeof(block)) goto parse_error;
|
||||
if (file->read(file, &bess_rtc.header + 1, LE32(block.size)) != LE32(block.size)) goto error;
|
||||
if (gb->cartridge_type->has_rtc && gb->cartridge_type->mbc_type != GB_HUC3) {
|
||||
gb->rtc_real.seconds = bess_rtc.real.seconds;
|
||||
gb->rtc_real.minutes = bess_rtc.real.minutes;
|
||||
gb->rtc_real.hours = bess_rtc.real.hours;
|
||||
gb->rtc_real.days = bess_rtc.real.days;
|
||||
gb->rtc_real.high = bess_rtc.real.high;
|
||||
gb->rtc_latched.seconds = bess_rtc.latched.seconds;
|
||||
gb->rtc_latched.minutes = bess_rtc.latched.minutes;
|
||||
gb->rtc_latched.hours = bess_rtc.latched.hours;
|
||||
gb->rtc_latched.days = bess_rtc.latched.days;
|
||||
gb->rtc_latched.high = bess_rtc.latched.high;
|
||||
gb->last_rtc_second = LE64(bess_rtc.last_rtc_second);
|
||||
if (!gb->cartridge_type->has_rtc || gb->cartridge_type->mbc_type != GB_MBC3) break;
|
||||
save.rtc_real.seconds = bess_rtc.real.seconds;
|
||||
save.rtc_real.minutes = bess_rtc.real.minutes;
|
||||
save.rtc_real.hours = bess_rtc.real.hours;
|
||||
save.rtc_real.days = bess_rtc.real.days;
|
||||
save.rtc_real.high = bess_rtc.real.high;
|
||||
save.rtc_latched.seconds = bess_rtc.latched.seconds;
|
||||
save.rtc_latched.minutes = bess_rtc.latched.minutes;
|
||||
save.rtc_latched.hours = bess_rtc.latched.hours;
|
||||
save.rtc_latched.days = bess_rtc.latched.days;
|
||||
save.rtc_latched.high = bess_rtc.latched.high;
|
||||
if (gb->rtc_mode == GB_RTC_MODE_SYNC_TO_HOST) {
|
||||
save.last_rtc_second = MIN(LE64(bess_rtc.last_rtc_second), time(NULL));
|
||||
}
|
||||
|
||||
break;
|
||||
case BE32('HUC3'):
|
||||
if (!found_core) goto parse_error;
|
||||
BESS_HUC3_t bess_huc3;
|
||||
if (LE32(block.size) != sizeof(bess_huc3) - sizeof(block)) goto parse_error;
|
||||
if (file->read(file, &bess_huc3.header + 1, LE32(block.size)) != LE32(block.size)) goto error;
|
||||
if (gb->cartridge_type->mbc_type == GB_HUC3) {
|
||||
gb->last_rtc_second = LE64(bess_huc3.data.last_rtc_second);
|
||||
gb->huc3_minutes = LE16(bess_huc3.data.minutes);
|
||||
gb->huc3_days = LE16(bess_huc3.data.days);
|
||||
gb->huc3_alarm_minutes = LE16(bess_huc3.data.alarm_minutes);
|
||||
gb->huc3_alarm_days = LE16(bess_huc3.data.alarm_days);
|
||||
gb->huc3_alarm_enabled = bess_huc3.data.alarm_enabled;
|
||||
if (gb->cartridge_type->mbc_type != GB_HUC3) break;
|
||||
if (gb->rtc_mode == GB_RTC_MODE_SYNC_TO_HOST) {
|
||||
save.last_rtc_second = MIN(LE64(bess_huc3.data.last_rtc_second), time(NULL));
|
||||
}
|
||||
save.huc3_minutes = LE16(bess_huc3.data.minutes);
|
||||
save.huc3_days = LE16(bess_huc3.data.days);
|
||||
save.huc3_alarm_minutes = LE16(bess_huc3.data.alarm_minutes);
|
||||
save.huc3_alarm_days = LE16(bess_huc3.data.alarm_days);
|
||||
save.huc3_alarm_enabled = bess_huc3.data.alarm_enabled;
|
||||
break;
|
||||
case BE32('TPP1'):
|
||||
if (!found_core) goto parse_error;
|
||||
BESS_TPP1_t bess_tpp1;
|
||||
if (LE32(block.size) != sizeof(bess_tpp1) - sizeof(block)) goto parse_error;
|
||||
if (file->read(file, &bess_tpp1.header + 1, LE32(block.size)) != LE32(block.size)) goto error;
|
||||
if (gb->cartridge_type->mbc_type != GB_TPP1) break;
|
||||
if (gb->rtc_mode == GB_RTC_MODE_SYNC_TO_HOST) {
|
||||
save.last_rtc_second = MIN(LE64(bess_tpp1.last_rtc_second), time(NULL));
|
||||
}
|
||||
unrolled for (unsigned i = 4; i--;) {
|
||||
save.rtc_real.data[i ^ 3] = bess_tpp1.real_rtc_data[i];
|
||||
save.rtc_latched.data[i ^ 3] = bess_tpp1.latched_rtc_data[i];
|
||||
}
|
||||
save.tpp1_mr4 = bess_tpp1.mr4;
|
||||
break;
|
||||
case BE32('SGB '):
|
||||
if (!found_core) goto parse_error;
|
||||
|
|
|
@ -283,27 +283,31 @@ static void GB_rtc_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
}
|
||||
return;
|
||||
}
|
||||
bool running = false;
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
running = gb->tpp1_mr4 & 0x4;
|
||||
}
|
||||
else {
|
||||
running = (gb->rtc_real.high & 0x40) == 0;
|
||||
}
|
||||
|
||||
if ((gb->rtc_real.high & 0x40) == 0) { /* is timer running? */
|
||||
if (running) { /* is timer running? */
|
||||
while (gb->last_rtc_second + 60 * 60 * 24 < current_time) {
|
||||
gb->last_rtc_second += 60 * 60 * 24;
|
||||
if (++gb->rtc_real.days == 0) {
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
if ((gb->rtc_real.high & 7) >= 6) { /* Bit 8 of days*/
|
||||
gb->rtc_real.high &= 0x40;
|
||||
gb->rtc_real.high |= 0x80; /* Overflow bit */
|
||||
}
|
||||
else {
|
||||
gb->rtc_real.high++;
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
if (++gb->rtc_real.tpp1.weekday == 7) {
|
||||
gb->rtc_real.tpp1.weekday = 0;
|
||||
if (++gb->rtc_real.tpp1.weeks == 0) {
|
||||
gb->tpp1_mr4 |= 8; /* Overflow bit */
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (gb->rtc_real.high & 1) { /* Bit 8 of days*/
|
||||
gb->rtc_real.high |= 0x80; /* Overflow bit */
|
||||
}
|
||||
|
||||
gb->rtc_real.high ^= 1;
|
||||
}
|
||||
else if (++gb->rtc_real.days == 0) {
|
||||
if (gb->rtc_real.high & 1) { /* Bit 8 of days*/
|
||||
gb->rtc_real.high |= 0x80; /* Overflow bit */
|
||||
}
|
||||
|
||||
gb->rtc_real.high ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,21 +319,21 @@ static void GB_rtc_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
if (++gb->rtc_real.minutes != 60) continue;
|
||||
gb->rtc_real.minutes = 0;
|
||||
|
||||
if (++gb->rtc_real.hours != 24) continue;
|
||||
gb->rtc_real.hours = 0;
|
||||
|
||||
if (++gb->rtc_real.days != 0) continue;
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
if ((gb->rtc_real.high & 7) >= 6) { /* Bit 8 of days*/
|
||||
gb->rtc_real.high &= 0x40;
|
||||
gb->rtc_real.high |= 0x80; /* Overflow bit */
|
||||
}
|
||||
else {
|
||||
gb->rtc_real.high++;
|
||||
if (++gb->rtc_real.tpp1.hours != 24) continue;
|
||||
gb->rtc_real.tpp1.hours = 0;
|
||||
if (++gb->rtc_real.tpp1.weekday != 7) continue;
|
||||
gb->rtc_real.tpp1.weekday = 0;
|
||||
if (++gb->rtc_real.tpp1.weeks == 0) {
|
||||
gb->tpp1_mr4 |= 8; /* Overflow bit */
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (++gb->rtc_real.hours != 24) continue;
|
||||
gb->rtc_real.hours = 0;
|
||||
|
||||
if (++gb->rtc_real.days != 0) continue;
|
||||
|
||||
if (gb->rtc_real.high & 1) { /* Bit 8 of days*/
|
||||
gb->rtc_real.high |= 0x80; /* Overflow bit */
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue