ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/CPU1541.h
Revision: 1.4
Committed: 2005-06-27T19:55:48Z (19 years, 4 months ago) by cebix
Content type: text/plain
Branch: MAIN
CVS Tags: VERSION_4_2
Changes since 1.3: +1 -1 lines
Log Message:
updated copyright dates

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * CPU1541.h - 6502 (1541) emulation (line based)
3     *
4 cebix 1.4 * Frodo (C) 1994-1997,2002-2005 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_1541_H
22     #define _CPU_1541_H
23    
24     #include "CIA.h"
25     #include "C64.h"
26    
27    
28     // Set this to 1 if the 6502 PC should be represented by a real pointer
29     #ifndef FRODO_SC
30     #ifndef PC_IS_POINTER
31     #define PC_IS_POINTER 1
32     #endif
33     #endif
34    
35     // Set this to 1 for more precise CPU cycle calculation
36     #ifndef PRECISE_CPU_CYCLES
37     #define PRECISE_CPU_CYCLES 0
38     #endif
39    
40    
41     // Interrupt types
42     enum {
43     INT_VIA1IRQ,
44     INT_VIA2IRQ,
45     INT_IECIRQ
46     // INT_RESET (private)
47     };
48    
49    
50     class C64;
51     class Job1541;
52     class C64Display;
53     struct MOS6502State;
54    
55    
56     // 6502 emulation (1541)
57     class MOS6502_1541 {
58     public:
59     MOS6502_1541(C64 *c64, Job1541 *job, C64Display *disp, uint8 *Ram, uint8 *Rom);
60    
61     #ifdef FRODO_SC
62     void EmulateCycle(void); // Emulate one clock cycle
63     #else
64     int EmulateLine(int cycles_left); // Emulate until cycles_left underflows
65     #endif
66     void Reset(void);
67     void AsyncReset(void); // Reset the CPU asynchronously
68     void GetState(MOS6502State *s);
69     void SetState(MOS6502State *s);
70     uint8 ExtReadByte(uint16 adr);
71     void ExtWriteByte(uint16 adr, uint8 byte);
72     void CountVIATimers(int cycles);
73     void NewATNState(void);
74     void IECInterrupt(void);
75     void TriggerJobIRQ(void);
76     bool InterruptEnabled(void);
77    
78     MOS6526_2 *TheCIA2; // Pointer to C64 CIA 2
79    
80     uint8 IECLines; // State of IEC lines (bit 7 - DATA, bit 6 - CLK)
81     bool Idle; // true: 1541 is idle
82    
83     private:
84     uint8 read_byte(uint16 adr);
85     uint8 read_byte_io(uint16 adr);
86     uint16 read_word(uint16 adr);
87     void write_byte(uint16 adr, uint8 byte);
88     void write_byte_io(uint16 adr, uint8 byte);
89    
90     uint8 read_zp(uint16 adr);
91     uint16 read_zp_word(uint16 adr);
92     void write_zp(uint16 adr, uint8 byte);
93    
94     void jump(uint16 adr);
95     void illegal_op(uint8 op, uint16 at);
96     void illegal_jump(uint16 at, uint16 to);
97    
98     void do_adc(uint8 byte);
99     void do_sbc(uint8 byte);
100    
101     uint8 *ram; // Pointer to main RAM
102     uint8 *rom; // Pointer to ROM
103     C64 *the_c64; // Pointer to C64 object
104     C64Display *the_display; // Pointer to C64 display object
105     Job1541 *the_job; // Pointer to 1541 job object
106    
107     union { // Pending interrupts
108     uint8 intr[4]; // Index: See definitions above
109     unsigned long intr_any;
110     } interrupt;
111    
112     uint8 n_flag, z_flag;
113     bool v_flag, d_flag, i_flag, c_flag;
114     uint8 a, x, y, sp;
115     #if PC_IS_POINTER
116     uint8 *pc, *pc_base;
117     #else
118     uint16 pc;
119     #endif
120    
121     #ifdef FRODO_SC
122     uint32 first_irq_cycle;
123    
124     uint8 state, op; // Current state and opcode
125     uint16 ar, ar2; // Address registers
126     uint8 rdbuf; // Data buffer for RMW instructions
127     uint8 ddr, pr; // Processor port
128     #else
129     int borrowed_cycles; // Borrowed cycles from next line
130     #endif
131    
132     uint8 via1_pra; // PRA of VIA 1
133     uint8 via1_ddra; // DDRA of VIA 1
134     uint8 via1_prb; // PRB of VIA 1
135     uint8 via1_ddrb; // DDRB of VIA 1
136     uint16 via1_t1c; // T1 Counter of VIA 1
137     uint16 via1_t1l; // T1 Latch of VIA 1
138     uint16 via1_t2c; // T2 Counter of VIA 1
139     uint16 via1_t2l; // T2 Latch of VIA 1
140     uint8 via1_sr; // SR of VIA 1
141     uint8 via1_acr; // ACR of VIA 1
142     uint8 via1_pcr; // PCR of VIA 1
143     uint8 via1_ifr; // IFR of VIA 1
144     uint8 via1_ier; // IER of VIA 1
145    
146     uint8 via2_pra; // PRA of VIA 2
147     uint8 via2_ddra; // DDRA of VIA 2
148     uint8 via2_prb; // PRB of VIA 2
149     uint8 via2_ddrb; // DDRB of VIA 2
150     uint16 via2_t1c; // T1 Counter of VIA 2
151     uint16 via2_t1l; // T1 Latch of VIA 2
152     uint16 via2_t2c; // T2 Counter of VIA 2
153     uint16 via2_t2l; // T2 Latch of VIA 2
154     uint8 via2_sr; // SR of VIA 2
155     uint8 via2_acr; // ACR of VIA 2
156     uint8 via2_pcr; // PCR of VIA 2
157     uint8 via2_ifr; // IFR of VIA 2
158     uint8 via2_ier; // IER of VIA 2
159     };
160    
161     // 6502 state
162     struct MOS6502State {
163     uint8 a, x, y;
164     uint8 p; // Processor flags
165     uint16 pc, sp;
166    
167     uint8 intr[4]; // Interrupt state
168     bool instruction_complete;
169     bool idle;
170    
171     uint8 via1_pra; // VIA 1
172     uint8 via1_ddra;
173     uint8 via1_prb;
174     uint8 via1_ddrb;
175     uint16 via1_t1c;
176     uint16 via1_t1l;
177     uint16 via1_t2c;
178     uint16 via1_t2l;
179     uint8 via1_sr;
180     uint8 via1_acr;
181     uint8 via1_pcr;
182     uint8 via1_ifr;
183     uint8 via1_ier;
184    
185     uint8 via2_pra; // VIA 2
186     uint8 via2_ddra;
187     uint8 via2_prb;
188     uint8 via2_ddrb;
189     uint16 via2_t1c;
190     uint16 via2_t1l;
191     uint16 via2_t2c;
192     uint16 via2_t2l;
193     uint8 via2_sr;
194     uint8 via2_acr;
195     uint8 via2_pcr;
196     uint8 via2_ifr;
197     uint8 via2_ier;
198     };
199    
200    
201    
202     /*
203     * Trigger job loop IRQ
204     */
205    
206     #ifdef FRODO_SC
207     inline void MOS6502_1541::TriggerJobIRQ(void)
208     {
209     if (!(interrupt.intr[INT_VIA2IRQ]))
210     first_irq_cycle = the_c64->CycleCounter;
211     interrupt.intr[INT_VIA2IRQ] = true;
212     Idle = false;
213     }
214     #else
215     inline void MOS6502_1541::TriggerJobIRQ(void)
216     {
217     interrupt.intr[INT_VIA2IRQ] = true;
218     Idle = false;
219     }
220     #endif
221    
222    
223     /*
224     * Count VIA timers
225     */
226    
227     inline void MOS6502_1541::CountVIATimers(int cycles)
228     {
229     unsigned long tmp;
230    
231     via1_t1c = tmp = via1_t1c - cycles;
232     if (tmp > 0xffff) {
233     if (via1_acr & 0x40) // Reload from latch in free-run mode
234     via1_t1c = via1_t1l;
235     via1_ifr |= 0x40;
236     }
237    
238     if (!(via1_acr & 0x20)) { // Only count in one-shot mode
239     via1_t2c = tmp = via1_t2c - cycles;
240     if (tmp > 0xffff)
241     via1_ifr |= 0x20;
242     }
243    
244     via2_t1c = tmp = via2_t1c - cycles;
245     if (tmp > 0xffff) {
246     if (via2_acr & 0x40) // Reload from latch in free-run mode
247     via2_t1c = via2_t1l;
248     via2_ifr |= 0x40;
249     if (via2_ier & 0x40)
250     TriggerJobIRQ();
251     }
252    
253     if (!(via2_acr & 0x20)) { // Only count in one-shot mode
254     via2_t2c = tmp = via2_t2c - cycles;
255     if (tmp > 0xffff)
256     via2_ifr |= 0x20;
257     }
258     }
259    
260    
261     /*
262     * ATN line probably changed state, recalc IECLines
263     */
264    
265     inline void MOS6502_1541::NewATNState(void)
266     {
267     uint8 byte = ~via1_prb & via1_ddrb;
268     IECLines = (byte << 6) & ((~byte ^ TheCIA2->IECLines) << 3) & 0x80 // DATA (incl. ATN acknowledge)
269     | (byte << 3) & 0x40; // CLK
270     }
271    
272    
273     /*
274     * Interrupt by negative edge of ATN on IEC bus
275     */
276    
277     inline void MOS6502_1541::IECInterrupt(void)
278     {
279     ram[0x7c] = 1;
280    
281     // Wake up 1541
282     Idle = false;
283     }
284    
285    
286     /*
287     * Test if interrupts are enabled (for job loop)
288     */
289    
290     inline bool MOS6502_1541::InterruptEnabled(void)
291     {
292     return !i_flag;
293     }
294    
295     #endif