ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/CPUC64.h
Revision: 1.4
Committed: 2004-01-12T15:13:20Z (20 years, 10 months ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.3: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * CPUC64.h - 6510 (C64) emulation (line based)
3     *
4 cebix 1.4 * Frodo (C) 1994-1997,2002-2004 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 illegal_op(uint8 op, uint16 at);
116     void illegal_jump(uint16 at, uint16 to);
117    
118     void do_adc(uint8 byte);
119     void do_sbc(uint8 byte);
120    
121     uint8 read_emulator_id(uint16 adr);
122    
123     C64 *the_c64; // Pointer to C64 object
124    
125     uint8 *ram; // Pointer to main RAM
126     uint8 *basic_rom, *kernal_rom, *char_rom, *color_ram; // Pointers to ROMs and color RAM
127    
128     union { // Pending interrupts
129     uint8 intr[4]; // Index: See definitions above
130     unsigned long intr_any;
131     } interrupt;
132     bool nmi_state; // State of NMI line
133    
134     uint8 n_flag, z_flag;
135     bool v_flag, d_flag, i_flag, c_flag;
136     uint8 a, x, y, sp;
137    
138     #if PC_IS_POINTER
139     uint8 *pc, *pc_base;
140     #else
141     uint16 pc;
142     #endif
143    
144     #ifdef FRODO_SC
145     uint32 first_irq_cycle, first_nmi_cycle;
146    
147     uint8 state, op; // Current state and opcode
148     uint16 ar, ar2; // Address registers
149     uint8 rdbuf; // Data buffer for RMW instructions
150     uint8 ddr, pr; // Processor port
151     #else
152     int borrowed_cycles; // Borrowed cycles from next line
153     #endif
154    
155     bool basic_in, kernal_in, char_in, io_in;
156     uint8 dfff_byte;
157     };
158    
159     // 6510 state
160     struct MOS6510State {
161     uint8 a, x, y;
162     uint8 p; // Processor flags
163     uint8 ddr, pr; // Port
164     uint16 pc, sp;
165     uint8 intr[4]; // Interrupt state
166     bool nmi_state;
167     uint8 dfff_byte;
168     bool instruction_complete;
169     };
170    
171    
172     // Interrupt functions
173     #ifdef FRODO_SC
174     inline void MOS6510::TriggerVICIRQ(void)
175     {
176     if (!(interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]))
177     first_irq_cycle = the_c64->CycleCounter;
178     interrupt.intr[INT_VICIRQ] = true;
179     }
180    
181     inline void MOS6510::TriggerCIAIRQ(void)
182     {
183     if (!(interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]))
184     first_irq_cycle = the_c64->CycleCounter;
185     interrupt.intr[INT_CIAIRQ] = true;
186     }
187    
188     inline void MOS6510::TriggerNMI(void)
189     {
190     if (!nmi_state) {
191     nmi_state = true;
192     interrupt.intr[INT_NMI] = true;
193     first_nmi_cycle = the_c64->CycleCounter;
194     }
195     }
196     #else
197     inline void MOS6510::TriggerVICIRQ(void)
198     {
199     interrupt.intr[INT_VICIRQ] = true;
200     }
201    
202     inline void MOS6510::TriggerCIAIRQ(void)
203     {
204     interrupt.intr[INT_CIAIRQ] = true;
205     }
206    
207     inline void MOS6510::TriggerNMI(void)
208     {
209     if (!nmi_state) {
210     nmi_state = true;
211     interrupt.intr[INT_NMI] = true;
212     }
213     }
214     #endif
215     inline void MOS6510::ClearVICIRQ(void)
216     {
217     interrupt.intr[INT_VICIRQ] = false;
218     }
219    
220     inline void MOS6510::ClearCIAIRQ(void)
221     {
222     interrupt.intr[INT_CIAIRQ] = false;
223     }
224    
225     inline void MOS6510::ClearNMI(void)
226     {
227     nmi_state = false;
228     }
229    
230     #endif