mirror of
https://github.com/LIV2/WinUAE.git
synced 2025-12-06 00:12:52 +00:00
CIA latch/timer=0 special case update
This commit is contained in:
parent
fe19d44193
commit
4f403c289a
89
cia.cpp
89
cia.cpp
@ -444,7 +444,7 @@ static uae_u8 cia_inmode_cnt(int num)
|
||||
return icr;
|
||||
}
|
||||
|
||||
static int process_pipe(struct CIATimer *t, int cc, uae_u8 crmask, int *ovfl)
|
||||
static int process_pipe(struct CIATimer *t, int cc, uae_u8 crmask, int *ovfl, int loadednow)
|
||||
{
|
||||
int ccout = cc;
|
||||
|
||||
@ -455,8 +455,8 @@ static int process_pipe(struct CIATimer *t, int cc, uae_u8 crmask, int *ovfl)
|
||||
t->inputpipe |= CIA_PIPE_INPUT;
|
||||
}
|
||||
// interrupt 1 cycle early if timer is already zero
|
||||
if (t->timer == 0 && (t->inputpipe & CIA_PIPE_OUTPUT)) {
|
||||
*ovfl = 1;
|
||||
if (t->timer == 0 && t->latch == 0 && (t->inputpipe & CIA_PIPE_OUTPUT)) {
|
||||
*ovfl = loadednow ? 1 : 2;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@ -494,7 +494,7 @@ static void CIA_update_check(void)
|
||||
for (int num = 0; num < 2; num++) {
|
||||
struct CIA *c = &cia[num];
|
||||
int ovfl[2], sp;
|
||||
bool loaded[2], loaded2[2];
|
||||
bool loaded[2], loaded2[2], loaded3[3];
|
||||
|
||||
c->icr1 |= c->icr2;
|
||||
c->icr2 = 0;
|
||||
@ -509,41 +509,45 @@ static void CIA_update_check(void)
|
||||
|
||||
loaded[tn] = false;
|
||||
loaded2[tn] = false;
|
||||
loaded3[tn] = false;
|
||||
|
||||
// CIA special cases
|
||||
if (t->loaddelay) {
|
||||
if (ciaclocks > 1) {
|
||||
abort();
|
||||
}
|
||||
if (t->loaddelay & 1) {
|
||||
|
||||
if (t->loaddelay & 0x00000001) {
|
||||
t->timer = t->latch;
|
||||
t->inputpipe &= ~CIA_PIPE_CLR1;
|
||||
}
|
||||
|
||||
if ((t->loaddelay & 0x0100) && t->timer != 0) {
|
||||
loaded2[tn] = true;
|
||||
// timer=0 special cases. TODO: better way to do this..
|
||||
// delayed timer stop and interrupt (timer=0 condition)
|
||||
if ((t->loaddelay & 0x00010000)) {
|
||||
t->cr &= ~CR_START;
|
||||
ovfl[tn] = 2;
|
||||
}
|
||||
if ((t->loaddelay & 0x010000)) {
|
||||
if ((t->timer != 1 || t->latch != 1) && (t->inputpipe & CIA_PIPE_OUTPUT)) {
|
||||
loaded2[tn] = true;
|
||||
}
|
||||
// Do not set START=0 until timer has started (timer==0 special case)
|
||||
if ((t->loaddelay & 0x00000100) && t->timer == 0) {
|
||||
loaded2[tn] = true;
|
||||
}
|
||||
if ((t->loaddelay & 0x01000000)) {
|
||||
loaded[tn] = true;
|
||||
if (t->timer == 0) {
|
||||
ovfl[tn] = true;
|
||||
}
|
||||
}
|
||||
if ((t->loaddelay & 0x10000000)) {
|
||||
loaded3[tn] = true;
|
||||
}
|
||||
|
||||
t->loaddelay >>= 1;
|
||||
t->loaddelay &= 0x7f7f7f7f;
|
||||
t->loaddelay &= 0x77777777;
|
||||
}
|
||||
}
|
||||
|
||||
// Timer A
|
||||
int cc = 0;
|
||||
if ((c->t[0].cr & (CR_INMODE | CR_START)) == CR_START || c->t[0].inputpipe) {
|
||||
cc = process_pipe(&c->t[0], ciaclocks, CR_INMODE | CR_START, &ovfl[0]);
|
||||
cc = process_pipe(&c->t[0], ciaclocks, CR_INMODE | CR_START, &ovfl[0], loaded3[0]);
|
||||
}
|
||||
if (cc > 0) {
|
||||
c->t[0].timer -= cc;
|
||||
@ -560,7 +564,7 @@ static void CIA_update_check(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
ovfl[0] = 1;
|
||||
ovfl[0] = 2;
|
||||
}
|
||||
}
|
||||
assert(c->t[0].timer < 0x10000);
|
||||
@ -568,15 +572,15 @@ static void CIA_update_check(void)
|
||||
// Timer B
|
||||
cc = 0;
|
||||
if ((c->t[1].cr & (CR_INMODE | CR_INMODE1 | CR_START)) == CR_START || c->t[1].inputpipe) {
|
||||
cc = process_pipe(&c->t[1], ciaclocks, CR_INMODE | CR_INMODE1 | CR_START, &ovfl[1]);
|
||||
cc = process_pipe(&c->t[1], ciaclocks, CR_INMODE | CR_INMODE1 | CR_START, &ovfl[1], loaded3[1]);
|
||||
}
|
||||
if (cc > 0) {
|
||||
if ((c->t[1].timer == 0 && (c->t[1].cr & (CR_INMODE | CR_INMODE1)))) {
|
||||
ovfl[1] = 1;
|
||||
ovfl[1] = 2;
|
||||
} else {
|
||||
c->t[1].timer -= cc;
|
||||
if ((c->t[1].timer == 0 && !(c->t[1].cr & (CR_INMODE | CR_INMODE1)))) {
|
||||
ovfl[1] = 1;
|
||||
ovfl[1] = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -591,18 +595,22 @@ static void CIA_update_check(void)
|
||||
struct CIATimer *t = &c->t[tn];
|
||||
|
||||
if (ovfl[tn] || t->preovfl) {
|
||||
c->icr2 |= tn ? ICR_B : ICR_A;
|
||||
t->timer = t->latch;
|
||||
if (ovfl[tn]) {
|
||||
if (ovfl[tn] > 1) {
|
||||
c->icr2 |= tn ? ICR_B : ICR_A;
|
||||
icr |= 1 << num;
|
||||
}
|
||||
t->timer = t->latch;
|
||||
}
|
||||
if (!loaded[tn]) {
|
||||
if (t->cr & CR_RUNMODE) {
|
||||
// if oneshot timer expires exactly when
|
||||
// CR is written with START and ONESHOT set:
|
||||
// timer does not stop.
|
||||
if (!loaded2[tn]) {
|
||||
if (loaded2[tn]) {
|
||||
t->loaddelay |= 0x00010000;
|
||||
} else {
|
||||
t->cr &= ~CR_START;
|
||||
if (!acc_mode()) {
|
||||
t->inputpipe = 0;
|
||||
}
|
||||
}
|
||||
if (!acc_mode()) {
|
||||
t->inputpipe = 0;
|
||||
}
|
||||
if (acc_mode()) {
|
||||
t->inputpipe &= ~CIA_PIPE_CLR2;
|
||||
@ -613,7 +621,6 @@ static void CIA_update_check(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
icr |= 1 << num;
|
||||
t->preovfl = false;
|
||||
}
|
||||
}
|
||||
@ -1504,15 +1511,18 @@ static void CIA_thi_write(int num, int tnum, uae_u8 val)
|
||||
// if accurate mode: handle delays cycle-accurately
|
||||
|
||||
if (!(t->cr & CR_START)) {
|
||||
t->loaddelay |= 1 << 1;
|
||||
t->loaddelay |= 1 << 2;
|
||||
t->loaddelay |= 0x00000001 << 1;
|
||||
t->loaddelay |= 0x00000001 << 2;
|
||||
}
|
||||
|
||||
if (t->cr & CR_RUNMODE) {
|
||||
t->cr |= CR_START;
|
||||
t->loaddelay |= 0x00000001 << 2;
|
||||
// timer=0 special case
|
||||
t->loaddelay |= 0x01000000 << 1;
|
||||
t->loaddelay |= 1 << 2;
|
||||
t->loaddelay |= 0x10000000 << 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1546,15 +1556,14 @@ static void CIA_cr_write(int num, int tnum, uae_u8 val)
|
||||
|
||||
if (val & CR_LOAD) {
|
||||
val &= ~CR_LOAD;
|
||||
t->loaddelay |= 0x0001 << 2;
|
||||
t->loaddelay |= 0x0100 << 0;
|
||||
t->loaddelay |= 0x00000001 << 2;
|
||||
t->loaddelay |= 0x00000100 << 0;
|
||||
t->loaddelay |= 0x00000100 << 1;
|
||||
if (!(t->cr & CR_START)) {
|
||||
t->loaddelay |= 0x0001 << 1;
|
||||
}
|
||||
} else {
|
||||
if ((val & CR_START)) {
|
||||
t->loaddelay |= 0x010000 << 0;
|
||||
t->loaddelay |= 0x00000001 << 1;
|
||||
}
|
||||
// timer=0 special case
|
||||
t->loaddelay |= 0x10000000 << 1;
|
||||
}
|
||||
|
||||
if (!(val & CR_START)) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user