Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

CPU1541.cpp

Go to the documentation of this file.
00001 /*
00002  *  CPU1541.cpp - 6502 (1541) emulation (line based)
00003  *
00004  *  Frodo (C) 1994-1997 Christian Bauer
00005  *
00006 
00007  *
00008  * Notes:
00009  * ------
00010  *
00011  *  - The EmulateLine() function is called for every emulated
00012  *    raster line. It has a cycle counter that is decremented
00013  *    by every executed opcode and if the counter goes below
00014  *    zero, the function returns.
00015  *  - Memory map (1541C, the 1541 and 1541-II are a bit different):
00016  *      $0000-$07ff RAM (2K)
00017  *      $0800-$0fff RAM mirror
00018  *      $1000-$17ff free
00019  *      $1800-$1bff VIA 1
00020  *      $1c00-$1fff VIA 2
00021  *      $2000-$bfff free
00022  *      $c000-$ffff ROM (16K)
00023  *  - All memory accesses are done with the read_byte() and
00024  *    write_byte() functions which also do the memory address
00025  *    decoding. The read_zp() and write_zp() functions allow
00026  *    faster access to the zero page, the pop_byte() and
00027  *    push_byte() macros for the stack.
00028  *  - The PC is either emulated with a 16 bit address or a
00029  *    direct memory pointer (for faster access), depending on
00030  *    the PC_IS_POINTER #define. In the latter case, a second
00031  *    pointer, pc_base, is kept to allow recalculating the
00032  *    16 bit 6502 PC if it has to be pushed on the stack.
00033  *  - The possible interrupt sources are:
00034  *      INT_VIA1IRQ: I flag is checked, jump to ($fffe) (unused)
00035  *      INT_VIA2IRQ: I flag is checked, jump to ($fffe) (unused)
00036  *      INT_IECIRQ: I flag is checked, jump to ($fffe) (unused)
00037  *      INT_RESET: Jump to ($fffc)
00038  *  - Interrupts are not checked before every opcode but only
00039  *    at certain times:
00040  *      On entering EmulateLine()
00041  *      On CLI
00042  *      On PLP if the I flag was cleared
00043  *      On RTI if the I flag was cleared
00044  *  - The z_flag variable has the inverse meaning of the
00045  *    6502 Z flag
00046  *  - Only the highest bit of the n_flag variable is used
00047  *  - The $f2 opcode that would normally crash the 6502 is
00048  *    used to implement emulator-specific functions
00049  *  - The 1541 6502 emulation also includes a very simple VIA
00050  *    emulation (enough to make the IEC bus and GCR loading work).
00051  *    It's too small to move it to a source file of its own.
00052  *
00053  * Incompatibilities:
00054  * ------------------
00055  *
00056  *  - If PC_IS_POINTER is set, neither branches accross memory
00057  *    areas nor jumps to I/O space are possible
00058  *  - Extra cycles for crossing page boundaries are not
00059  *    accounted for
00060  */
00061 
00062 #include "sysdeps.h"
00063 
00064 #include "CPU1541.h"
00065 #include "1541job.h"
00066 #include "C64.h"
00067 #include "CIA.h"
00068 #include "Display.h"
00069 
00070 #include "main.h"
00071 
00072 
00073 enum {
00074         INT_RESET = 3
00075 };
00076 
00077 
00078 /*
00079  *  6502 constructor: Initialize registers
00080  */
00081 
00082 MOS6502_1541::MOS6502_1541(C64 *c64, Job1541 *job, C64Display *disp, uint8 *Ram, uint8 *Rom)
00083  : ram(Ram), rom(Rom), the_c64(c64), the_display(disp), the_job(job)
00084 {
00085         __CHECK_NULL(c64);
00086         __CHECK_NULL(job);
00087         __CHECK_NULL(disp);
00088         __CHECK_NULL(Ram);
00089         __CHECK_NULL(Rom);
00090 
00091         a = x = y = 0;
00092         sp = 0xff;
00093         n_flag = z_flag = 0;
00094         v_flag = d_flag = c_flag = false;
00095         i_flag = true;
00096 
00097         borrowed_cycles = 0;
00098 
00099         via1_t1c = via1_t1l = via1_t2c = via1_t2l = 0;
00100         via1_sr = 0;
00101         via2_t1c = via2_t1l = via2_t2c = via2_t2l = 0;
00102         via2_sr = 0;
00103 
00104         Idle = false;
00105 
00106         CTOR(MOS6502_1541);
00107 }
00108 
00109 
00110 /*
00111  *  6502 destructor
00112  */
00113 
00114 MOS6502_1541::~MOS6502_1541()
00115 {
00116         DTOR(MOS6502_1541);
00117 }
00118 
00119 
00120 /*
00121  *  Reset CPU asynchronously
00122  */
00123 
00124 void MOS6502_1541::AsyncReset(void)
00125 {
00126         interrupt.intr[INT_RESET] = true;
00127         Idle = false;
00128 }
00129 
00130 
00131 /*
00132  *  Read a byte from I/O space
00133  */
00134 
00135 inline uint8 MOS6502_1541::read_byte_io(uint16 adr)
00136 {
00137         if ((adr & 0xfc00) == 0x1800)   // VIA 1
00138                 switch (adr & 0xf) {
00139                         case 0:
00140                                 return (via1_prb & 0x1a
00141                                         | ((IECLines & TheCIA2->IECLines) >> 7)         // DATA
00142                                         | ((IECLines & TheCIA2->IECLines) >> 4) & 0x04  // CLK
00143                                         | (TheCIA2->IECLines << 3) & 0x80) ^ 0x85;              // ATN
00144                         case 1:
00145                         case 15:
00146                                 return 0xff;    // Keep 1541C ROMs happy (track 0 sensor)
00147                         case 2:
00148                                 return via1_ddrb;
00149                         case 3:
00150                                 return via1_ddra;
00151                         case 4:
00152                                 via1_ifr &= 0xbf;
00153 //                              return via1_t1c;
00154                                 return (uint8)via1_t1c; //AEH 991113
00155                         case 5:
00156                                 return via1_t1c >> 8;
00157                         case 6:
00158 //                              return via1_t1l;
00159                                 return (uint8)via1_t1l; //AEH 991113
00160                         case 7:
00161                                 return via1_t1l >> 8;
00162                         case 8:
00163                                 via1_ifr &= 0xdf;
00164 //                              return via1_t2c;
00165                                 return (uint8)via1_t2c; // AEH 991113
00166                         case 9:
00167                                 return via1_t2c >> 8;
00168                         case 10:
00169                                 return via1_sr;
00170                         case 11:
00171                                 return via1_acr;
00172                         case 12:
00173                                 return via1_pcr;
00174                         case 13:
00175                                 return via1_ifr | (via1_ifr & via1_ier ? 0x80 : 0);
00176                         case 14:
00177                                 return via1_ier | 0x80;
00178                         default:        // Can't happen
00179                                 return 0;
00180                 }
00181 
00182         else if ((adr & 0xfc00) == 0x1c00)      // VIA 2
00183                 switch (adr & 0xf) {
00184                         case 0:
00185                                 if (the_job->SyncFound())
00186                                         return via2_prb & 0x7f | the_job->WPState();
00187                                 else
00188                                         return via2_prb | 0x80 | the_job->WPState();
00189                         case 1:
00190                         case 15:
00191                                 return the_job->ReadGCRByte();
00192                         case 2:
00193                                 return via2_ddrb;
00194                         case 3:
00195                                 return via2_ddra;
00196                         case 4:
00197                                 via2_ifr &= 0xbf;
00198                                 interrupt.intr[INT_VIA2IRQ] = false;    // Clear job IRQ
00199 //                              return via2_t1c;
00200                                 return (uint8)via2_t1c; //AEH 991113
00201                         case 5:
00202                                 return via2_t1c >> 8;
00203                         case 6:
00204 //                              return via2_t1l;
00205                                 return (uint8)via2_t1l; //AEH 991113
00206                         case 7:
00207                                 return via2_t1l >> 8;
00208                         case 8:
00209                                 via2_ifr &= 0xdf;
00210 //                              return via2_t2c;
00211                                 return (uint8)via2_t2c; //AEH 991113
00212                         case 9:
00213                                 return via2_t2c >> 8;
00214                         case 10:
00215                                 return via2_sr;
00216                         case 11:
00217                                 return via2_acr;
00218                         case 12:
00219                                 return via2_pcr;
00220                         case 13:
00221                                 return via2_ifr | (via2_ifr & via2_ier ? 0x80 : 0);
00222                         case 14:
00223                                 return via2_ier | 0x80;
00224                         default:        // Can't happen
00225                                 return 0;
00226                 }
00227 
00228         else
00229                 return adr >> 8;
00230 }
00231 
00232 
00233 /*
00234  *  Read a byte from the CPU's address space
00235  */
00236 
00237 uint8 MOS6502_1541::read_byte(uint16 adr)
00238 {
00239         if (adr >= 0xc000)
00240                 return rom[adr & 0x3fff];
00241         else if (adr < 0x1000)
00242                 return ram[adr & 0x07ff];
00243         else
00244                 return read_byte_io(adr);
00245 }
00246 
00247 
00248 /*
00249  *  Read a word (little-endian) from the CPU's address space
00250  */
00251 
00252 inline uint16 MOS6502_1541::read_word(uint16 adr)
00253 {
00254         return read_byte(adr) | (read_byte(adr+1) << 8);
00255 }
00256 
00257 
00258 /*
00259  *  Write a byte to I/O space
00260  */
00261 
00262 void MOS6502_1541::write_byte_io(uint16 adr, uint8 byte)
00263 {
00264         if ((adr & 0xfc00) == 0x1800)   // VIA 1
00265                 switch (adr & 0xf) {
00266                         case 0:
00267                                 via1_prb = byte;
00268                                 byte = ~via1_prb & via1_ddrb;
00269                                 IECLines = (byte << 6) & ((~byte ^ TheCIA2->IECLines) << 3) & 0x80
00270                                         | (byte << 3) & 0x40;
00271                                 break;
00272                         case 1:
00273                         case 15:
00274                                 via1_pra = byte;
00275                                 break;
00276                         case 2:
00277                                 via1_ddrb = byte;
00278                                 byte &= ~via1_prb;
00279                                 IECLines = (byte << 6) & ((~byte ^ TheCIA2->IECLines) << 3) & 0x80
00280                                         | (byte << 3) & 0x40;
00281                                 break;
00282                         case 3:
00283                                 via1_ddra = byte;
00284                                 break;
00285                         case 4:
00286                         case 6:
00287                                 via1_t1l = via1_t1l & 0xff00 | byte;
00288                                 break;
00289                         case 5:
00290                                 via1_t1l = via1_t1l & 0xff | (byte << 8);
00291                                 via1_ifr &= 0xbf;
00292                                 via1_t1c = via1_t1l;
00293                                 break;
00294                         case 7:
00295                                 via1_t1l = via1_t1l & 0xff | (byte << 8);
00296                                 break;
00297                         case 8:
00298                                 via1_t2l = via1_t2l & 0xff00 | byte;
00299                                 break;
00300                         case 9:
00301                                 via1_t2l = via1_t2l & 0xff | (byte << 8);
00302                                 via1_ifr &= 0xdf;
00303                                 via1_t2c = via1_t2l;
00304                                 break;
00305                         case 10:
00306                                 via1_sr = byte;
00307                                 break;
00308                         case 11:
00309                                 via1_acr = byte;
00310                                 break;
00311                         case 12:
00312                                 via1_pcr = byte;
00313                                 break;
00314                         case 13:
00315                                 via1_ifr &= ~byte;
00316                                 break;
00317                         case 14:
00318                                 if (byte & 0x80)
00319                                         via1_ier |= byte & 0x7f;
00320                                 else
00321                                         via1_ier &= ~byte;
00322                                 break;
00323                 }
00324 
00325         else if ((adr & 0xfc00) == 0x1c00)      // VIA 2
00326                 switch (adr & 0xf) {
00327                         case 0:
00328                                 if ((via2_prb ^ byte) & 8)      // Bit 3: Drive LED
00329                                         the_display->UpdateLEDs(byte & 8 ? 1 : 0, 0, 0, 0);
00330                                 if ((via2_prb ^ byte) & 3)      // Bits 0/1: Stepper motor
00331                                         if ((via2_prb & 3) == ((byte+1) & 3))
00332                                                 the_job->MoveHeadOut();
00333                                         else if ((via2_prb & 3) == ((byte-1) & 3))
00334                                                 the_job->MoveHeadIn();
00335                                 via2_prb = byte & 0xef;
00336                                 break;
00337                         case 1:
00338                         case 15:
00339                                 via2_pra = byte;
00340                                 break;
00341                         case 2:
00342                                 via2_ddrb = byte;
00343                                 break;
00344                         case 3:
00345                                 via2_ddra = byte;
00346                                 break;
00347                         case 4:
00348                         case 6:
00349                                 via2_t1l = via2_t1l & 0xff00 | byte;
00350                                 break;
00351                         case 5:
00352                                 via2_t1l = via2_t1l & 0xff | (byte << 8);
00353                                 via2_ifr &= 0xbf;
00354                                 via2_t1c = via2_t1l;
00355                                 break;
00356                         case 7:
00357                                 via2_t1l = via2_t1l & 0xff | (byte << 8);
00358                                 break;
00359                         case 8:
00360                                 via2_t2l = via2_t2l & 0xff00 | byte;
00361                                 break;
00362                         case 9:
00363                                 via2_t2l = via2_t2l & 0xff | (byte << 8);
00364                                 via2_ifr &= 0xdf;
00365                                 via2_t2c = via2_t2l;
00366                                 break;
00367                         case 10:
00368                                 via2_sr = byte;
00369                                 break;
00370                         case 11:
00371                                 via2_acr = byte;
00372                                 break;
00373                         case 12:
00374                                 via2_pcr = byte;
00375                                 break;
00376                         case 13:
00377                                 via2_ifr &= ~byte;
00378                                 break;
00379                         case 14:
00380                                 if (byte & 0x80)
00381                                         via2_ier |= byte & 0x7f;
00382                                 else
00383                                         via2_ier &= ~byte;
00384                                 break;
00385                 }
00386 }
00387 
00388 
00389 /*
00390  *  Write a byte to the CPU's address space
00391  */
00392 
00393 inline void MOS6502_1541::write_byte(uint16 adr, uint8 byte)
00394 {
00395         if (adr < 0x1000)
00396                 ram[adr & 0x7ff] = byte;
00397         else
00398                 write_byte_io(adr, byte);
00399 }
00400 
00401 
00402 /*
00403  *  Read a byte from the zeropage
00404  */
00405 
00406 inline uint8 MOS6502_1541::read_zp(uint16 adr)
00407 {
00408         return ram[adr];
00409 }
00410 
00411 
00412 /*
00413  *  Read a word (little-endian) from the zeropage
00414  */
00415 
00416 inline uint16 MOS6502_1541::read_zp_word(uint16 adr)
00417 {
00418         return ram[adr & 0xff] | (ram[(adr+1) & 0xff] << 8);
00419 }
00420 
00421 
00422 /*
00423  *  Write a byte to the zeropage
00424  */
00425 
00426 inline void MOS6502_1541::write_zp(uint16 adr, uint8 byte)
00427 {
00428         ram[adr] = byte;
00429 }
00430 
00431 
00432 /*
00433  *  Read byte from 6502/1541 address space (used by SAM)
00434  */
00435 
00436 uint8 MOS6502_1541::ExtReadByte(uint16 adr)
00437 {
00438         return read_byte(adr);
00439 }
00440 
00441 
00442 /*
00443  *  Write byte to 6502/1541 address space (used by SAM)
00444  */
00445 
00446 void MOS6502_1541::ExtWriteByte(uint16 adr, uint8 byte)
00447 {
00448         write_byte(adr, byte);
00449 }
00450 
00451 
00452 /*
00453  *  Jump to address
00454  */
00455 
00456 #if PC_IS_POINTER
00457 void MOS6502_1541::jump(uint16 adr)
00458 {
00459         if (adr >= 0xc000) {
00460                 pc = rom + (adr & 0x3fff);
00461                 pc_base = rom - 0xc000;
00462         } else if (adr < 0x800) {
00463                 pc = ram + adr;
00464                 pc_base = ram;
00465         } else
00466                 illegal_jump(pc-pc_base, adr);
00467 }
00468 #else
00469 inline void MOS6502_1541::jump(uint16 adr)
00470 {
00471         pc = adr;
00472 }
00473 #endif
00474 
00475 
00476 /*
00477  *  Adc instruction
00478  */
00479 
00480 void MOS6502_1541::do_adc(uint8 byte)
00481 {
00482         if (!d_flag) {
00483                 uint16 tmp;
00484 
00485                 // Binary mode
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                 z_flag = n_flag = a = (uint8)tmp;       //AEH 991113
00491 
00492         } else {
00493                 uint16 al, ah;
00494 
00495                 // Decimal mode
00496                 al = (a & 0x0f) + (byte & 0x0f) + (c_flag ? 1 : 0);     // Calculate lower nybble
00497                 if (al > 9) al += 6;                                                                    // BCD fixup for lower nybble
00498 
00499                 ah = (a >> 4) + (byte >> 4);                                                    // Calculate upper nybble
00500                 if (al > 0x0f) ah++;
00501 
00502                 z_flag = a + byte + (c_flag ? 1 : 0);                                   // Set flags
00503                 n_flag = ah << 4;       // Only highest bit used
00504                 v_flag = (((ah << 4) ^ a) & 0x80) && !((a ^ byte) & 0x80);
00505 
00506                 if (ah > 9) ah += 6;                                                                    // BCD fixup for upper nybble
00507                 c_flag = ah > 0x0f;                                                                             // Set carry flag
00508                 a = (ah << 4) | (al & 0x0f);                                                    // Compose result
00509         }
00510 }
00511 
00512 
00513 /*
00514  * Sbc instruction
00515  */
00516 
00517 void MOS6502_1541::do_sbc(uint8 byte)
00518 {
00519         uint16 tmp = a - byte - (c_flag ? 0 : 1);
00520 
00521         if (!d_flag) {
00522 
00523                 // Binary mode
00524                 c_flag = tmp < 0x100;
00525                 v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80);
00526 //              z_flag = n_flag = a = tmp;
00527                 z_flag = n_flag = a = (uint8)tmp;       //AEH 991113
00528 
00529         } else {
00530                 uint16 al, ah;
00531 
00532                 // Decimal mode
00533                 al = (a & 0x0f) - (byte & 0x0f) - (c_flag ? 0 : 1);             // Calculate lower nybble
00534                 ah = (a >> 4) - (byte >> 4);                                                    // Calculate upper nybble
00535                 if (al & 0x10) {
00536                         al -= 6;                                                                                        // BCD fixup for lower nybble
00537                         ah--;
00538                 }
00539                 if (ah & 0x10) ah -= 6;                                                                 // BCD fixup for upper nybble
00540 
00541                 c_flag = tmp < 0x100;                                                                   // Set flags
00542                 v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80);
00543 //              z_flag = n_flag = tmp;
00544                 z_flag = n_flag = (uint8)tmp;   //AEH 991113
00545 
00546                 a = (ah << 4) | (al & 0x0f);                                                    // Compose result
00547         }
00548 }
00549 
00550 
00551 /*
00552  *  Get 6502 register state
00553  */
00554 
00555 void MOS6502_1541::GetState(MOS6502State *s)
00556 {
00557         s->a = a;
00558         s->x = x;
00559         s->y = y;
00560 
00561         s->p = 0x20 | (n_flag & 0x80);
00562         if (v_flag) s->p |= 0x40;
00563         if (d_flag) s->p |= 0x08;
00564         if (i_flag) s->p |= 0x04;
00565         if (!z_flag) s->p |= 0x02;
00566         if (c_flag) s->p |= 0x01;
00567         
00568 #if PC_IS_POINTER
00569         s->pc = pc - pc_base;
00570 #else
00571         s->pc = pc;
00572 #endif
00573         s->sp = sp | 0x0100;
00574 
00575         s->intr[INT_VIA1IRQ] = interrupt.intr[INT_VIA1IRQ];
00576         s->intr[INT_VIA2IRQ] = interrupt.intr[INT_VIA2IRQ];
00577         s->intr[INT_IECIRQ] = interrupt.intr[INT_IECIRQ];
00578         s->intr[INT_RESET] = interrupt.intr[INT_RESET];
00579         s->instruction_complete = true;
00580         s->idle = Idle;
00581 
00582         s->via1_pra = via1_pra; s->via1_ddra = via1_ddra;
00583         s->via1_prb = via1_prb; s->via1_ddrb = via1_ddrb;
00584         s->via1_t1c = via1_t1c; s->via1_t1l = via1_t1l;
00585         s->via1_t2c = via1_t2c; s->via1_t2l = via1_t2l;
00586         s->via1_sr = via1_sr;
00587         s->via1_acr = via1_acr; s->via1_pcr = via1_pcr;
00588         s->via1_ifr = via1_ifr; s->via1_ier = via1_ier;
00589 
00590         s->via2_pra = via2_pra; s->via2_ddra = via2_ddra;
00591         s->via2_prb = via2_prb; s->via2_ddrb = via2_ddrb;
00592         s->via2_t1c = via2_t1c; s->via2_t1l = via2_t1l;
00593         s->via2_t2c = via2_t2c; s->via2_t2l = via2_t2l;
00594         s->via2_sr = via2_sr;
00595         s->via2_acr = via2_acr; s->via2_pcr = via2_pcr;
00596         s->via2_ifr = via2_ifr; s->via2_ier = via2_ier;
00597 }
00598 
00599 
00600 /*
00601  *  Restore 6502 state
00602  */
00603 
00604 void MOS6502_1541::SetState(MOS6502State *s)
00605 {
00606         a = s->a;
00607         x = s->x;
00608         y = s->y;
00609 
00610         n_flag = s->p;
00611 //      v_flag = s->p & 0x40;
00612         v_flag = (s->p & 0x40) == 0x40; //AEH 991113
00613 //      d_flag = s->p & 0x08;
00614         d_flag = (s->p & 0x08) == 0x08; //AEH 991113
00615 //      i_flag = s->p & 0x04;
00616         i_flag = (s->p & 0x04) == 0x04; //AEH 991113
00617         z_flag = !(s->p & 0x02);
00618         c_flag = s->p & 0x01;
00619 
00620         jump(s->pc);
00621         sp = s->sp & 0xff;
00622 
00623         interrupt.intr[INT_VIA1IRQ] = s->intr[INT_VIA1IRQ];
00624         interrupt.intr[INT_VIA2IRQ] = s->intr[INT_VIA2IRQ];
00625         interrupt.intr[INT_IECIRQ] = s->intr[INT_IECIRQ];
00626         interrupt.intr[INT_RESET] = s->intr[INT_RESET];
00627         Idle = s->idle;
00628 
00629         via1_pra = s->via1_pra; via1_ddra = s->via1_ddra;
00630         via1_prb = s->via1_prb; via1_ddrb = s->via1_ddrb;
00631         via1_t1c = s->via1_t1c; via1_t1l = s->via1_t1l;
00632         via1_t2c = s->via1_t2c; via1_t2l = s->via1_t2l;
00633         via1_sr = s->via1_sr;
00634         via1_acr = s->via1_acr; via1_pcr = s->via1_pcr;
00635         via1_ifr = s->via1_ifr; via1_ier = s->via1_ier;
00636 
00637         via2_pra = s->via2_pra; via2_ddra = s->via2_ddra;
00638         via2_prb = s->via2_prb; via2_ddrb = s->via2_ddrb;
00639         via2_t1c = s->via2_t1c; via2_t1l = s->via2_t1l;
00640         via2_t2c = s->via2_t2c; via2_t2l = s->via2_t2l;
00641         via2_sr = s->via2_sr;
00642         via2_acr = s->via2_acr; via2_pcr = s->via2_pcr;
00643         via2_ifr = s->via2_ifr; via2_ier = s->via2_ier;
00644 }
00645 
00646 
00647 /*
00648  *  Reset CPU
00649  */
00650 
00651 void MOS6502_1541::Reset(void)
00652 {
00653         // IEC lines and VIA registers
00654         IECLines = 0xc0;
00655 
00656         via1_pra = via1_ddra = via1_prb = via1_ddrb = 0;
00657         via1_acr = via1_pcr = 0;
00658         via1_ifr = via1_ier = 0;
00659         via2_pra = via2_ddra = via2_prb = via2_ddrb = 0;
00660         via2_acr = via2_pcr = 0;
00661         via2_ifr = via2_ier = 0;
00662 
00663         // Clear all interrupt lines
00664         interrupt.intr_any = 0;
00665 
00666         // Read reset vector
00667         jump(read_word(0xfffc));
00668 
00669         // Wake up 1541
00670         Idle = false;
00671 
00672         ELOG1(_L8("6502 in 1541 reset\n"));
00673 }
00674 
00675 
00676 /*
00677  *  Illegal opcode encountered
00678  */
00679 
00680 void MOS6502_1541::illegal_op(uint8 op, uint16 at)
00681 {
00682         char illop_msg[80];
00683 
00684         sprintf(illop_msg, "Illegal opcode %02x at %04x.\n Will reset c64 & 1541", op, at);
00685 
00686         if(ShowRequester(illop_msg, "Reset 1541", "Reset C64"))
00687                 the_c64->Reset();
00688         
00689         the_c64->Reset();
00690         Reset();
00691 }
00692 
00693 
00694 /*
00695  *  Jump to illegal address space (PC_IS_POINTER only)
00696  */
00697 
00698 void MOS6502_1541::illegal_jump(uint16 at, uint16 to)
00699 {
00700         char illop_msg[80];
00701 
00702         sprintf(illop_msg, "Jump to I/O space at %04x to %04x.\n Will reset c64 & 1541", at, to);
00703 
00704         if (ShowRequester(illop_msg, "Reset 1541", "Reset C64"))
00705                 the_c64->Reset();
00706         Reset();
00707 }
00708 
00709 
00710 /*
00711  *  Stack macros
00712  */
00713 
00714 // Pop a byte from the stack
00715 #define pop_byte() ram[(++sp) | 0x0100]
00716 
00717 // Push a byte onto the stack
00718 #define push_byte(byte) (ram[(sp--) & 0xff | 0x0100] = (byte))
00719 
00720 
00721 // Pop processor flags from the stack   AEH 991113
00722 #define pop_flags() \
00723         n_flag = tmp = pop_byte(); \
00724         v_flag = BOOL_BIT(tmp, 0x40); \
00725         d_flag = BOOL_BIT(tmp, 0x08); \
00726         i_flag = BOOL_BIT(tmp, 0x04); \
00727         z_flag = !(tmp & 0x02); \
00728         c_flag = BOOL_BIT(tmp, 0x01);
00729 
00730 // Push processor flags onto the stack
00731 #define push_flags(b_flag) \
00732         tmp = 0x20 | (n_flag & 0x80); \
00733         if (v_flag) tmp |= 0x40; \
00734         if (b_flag) tmp |= 0x10; \
00735         if (d_flag) tmp |= 0x08; \
00736         if (i_flag) tmp |= 0x04; \
00737         if (!z_flag) tmp |= 0x02; \
00738         if (c_flag) tmp |= 0x01; \
00739         push_byte(tmp);
00740 
00741 
00742 /*
00743  *  Emulate cycles_left worth of 6502 instructions
00744  *  Returns number of cycles of last instruction
00745  */
00746 
00747 int MOS6502_1541::EmulateLine(int cycles_left)
00748 {
00749         uint8 tmp, tmp2, tmpb;
00750         uint16 adr;
00751         int last_cycles = 0;
00752 
00753         // Any pending interrupts?
00754         if (interrupt.intr_any) {
00755 handle_int:
00756                 if (interrupt.intr[INT_RESET])
00757                         Reset();
00758 
00759                 else if ((interrupt.intr[INT_VIA1IRQ] || interrupt.intr[INT_VIA2IRQ] || interrupt.intr[INT_IECIRQ]) && !i_flag) {
00760 #if PC_IS_POINTER
00761                         push_byte((pc-pc_base) >> 8); push_byte(pc-pc_base);
00762 #else
00763                         push_byte(pc >> 8); push_byte(pc);
00764 #endif
00765                         push_flags(false);
00766                         i_flag = true;
00767                         jump(read_word(0xfffe));
00768                         last_cycles = 7;
00769                 }
00770         }
00771 
00772 #define IS_CPU_1541
00773 #include "CPU_emulline.i"
00774 
00775                 // Extension opcode
00776                 case 0xf2:
00777 #if PC_IS_POINTER
00778                         if ((pc-pc_base) < 0xc000) {
00779                                 illegal_op(0xf2, pc-pc_base-1);
00780 #else
00781                         if (pc < 0xc000) {
00782                                 illegal_op(0xf2, pc-1);
00783 #endif
00784                                 break;
00785                         }
00786                         switch (read_byte_imm()) {
00787                                 case 0x00:      // Go to sleep in DOS idle loop if error flag is clear and no command received
00788                                         Idle = !(ram[0x26c] | ram[0x7c]);
00789                                         jump(0xebff);
00790                                         break;
00791                                 case 0x01:      // Write sector
00792                                         the_job->WriteSector();
00793                                         jump(0xf5dc);
00794                                         break;
00795                                 case 0x02:      // Format track
00796                                         the_job->FormatTrack();
00797                                         jump(0xfd8b);
00798                                         break;
00799                                 default:
00800 #if PC_IS_POINTER
00801                                         illegal_op(0xf2, pc-pc_base-1);
00802 #else
00803                                         illegal_op(0xf2, pc-1);
00804 #endif
00805                                         break;
00806                         }
00807                         break;
00808                 }
00809         }
00810         return last_cycles;
00811 }

Generated on Tue Feb 8 04:07:30 2005 for E32frodo by doxygen 1.3.3