ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/CPUC64.h
Revision: 1.7
Committed: 2010-04-22T15:08:18Z (13 years, 11 months ago) by cebix
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +8 -1 lines
Log Message:
better interrupt timing

File Contents

# Content
1 /*
2 * CPUC64.h - 6510 (C64) emulation (line based)
3 *
4 * Frodo Copyright (C) Christian Bauer
5 *
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 enum {
148 OPFLAG_IRQ_DISABLED = 0x01,
149 OPFLAG_IRQ_ENABLED = 0x02,
150 OPFLAG_INT_DELAYED = 0x04
151 };
152 uint8 opflags; // Interrupt operation flags
153
154 uint8 state, op; // Current state and opcode
155 uint16 ar, ar2; // Address registers
156 uint8 rdbuf; // Data buffer for RMW instructions
157 uint8 ddr, pr, pr_out; // Processor port
158 #else
159 int borrowed_cycles; // Borrowed cycles from next line
160 #endif
161
162 bool basic_in, kernal_in, char_in, io_in;
163 uint8 dfff_byte;
164 };
165
166 // 6510 state
167 struct MOS6510State {
168 uint8 a, x, y;
169 uint8 p; // Processor flags
170 uint8 ddr, pr; // Port
171 uint16 pc, sp;
172 uint8 intr[4]; // Interrupt state
173 bool nmi_state;
174 uint8 dfff_byte;
175 bool instruction_complete;
176 };
177
178
179 // Interrupt functions
180 #ifdef FRODO_SC
181 inline void MOS6510::TriggerVICIRQ(void)
182 {
183 if (!(interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]))
184 first_irq_cycle = the_c64->CycleCounter;
185 interrupt.intr[INT_VICIRQ] = true;
186 }
187
188 inline void MOS6510::TriggerCIAIRQ(void)
189 {
190 if (!(interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]))
191 first_irq_cycle = the_c64->CycleCounter;
192 interrupt.intr[INT_CIAIRQ] = true;
193 }
194
195 inline void MOS6510::TriggerNMI(void)
196 {
197 if (!nmi_state) {
198 nmi_state = true;
199 interrupt.intr[INT_NMI] = true;
200 first_nmi_cycle = the_c64->CycleCounter;
201 }
202 }
203 #else
204 inline void MOS6510::TriggerVICIRQ(void)
205 {
206 interrupt.intr[INT_VICIRQ] = true;
207 }
208
209 inline void MOS6510::TriggerCIAIRQ(void)
210 {
211 interrupt.intr[INT_CIAIRQ] = true;
212 }
213
214 inline void MOS6510::TriggerNMI(void)
215 {
216 if (!nmi_state) {
217 nmi_state = true;
218 interrupt.intr[INT_NMI] = true;
219 }
220 }
221 #endif
222 inline void MOS6510::ClearVICIRQ(void)
223 {
224 interrupt.intr[INT_VICIRQ] = false;
225 }
226
227 inline void MOS6510::ClearCIAIRQ(void)
228 {
229 interrupt.intr[INT_CIAIRQ] = false;
230 }
231
232 inline void MOS6510::ClearNMI(void)
233 {
234 nmi_state = false;
235 }
236
237 #endif