00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #include "sysdeps.h"
00055
00056 #include "CPU1541.h"
00057 #include "CPU_common.h"
00058 #include "1541job.h"
00059 #include "C64.h"
00060 #include "CIA.h"
00061 #include "Display.h"
00062
00063
00064 enum {
00065 INT_RESET = 3
00066 };
00067
00068
00069
00070
00071
00072
00073 MOS6502_1541::MOS6502_1541(C64 *c64, Job1541 *job, C64Display *disp, uint8 *Ram, uint8 *Rom)
00074 : ram(Ram), rom(Rom), the_c64(c64), the_display(disp), the_job(job)
00075 {
00076 a = x = y = 0;
00077 sp = 0xff;
00078 n_flag = z_flag = 0;
00079 v_flag = d_flag = c_flag = false;
00080 i_flag = true;
00081
00082 via1_t1c = via1_t1l = via1_t2c = via1_t2l = 0;
00083 via1_sr = 0;
00084 via2_t1c = via2_t1l = via2_t2c = via2_t2l = 0;
00085 via2_sr = 0;
00086
00087 first_irq_cycle = 0;
00088 Idle = false;
00089 }
00090
00091
00092
00093
00094
00095
00096 void MOS6502_1541::AsyncReset(void)
00097 {
00098 interrupt.intr[INT_RESET] = true;
00099 Idle = false;
00100 }
00101
00102
00103
00104
00105
00106
00107 void MOS6502_1541::GetState(MOS6502State *s)
00108 {
00109 s->a = a;
00110 s->x = x;
00111 s->y = y;
00112
00113 s->p = 0x20 | (n_flag & 0x80);
00114 if (v_flag) s->p |= 0x40;
00115 if (d_flag) s->p |= 0x08;
00116 if (i_flag) s->p |= 0x04;
00117 if (!z_flag) s->p |= 0x02;
00118 if (c_flag) s->p |= 0x01;
00119
00120 s->pc = pc;
00121 s->sp = sp | 0x0100;
00122
00123 s->intr[INT_VIA1IRQ] = interrupt.intr[INT_VIA1IRQ];
00124 s->intr[INT_VIA2IRQ] = interrupt.intr[INT_VIA2IRQ];
00125 s->intr[INT_IECIRQ] = interrupt.intr[INT_IECIRQ];
00126 s->intr[INT_RESET] = interrupt.intr[INT_RESET];
00127 s->idle = Idle;
00128
00129 s->via1_pra = via1_pra; s->via1_ddra = via1_ddra;
00130 s->via1_prb = via1_prb; s->via1_ddrb = via1_ddrb;
00131 s->via1_t1c = via1_t1c; s->via1_t1l = via1_t1l;
00132 s->via1_t2c = via1_t2c; s->via1_t2l = via1_t2l;
00133 s->via1_sr = via1_sr;
00134 s->via1_acr = via1_acr; s->via1_pcr = via1_pcr;
00135 s->via1_ifr = via1_ifr; s->via1_ier = via1_ier;
00136
00137 s->via2_pra = via2_pra; s->via2_ddra = via2_ddra;
00138 s->via2_prb = via2_prb; s->via2_ddrb = via2_ddrb;
00139 s->via2_t1c = via2_t1c; s->via2_t1l = via2_t1l;
00140 s->via2_t2c = via2_t2c; s->via2_t2l = via2_t2l;
00141 s->via2_sr = via2_sr;
00142 s->via2_acr = via2_acr; s->via2_pcr = via2_pcr;
00143 s->via2_ifr = via2_ifr; s->via2_ier = via2_ier;
00144 }
00145
00146
00147
00148
00149
00150
00151 void MOS6502_1541::SetState(MOS6502State *s)
00152 {
00153 a = s->a;
00154 x = s->x;
00155 y = s->y;
00156
00157 n_flag = s->p;
00158 v_flag = s->p & 0x40;
00159 d_flag = s->p & 0x08;
00160 i_flag = s->p & 0x04;
00161 z_flag = !(s->p & 0x02);
00162 c_flag = s->p & 0x01;
00163
00164 pc = s->pc;
00165 sp = s->sp & 0xff;
00166
00167 interrupt.intr[INT_VIA1IRQ] = s->intr[INT_VIA1IRQ];
00168 interrupt.intr[INT_VIA2IRQ] = s->intr[INT_VIA2IRQ];
00169 interrupt.intr[INT_IECIRQ] = s->intr[INT_IECIRQ];
00170 interrupt.intr[INT_RESET] = s->intr[INT_RESET];
00171 Idle = s->idle;
00172
00173 via1_pra = s->via1_pra; via1_ddra = s->via1_ddra;
00174 via1_prb = s->via1_prb; via1_ddrb = s->via1_ddrb;
00175 via1_t1c = s->via1_t1c; via1_t1l = s->via1_t1l;
00176 via1_t2c = s->via1_t2c; via1_t2l = s->via1_t2l;
00177 via1_sr = s->via1_sr;
00178 via1_acr = s->via1_acr; via1_pcr = s->via1_pcr;
00179 via1_ifr = s->via1_ifr; via1_ier = s->via1_ier;
00180
00181 via2_pra = s->via2_pra; via2_ddra = s->via2_ddra;
00182 via2_prb = s->via2_prb; via2_ddrb = s->via2_ddrb;
00183 via2_t1c = s->via2_t1c; via2_t1l = s->via2_t1l;
00184 via2_t2c = s->via2_t2c; via2_t2l = s->via2_t2l;
00185 via2_sr = s->via2_sr;
00186 via2_acr = s->via2_acr; via2_pcr = s->via2_pcr;
00187 via2_ifr = s->via2_ifr; via2_ier = s->via2_ier;
00188 }
00189
00190
00191
00192
00193
00194
00195 inline uint8 MOS6502_1541::read_byte_io(uint16 adr)
00196 {
00197 if ((adr & 0xfc00) == 0x1800)
00198 switch (adr & 0xf) {
00199 case 0:
00200 return (via1_prb & 0x1a
00201 | ((IECLines & TheCIA2->IECLines) >> 7)
00202 | ((IECLines & TheCIA2->IECLines) >> 4) & 0x04
00203 | (TheCIA2->IECLines << 3) & 0x80) ^ 0x85;
00204 case 1:
00205 case 15:
00206 return 0xff;
00207 case 2:
00208 return via1_ddrb;
00209 case 3:
00210 return via1_ddra;
00211 case 4:
00212 via1_ifr &= 0xbf;
00213 return via1_t1c;
00214 case 5:
00215 return via1_t1c >> 8;
00216 case 6:
00217 return via1_t1l;
00218 case 7:
00219 return via1_t1l >> 8;
00220 case 8:
00221 via1_ifr &= 0xdf;
00222 return via1_t2c;
00223 case 9:
00224 return via1_t2c >> 8;
00225 case 10:
00226 return via1_sr;
00227 case 11:
00228 return via1_acr;
00229 case 12:
00230 return via1_pcr;
00231 case 13:
00232 return via1_ifr | (via1_ifr & via1_ier ? 0x80 : 0);
00233 case 14:
00234 return via1_ier | 0x80;
00235 default:
00236 return 0;
00237 }
00238
00239 else if ((adr & 0xfc00) == 0x1c00)
00240 switch (adr & 0xf) {
00241 case 0:
00242 if (the_job->SyncFound())
00243 return via2_prb & 0x7f | the_job->WPState();
00244 else
00245 return via2_prb | 0x80 | the_job->WPState();
00246 case 1:
00247 case 15:
00248 return the_job->ReadGCRByte();
00249 case 2:
00250 return via2_ddrb;
00251 case 3:
00252 return via2_ddra;
00253 case 4:
00254 via2_ifr &= 0xbf;
00255 interrupt.intr[INT_VIA2IRQ] = false;
00256 return via2_t1c;
00257 case 5:
00258 return via2_t1c >> 8;
00259 case 6:
00260 return via2_t1l;
00261 case 7:
00262 return via2_t1l >> 8;
00263 case 8:
00264 via2_ifr &= 0xdf;
00265 return via2_t2c;
00266 case 9:
00267 return via2_t2c >> 8;
00268 case 10:
00269 return via2_sr;
00270 case 11:
00271 return via2_acr;
00272 case 12:
00273 return via2_pcr;
00274 case 13:
00275 return via2_ifr | (via2_ifr & via2_ier ? 0x80 : 0);
00276 case 14:
00277 return via2_ier | 0x80;
00278 default:
00279 return 0;
00280 }
00281
00282 else
00283 return adr >> 8;
00284 }
00285
00286
00287
00288
00289
00290
00291 uint8 MOS6502_1541::read_byte(uint16 adr)
00292 {
00293 if (adr >= 0xc000)
00294 return rom[adr & 0x3fff];
00295 else if (adr < 0x1000)
00296 return ram[adr & 0x07ff];
00297 else
00298 return read_byte_io(adr);
00299 }
00300
00301
00302
00303
00304
00305
00306 inline uint16 MOS6502_1541::read_word(uint16 adr)
00307 {
00308 return read_byte(adr) | (read_byte(adr+1) << 8);
00309 }
00310
00311
00312
00313
00314
00315
00316 void MOS6502_1541::write_byte_io(uint16 adr, uint8 byte)
00317 {
00318 if ((adr & 0xfc00) == 0x1800)
00319 switch (adr & 0xf) {
00320 case 0:
00321 via1_prb = byte;
00322 byte = ~via1_prb & via1_ddrb;
00323 IECLines = (byte << 6) & ((~byte ^ TheCIA2->IECLines) << 3) & 0x80
00324 | (byte << 3) & 0x40;
00325 break;
00326 case 1:
00327 case 15:
00328 via1_pra = byte;
00329 break;
00330 case 2:
00331 via1_ddrb = byte;
00332 byte &= ~via1_prb;
00333 IECLines = (byte << 6) & ((~byte ^ TheCIA2->IECLines) << 3) & 0x80
00334 | (byte << 3) & 0x40;
00335 break;
00336 case 3:
00337 via1_ddra = byte;
00338 break;
00339 case 4:
00340 case 6:
00341 via1_t1l = via1_t1l & 0xff00 | byte;
00342 break;
00343 case 5:
00344 via1_t1l = via1_t1l & 0xff | (byte << 8);
00345 via1_ifr &= 0xbf;
00346 via1_t1c = via1_t1l;
00347 break;
00348 case 7:
00349 via1_t1l = via1_t1l & 0xff | (byte << 8);
00350 break;
00351 case 8:
00352 via1_t2l = via1_t2l & 0xff00 | byte;
00353 break;
00354 case 9:
00355 via1_t2l = via1_t2l & 0xff | (byte << 8);
00356 via1_ifr &= 0xdf;
00357 via1_t2c = via1_t2l;
00358 break;
00359 case 10:
00360 via1_sr = byte;
00361 break;
00362 case 11:
00363 via1_acr = byte;
00364 break;
00365 case 12:
00366 via1_pcr = byte;
00367 break;
00368 case 13:
00369 via1_ifr &= ~byte;
00370 break;
00371 case 14:
00372 if (byte & 0x80)
00373 via1_ier |= byte & 0x7f;
00374 else
00375 via1_ier &= ~byte;
00376 break;
00377 }
00378
00379 else if ((adr & 0xfc00) == 0x1c00)
00380 switch (adr & 0xf) {
00381 case 0:
00382 if ((via2_prb ^ byte) & 8)
00383 the_display->UpdateLEDs(byte & 8 ? 1 : 0, 0, 0, 0);
00384 if ((via2_prb ^ byte) & 3)
00385 if ((via2_prb & 3) == ((byte+1) & 3))
00386 the_job->MoveHeadOut();
00387 else if ((via2_prb & 3) == ((byte-1) & 3))
00388 the_job->MoveHeadIn();
00389 via2_prb = byte & 0xef;
00390 break;
00391 case 1:
00392 case 15:
00393 via2_pra = byte;
00394 break;
00395 case 2:
00396 via2_ddrb = byte;
00397 break;
00398 case 3:
00399 via2_ddra = byte;
00400 break;
00401 case 4:
00402 case 6:
00403 via2_t1l = via2_t1l & 0xff00 | byte;
00404 break;
00405 case 5:
00406 via2_t1l = via2_t1l & 0xff | (byte << 8);
00407 via2_ifr &= 0xbf;
00408 via2_t1c = via2_t1l;
00409 break;
00410 case 7:
00411 via2_t1l = via2_t1l & 0xff | (byte << 8);
00412 break;
00413 case 8:
00414 via2_t2l = via2_t2l & 0xff00 | byte;
00415 break;
00416 case 9:
00417 via2_t2l = via2_t2l & 0xff | (byte << 8);
00418 via2_ifr &= 0xdf;
00419 via2_t2c = via2_t2l;
00420 break;
00421 case 10:
00422 via2_sr = byte;
00423 break;
00424 case 11:
00425 via2_acr = byte;
00426 break;
00427 case 12:
00428 via2_pcr = byte;
00429 break;
00430 case 13:
00431 via2_ifr &= ~byte;
00432 break;
00433 case 14:
00434 if (byte & 0x80)
00435 via2_ier |= byte & 0x7f;
00436 else
00437 via2_ier &= ~byte;
00438 break;
00439 }
00440 }
00441
00442
00443
00444
00445
00446
00447 inline void MOS6502_1541::write_byte(uint16 adr, uint8 byte)
00448 {
00449 if (adr < 0x1000)
00450 ram[adr & 0x7ff] = byte;
00451 else
00452 write_byte_io(adr, byte);
00453 }
00454
00455
00456
00457
00458
00459
00460 uint8 MOS6502_1541::ExtReadByte(uint16 adr)
00461 {
00462 return read_byte(adr);
00463 }
00464
00465
00466
00467
00468
00469
00470 void MOS6502_1541::ExtWriteByte(uint16 adr, uint8 byte)
00471 {
00472 write_byte(adr, byte);
00473 }
00474
00475
00476
00477
00478
00479
00480 inline void MOS6502_1541::do_adc(uint8 byte)
00481 {
00482 if (!d_flag) {
00483 uint16 tmp;
00484
00485
00486 tmp = a + byte + (c_flag ? 1 : 0);
00487 c_flag = tmp > 0xff;
00488 v_flag = !((a ^ byte) & 0x80) && ((a ^ tmp) & 0x80);
00489 z_flag = n_flag = a = tmp;
00490
00491 } else {
00492 uint16 al, ah;
00493
00494
00495 al = (a & 0x0f) + (byte & 0x0f) + (c_flag ? 1 : 0);
00496 if (al > 9) al += 6;
00497
00498 ah = (a >> 4) + (byte >> 4);
00499 if (al > 0x0f) ah++;
00500
00501 z_flag = a + byte + (c_flag ? 1 : 0);
00502 n_flag = ah << 4;
00503 v_flag = (((ah << 4) ^ a) & 0x80) && !((a ^ byte) & 0x80);
00504
00505 if (ah > 9) ah += 6;
00506 c_flag = ah > 0x0f;
00507 a = (ah << 4) | (al & 0x0f);
00508 }
00509 }
00510
00511
00512
00513
00514
00515
00516 inline void MOS6502_1541::do_sbc(uint8 byte)
00517 {
00518 uint16 tmp = a - byte - (c_flag ? 0 : 1);
00519
00520 if (!d_flag) {
00521
00522
00523 c_flag = tmp < 0x100;
00524 v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80);
00525 z_flag = n_flag = a = tmp;
00526
00527 } else {
00528 uint16 al, ah;
00529
00530
00531 al = (a & 0x0f) - (byte & 0x0f) - (c_flag ? 0 : 1);
00532 ah = (a >> 4) - (byte >> 4);
00533 if (al & 0x10) {
00534 al -= 6;
00535 ah--;
00536 }
00537 if (ah & 0x10) ah -= 6;
00538
00539 c_flag = tmp < 0x100;
00540 v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80);
00541 z_flag = n_flag = tmp;
00542
00543 a = (ah << 4) | (al & 0x0f);
00544 }
00545 }
00546
00547
00548
00549
00550
00551
00552 void MOS6502_1541::Reset(void)
00553 {
00554
00555 IECLines = 0xc0;
00556
00557 via1_pra = via1_ddra = via1_prb = via1_ddrb = 0;
00558 via1_acr = via1_pcr = 0;
00559 via1_ifr = via1_ier = 0;
00560 via2_pra = via2_ddra = via2_prb = via2_ddrb = 0;
00561 via2_acr = via2_pcr = 0;
00562 via2_ifr = via2_ier = 0;
00563
00564
00565 interrupt.intr_any = 0;
00566
00567
00568 pc = read_word(0xfffc);
00569 state = 0;
00570
00571
00572 Idle = false;
00573 }
00574
00575
00576
00577
00578
00579
00580 void MOS6502_1541::illegal_op(uint8 op, uint16 at)
00581 {
00582 char illop_msg[80];
00583
00584 sprintf(illop_msg, "1541: Illegal opcode %02x at %04x.", op, at);
00585 if (ShowRequester(illop_msg, "Reset 1541", "Reset C64"))
00586 the_c64->Reset();
00587 Reset();
00588 }
00589
00590
00591
00592
00593
00594
00595
00596 #define read_to(adr, to) \
00597 to = read_byte(adr);
00598
00599
00600 #define read_idle(adr) \
00601 read_byte(adr);
00602
00603 void MOS6502_1541::EmulateCycle(void)
00604 {
00605 uint8 data, tmp;
00606
00607
00608 if (!state && interrupt.intr_any) {
00609 if (interrupt.intr[INT_RESET])
00610 Reset();
00611 else if ((interrupt.intr[INT_VIA1IRQ] || interrupt.intr[INT_VIA2IRQ] || interrupt.intr[INT_IECIRQ]) && (the_c64->CycleCounter-first_irq_cycle >= 2) && !i_flag)
00612 state = 0x0008;
00613 }
00614
00615 #define IS_CPU_1541
00616 #include "CPU_emulcycle.i"
00617
00618
00619 case O_EXT:
00620 if (pc < 0xc000) {
00621 illegal_op(0xf2, pc-1);
00622 break;
00623 }
00624 switch (read_byte(pc++)) {
00625 case 0x00:
00626 Idle = !(ram[0x26c] | ram[0x7c]);
00627 pc = 0xebff;
00628 Last;
00629 case 0x01:
00630 the_job->WriteSector();
00631 pc = 0xf5dc;
00632 Last;
00633 case 0x02:
00634 the_job->FormatTrack();
00635 pc = 0xfd8b;
00636 Last;
00637 default:
00638 illegal_op(0xf2, pc-1);
00639 break;
00640 }
00641 break;
00642
00643 default:
00644 illegal_op(op, pc-1);
00645 break;
00646 }
00647 }