57 using ClockFunc = event_clock_t (
MOS656X::*)();
59 using model_data_t =
struct
61 unsigned int rasterLines;
62 unsigned int cyclesPerLine;
67 static const model_data_t modelData[];
70 static constexpr int IRQ_RASTER = 1 << 0;
73 static constexpr int IRQ_LIGHTPEN = 1 << 3;
76 static constexpr unsigned int FIRST_DMA_LINE = 0x30;
79 static constexpr unsigned int LAST_DMA_LINE = 0xf7;
86 event_clock_t rasterClk;
89 EventScheduler &eventScheduler;
92 unsigned int cyclesPerLine;
95 unsigned int maxRasters;
98 unsigned int lineCycle;
101 unsigned int rasterY;
104 unsigned int yscroll;
107 bool areBadLinesEnabled;
113 bool rasterYIRQCondition;
128 uint8_t regs[0x40] = {0};
136 EventCallback<MOS656X> badLineStateChangeEvent;
138 EventCallback<MOS656X> rasterYIRQEdgeDetectorEvent;
140 EventCallback<MOS656X> lightpenTriggerEvent;
143 event_clock_t clockPAL();
144 event_clock_t clockNTSC();
145 event_clock_t clockOldNTSC();
150 void handleIrqState();
155 void badLineStateChange() { setBA(!isBadLine); }
160 void rasterYIRQEdgeDetector()
162 const bool oldRasterYIRQCondition = rasterYIRQCondition;
163 rasterYIRQCondition = rasterY == readRasterLineIRQ();
164 if (!oldRasterYIRQCondition && rasterYIRQCondition)
165 activateIRQFlag(IRQ_RASTER);
168 void lightpenTrigger()
173 if (lp.trigger(lineCycle, rasterY))
175 activateIRQFlag(IRQ_LIGHTPEN);
183 void activateIRQFlag(
int flag)
194 inline unsigned int readRasterLineIRQ()
const
196 return regs[0x12] + ((regs[0x11] & 0x80) << 1);
204 inline bool readDEN()
const {
return (regs[0x11] & 0x10) != 0; }
206 inline bool evaluateIsBadLine()
const
208 return areBadLinesEnabled
209 && rasterY >= FIRST_DMA_LINE
210 && rasterY <= LAST_DMA_LINE
211 && (rasterY & 7) == yscroll;
217 inline unsigned int oldRasterY()
const
219 return (rasterY > 0 ? rasterY : maxRasters) - 1;
224 eventScheduler.cancel(*
this);
231 inline void checkVblank()
234 if (rasterY == (maxRasters - 1))
240 if (rasterY == FIRST_DMA_LINE
241 && !areBadLinesEnabled
244 areBadLinesEnabled =
true;
248 if (rasterY == LAST_DMA_LINE)
250 areBadLinesEnabled =
false;
258 rasterYIRQEdgeDetector();
259 if ((rasterY == FIRST_DMA_LINE) && !areBadLinesEnabled)
260 areBadLinesEnabled = readDEN();
263 if (evaluateIsBadLine())
276 rasterYIRQEdgeDetector();
278 if (lpAsserted && lp.retrigger())
280 activateIRQFlag(IRQ_LIGHTPEN);
289 inline void startDma()
291 if (sprites.isDma(0x01 << n))
301 if (!sprites.isDma(0x06 << n))
308 inline void startBadline()
315 MOS656X(EventScheduler &scheduler);
316 ~MOS656X() =
default;
319 virtual void interrupt(
bool state) = 0;
320 virtual void setBA(
bool state) = 0;
328 uint8_t
read(uint_least8_t addr);
338 void write(uint_least8_t addr, uint8_t data);
341 void event()
override;
363 static const char *credits();