58 using ClockFunc = event_clock_t (
MOS656X::*)();
60 using model_data_t =
struct
62 unsigned int rasterLines;
63 unsigned int cyclesPerLine;
68 static const model_data_t modelData[];
71 static constexpr int IRQ_RASTER = 1 << 0;
74 static constexpr int IRQ_LIGHTPEN = 1 << 3;
77 static constexpr unsigned int FIRST_DMA_LINE = 0x30;
80 static constexpr unsigned int LAST_DMA_LINE = 0xf7;
87 event_clock_t rasterClk;
90 EventScheduler &eventScheduler;
93 unsigned int cyclesPerLine;
96 unsigned int maxRasters;
99 unsigned int lineCycle;
102 unsigned int rasterY;
105 unsigned int yscroll;
108 bool areBadLinesEnabled;
114 bool rasterYIRQCondition;
129 uint8_t regs[0x40] = {0};
137 EventCallback<MOS656X> badLineStateChangeEvent;
139 EventCallback<MOS656X> rasterYIRQEdgeDetectorEvent;
141 EventCallback<MOS656X> lightpenTriggerEvent;
144 event_clock_t clockPAL();
145 event_clock_t clockNTSC();
146 event_clock_t clockOldNTSC();
151 void handleIrqState();
156 void badLineStateChange() { setBA(!isBadLine); }
161 void rasterYIRQEdgeDetector()
163 const bool oldRasterYIRQCondition = rasterYIRQCondition;
164 rasterYIRQCondition = rasterY == readRasterLineIRQ();
165 if (!oldRasterYIRQCondition && rasterYIRQCondition)
166 activateIRQFlag(IRQ_RASTER);
169 void lightpenTrigger()
174 if (lp.trigger(lineCycle, rasterY))
176 activateIRQFlag(IRQ_LIGHTPEN);
184 void activateIRQFlag(
int flag)
195 unsigned int readRasterLineIRQ()
const
197 return regs[0x12] + ((regs[0x11] & 0x80) << 1);
205 bool readDEN()
const {
return (regs[0x11] & 0x10) != 0; }
207 bool evaluateIsBadLine()
const
209 return areBadLinesEnabled
210 && rasterY >= FIRST_DMA_LINE
211 && rasterY <= LAST_DMA_LINE
212 && (rasterY & 7) == yscroll;
218 inline unsigned int oldRasterY()
const
220 return (rasterY > 0 ? rasterY : maxRasters) - 1;
225 eventScheduler.cancel(*
this);
232 inline void checkVblank()
235 if (rasterY == (maxRasters - 1))
241 if (rasterY == FIRST_DMA_LINE
242 && !areBadLinesEnabled
245 areBadLinesEnabled =
true;
249 if (rasterY == LAST_DMA_LINE)
251 areBadLinesEnabled =
false;
259 rasterYIRQEdgeDetector();
260 if ((rasterY == FIRST_DMA_LINE) && !areBadLinesEnabled)
261 areBadLinesEnabled = readDEN();
264 if (evaluateIsBadLine())
277 rasterYIRQEdgeDetector();
279 if (lpAsserted && lp.retrigger())
281 activateIRQFlag(IRQ_LIGHTPEN);
290 inline void startDma()
292 if (sprites.isDma(0x01 << n))
302 if (!sprites.isDma(0x06 << n))
309 inline void startBadline()
316 MOS656X(EventScheduler &scheduler);
317 ~MOS656X() =
default;
320 virtual void interrupt(
bool state) = 0;
321 virtual void setBA(
bool state) = 0;
329 uint8_t
read(uint_least8_t addr);
339 void write(uint_least8_t addr, uint8_t data);
342 void event()
override;
364 static const char *credits();