Version 1.0a - fix for TOD clock not running (fixes some utilities). Slight VIC refactor for additional speed (1-2 frames).

This commit is contained in:
Dave Bernazzani 2025-05-10 10:16:33 -04:00
parent 12cad5f3fa
commit 26d89638b1
5 changed files with 108 additions and 34 deletions

Binary file not shown.

View File

@ -9,7 +9,7 @@ include $(DEVKITARM)/ds_rules
export TARGET := GimliDS
export TOPDIR := $(CURDIR)
export VERSION := 1.0
export VERSION := 1.0a
ICON := -b $(CURDIR)/C64_icon.bmp "GimliDS $(VERSION);wavemotion-dave;https://github.com/wavemotion-dave/GimliDS"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -86,13 +86,15 @@ void MOS6526::Reset(void)
ta = tb = 0xffff;
latcha = latchb = 1;
tod_10ths = tod_sec = tod_min = tod_hr = 0;
tod_10ths = tod_sec = tod_min = 0; tod_hr = 1;
alm_10ths = alm_sec = alm_min = alm_hr = 0;
sdr = icr = cra = crb = int_mask = 0;
tod_halt = ta_cnt_phi2 = tb_cnt_phi2 = tb_cnt_ta = false;
ta_cnt_phi2 = tb_cnt_phi2 = tb_cnt_ta = false;
tod_divider = 0;
tod_alarm = false;
tod_halt = true;
}
void MOS6526_1::Reset(void)
@ -231,12 +233,13 @@ uint8 MOS6526_1::ReadRegister(uint16 adr)
case 0x05: return ta >> 8;
case 0x06: return tb;
case 0x07: return tb >> 8;
case 0x08: tod_halt = false; return tod_10ths;
case 0x08: return tod_10ths; // TODO: unlatch
case 0x09: return tod_sec;
case 0x0a: return tod_min;
case 0x0b: tod_halt = true; return tod_hr;
case 0x0b: return tod_hr; // TODO: latch
case 0x0c: return sdr;
case 0x0d: {
case 0x0d:
{
uint8 ret = icr; // Read and clear ICR
icr = 0;
the_cpu->ClearCIAIRQ(); // Clear IRQ
@ -265,12 +268,13 @@ uint8 MOS6526_2::ReadRegister(uint16 adr)
case 0x05: return ta >> 8;
case 0x06: return tb;
case 0x07: return tb >> 8;
case 0x08: tod_halt = false; return tod_10ths;
case 0x08: return tod_10ths; // TODO: unlatch
case 0x09: return tod_sec;
case 0x0a: return tod_min;
case 0x0b: tod_halt = true; return tod_hr;
case 0x0b: return tod_hr; // TODO: latch
case 0x0c: return sdr;
case 0x0d: {
case 0x0d:
{
uint8 ret = icr; // Read and clear ICR
icr = 0;
the_cpu->ClearNMI(); // Clear NMI
@ -324,28 +328,49 @@ void MOS6526_1::WriteRegister(uint16 adr, uint8 byte)
break;
case 0x8:
byte &= 0x0f;
if (crb & 0x80)
alm_10ths = byte & 0x0f;
{
if (alm_10ths != byte)
{
check_tod_alarm();
}
alm_10ths = byte;
}
else
tod_10ths = byte & 0x0f;
{
if (tod_10ths != byte)
{
check_tod_alarm();
}
tod_10ths = byte;
tod_halt = false;
}
check_tod_alarm();
break;
case 0x9:
if (crb & 0x80)
alm_sec = byte & 0x7f;
else
tod_sec = byte & 0x7f;
check_tod_alarm();
break;
case 0xa:
if (crb & 0x80)
alm_min = byte & 0x7f;
else
tod_min = byte & 0x7f;
check_tod_alarm();
break;
case 0xb:
if (crb & 0x80)
alm_hr = byte & 0x9f;
else
{
tod_hr = byte & 0x9f;
tod_halt = true;
}
check_tod_alarm();
break;
case 0xc:
@ -357,8 +382,8 @@ void MOS6526_1::WriteRegister(uint16 adr, uint8 byte)
if (ThePrefs.CIAIRQHack) // Hack for addressing modes that read from the address
icr = 0;
if (byte & 0x80) {
int_mask |= byte & 0x7f;
if (icr & int_mask & 0x1f) { // Trigger IRQ if pending
int_mask |= byte & 0x1f;
if (icr & int_mask) { // Trigger IRQ if pending
icr |= 0x80;
the_cpu->TriggerCIAIRQ();
}
@ -393,7 +418,8 @@ inline void MOS6526_2::write_pa(uint8_t byte)
| ((byte << 2) & 0x40) // CLK
| ((byte << 1) & 0x10); // ATN
if ((IECLines ^ old_lines) & 0x10) { // ATN changed
if ((IECLines ^ old_lines) & 0x10) // ATN changed
{
the_cpu_1541->NewATNState();
if (old_lines & 0x10) // ATN 1->0
the_cpu_1541->TriggerIECInterrupt();
@ -438,28 +464,48 @@ void MOS6526_2::WriteRegister(uint16 adr, uint8 byte)
break;
case 0x8:
byte &= 0x0f;
if (crb & 0x80)
alm_10ths = byte & 0x0f;
{
if (alm_10ths != byte)
{
check_tod_alarm();
}
alm_10ths = byte;
}
else
tod_10ths = byte & 0x0f;
break;
{
if (tod_10ths != byte)
{
check_tod_alarm();
}
tod_10ths = byte;
tod_halt = false;
}
check_tod_alarm();
case 0x9:
if (crb & 0x80)
alm_sec = byte & 0x7f;
else
tod_sec = byte & 0x7f;
check_tod_alarm();
break;
case 0xa:
if (crb & 0x80)
alm_min = byte & 0x7f;
else
tod_min = byte & 0x7f;
check_tod_alarm();
break;
case 0xb:
if (crb & 0x80)
alm_hr = byte & 0x9f;
else
{
tod_hr = byte & 0x9f;
tod_halt = true;
}
check_tod_alarm();
break;
case 0xc:
@ -506,10 +552,13 @@ void MOS6526::CountTOD(void)
{
uint8 lo, hi;
if (tod_halt) return; // Clock halted - skip clocking
// Decrement frequency divider
if (tod_divider)
tod_divider--;
else {
else
{
// Reload divider according to 50/60 Hz flag
if (cra & 0x80)
@ -519,27 +568,32 @@ void MOS6526::CountTOD(void)
// 1/10 seconds
tod_10ths++;
if (tod_10ths > 9) {
if (tod_10ths > 9)
{
tod_10ths = 0;
// Seconds
lo = (tod_sec & 0x0f) + 1;
hi = tod_sec >> 4;
if (lo > 9) {
if (lo > 9)
{
lo = 0;
hi++;
}
if (hi > 5) {
if (hi > 5)
{
tod_sec = 0;
// Minutes
lo = (tod_min & 0x0f) + 1;
hi = tod_min >> 4;
if (lo > 9) {
if (lo > 9)
{
lo = 0;
hi++;
}
if (hi > 5) {
if (hi > 5)
{
tod_min = 0;
// Hours
@ -559,10 +613,7 @@ void MOS6526::CountTOD(void)
tod_sec = (hi << 4) | lo;
}
// Alarm time reached? Trigger interrupt if enabled
if (tod_10ths == alm_10ths && tod_sec == alm_sec &&
tod_min == alm_min && tod_hr == alm_hr)
TriggerInterrupt(4);
check_tod_alarm();
}
}
@ -574,7 +625,8 @@ void MOS6526::CountTOD(void)
void MOS6526_1::TriggerInterrupt(int bit)
{
icr |= bit;
if (int_mask & bit) {
if (int_mask & bit)
{
icr |= 0x80;
the_cpu->TriggerCIAIRQ();
}
@ -588,7 +640,8 @@ void MOS6526_1::TriggerInterrupt(int bit)
void MOS6526_2::TriggerInterrupt(int bit)
{
icr |= bit;
if (int_mask & bit) {
if (int_mask & bit)
{
icr |= 0x80;
the_cpu->TriggerNMI();
}

View File

@ -77,6 +77,9 @@ protected:
ta_cnt_phi2, // Flag: Timer A is counting Phi 2
tb_cnt_phi2, // Flag: Timer B is counting Phi 2
tb_cnt_ta; // Flag: Timer B is counting underflows of Timer A
bool tod_alarm; // Flag: TOD in alarm state
void check_tod_alarm();
};
@ -151,6 +154,24 @@ struct MOS6526State {
uint8 int_mask; // Enabled interrupts
};
/*
* Check for TOD alarm
*/
inline void MOS6526::check_tod_alarm()
{
bool alarm_match = (tod_10ths == alm_10ths && tod_sec == alm_sec &&
tod_min == alm_min && tod_hr == alm_hr);
// Raise interrupt on positive edge of alarm match
if (alarm_match && !tod_alarm)
{
TriggerInterrupt(4);
}
tod_alarm = alarm_match;
}
/*
* Emulate CIA for one cycle/raster line