libsidplayfp  1.6.2
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 struct
49  {
50  unsigned int rasterLines;
51  unsigned int cyclesPerLine;
52  event_clock_t (MOS656X::*clock)();
53  } model_data_t;
54 
55 private:
56  static const char *credit;
57 
58  static const model_data_t modelData[];
59 
61  static const int IRQ_RASTER = 1 << 0;
62 
64  static const int IRQ_LIGHTPEN = 1 << 3;
65 
67  static const unsigned int FIRST_DMA_LINE = 0x30;
68 
70  static const unsigned int LAST_DMA_LINE = 0xf7;
71 
72 private:
73  event_clock_t (MOS656X::*clock)();
74 
75  event_clock_t rasterClk;
76 
78  EventContext &event_context;
79 
81  unsigned int cyclesPerLine;
82 
84  unsigned int maxRasters;
85 
87  unsigned int lineCycle;
88 
90  unsigned int rasterY;
91 
93  unsigned int yscroll;
94 
96  bool areBadLinesEnabled;
97 
99  bool isBadLine;
100 
102  bool rasterYIRQCondition;
103 
105  bool vblanking;
106 
108  bool lpAsserted;
109 
111  uint8_t irqFlags;
112 
114  uint8_t irqMask;
115 
117  Lightpen lp;
118 
120  Sprites sprites;
121 
123  uint8_t regs[0x40];
124 
125 private:
126  event_clock_t clockPAL();
127  event_clock_t clockNTSC();
128  event_clock_t clockOldNTSC();
129 
133  void handleIrqState();
134 
135  EventCallback<MOS656X> badLineStateChangeEvent;
136 
140  void badLineStateChange() { setBA(!isBadLine); }
141 
142  EventCallback<MOS656X> rasterYIRQEdgeDetectorEvent;
143 
147  void rasterYIRQEdgeDetector()
148  {
149  const bool oldRasterYIRQCondition = rasterYIRQCondition;
150  rasterYIRQCondition = rasterY == readRasterLineIRQ();
151  if (!oldRasterYIRQCondition && rasterYIRQCondition)
152  activateIRQFlag(IRQ_RASTER);
153  }
154 
159  void activateIRQFlag(int flag)
160  {
161  irqFlags |= flag;
162  handleIrqState();
163  }
164 
170  unsigned int readRasterLineIRQ() const
171  {
172  return (regs[0x12] & 0xff) + ((regs[0x11] & 0x80) << 1);
173  }
174 
180  bool readDEN() const { return (regs[0x11] & 0x10) != 0; }
181 
182  bool evaluateIsBadLine() const
183  {
184  return areBadLinesEnabled
185  && rasterY >= FIRST_DMA_LINE
186  && rasterY <= LAST_DMA_LINE
187  && (rasterY & 7) == yscroll;
188  }
189 
193  inline unsigned int oldRasterY() const
194  {
195  return rasterY > 0 ? rasterY - 1 : maxRasters - 1;
196  }
197 
198  inline void sync()
199  {
200  event_context.cancel(*this);
201  event();
202  }
203 
207  inline void checkVblank()
208  {
209  // IRQ occurred (xraster != 0)
210  if (rasterY == (maxRasters - 1))
211  {
212  vblanking = true;
213  }
214 
215  // Check DEN bit on first cycle of the line following the first DMA line
216  if (rasterY == FIRST_DMA_LINE
217  && !areBadLinesEnabled
218  && readDEN())
219  {
220  areBadLinesEnabled = true;
221  }
222 
223  // Disallow bad lines after the last possible one has passed
224  if (rasterY == LAST_DMA_LINE)
225  {
226  areBadLinesEnabled = false;
227  }
228 
229  isBadLine = false;
230 
231  if (!vblanking)
232  {
233  rasterY++;
234  rasterYIRQEdgeDetector();
235  }
236 
237  if (evaluateIsBadLine())
238  isBadLine = true;
239  }
240 
241  inline void vblank()
242  {
243  // Vertical blank (line 0)
244  if (vblanking)
245  {
246  vblanking = false;
247  rasterY = 0;
248  rasterYIRQEdgeDetector();
249  lp.untrigger();
250  if (lpAsserted && lp.retrigger(lineCycle, rasterY))
251  {
252  activateIRQFlag(IRQ_LIGHTPEN);
253  }
254  }
255  }
256 
260  template<int n>
261  inline void startDma()
262  {
263  if (sprites.isDma(0x01 << n))
264  setBA(false);
265  }
266 
270  template<int n>
271  inline void endDma()
272  {
273  if (!sprites.isDma(0x06 << n))
274  setBA(true);
275  }
276 
280  inline void startBadline()
281  {
282  if (isBadLine)
283  setBA(false);
284  }
285 
286 protected:
287  MOS656X(EventContext *context);
288  ~MOS656X() {}
289 
290  // Environment Interface
291  virtual void interrupt (bool state) = 0;
292  virtual void setBA (bool state) = 0;
293 
300  uint8_t read(uint_least8_t addr);
301 
310  void write(uint_least8_t addr, uint8_t data);
311 
312 public:
313  void event();
314 
315  void chip(model_t model);
316 
320  void triggerLightpen();
321 
325  void clearLightpen();
326 
327  // Component Standard Calls
328  void reset();
329 
330  static const char *credits() { return credit; }
331 };
332 
333 // Template specializations
334 
338 template<>
339 inline void MOS656X::startDma<0>()
340 {
341  setBA(!sprites.isDma(0x01));
342 }
343 
347 template<>
348 inline void MOS656X::endDma<7>()
349 {
350  setBA(true);
351 }
352 
353 #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:246
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:102
void clearLightpen()
Definition: mos656x.cpp:679
void write(uint_least8_t addr, uint8_t data)
Definition: mos656x.cpp:138
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:666
PAL-B.
Definition: mos656x.h:43