libsidplayfp 1.8.8
mos656x.h
1/*
2 * This file is part of libsidplayfp, a SID player engine.
3 *
4 * Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
5 * Copyright 2009-2014 VICE Project
6 * Copyright 2007-2010 Antti Lankila
7 * Copyright 2001 Simon White
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24#ifndef MOS656X_H
25#define MOS656X_H
26
27#include <stdint.h>
28
29#include "lightpen.h"
30#include "sprites.h"
31#include "sidplayfp/event.h"
32#include "c64/component.h"
33#include "EventScheduler.h"
34
35
36class MOS656X: public component, private Event
37{
38public:
39 typedef enum
40 {
41 MOS6567R56A = 0
46
47private:
48 typedef event_clock_t (MOS656X::*ClockFunc)();
49
50 typedef struct
51 {
52 unsigned int rasterLines;
53 unsigned int cyclesPerLine;
54 ClockFunc clock;
56
57private:
58 static const char *credit;
59
60 static const model_data_t modelData[];
61
63 static const int IRQ_RASTER = 1 << 0;
64
66 static const int IRQ_LIGHTPEN = 1 << 3;
67
69 static const unsigned int FIRST_DMA_LINE = 0x30;
70
72 static const unsigned int LAST_DMA_LINE = 0xf7;
73
74private:
75 ClockFunc clock;
76
77 event_clock_t rasterClk;
78
80 EventContext &event_context;
81
83 unsigned int cyclesPerLine;
84
86 unsigned int maxRasters;
87
89 unsigned int lineCycle;
90
92 unsigned int rasterY;
93
95 unsigned int yscroll;
96
98 bool areBadLinesEnabled;
99
101 bool isBadLine;
102
104 bool rasterYIRQCondition;
105
107 bool vblanking;
108
110 bool lpAsserted;
111
113 uint8_t irqFlags;
114
116 uint8_t irqMask;
117
119 Lightpen lp;
120
122 Sprites sprites;
123
125 uint8_t regs[0x40];
126
127private:
128 event_clock_t clockPAL();
129 event_clock_t clockNTSC();
130 event_clock_t clockOldNTSC();
131
135 void handleIrqState();
136
137 EventCallback<MOS656X> badLineStateChangeEvent;
138
142 void badLineStateChange() { setBA(!isBadLine); }
143
144 EventCallback<MOS656X> rasterYIRQEdgeDetectorEvent;
145
149 void rasterYIRQEdgeDetector()
150 {
151 const bool oldRasterYIRQCondition = rasterYIRQCondition;
152 rasterYIRQCondition = rasterY == readRasterLineIRQ();
153 if (!oldRasterYIRQCondition && rasterYIRQCondition)
154 activateIRQFlag(IRQ_RASTER);
155 }
156
161 void activateIRQFlag(int flag)
162 {
163 irqFlags |= flag;
164 handleIrqState();
165 }
166
172 unsigned int readRasterLineIRQ() const
173 {
174 return (regs[0x12] & 0xff) + ((regs[0x11] & 0x80) << 1);
175 }
176
182 bool readDEN() const { return (regs[0x11] & 0x10) != 0; }
183
184 bool evaluateIsBadLine() const
185 {
186 return areBadLinesEnabled
187 && rasterY >= FIRST_DMA_LINE
188 && rasterY <= LAST_DMA_LINE
189 && (rasterY & 7) == yscroll;
190 }
191
195 inline unsigned int oldRasterY() const
196 {
197 return rasterY > 0 ? rasterY - 1 : maxRasters - 1;
198 }
199
200 inline void sync()
201 {
202 event_context.cancel(*this);
203 event();
204 }
205
209 inline void checkVblank()
210 {
211 // IRQ occurred (xraster != 0)
212 if (rasterY == (maxRasters - 1))
213 {
214 vblanking = true;
215 }
216
217 // Check DEN bit on first cycle of the line following the first DMA line
218 if (rasterY == FIRST_DMA_LINE
219 && !areBadLinesEnabled
220 && readDEN())
221 {
222 areBadLinesEnabled = true;
223 }
224
225 // Disallow bad lines after the last possible one has passed
226 if (rasterY == LAST_DMA_LINE)
227 {
228 areBadLinesEnabled = false;
229 }
230
231 isBadLine = false;
232
233 if (!vblanking)
234 {
235 rasterY++;
236 rasterYIRQEdgeDetector();
237 }
238
239 if (evaluateIsBadLine())
240 isBadLine = true;
241 }
242
243 inline void vblank()
244 {
245 // Vertical blank (line 0)
246 if (vblanking)
247 {
248 vblanking = false;
249 rasterY = 0;
250 rasterYIRQEdgeDetector();
251 lp.untrigger();
252 if (lpAsserted && lp.retrigger(lineCycle, rasterY))
253 {
254 activateIRQFlag(IRQ_LIGHTPEN);
255 }
256 }
257 }
258
262 template<int n>
263 inline void startDma()
264 {
265 if (sprites.isDma(0x01 << n))
266 setBA(false);
267 }
268
272 template<int n>
273 inline void endDma()
274 {
275 if (!sprites.isDma(0x06 << n))
276 setBA(true);
277 }
278
282 inline void startBadline()
283 {
284 if (isBadLine)
285 setBA(false);
286 }
287
288protected:
289 MOS656X(EventContext *context);
290 ~MOS656X() {}
291
292 // Environment Interface
293 virtual void interrupt (bool state) = 0;
294 virtual void setBA (bool state) = 0;
295
302 uint8_t read(uint_least8_t addr);
303
312 void write(uint_least8_t addr, uint8_t data);
313
314public:
315 void event();
316
317 void chip(model_t model);
318
322 void triggerLightpen();
323
327 void clearLightpen();
328
329 // Component Standard Calls
330 void reset();
331
332 static const char *credits() { return credit; }
333};
334
335// Template specializations
336
340template<>
341inline void MOS656X::startDma<0>()
342{
343 setBA(!sprites.isDma(0x01));
344}
345
349template<>
350inline void MOS656X::endDma<7>()
351{
352 setBA(true);
353}
354
355#endif // MOS656X_H
Definition: EventScheduler.h:31
Definition: event.h:108
virtual void cancel(Event &event)=0
Definition: event.h:51
Definition: lightpen.h:31
void untrigger()
Definition: lightpen.h:133
bool retrigger(unsigned int lineCycle, unsigned int rasterY)
Definition: lightpen.h:88
Definition: mos656x.h:37
void clearLightpen()
Definition: mos656x.cpp:675
void write(uint_least8_t addr, uint8_t data)
Definition: mos656x.cpp:140
void triggerLightpen()
Definition: mos656x.cpp:662
model_t
Definition: mos656x.h:40
@ MOS6567R8
NTSC-M.
Definition: mos656x.h:42
@ MOS6572
PAL-N.
Definition: mos656x.h:44
@ MOS6567R56A
OLD NTSC CHIP.
Definition: mos656x.h:41
@ MOS6569
PAL-B.
Definition: mos656x.h:43
uint8_t read(uint_least8_t addr)
Definition: mos656x.cpp:104
void event()
Definition: mos656x.cpp:245
Definition: sprites.h:34
bool isDma(unsigned int val) const
Definition: sprites.h:159
Definition: component.h:29
Definition: c64.cpp:30