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

CPUC64.h

Go to the documentation of this file.
00001 /*
00002  *  CPUC64.h - 6510 (C64) emulation (line based)
00003  *
00004  *  Frodo (C) 1994-1997 Christian Bauer
00005  */
00006 
00007 #ifndef _CPU_C64_H
00008 #define _CPU_C64_H
00009 
00010 #include "C64.h"
00011 
00012 
00013 // Set this to 1 if the 6502 PC should be represented by a real pointer
00014 #ifndef FRODO_SC
00015 #ifndef PC_IS_POINTER
00016 #define PC_IS_POINTER 1
00017 #endif
00018 #endif
00019 
00020 // Set this to 1 for more precise CPU cycle calculation
00021 #ifndef PRECISE_CPU_CYCLES
00022 #define PRECISE_CPU_CYCLES 0
00023 #endif
00024 
00025 // Set this to 1 for instruction-aligned CIA emulation
00026 #ifndef PRECISE_CIA_CYCLES
00027 #define PRECISE_CIA_CYCLES 0
00028 #endif
00029 
00030 
00031 // Interrupt types
00032 enum {
00033         INT_VICIRQ,
00034         INT_CIAIRQ,
00035         INT_NMI
00036         // INT_RESET (private)
00037 };
00038 
00039 
00040 class MOS6569;
00041 class MOS6581;
00042 class MOS6526_1;
00043 class MOS6526_2;
00044 class REU;
00045 class IEC;
00046 struct MOS6510State;
00047 
00048 
00049 // 6510 emulation (C64)
00050 class MOS6510 {
00051 public:
00052         MOS6510(C64 *c64, uint8 *Ram, uint8 *Basic, uint8 *Kernal, uint8 *Char, uint8 *Color);
00053         ~MOS6510();
00054 
00055 #ifdef FRODO_SC
00056         void EmulateCycle(void);                        // Emulate one clock cycle
00057 #else
00058         int EmulateLine(int cycles_left);       // Emulate until cycles_left underflows
00059 #endif
00060         void Reset(void);
00061         void AsyncReset(void);                          // Reset the CPU asynchronously
00062         void AsyncNMI(void);                            // Raise NMI asynchronously (NMI pulse)
00063         void GetState(MOS6510State *s);
00064         void SetState(MOS6510State *s);
00065         uint8 ExtReadByte(uint16 adr);
00066         void ExtWriteByte(uint16 adr, uint8 byte);
00067         uint8 REUReadByte(uint16 adr);
00068         void REUWriteByte(uint16 adr, uint8 byte);
00069 
00070         void TriggerVICIRQ(void);
00071         void ClearVICIRQ(void);
00072         void TriggerCIAIRQ(void);
00073         void ClearCIAIRQ(void);
00074         void TriggerNMI(void);
00075         void ClearNMI(void);
00076 
00077         int ExtConfig;  // Memory configuration for ExtRead/WriteByte (0..7)
00078 
00079         MOS6569 *TheVIC;        // Pointer to VIC
00080         MOS6581 *TheSID;        // Pointer to SID
00081         MOS6526_1 *TheCIA1;     // Pointer to CIA 1
00082         MOS6526_2 *TheCIA2;     // Pointer to CIA 2
00083         REU *TheREU;            // Pointer to REU
00084         IEC *TheIEC;            // Pointer to drive array
00085 
00086 #ifdef FRODO_SC
00087         bool BALow;                     // BA line for Frodo SC
00088 #endif
00089 
00090 private:
00091         uint8 read_byte(uint16 adr);
00092         uint8 read_byte_io(uint16 adr);
00093         uint16 read_word(uint16 adr);
00094         void write_byte(uint16 adr, uint8 byte);
00095         void write_byte_io(uint16 adr, uint8 byte);
00096 
00097         uint8 read_zp(uint16 adr);
00098         uint16 read_zp_word(uint16 adr);
00099         void write_zp(uint16 adr, uint8 byte);
00100 
00101         void new_config(void);
00102         void jump(uint16 adr);
00103         void illegal_op(uint8 op, uint16 at);
00104         void illegal_jump(uint16 at, uint16 to);
00105 
00106         void do_adc(uint8 byte);
00107         void do_sbc(uint8 byte);
00108 
00109         uint8 read_emulator_id(uint16 adr);
00110 
00111         C64 *the_c64;           // Pointer to C64 object
00112 
00113         uint8 *ram;                     // Pointer to main RAM
00114         uint8 *basic_rom, *kernal_rom, *char_rom, *color_ram; // Pointers to ROMs and color RAM
00115 
00116         union {                         // Pending interrupts
00117                 uint8 intr[4];  // Index: See definitions above
00118                 unsigned long intr_any;
00119         } interrupt;
00120         bool nmi_state;         // State of NMI line
00121 
00122         uint8 n_flag, z_flag;
00123         bool v_flag, d_flag, i_flag, c_flag;
00124         uint8 a, x, y, sp;
00125 
00126 #if PC_IS_POINTER
00127         uint8 *pc, *pc_base;
00128 #else
00129         uint16 pc;
00130 #endif
00131 
00132 #ifdef FRODO_SC
00133         uint32 first_irq_cycle, first_nmi_cycle;
00134 
00135         uint8 state, op;                // Current state and opcode
00136         uint16 ar, ar2;                 // Address registers
00137         uint8 rdbuf;                    // Data buffer for RMW instructions
00138         uint8 ddr, pr;                  // Processor port
00139 #else
00140         int     borrowed_cycles;        // Borrowed cycles from next line
00141 #endif
00142 
00143         bool basic_in, kernal_in, char_in, io_in;
00144         uint8 dfff_byte;
00145 };
00146 
00147 // 6510 state
00148 struct MOS6510State {
00149         uint8 a, x, y;
00150         uint8 p;                        // Processor flags
00151         uint8 ddr, pr;          // Port
00152         uint16 pc, sp;
00153         uint8 intr[4];          // Interrupt state
00154         bool nmi_state; 
00155         uint8 dfff_byte;
00156         bool instruction_complete;
00157 };
00158 
00159 
00160 // Interrupt functions
00161 #ifdef FRODO_SC
00162 inline void MOS6510::TriggerVICIRQ(void)
00163 {
00164         if (!(interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]))
00165                 first_irq_cycle = the_c64->CycleCounter;
00166         interrupt.intr[INT_VICIRQ] = true;
00167 }
00168 
00169 inline void MOS6510::TriggerCIAIRQ(void)
00170 {
00171         if (!(interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]))
00172                 first_irq_cycle = the_c64->CycleCounter;
00173         interrupt.intr[INT_CIAIRQ] = true;
00174 }
00175 
00176 inline void MOS6510::TriggerNMI(void)
00177 {
00178         if (!nmi_state) {
00179                 nmi_state = true;
00180                 interrupt.intr[INT_NMI] = true;
00181                 first_nmi_cycle = the_c64->CycleCounter;
00182         }
00183 }
00184 #else
00185 inline void MOS6510::TriggerVICIRQ(void)
00186 {
00187         interrupt.intr[INT_VICIRQ] = true;
00188 }
00189 
00190 inline void MOS6510::TriggerCIAIRQ(void)
00191 {
00192         interrupt.intr[INT_CIAIRQ] = true;
00193 }
00194 
00195 inline void MOS6510::TriggerNMI(void)
00196 {
00197         if (!nmi_state) {
00198                 nmi_state = true;
00199                 interrupt.intr[INT_NMI] = true;
00200         }
00201 }
00202 #endif
00203 inline void MOS6510::ClearVICIRQ(void)
00204 {
00205         interrupt.intr[INT_VICIRQ] = false;
00206 }
00207 
00208 inline void MOS6510::ClearCIAIRQ(void)
00209 {
00210         interrupt.intr[INT_CIAIRQ] = false;
00211 }
00212 
00213 inline void MOS6510::ClearNMI(void)
00214 {
00215         nmi_state = false;
00216 }
00217 
00218 #endif

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