ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/CPUC64.h
Revision: 1.2
Committed: 2003-07-01T17:51:17Z (20 years, 9 months ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
updated copyright date

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * CPUC64.h - 6510 (C64) emulation (line based)
3     *
4 cebix 1.2 * Frodo (C) 1994-1997,2002-2003 Christian Bauer
5 cebix 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #ifndef _CPU_C64_H
22     #define _CPU_C64_H
23    
24     #include "C64.h"
25    
26    
27     // Set this to 1 if the 6502 PC should be represented by a real pointer
28     #ifndef FRODO_SC
29     #ifndef PC_IS_POINTER
30     #define PC_IS_POINTER 1
31     #endif
32     #endif
33    
34     // Set this to 1 for more precise CPU cycle calculation
35     #ifndef PRECISE_CPU_CYCLES
36     #define PRECISE_CPU_CYCLES 0
37     #endif
38    
39     // Set this to 1 for instruction-aligned CIA emulation
40     #ifndef PRECISE_CIA_CYCLES
41     #define PRECISE_CIA_CYCLES 0
42     #endif
43    
44    
45     // Interrupt types
46     enum {
47     INT_VICIRQ,
48     INT_CIAIRQ,
49     INT_NMI
50     // INT_RESET (private)
51     };
52    
53    
54     class MOS6569;
55     class MOS6581;
56     class MOS6526_1;
57     class MOS6526_2;
58     class REU;
59     class IEC;
60     struct MOS6510State;
61    
62    
63     // 6510 emulation (C64)
64     class MOS6510 {
65     public:
66     MOS6510(C64 *c64, uint8 *Ram, uint8 *Basic, uint8 *Kernal, uint8 *Char, uint8 *Color);
67    
68     #ifdef FRODO_SC
69     void EmulateCycle(void); // Emulate one clock cycle
70     #else
71     int EmulateLine(int cycles_left); // Emulate until cycles_left underflows
72     #endif
73     void Reset(void);
74     void AsyncReset(void); // Reset the CPU asynchronously
75     void AsyncNMI(void); // Raise NMI asynchronously (NMI pulse)
76     void GetState(MOS6510State *s);
77     void SetState(MOS6510State *s);
78     uint8 ExtReadByte(uint16 adr);
79     void ExtWriteByte(uint16 adr, uint8 byte);
80     uint8 REUReadByte(uint16 adr);
81     void REUWriteByte(uint16 adr, uint8 byte);
82    
83     void TriggerVICIRQ(void);
84     void ClearVICIRQ(void);
85     void TriggerCIAIRQ(void);
86     void ClearCIAIRQ(void);
87     void TriggerNMI(void);
88     void ClearNMI(void);
89    
90     int ExtConfig; // Memory configuration for ExtRead/WriteByte (0..7)
91    
92     MOS6569 *TheVIC; // Pointer to VIC
93     MOS6581 *TheSID; // Pointer to SID
94     MOS6526_1 *TheCIA1; // Pointer to CIA 1
95     MOS6526_2 *TheCIA2; // Pointer to CIA 2
96     REU *TheREU; // Pointer to REU
97     IEC *TheIEC; // Pointer to drive array
98    
99     #ifdef FRODO_SC
100     bool BALow; // BA line for Frodo SC
101     #endif
102    
103     private:
104     uint8 read_byte(uint16 adr);
105     uint8 read_byte_io(uint16 adr);
106     uint16 read_word(uint16 adr);
107     void write_byte(uint16 adr, uint8 byte);
108     void write_byte_io(uint16 adr, uint8 byte);
109    
110     uint8 read_zp(uint16 adr);
111     uint16 read_zp_word(uint16 adr);
112     void write_zp(uint16 adr, uint8 byte);
113    
114     void new_config(void);
115     void jump(uint16 adr);
116     void illegal_op(uint8 op, uint16 at);
117     void illegal_jump(uint16 at, uint16 to);
118    
119     void do_adc(uint8 byte);
120     void do_sbc(uint8 byte);
121    
122     uint8 read_emulator_id(uint16 adr);
123    
124     C64 *the_c64; // Pointer to C64 object
125    
126     uint8 *ram; // Pointer to main RAM
127     uint8 *basic_rom, *kernal_rom, *char_rom, *color_ram; // Pointers to ROMs and color RAM
128    
129     union { // Pending interrupts
130     uint8 intr[4]; // Index: See definitions above
131     unsigned long intr_any;
132     } interrupt;
133     bool nmi_state; // State of NMI line
134    
135     uint8 n_flag, z_flag;
136     bool v_flag, d_flag, i_flag, c_flag;
137     uint8 a, x, y, sp;
138    
139     #if PC_IS_POINTER
140     uint8 *pc, *pc_base;
141     #else
142     uint16 pc;
143     #endif
144    
145     #ifdef FRODO_SC
146     uint32 first_irq_cycle, first_nmi_cycle;
147    
148     uint8 state, op; // Current state and opcode
149     uint16 ar, ar2; // Address registers
150     uint8 rdbuf; // Data buffer for RMW instructions
151     uint8 ddr, pr; // Processor port
152     #else
153     int borrowed_cycles; // Borrowed cycles from next line
154     #endif
155    
156     bool basic_in, kernal_in, char_in, io_in;
157     uint8 dfff_byte;
158     };
159    
160     // 6510 state
161     struct MOS6510State {
162     uint8 a, x, y;
163     uint8 p; // Processor flags
164     uint8 ddr, pr; // Port
165     uint16 pc, sp;
166     uint8 intr[4]; // Interrupt state
167     bool nmi_state;
168     uint8 dfff_byte;
169     bool instruction_complete;
170     };
171    
172    
173     // Interrupt functions
174     #ifdef FRODO_SC
175     inline void MOS6510::TriggerVICIRQ(void)
176     {
177     if (!(interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]))
178     first_irq_cycle = the_c64->CycleCounter;
179     interrupt.intr[INT_VICIRQ] = true;
180     }
181    
182     inline void MOS6510::TriggerCIAIRQ(void)
183     {
184     if (!(interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]))
185     first_irq_cycle = the_c64->CycleCounter;
186     interrupt.intr[INT_CIAIRQ] = true;
187     }
188    
189     inline void MOS6510::TriggerNMI(void)
190     {
191     if (!nmi_state) {
192     nmi_state = true;
193     interrupt.intr[INT_NMI] = true;
194     first_nmi_cycle = the_c64->CycleCounter;
195     }
196     }
197     #else
198     inline void MOS6510::TriggerVICIRQ(void)
199     {
200     interrupt.intr[INT_VICIRQ] = true;
201     }
202    
203     inline void MOS6510::TriggerCIAIRQ(void)
204     {
205     interrupt.intr[INT_CIAIRQ] = true;
206     }
207    
208     inline void MOS6510::TriggerNMI(void)
209     {
210     if (!nmi_state) {
211     nmi_state = true;
212     interrupt.intr[INT_NMI] = true;
213     }
214     }
215     #endif
216     inline void MOS6510::ClearVICIRQ(void)
217     {
218     interrupt.intr[INT_VICIRQ] = false;
219     }
220    
221     inline void MOS6510::ClearCIAIRQ(void)
222     {
223     interrupt.intr[INT_CIAIRQ] = false;
224     }
225    
226     inline void MOS6510::ClearNMI(void)
227     {
228     nmi_state = false;
229     }
230    
231     #endif