libsidplayfp  1.8.3
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 
36 class MOS656X: public component, private Event
37 {
38 public:
39  typedef enum
40  {
45  } model_t;
46 
47 private:
48  typedef event_clock_t (MOS656X::*ClockFunc)();
49 
50  typedef struct
51  {
52  unsigned int rasterLines;
53  unsigned int cyclesPerLine;
54  ClockFunc clock;
55  } model_data_t;
56 
57 private:
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 
74 private:
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 
127 private:
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 
288 protected:
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 
314 public:
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 
340 template<>
341 inline void MOS656X::startDma<0>()
342 {
343  setBA(!sprites.isDma(0x01));
344 }
345 
349 template<>
350 inline void MOS656X::endDma<7>()
351 {
352  setBA(true);
353 }
354 
355 #endif // MOS656X_H
bool isDma(unsigned int val) const
Definition: sprites.h:159
void untrigger()
Definition: lightpen.h:133
Definition: mos656x.h:36
Definition: sprites.h:33
model_t
Definition: mos656x.h:39
void event()
Definition: mos656x.cpp:248
Definition: event.h:107
PAL-N.
Definition: mos656x.h:44
Definition: c64.cpp:29
Definition: component.h:28
Definition: lightpen.h:30
uint8_t read(uint_least8_t addr)
Definition: mos656x.cpp:104
void clearLightpen()
Definition: mos656x.cpp:681
void write(uint_least8_t addr, uint8_t data)
Definition: mos656x.cpp:140
bool retrigger(unsigned int lineCycle, unsigned int rasterY)
Definition: lightpen.h:88
Definition: event.h:50
virtual void cancel(Event &event)=0
OLD NTSC CHIP.
Definition: mos656x.h:41
NTSC-M.
Definition: mos656x.h:42
void triggerLightpen()
Definition: mos656x.cpp:668
PAL-B.
Definition: mos656x.h:43