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

# User Rev Content
1 cebix 1.1 /*
2     * CPUC64.h - 6510 (C64) emulation (line based)
3     *
4 cebix 1.7 * Frodo Copyright (C) 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 cebix 1.7 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 cebix 1.1 uint8 state, op; // Current state and opcode
155     uint16 ar, ar2; // Address registers
156     uint8 rdbuf; // Data buffer for RMW instructions
157 cebix 1.6 uint8 ddr, pr, pr_out; // Processor port
158 cebix 1.1 #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