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

CPU1541.h

Go to the documentation of this file.
00001 /*
00002  *  CPU1541.h - 6502 (1541) emulation (line based)
00003  *
00004  *  Frodo (C) 1994-1997 Christian Bauer
00005  */
00006 
00007 #ifndef _CPU_1541_H
00008 #define _CPU_1541_H
00009 
00010 #include "CIA.h"
00011 #include "C64.h"
00012 
00013 
00014 // Set this to 1 if the 6502 PC should be represented by a real pointer
00015 #ifndef FRODO_SC
00016 #ifndef PC_IS_POINTER
00017 #define PC_IS_POINTER 1
00018 #endif
00019 #endif
00020 
00021 // Set this to 1 for more precise CPU cycle calculation
00022 #ifndef PRECISE_CPU_CYCLES
00023 #define PRECISE_CPU_CYCLES 0
00024 #endif
00025 
00026 
00027 // Interrupt types
00028 enum {
00029         INT_VIA1IRQ,
00030         INT_VIA2IRQ,
00031         INT_IECIRQ
00032         // INT_RESET (private)
00033 };
00034 
00035 
00036 class C64;
00037 class Job1541;
00038 class C64Display;
00039 struct MOS6502State;
00040 
00041 
00042 // 6502 emulation (1541)
00043 class MOS6502_1541 {
00044 public:
00045         MOS6502_1541(C64 *c64, Job1541 *job, C64Display *disp, uint8 *Ram, uint8 *Rom);
00046         ~MOS6502_1541();
00047 
00048 #ifdef FRODO_SC
00049         void EmulateCycle(void);                        // Emulate one clock cycle
00050 #else
00051         int EmulateLine(int cycles_left);       // Emulate until cycles_left underflows
00052 #endif
00053         void Reset(void);
00054         void AsyncReset(void);                          // Reset the CPU asynchronously
00055         void GetState(MOS6502State *s);
00056         void SetState(MOS6502State *s);
00057         uint8 ExtReadByte(uint16 adr);
00058         void ExtWriteByte(uint16 adr, uint8 byte);
00059         void CountVIATimers(int cycles);
00060         void NewATNState(void);
00061         void IECInterrupt(void);
00062         void TriggerJobIRQ(void);
00063         bool InterruptEnabled(void);
00064 
00065         MOS6526_2 *TheCIA2;             // Pointer to C64 CIA 2
00066 
00067         uint8 IECLines;                 // State of IEC lines (bit 7 - DATA, bit 6 - CLK)
00068         bool Idle;                              // true: 1541 is idle
00069 
00070 private:
00071         uint8 read_byte(uint16 adr);
00072         uint8 read_byte_io(uint16 adr);
00073         uint16 read_word(uint16 adr);
00074         void write_byte(uint16 adr, uint8 byte);
00075         void write_byte_io(uint16 adr, uint8 byte);
00076 
00077         uint8 read_zp(uint16 adr);
00078         uint16 read_zp_word(uint16 adr);
00079         void write_zp(uint16 adr, uint8 byte);
00080 
00081         void jump(uint16 adr);
00082         void illegal_op(uint8 op, uint16 at);
00083         void illegal_jump(uint16 at, uint16 to);
00084 
00085         void do_adc(uint8 byte);
00086         void do_sbc(uint8 byte);
00087 
00088         uint8 *ram;                             // Pointer to main RAM
00089         uint8 *rom;                             // Pointer to ROM
00090         C64 *the_c64;                   // Pointer to C64 object
00091         C64Display *the_display; // Pointer to C64 display object
00092         Job1541 *the_job;               // Pointer to 1541 job object
00093 
00094         union {                                 // Pending interrupts
00095                 uint8 intr[4];          // Index: See definitions above
00096                 unsigned long intr_any;
00097         } interrupt;
00098 
00099         uint8 n_flag, z_flag;
00100         bool v_flag, d_flag, i_flag, c_flag;
00101         uint8 a, x, y, sp;
00102 #if PC_IS_POINTER
00103         uint8 *pc, *pc_base;
00104 #else
00105         uint16 pc;
00106 #endif
00107 
00108 #ifdef FRODO_SC
00109         uint32 first_irq_cycle;
00110 
00111         uint8 state, op;                // Current state and opcode
00112         uint16 ar, ar2;                 // Address registers
00113         uint8 rdbuf;                    // Data buffer for RMW instructions
00114         uint8 ddr, pr;                  // Processor port
00115 #else
00116         int borrowed_cycles;    // Borrowed cycles from next line
00117 #endif
00118 
00119         uint8 via1_pra;         // PRA of VIA 1
00120         uint8 via1_ddra;        // DDRA of VIA 1
00121         uint8 via1_prb;         // PRB of VIA 1
00122         uint8 via1_ddrb;        // DDRB of VIA 1
00123         uint16 via1_t1c;                // T1 Counter of VIA 1
00124         uint16 via1_t1l;                // T1 Latch of VIA 1
00125         uint16 via1_t2c;                // T2 Counter of VIA 1
00126         uint16 via1_t2l;                // T2 Latch of VIA 1
00127         uint8 via1_sr;          // SR of VIA 1
00128         uint8 via1_acr;         // ACR of VIA 1
00129         uint8 via1_pcr;         // PCR of VIA 1
00130         uint8 via1_ifr;         // IFR of VIA 1
00131         uint8 via1_ier;         // IER of VIA 1
00132 
00133         uint8 via2_pra;         // PRA of VIA 2
00134         uint8 via2_ddra;        // DDRA of VIA 2
00135         uint8 via2_prb;         // PRB of VIA 2
00136         uint8 via2_ddrb;        // DDRB of VIA 2
00137         uint16 via2_t1c;                // T1 Counter of VIA 2
00138         uint16 via2_t1l;                // T1 Latch of VIA 2
00139         uint16 via2_t2c;                // T2 Counter of VIA 2
00140         uint16 via2_t2l;                // T2 Latch of VIA 2
00141         uint8 via2_sr;          // SR of VIA 2
00142         uint8 via2_acr;         // ACR of VIA 2
00143         uint8 via2_pcr;         // PCR of VIA 2
00144         uint8 via2_ifr;         // IFR of VIA 2
00145         uint8 via2_ier;         // IER of VIA 2
00146 };
00147 
00148 // 6502 state
00149 struct MOS6502State {
00150         uint8 a, x, y;
00151         uint8 p;                        // Processor flags
00152         uint16 pc, sp;
00153 
00154         uint8 intr[4];          // Interrupt state
00155         bool instruction_complete;
00156         bool idle;
00157 
00158         uint8 via1_pra;         // VIA 1
00159         uint8 via1_ddra;
00160         uint8 via1_prb;
00161         uint8 via1_ddrb;
00162         uint16 via1_t1c;
00163         uint16 via1_t1l;
00164         uint16 via1_t2c;
00165         uint16 via1_t2l;
00166         uint8 via1_sr;
00167         uint8 via1_acr;
00168         uint8 via1_pcr;
00169         uint8 via1_ifr;
00170         uint8 via1_ier;
00171 
00172         uint8 via2_pra;         // VIA 2
00173         uint8 via2_ddra;
00174         uint8 via2_prb;
00175         uint8 via2_ddrb;
00176         uint16 via2_t1c;
00177         uint16 via2_t1l;
00178         uint16 via2_t2c;
00179         uint16 via2_t2l;
00180         uint8 via2_sr;
00181         uint8 via2_acr;
00182         uint8 via2_pcr;
00183         uint8 via2_ifr;
00184         uint8 via2_ier;
00185 };
00186 
00187 
00188 
00189 /*
00190  *  Trigger job loop IRQ
00191  */
00192 
00193 #ifdef FRODO_SC
00194 inline void MOS6502_1541::TriggerJobIRQ(void)
00195 {
00196         if (!(interrupt.intr[INT_VIA2IRQ]))
00197                 first_irq_cycle = the_c64->CycleCounter;
00198         interrupt.intr[INT_VIA2IRQ] = true;
00199         Idle = false;
00200 }
00201 #else
00202 inline void MOS6502_1541::TriggerJobIRQ(void)
00203 {
00204         interrupt.intr[INT_VIA2IRQ] = true;
00205         Idle = false;
00206 }
00207 #endif
00208 
00209 
00210 /*
00211  *  Count VIA timers
00212  */
00213 
00214 inline void MOS6502_1541::CountVIATimers(int cycles)
00215 {
00216         unsigned long tmp;
00217 
00218         via1_t1c = tmp = via1_t1c - cycles;
00219         if (tmp > 0xffff) {
00220                 if (via1_acr & 0x40)    // Reload from latch in free-run mode
00221                         via1_t1c = via1_t1l;
00222                 via1_ifr |= 0x40;
00223         }
00224 
00225         if (!(via1_acr & 0x20)) {       // Only count in one-shot mode
00226                 via1_t2c = tmp = via1_t2c - cycles;
00227                 if (tmp > 0xffff)
00228                         via1_ifr |= 0x20;
00229         }
00230 
00231         via2_t1c = tmp = via2_t1c - cycles;
00232         if (tmp > 0xffff) {
00233                 if (via2_acr & 0x40)    // Reload from latch in free-run mode
00234                         via2_t1c = via2_t1l;
00235                 via2_ifr |= 0x40;
00236                 if (via2_ier & 0x40)
00237                         TriggerJobIRQ();
00238         }
00239 
00240         if (!(via2_acr & 0x20)) {       // Only count in one-shot mode
00241                 via2_t2c = tmp = via2_t2c - cycles;
00242                 if (tmp > 0xffff)
00243                         via2_ifr |= 0x20;
00244         }
00245 }
00246 
00247 
00248 /*
00249  *  ATN line probably changed state, recalc IECLines
00250  */
00251 
00252 inline void MOS6502_1541::NewATNState(void)
00253 {
00254         uint8 byte = ~via1_prb & via1_ddrb;
00255         IECLines = (byte << 6) & ((~byte ^ TheCIA2->IECLines) << 3) & 0x80      // DATA (incl. ATN acknowledge)
00256                 | (byte << 3) & 0x40;                                                                                   // CLK
00257 }
00258 
00259 
00260 /*
00261  *  Interrupt by negative edge of ATN on IEC bus
00262  */
00263 
00264 inline void MOS6502_1541::IECInterrupt(void)
00265 {
00266         ram[0x7c] = 1;
00267 
00268         // Wake up 1541
00269         Idle = false;
00270 }
00271 
00272 
00273 /*
00274  *  Test if interrupts are enabled (for job loop)
00275  */
00276 
00277 inline bool MOS6502_1541::InterruptEnabled(void)
00278 {
00279         return !i_flag;
00280 }
00281 
00282 #endif

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