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
00055
00056
00057
00058 #include "sysdeps.h"
00059
00060 #include "CPUC64.h"
00061 #include "CPU_common.h"
00062 #include "C64.h"
00063 #include "VIC.h"
00064 #include "SID.h"
00065 #include "CIA.h"
00066 #include "REU.h"
00067 #include "IEC.h"
00068 #include "Display.h"
00069 #include "Version.h"
00070
00071
00072 enum {
00073 INT_RESET = 3
00074 };
00075
00076
00077
00078
00079
00080
00081 MOS6510::MOS6510(C64 *c64, uint8 *Ram, uint8 *Basic, uint8 *Kernal, uint8 *Char, uint8 *Color)
00082 : the_c64(c64), ram(Ram), basic_rom(Basic), kernal_rom(Kernal), char_rom(Char), color_ram(Color)
00083 {
00084 a = x = y = 0;
00085 sp = 0xff;
00086 n_flag = z_flag = 0;
00087 v_flag = d_flag = c_flag = false;
00088 i_flag = true;
00089 dfff_byte = 0x55;
00090 BALow = false;
00091 first_irq_cycle = first_nmi_cycle = 0;
00092 }
00093
00094
00095
00096
00097
00098
00099 void MOS6510::AsyncReset(void)
00100 {
00101 interrupt.intr[INT_RESET] = true;
00102 }
00103
00104
00105
00106
00107
00108
00109 void MOS6510::AsyncNMI(void)
00110 {
00111 if (!nmi_state)
00112 interrupt.intr[INT_NMI] = true;
00113 }
00114
00115
00116
00117
00118
00119
00120 void MOS6510::GetState(MOS6510State *s)
00121 {
00122 s->a = a;
00123 s->x = x;
00124 s->y = y;
00125
00126 s->p = 0x20 | (n_flag & 0x80);
00127 if (v_flag) s->p |= 0x40;
00128 if (d_flag) s->p |= 0x08;
00129 if (i_flag) s->p |= 0x04;
00130 if (!z_flag) s->p |= 0x02;
00131 if (c_flag) s->p |= 0x01;
00132
00133 s->ddr = ddr;
00134 s->pr = pr;
00135
00136 s->pc = pc;
00137 s->sp = sp | 0x0100;
00138
00139 s->intr[INT_VICIRQ] = interrupt.intr[INT_VICIRQ];
00140 s->intr[INT_CIAIRQ] = interrupt.intr[INT_CIAIRQ];
00141 s->intr[INT_NMI] = interrupt.intr[INT_NMI];
00142 s->intr[INT_RESET] = interrupt.intr[INT_RESET];
00143 s->nmi_state = nmi_state;
00144 s->dfff_byte = dfff_byte;
00145 s->instruction_complete = (state == 0);
00146 }
00147
00148
00149
00150
00151
00152
00153 void MOS6510::SetState(MOS6510State *s)
00154 {
00155 a = s->a;
00156 x = s->x;
00157 y = s->y;
00158
00159 n_flag = s->p;
00160 v_flag = s->p & 0x40;
00161 d_flag = s->p & 0x08;
00162 i_flag = s->p & 0x04;
00163 z_flag = !(s->p & 0x02);
00164 c_flag = s->p & 0x01;
00165
00166 ddr = s->ddr;
00167 pr = s->pr;
00168 new_config();
00169
00170 pc = s->pc;
00171 sp = s->sp & 0xff;
00172
00173 interrupt.intr[INT_VICIRQ] = s->intr[INT_VICIRQ];
00174 interrupt.intr[INT_CIAIRQ] = s->intr[INT_CIAIRQ];
00175 interrupt.intr[INT_NMI] = s->intr[INT_NMI];
00176 interrupt.intr[INT_RESET] = s->intr[INT_RESET];
00177 nmi_state = s->nmi_state;
00178 dfff_byte = s->dfff_byte;
00179 if (s->instruction_complete)
00180 state = 0;
00181 }
00182
00183
00184
00185
00186
00187
00188 void MOS6510::new_config(void)
00189 {
00190 uint8 port = ~ddr | pr;
00191
00192 basic_in = (port & 3) == 3;
00193 kernal_in = port & 2;
00194 char_in = (port & 3) && !(port & 4);
00195 io_in = (port & 3) && (port & 4);
00196 }
00197
00198
00199
00200
00201
00202
00203 inline uint8 MOS6510::read_byte_io(uint16 adr)
00204 {
00205 switch (adr >> 12) {
00206 case 0xa:
00207 case 0xb:
00208 if (basic_in)
00209 return basic_rom[adr & 0x1fff];
00210 else
00211 return ram[adr];
00212 case 0xc:
00213 return ram[adr];
00214 case 0xd:
00215 if (io_in)
00216 switch ((adr >> 8) & 0x0f) {
00217 case 0x0:
00218 case 0x1:
00219 case 0x2:
00220 case 0x3:
00221 return TheVIC->ReadRegister(adr & 0x3f);
00222 case 0x4:
00223 case 0x5:
00224 case 0x6:
00225 case 0x7:
00226 return TheSID->ReadRegister(adr & 0x1f);
00227 case 0x8:
00228 case 0x9:
00229 case 0xa:
00230 case 0xb:
00231 return color_ram[adr & 0x03ff] & 0x0f | TheVIC->LastVICByte & 0xf0;
00232 case 0xc:
00233 return TheCIA1->ReadRegister(adr & 0x0f);
00234 case 0xd:
00235 return TheCIA2->ReadRegister(adr & 0x0f);
00236 case 0xe:
00237 case 0xf:
00238 if ((adr & 0xfff0) == 0xdf00)
00239 return TheREU->ReadRegister(adr & 0x0f);
00240 else if (adr < 0xdfa0)
00241 return TheVIC->LastVICByte;
00242 else
00243 return read_emulator_id(adr & 0x7f);
00244 }
00245 else if (char_in)
00246 return char_rom[adr & 0x0fff];
00247 else
00248 return ram[adr];
00249 case 0xe:
00250 case 0xf:
00251 if (kernal_in)
00252 return kernal_rom[adr & 0x1fff];
00253 else
00254 return ram[adr];
00255 default:
00256 return 0;
00257 }
00258 }
00259
00260
00261
00262
00263
00264
00265 #ifdef __i386
00266 inline
00267 #endif
00268 uint8 MOS6510::read_byte(uint16 adr)
00269 {
00270 if (adr < 0xa000) {
00271 if (adr >= 2)
00272 return ram[adr];
00273 else if (adr == 0)
00274 return ddr;
00275 else
00276 return (ddr & pr) | (~ddr & 0x17);
00277 } else
00278 return read_byte_io(adr);
00279 }
00280
00281
00282
00283
00284
00285
00286 const char frodo_id[0x5c] = "FRODO\r(C) 1994-1997 CHRISTIAN BAUER";
00287
00288 uint8 MOS6510::read_emulator_id(uint16 adr)
00289 {
00290 switch (adr) {
00291 case 0x7c:
00292 return FRODO_REVISION << 4;
00293 case 0x7d:
00294 return FRODO_VERSION;
00295 case 0x7e:
00296 return 'F';
00297 case 0x7f:
00298 dfff_byte = ~dfff_byte;
00299 return dfff_byte;
00300 default:
00301 return frodo_id[adr - 0x20];
00302 }
00303 }
00304
00305
00306
00307
00308
00309
00310 inline uint16 MOS6510::read_word(uint16 adr)
00311 {
00312 return read_byte(adr) | (read_byte(adr+1) << 8);
00313 }
00314
00315
00316
00317
00318
00319
00320 inline void MOS6510::write_byte_io(uint16 adr, uint8 byte)
00321 {
00322 if (adr >= 0xe000) {
00323 ram[adr] = byte;
00324 if (adr == 0xff00)
00325 TheREU->FF00Trigger();
00326 } else if (io_in)
00327 switch ((adr >> 8) & 0x0f) {
00328 case 0x0:
00329 case 0x1:
00330 case 0x2:
00331 case 0x3:
00332 TheVIC->WriteRegister(adr & 0x3f, byte);
00333 return;
00334 case 0x4:
00335 case 0x5:
00336 case 0x6:
00337 case 0x7:
00338 TheSID->WriteRegister(adr & 0x1f, byte);
00339 return;
00340 case 0x8:
00341 case 0x9:
00342 case 0xa:
00343 case 0xb:
00344 color_ram[adr & 0x03ff] = byte & 0x0f;
00345 return;
00346 case 0xc:
00347 TheCIA1->WriteRegister(adr & 0x0f, byte);
00348 return;
00349 case 0xd:
00350 TheCIA2->WriteRegister(adr & 0x0f, byte);
00351 return;
00352 case 0xe:
00353 case 0xf:
00354 if ((adr & 0xfff0) == 0xdf00)
00355 TheREU->WriteRegister(adr & 0x0f, byte);
00356 return;
00357 }
00358 else
00359 ram[adr] = byte;
00360 }
00361
00362
00363
00364
00365
00366
00367 void MOS6510::write_byte(uint16 adr, uint8 byte)
00368 {
00369 if (adr < 0xd000) {
00370 if (adr >= 2)
00371 ram[adr] = byte;
00372 else if (adr == 0) {
00373 ddr = byte;
00374 ram[0] = TheVIC->LastVICByte;
00375 new_config();
00376 } else {
00377 pr = byte;
00378 ram[1] = TheVIC->LastVICByte;
00379 new_config();
00380 }
00381 } else
00382 write_byte_io(adr, byte);
00383 }
00384
00385
00386
00387
00388
00389
00390 uint8 MOS6510::ExtReadByte(uint16 adr)
00391 {
00392
00393 bool bi = basic_in, ki = kernal_in, ci = char_in, ii = io_in;
00394
00395
00396 basic_in = (ExtConfig & 3) == 3;
00397 kernal_in = ExtConfig & 2;
00398 char_in = (ExtConfig & 3) && ~(ExtConfig & 4);
00399 io_in = (ExtConfig & 3) && (ExtConfig & 4);
00400
00401
00402 uint8 byte = read_byte(adr);
00403
00404
00405 basic_in = bi; kernal_in = ki; char_in = ci; io_in = ii;
00406
00407 return byte;
00408 }
00409
00410
00411
00412
00413
00414
00415 void MOS6510::ExtWriteByte(uint16 adr, uint8 byte)
00416 {
00417
00418 bool bi = basic_in, ki = kernal_in, ci = char_in, ii = io_in;
00419
00420
00421 basic_in = (ExtConfig & 3) == 3;
00422 kernal_in = ExtConfig & 2;
00423 char_in = (ExtConfig & 3) && ~(ExtConfig & 4);
00424 io_in = (ExtConfig & 3) && (ExtConfig & 4);
00425
00426
00427 write_byte(adr, byte);
00428
00429
00430 basic_in = bi; kernal_in = ki; char_in = ci; io_in = ii;
00431 }
00432
00433
00434
00435
00436
00437
00438 uint8 MOS6510::REUReadByte(uint16 adr)
00439 {
00440 return read_byte(adr);
00441 }
00442
00443
00444
00445
00446
00447
00448 void MOS6510::REUWriteByte(uint16 adr, uint8 byte)
00449 {
00450 write_byte(adr, byte);
00451 }
00452
00453
00454
00455
00456
00457
00458 inline void MOS6510::do_adc(uint8 byte)
00459 {
00460 if (!d_flag) {
00461 uint16 tmp;
00462
00463
00464 tmp = a + byte + (c_flag ? 1 : 0);
00465 c_flag = tmp > 0xff;
00466 v_flag = !((a ^ byte) & 0x80) && ((a ^ tmp) & 0x80);
00467 z_flag = n_flag = a = tmp;
00468
00469 } else {
00470 uint16 al, ah;
00471
00472
00473 al = (a & 0x0f) + (byte & 0x0f) + (c_flag ? 1 : 0);
00474 if (al > 9) al += 6;
00475
00476 ah = (a >> 4) + (byte >> 4);
00477 if (al > 0x0f) ah++;
00478
00479 z_flag = a + byte + (c_flag ? 1 : 0);
00480 n_flag = ah << 4;
00481 v_flag = (((ah << 4) ^ a) & 0x80) && !((a ^ byte) & 0x80);
00482
00483 if (ah > 9) ah += 6;
00484 c_flag = ah > 0x0f;
00485 a = (ah << 4) | (al & 0x0f);
00486 }
00487 }
00488
00489
00490
00491
00492
00493
00494 inline void MOS6510::do_sbc(uint8 byte)
00495 {
00496 uint16 tmp = a - byte - (c_flag ? 0 : 1);
00497
00498 if (!d_flag) {
00499
00500
00501 c_flag = tmp < 0x100;
00502 v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80);
00503 z_flag = n_flag = a = tmp;
00504
00505 } else {
00506 uint16 al, ah;
00507
00508
00509 al = (a & 0x0f) - (byte & 0x0f) - (c_flag ? 0 : 1);
00510 ah = (a >> 4) - (byte >> 4);
00511 if (al & 0x10) {
00512 al -= 6;
00513 ah--;
00514 }
00515 if (ah & 0x10) ah -= 6;
00516
00517 c_flag = tmp < 0x100;
00518 v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80);
00519 z_flag = n_flag = tmp;
00520
00521 a = (ah << 4) | (al & 0x0f);
00522 }
00523 }
00524
00525
00526
00527
00528
00529
00530 void MOS6510::Reset(void)
00531 {
00532
00533 if (ram[0x8004] == 0xc3 && ram[0x8005] == 0xc2 && ram[0x8006] == 0xcd
00534 && ram[0x8007] == 0x38 && ram[0x8008] == 0x30)
00535 ram[0x8004] = 0;
00536
00537
00538 ddr = pr = 0;
00539 new_config();
00540
00541
00542 interrupt.intr_any = 0;
00543 nmi_state = false;
00544
00545
00546 pc = read_word(0xfffc);
00547 state = 0;
00548 }
00549
00550
00551
00552
00553
00554
00555 void MOS6510::illegal_op(uint8 op, uint16 at)
00556 {
00557 char illop_msg[80];
00558
00559 sprintf(illop_msg, "Illegal opcode %02x at %04x.", op, at);
00560 ShowRequester(illop_msg, "Reset");
00561 the_c64->Reset();
00562 Reset();
00563 }
00564
00565
00566
00567
00568
00569
00570
00571 #define read_to(adr, to) \
00572 if (BALow) \
00573 return; \
00574 to = read_byte(adr);
00575
00576
00577 #define read_idle(adr) \
00578 if (BALow) \
00579 return; \
00580 read_byte(adr);
00581
00582 void MOS6510::EmulateCycle(void)
00583 {
00584 uint8 data, tmp;
00585
00586
00587 if (!state && interrupt.intr_any) {
00588 if (interrupt.intr[INT_RESET])
00589 Reset();
00590 else if (interrupt.intr[INT_NMI] && (the_c64->CycleCounter-first_nmi_cycle >= 2)) {
00591 interrupt.intr[INT_NMI] = false;
00592 state = 0x0010;
00593 } else if ((interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]) && (the_c64->CycleCounter-first_irq_cycle >= 2) && !i_flag)
00594 state = 0x0008;
00595 }
00596
00597 #include "CPU_emulcycle.i"
00598
00599
00600 case O_EXT:
00601 if (pc < 0xe000) {
00602 illegal_op(0xf2, pc-1);
00603 break;
00604 }
00605 switch (read_byte(pc++)) {
00606 case 0x00:
00607 ram[0x90] |= TheIEC->Out(ram[0x95], ram[0xa3] & 0x80);
00608 c_flag = false;
00609 pc = 0xedac;
00610 Last;
00611 case 0x01:
00612 ram[0x90] |= TheIEC->OutATN(ram[0x95]);
00613 c_flag = false;
00614 pc = 0xedac;
00615 Last;
00616 case 0x02:
00617 ram[0x90] |= TheIEC->OutSec(ram[0x95]);
00618 c_flag = false;
00619 pc = 0xedac;
00620 Last;
00621 case 0x03:
00622 ram[0x90] |= TheIEC->In(&a);
00623 set_nz(a);
00624 c_flag = false;
00625 pc = 0xedac;
00626 Last;
00627 case 0x04:
00628 TheIEC->SetATN();
00629 pc = 0xedfb;
00630 Last;
00631 case 0x05:
00632 TheIEC->RelATN();
00633 pc = 0xedac;
00634 Last;
00635 case 0x06:
00636 TheIEC->Turnaround();
00637 pc = 0xedac;
00638 Last;
00639 case 0x07:
00640 TheIEC->Release();
00641 pc = 0xedac;
00642 Last;
00643 default:
00644 illegal_op(0xf2, pc-1);
00645 break;
00646 }
00647 break;
00648
00649 default:
00650 illegal_op(op, pc-1);
00651 break;
00652 }
00653 }