|
|
1.1 root 1: /*
2: * UAE - The Unusable Amiga Emulator
3: *
4: * custom chip support v0.6
5: *
6: * v0.0: 950228
7: * provide DMACON/INTENA/INTREQ dummys so that KS gets the memory check
8: * right
9: * v0.1: 950304
10: * more registers (partially) implemented
11: * copper and beam position should work, so should interrupts
12: * v0.2: 950305
13: * Blitter implemented. Doesn't work.
14: * some b/w playfield support
15: * v0.3: 950306
16: * many bug fixes
17: * v0.4: 950309
18: * lots more bug fixes. A hand holding a disk appears in the X window!
19: * But it sure looks messed up.
20: * v0.5: 950311
21: * hopefully fixed all remaining blitter bugs. The hand and the disk
22: * look PERFECT!
23: * v0.6: 950312
24: * interface to disk code
25: *
26: * (c) 1995 Bernd Schmidt
27: */
28:
29: #include <iostream.h>
30: #include <iomanip.h>
31:
32: #include "amiga.h"
33: #include "memory.h"
34: #include "custom.h"
35: #include "cia.h"
36: #include "disk.h"
37: #include "xwin.h"
38:
39: static const int maxhpos = 227,maxvpos = 312;
40: static const int dskdelay = 80; // FIXME: ???
41:
42: UWORD custom64k::wget(UWORD addr)
43: {
44: UWORD (*f)() = cchiptable[(addr >> 1) & 0xFF].get;
45: if (f != 0) return (*f)();
46: else {
47: cout << "Custom read at " << hex << addr << "\n";
48: return 0;
49: }
50: }
51:
52: UBYTE custom64k::bget(UWORD addr)
53: {
54: return wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
55: }
56:
57: void custom64k::wput(UWORD addr,UWORD value)
58: {
59: void (*f)(UWORD) = cchiptable[(addr >> 1) & 0xFF].put;
60: if (f != 0) (*f)(value);
61: else {
62: cout << "Custom write " << hex << value << " at " << addr << "\n";
63: }
64: }
65:
66: void custom64k::bput(UWORD addr,UBYTE value)
67: {
68: wput(addr & 0xfffe,value << (addr & 1 ? 0 : 8)); // ??
69: }
70:
71: static void setclr(UWORD &p, UWORD val)
72: {
73: // cout << "setclr, new val ";
74: if (val & 0x8000) {
75: p |= val & 0x7FFF;
76: } else {
77: p &= ~val;
78: }
79: // cout << hex << p << "\n";
80: }
81:
82: /*
83: * hardware register values that are visible/can be written to by someone
84: */
85:
86: static UWORD dmacon,intena,intreq,adkcon;
87: static UWORD vpos, hpos, lof;
88:
89: static ULONG cop1lc,cop2lc,copcon;
90:
91: static ULONG bpl1pt,bpl2pt,bpl3pt,bpl4pt,bpl5pt,bpl6pt;
92: static UWORD bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat;
93: static UWORD bplcon0,bplcon1,bplcon2,bplcon3;
94: static UWORD diwstrt,diwstop,ddfstrt,ddfstop;
95: static WORD bpl1mod,bpl2mod;
96:
97: static UWORD bltadat,bltbdat,bltcdat,bltddat,bltafwm,bltalwm,bltsize;
98: static WORD bltamod,bltbmod,bltcmod,bltdmod;
99: static UWORD bltcon0,bltcon1;
100: static ULONG bltapt,bltbpt,bltcpt,bltdpt,bltcnxlpt,bltdnxlpt;
101:
102: static ULONG dskpt;
103: static UWORD dsklen,dsksync;
104:
105: /*
106: * "hidden" hardware registers
107: */
108:
109: static ULONG coplc;
110: static UWORD copi1,copi2;
111:
112: static enum {
113: COP_stop, COP_read, COP_wait, COP_move, COP_skip
114: } copstate;
115:
116: static UWORD vblitsize,hblitsize,blitpreva,blitprevb;
117: static UWORD blitlpos,blitashift,blitbshift,blinea,blineb;
118: static bool blitline,blitfc,blitzero,blitfill,blitife,blitdesc,blitsing;
119: static bool blitonedot,blitsign;
120: static long int bltwait;
121:
122: static enum {
123: BLT_done, BLT_init, BLT_read, BLT_work, BLT_write, BLT_next,BLT_wait
124: } bltstate;
125:
126: static UWORD plffirstline,plflastline,plffirstword,plflastword;
127:
128: static enum {
129: PF_above, PF_left, PF_within, PF_right, PF_below
130: } pfieldstate;
131:
132: static UWORD dskmfm,dskbyte,dskdmaen,dsktime;
133: static bool dsksynced;
134:
135: /*
136: * helper functions
137: */
138:
139: static void calcdiw()
140: {
141: plffirstline = diwstrt >> 8;
142: plflastline = diwstop >> 8;
143: if ((plflastline & 0x80) == 0) plflastline |= 0x100;
144: plffirstword = (ddfstrt & 0x1FC) * 4;
145: plflastword = ((ddfstop & 0x1FC)+8) *4;
146: }
147:
148: /*
149: * register functions
150: */
151:
152: static UWORD DMACONR()
153: {
154: return dmacon | (bltstate==BLT_done ? 0 : 0x4000)
155: | (blitzero ? 0x2000 : 0);
156: }
157: static UWORD INTENAR() { return intena; }
158: static UWORD INTREQR() { return intreq; }
159: static UWORD ADKCONR() { return adkcon; }
160: static UWORD VPOSR() { return (vpos >> 8) | lof; }
161: static UWORD VHPOSR() { return (vpos << 8) | hpos; }
162:
163: static void DMACON(UWORD v) { setclr(dmacon,v); dmacon &= 0x1FFF; }
164: static void INTENA(UWORD v) { setclr(intena,v); }
165: static void INTREQ(UWORD v) { setclr(intreq,v); }
166: static void ADKCON(UWORD v) { setclr(adkcon,v); }
167:
168: static void BPL1PTH(UWORD v) { bpl1pt= (bpl1pt & 0xffff) | ((ULONG)v << 16); }
169: static void BPL1PTL(UWORD v) { bpl1pt= (bpl1pt & ~0xffff) | v; }
170: static void BPL2PTH(UWORD v) { bpl2pt= (bpl2pt & 0xffff) | ((ULONG)v << 16); }
171: static void BPL2PTL(UWORD v) { bpl2pt= (bpl2pt & ~0xffff) | v; }
172: static void BPL3PTH(UWORD v) { bpl3pt= (bpl3pt & 0xffff) | ((ULONG)v << 16); }
173: static void BPL3PTL(UWORD v) { bpl3pt= (bpl3pt & ~0xffff) | v; }
174: static void BPL4PTH(UWORD v) { bpl4pt= (bpl4pt & 0xffff) | ((ULONG)v << 16); }
175: static void BPL4PTL(UWORD v) { bpl4pt= (bpl4pt & ~0xffff) | v; }
176: static void BPL5PTH(UWORD v) { bpl5pt= (bpl5pt & 0xffff) | ((ULONG)v << 16); }
177: static void BPL5PTL(UWORD v) { bpl5pt= (bpl5pt & ~0xffff) | v; }
178: static void BPL6PTH(UWORD v) { bpl6pt= (bpl6pt & 0xffff) | ((ULONG)v << 16); }
179: static void BPL6PTL(UWORD v) { bpl6pt= (bpl6pt & ~0xffff) | v; }
180:
181: static void BPLCON0(UWORD v) { bplcon0 = v; }
182: static void BPLCON1(UWORD v) { bplcon1 = v; }
183: static void BPLCON2(UWORD v) { bplcon2 = v; }
184: static void BPLCON3(UWORD v) { bplcon3 = v; }
185:
186: static void BPL1MOD(UWORD v) { bpl1mod = v; }
187: static void BPL2MOD(UWORD v) { bpl2mod = v; }
188:
189: static void BPL1DAT(UWORD v) { bpl1dat = v; }
190: static void BPL2DAT(UWORD v) { bpl2dat = v; }
191: static void BPL3DAT(UWORD v) { bpl3dat = v; }
192: static void BPL4DAT(UWORD v) { bpl4dat = v; }
193: static void BPL5DAT(UWORD v) { bpl5dat = v; }
194: static void BPL6DAT(UWORD v) { bpl6dat = v; }
195:
196: static void DIWSTRT(UWORD v) { diwstrt = v; calcdiw(); }
197: static void DIWSTOP(UWORD v) { diwstop = v; calcdiw(); }
198: static void DDFSTRT(UWORD v) { ddfstrt = v; calcdiw(); }
199: static void DDFSTOP(UWORD v) { ddfstop = v; calcdiw(); }
200:
201: static void COP1LCH(UWORD v) { cop1lc= (cop1lc & 0xffff) | ((ULONG)v << 16); }
202: static void COP1LCL(UWORD v) { cop1lc= (cop1lc & ~0xffff) | v; }
203: static void COP2LCH(UWORD v) { cop2lc= (cop2lc & 0xffff) | ((ULONG)v << 16); }
204: static void COP2LCL(UWORD v) { cop2lc= (cop2lc & ~0xffff) | v; }
205:
206: static UWORD COPJMPR1() { coplc = cop1lc; copstate = COP_read; cout << "CJMP1\n"; return 0; }
207: static UWORD COPJMPR2() { coplc = cop2lc; copstate = COP_read; cout << "CJMP2\n"; return 0; }
208: static void COPJMP1(UWORD) { coplc = cop1lc; copstate = COP_read; cout << "CJMP1\n"; }
209: static void COPJMP2(UWORD) { coplc = cop2lc; copstate = COP_read; cout << "CJMP2\n"; }
210:
211: static void BLTADAT(UWORD v) { bltadat = v; }
212: static void BLTBDAT(UWORD v) { bltbdat = v; }
213: static void BLTCDAT(UWORD v) { bltcdat = v; }
214:
215: static void BLTAMOD(UWORD v) { bltamod = v; }
216: static void BLTBMOD(UWORD v) { bltbmod = v; }
217: static void BLTCMOD(UWORD v) { bltcmod = v; }
218: static void BLTDMOD(UWORD v) { bltdmod = v; }
219:
220: static void BLTCON0(UWORD v) { bltcon0 = v; }
221: static void BLTCON1(UWORD v) { bltcon1 = v; }
222:
223: static void BLTAFWM(UWORD v) { bltafwm = v; }
224: static void BLTALWM(UWORD v) { bltalwm = v; }
225:
226: static void BLTAPTH(UWORD v) { bltapt= (bltapt & 0xffff) | ((ULONG)v << 16); }
227: static void BLTAPTL(UWORD v) { bltapt= (bltapt & ~0xffff) | (v); }
228: static void BLTBPTH(UWORD v) { bltbpt= (bltbpt & 0xffff) | ((ULONG)v << 16); }
229: static void BLTBPTL(UWORD v) { bltbpt= (bltbpt & ~0xffff) | (v); }
230: static void BLTCPTH(UWORD v) { bltcpt= (bltcpt & 0xffff) | ((ULONG)v << 16); }
231: static void BLTCPTL(UWORD v) { bltcpt= (bltcpt & ~0xffff) | (v); }
232: static void BLTDPTH(UWORD v) { bltdpt= (bltdpt & 0xffff) | ((ULONG)v << 16); }
233: static void BLTDPTL(UWORD v) { bltdpt= (bltdpt & ~0xffff) | (v); }
234: static void BLTSIZE(UWORD v) { bltsize = v; bltstate = BLT_init; }
235:
236: static void DSKSYNC(UWORD v) { dsksync = v; }
237: static void DSKDAT(UWORD v) { dskmfm = v; }
238: static void DSKPTH(UWORD v) { dskpt = (dskpt & 0xffff) | ((ULONG)v << 16); }
239: static void DSKPTL(UWORD v) { dskpt = (dskpt & ~0xffff) | (v); }
240:
241: static void DSKLEN(UWORD v)
242: {
243: if (v & 0x8000) { dskdmaen++; } else { dskdmaen = 0; }
244: dsktime = dskdelay; dsksynced = false;
245: dsklen = v;
246: }
247:
248: static UWORD DSKBYTR()
249: {
250: UWORD v = dsklen >> 1 & 0x6000;
251: v |= dskbyte;
252: dskbyte &= ~0x8000;
253: if (dsksync == dskmfm) v |= 0x1000;
254: return v;
255: }
256:
257: static UWORD DSKDATR() { return dskmfm; }
258:
259: custom64k::custom_func custom64k::functable[] = {
260: { 0x002, { &DMACONR, 0 }},
261: { 0x096, { 0, DMACON }},
262: { 0x01C, { &INTENAR, 0 }},
263: { 0x09A, { 0, INTENA }},
264: { 0x01E, { &INTREQR, 0 }},
265: { 0x09C, { 0, INTREQ }},
266: { 0x010, { &ADKCONR, 0 }},
267: { 0x09E, { 0, ADKCON }},
268:
269: { 0x006, { &VHPOSR, 0 }},
270: { 0x004, { &VPOSR, 0 }},
271:
272: { 0x080, { 0, &COP1LCH }},
273: { 0x082, { 0, &COP1LCL }},
274: { 0x084, { 0, &COP2LCH }},
275: { 0x086, { 0, &COP2LCL }},
276:
277: { 0x088, { &COPJMPR1, &COPJMP1 }},
278: { 0x08A, { &COPJMPR2, &COPJMP2 }},
279:
280: { 0x08E, { 0, &DIWSTRT }},
281: { 0x090, { 0, &DIWSTOP }},
282: { 0x092, { 0, &DDFSTRT }},
283: { 0x094, { 0, &DDFSTOP }},
284:
285: { 0x0E0, { 0, &BPL1PTH }},
286: { 0x0E2, { 0, &BPL1PTL }},
287: { 0x0E4, { 0, &BPL2PTH }},
288: { 0x0E6, { 0, &BPL2PTL }},
289: { 0x0E8, { 0, &BPL3PTH }},
290: { 0x0EA, { 0, &BPL3PTL }},
291: { 0x0EC, { 0, &BPL4PTH }},
292: { 0x0EE, { 0, &BPL4PTL }},
293: { 0x0F0, { 0, &BPL5PTH }},
294: { 0x0F2, { 0, &BPL5PTL }},
295: { 0x0F4, { 0, &BPL6PTH }},
296: { 0x0F6, { 0, &BPL6PTL }},
297:
298: { 0x100, { 0, &BPLCON0 }},
299: { 0x102, { 0, &BPLCON1 }},
300: { 0x104, { 0, &BPLCON2 }},
301: { 0x106, { 0, &BPLCON3 }},
302:
303: { 0x108, { 0, &BPL1MOD }},
304: { 0x10A, { 0, &BPL2MOD }},
305:
306: { 0x110, { 0, &BPL1DAT }},
307: { 0x112, { 0, &BPL2DAT }},
308: { 0x114, { 0, &BPL3DAT }},
309: { 0x116, { 0, &BPL4DAT }},
310: { 0x118, { 0, &BPL5DAT }},
311: { 0x11A, { 0, &BPL6DAT }},
312:
313: { 0x040, { 0, &BLTCON0 }},
314: { 0x042, { 0, &BLTCON1 }},
315:
316: { 0x044, { 0, &BLTAFWM }},
317: { 0x046, { 0, &BLTALWM }},
318:
319: { 0x064, { 0, &BLTAMOD }},
320: { 0x062, { 0, &BLTBMOD }},
321: { 0x060, { 0, &BLTCMOD }},
322: { 0x066, { 0, &BLTDMOD }},
323:
324: { 0x050, { 0, &BLTAPTH }},
325: { 0x052, { 0, &BLTAPTL }},
326: { 0x04C, { 0, &BLTBPTH }},
327: { 0x04E, { 0, &BLTBPTL }},
328: { 0x048, { 0, &BLTCPTH }},
329: { 0x04A, { 0, &BLTCPTL }},
330: { 0x054, { 0, &BLTDPTH }},
331: { 0x056, { 0, &BLTDPTL }},
332:
333: { 0x070, { 0, &BLTCDAT }},
334: { 0x072, { 0, &BLTBDAT }},
335: { 0x074, { 0, &BLTADAT }},
336:
337: { 0x058, { 0, &BLTSIZE }},
338:
339: { 0x008, { &DSKDATR, 0 }},
340: { 0x01A, { &DSKBYTR, 0 }},
341: { 0x026, { 0, &DSKDAT }},
342: { 0x024, { 0, &DSKLEN }},
343: { 0x020, { 0, &DSKPTH }},
344: { 0x022, { 0, &DSKPTL }},
345: { 0x07E, { 0, &DSKSYNC }},
346:
347: { 0xFFFF, { 0, 0 }}
348: };
349:
350: custom64k::cchipaddr *custom64k::cchiptable = 0;
351:
352: custom64k::custom64k()
353: {
354: if (!cchiptable){
355: // CUSTOM CHIP INITIALIZATION
356: // build function pointer table
357: cchiptable = new cchipaddr[256];
358: for (int i=0;i<256;i++) {
359: cchiptable[i].get = 0;
360: cchiptable[i].put = 0;
361: }
362: for(custom_func *f = functable; f->addr != 0xffff; f++){
363: cchiptable[f->addr >> 1] = f->fptrs;
364: }
365: customreset();
366: }
367: }
368:
369: void customreset()
370: {
371: // reset some values
372: vpos = hpos = lof = 0;
373: dmacon = intena = 0;
374: bltstate = BLT_done;
375: copstate = COP_stop;
376: copcon = 0;
377: dskdmaen = 0;
378: }
379:
380: static bool dmaen(UWORD dmamask)
381: {
382: return (dmamask & dmacon) && (dmacon & 0x200);
383: }
384:
385: static bool copcomp()
386: {
387: UWORD vp = vpos & ((copi2 >> 8) & 0x7F);
388: UWORD hp = hpos & (copi2 & 0xFE);
389: UWORD vcmp = copi1 >> 8;
390: UWORD hcmp = copi1 & 0xFE;
391: return (vp >= vcmp) && (hp >= hcmp) && ((copi2 & 0x8000) /*|| bfd FIXME*/);
392: }
393:
394: static void do_copper()
395: {
396: switch(copstate){
397: case COP_read:
398: if (dmaen(0x80)){
399: // cout << "copper read at " << hex << coplc << "\n";
400: copi1 = mem.get_word(coplc);
401: copi2 = mem.get_word(coplc+2);
402: coplc += 4;
403: copstate = (copi1 & 1) ? (copi2 & 1) ? COP_skip : COP_wait : COP_move;
404: }
405: break;
406: case COP_move:
407: // cout << "copper move " << hex << copi1 << " " << copi2 << "\n";
408: if (copi1 >= (copcon & 2 ? 0x40 : 0x80))
409: mem.put_word(0xDFF000+copi1,copi2);
410: copstate = COP_read; // FIXME: copdang
411: break;
412: case COP_skip:
413: if (copcomp()) coplc += 4;
414: copstate = COP_read;
415: break;
416: case COP_wait:
417: if (copcomp()) copstate = COP_read;
418: break;
419: case COP_stop:
420: break;
421: }
422: }
423:
424: static void blitter_read()
425: {
426: if (bltcon0 & 0xe00){
427: if (!dmaen(0x40)) return; // blitter stopped
428: if (!blitline){
429: if (bltcon0 & 0x800) bltadat = mem.get_word(bltapt);
430: if (bltcon0 & 0x400) bltbdat = mem.get_word(bltbpt);
431: }
432: if (bltcon0 & 0x200) bltcdat = mem.get_word(bltcpt);
433: }
434: bltstate = BLT_work;
435: }
436:
437: static void blitter_write()
438: {
439: if (bltddat) blitzero = false;
440: if (bltcon0 & 0x100){
441: if (!dmaen(0x40)) return;
442: mem.put_word(bltdpt,bltddat);
443: }
444: bltstate = BLT_next;
445: }
446:
447: static void blitter_blit()
448: {
449: UWORD blitahold,blitbhold,blitchold;
450:
451: if (blitdesc) { // aaarggh!
452: UWORD bltamask = 0xffff;
453:
454: if (!blitlpos) { bltamask &= bltafwm; }
455: if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }
456:
457: // FIXME? The following two lines are probably not 100% exact
458: blitahold = ((ULONG)((bltadat & bltamask) << 16) | blitpreva)
459: >> (16-blitashift);
460: blitbhold = ((ULONG)(bltbdat << 16) | blitprevb) >> (16-blitbshift);
461: blitchold = bltcdat;
462: } else {
463: UWORD bltamask = 0xffff;
464:
465: if (!blitlpos) { bltamask &= bltafwm; }
466: if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }
467: // FIXME? The following two lines are probably not 100% exact
468: blitahold = ((ULONG)(blitpreva << 16) | (bltadat&bltamask)) >> blitashift;
469: blitbhold = ((ULONG)(blitprevb << 16) | bltbdat) >> blitbshift;
470: blitchold = bltcdat;
471: }
472: bltddat = 0;
473: for(int i=0; i<16; i++) {
474: // oh dear, this is SLOW!
475: int minterm = ((blitahold >> 13) & 4) | ((blitbhold >> 14) & 2)
476: | ((blitchold >> 15) & 1);
477: blitahold <<= 1; blitbhold <<= 1; blitchold <<= 1;
478: if (bltcon0 & (1 << minterm))
479: bltddat |= (1 << (15-i));
480: }
481: if (blitfill){
482: UWORD fillmask = 1;
483: for (;fillmask;fillmask <<= 1){
484: UWORD tmp = bltddat;
485: if (blitfc) {
486: if (blitife) bltddat |= fillmask; else bltddat ^= fillmask;
487: }
488: if (tmp & fillmask) blitfc = !blitfc;
489: }
490: }
491: bltstate = BLT_write;
492: blitpreva = bltadat; blitprevb = bltbdat;
493: }
494:
495: static void blitter_nxblit()
496: {
497: bltstate = BLT_read;
498: if (blitdesc){
499: if (++blitlpos == hblitsize) {
500: if (--vblitsize == 0) {
501: bltstate = BLT_done; mem.put_word(0xDFF09C,0x8040);
502: }
503: blitlpos = 0;
504: if (bltcon0 & 0x800) bltapt -= 2+bltamod;
505: if (bltcon0 & 0x400) bltbpt -= 2+bltbmod;
506: if (bltcon0 & 0x200) bltcpt -= 2+bltcmod;
507: if (bltcon0 & 0x100) bltdpt -= 2+bltdmod;
508: } else {
509: if (bltcon0 & 0x800) bltapt -= 2;
510: if (bltcon0 & 0x400) bltbpt -= 2;
511: if (bltcon0 & 0x200) bltcpt -= 2;
512: if (bltcon0 & 0x100) bltdpt -= 2;
513:
514: }
515: } else {
516: if (++blitlpos == hblitsize) {
517: if (--vblitsize == 0) {
518: bltstate = BLT_done; mem.put_word(0xDFF09C,0x8040);
519: }
520: blitlpos = 0;
521: if (bltcon0 & 0x800) bltapt += 2+bltamod;
522: if (bltcon0 & 0x400) bltbpt += 2+bltbmod;
523: if (bltcon0 & 0x200) bltcpt += 2+bltcmod;
524: if (bltcon0 & 0x100) bltdpt += 2+bltdmod;
525: } else {
526: if (bltcon0 & 0x800) bltapt += 2;
527: if (bltcon0 & 0x400) bltbpt += 2;
528: if (bltcon0 & 0x200) bltcpt += 2;
529: if (bltcon0 & 0x100) bltdpt += 2;
530: }
531: }
532: }
533:
534: static void blitter_line_incx(int =1)
535: {
536: blinea >>= 1;
537: if (!blinea) {
538: blinea = 0x8000;
539: bltcnxlpt += 2;
540: bltdnxlpt += 2;
541: }
542: }
543:
544: static void blitter_line_decx(int shm=1)
545: {
546: if (shm) blineb = (blineb << 2) | (blineb >> 14);
547: blinea <<= 1;
548: if (!blinea) {
549: blinea = 1;
550: bltcnxlpt -= 2;
551: bltdnxlpt -= 2;
552: }
553: }
554:
555: static void blitter_line_decy(int shm=1)
556: {
557: if (shm) blineb = (blineb >> 1) | (blineb << 15);
558: bltcnxlpt -= bltcmod;
559: bltdnxlpt -= bltcmod; // ??? ??? ??? am I wrong or doesn't KS1.3 set bltdmod?
560: blitonedot = 0;
561: }
562:
563: static void blitter_line_incy(int shm=1)
564: {
565: if (shm) blineb = (blineb >> 1) | (blineb << 15);
566: bltcnxlpt += bltcmod;
567: bltdnxlpt += bltcmod; // ??? ??? ???
568: blitonedot = 0;
569: }
570:
571: static void blitter_line()
572: {
573: bltddat = 0;
574: UWORD blitahold = blinea, blitbhold = blineb, blitchold = bltcdat;
575: if (blitsing && blitonedot) blitahold = 0;
576: blitonedot = 1;
577: for(int i=0; i<16; i++) {
578: int minterm = ((blitahold >> 13) & 4) | ((blitbhold >> 14) & 2)
579: | ((blitchold >> 15) & 1);
580: blitahold <<= 1; blitbhold <<= 1; blitchold <<= 1;
581: if (bltcon0 & (1 << minterm)) bltddat |= (1 << (15-i));
582: }
583: if (!blitsign){
584: bltapt += (WORD)bltamod;
585: if (bltcon1 & 0x10){
586: if (bltcon1 & 0x8) blitter_line_decy(0); else blitter_line_incy(0);
587: } else {
588: if (bltcon1 & 0x8) blitter_line_decx(0); else blitter_line_incx(0);
589: }
590: } else {
591: bltapt += (WORD)bltbmod;
592: }
593: if (bltcon1 & 0x10){
594: if (bltcon1 & 0x4) blitter_line_decx(); else blitter_line_incx();
595: } else {
596: if (bltcon1 & 0x4) blitter_line_decy(); else blitter_line_incy();
597: }
598: blitsign = 0 > (WORD)bltapt;
599: bltstate = BLT_write;
600: }
601:
602: static void blitter_nxline()
603: {
604: if (--vblitsize == 0) {
605: bltstate = BLT_wait; bltwait = /*0xE2*31*/2; mem.put_word(0xDFF09C,0x8040);
606: } else {
607: bltstate = BLT_read;
608: bltcpt = bltcnxlpt;
609: bltdpt = bltdnxlpt;
610: }
611: }
612:
613: static void do_blitter()
614: {
615: switch(bltstate) {
616: case BLT_init:
617: cout << "Blit started!";
618: vblitsize = bltsize >> 6;
619: hblitsize = bltsize & 0x3F;
620: if (!vblitsize) vblitsize = 1024;
621: if (!hblitsize) hblitsize = 64;
622: blitlpos = 0;
623: blitzero = true; blitpreva = blitprevb = 0;
624: blitline = bltcon1 & 1;
625: blitashift = bltcon0 >> 12; blitbshift = bltcon1 >> 12;
626:
627: if (blitline) {
628: cout << " line\n";
629: bltcnxlpt = bltcpt;
630: bltdnxlpt = bltdpt;
631: blitsing = bltcon1 & 0x2;
632: blinea = bltadat >> blitashift;
633: blineb = (bltbdat >> blitbshift) | (bltbdat << (16-blitbshift));
634: blitsign = bltcon1 & 0x40;
635: blitonedot = false;
636: bltamod &= 0xfffe; bltbmod &= 0xfffe; bltapt &= 0xfffe;
637: } else {
638: blitfc = bltcon1 & 0x4;
639: blitife = bltcon1 & 0x8;
640: blitfill = bltcon1 & 0x18;
641: if (blitfill) cout << " fill";
642: if ((bltcon1 & 0x18) == 0x18) cout << "STRANGE FILL MODE ALERT!!\n";
643: blitdesc = bltcon1 & 0x2;
644: if(blitdesc) cout << " desc";
645: cout << "\n";
646: }
647: bltstate = BLT_read;
648: break;
649: case BLT_read:
650: blitter_read();
651: break;
652: case BLT_write:
653: blitter_write();
654: break;
655: case BLT_work:
656: if (blitline) blitter_line(); else blitter_blit();
657: break;
658: case BLT_next:
659: if (blitline) blitter_nxline(); else blitter_nxblit();
660: break;
661: case BLT_wait:
662: if (!--bltwait) bltstate = BLT_done;
663: break;
664: case BLT_done:
665: break;
666: }
667: }
668:
669: // note: fall-throughs in all playfield functions
670:
671: static void pfield_fetchdata()
672: {
673: if (/*dmaen(0x100)*/ 1) {
674: switch(bplcon0 & 0x7000){
675: case 0x6000:
676: bpl6dat = mem.get_word(bpl6pt); bpl6pt += 2;
677: case 0x5000:
678: bpl5dat = mem.get_word(bpl5pt); bpl5pt += 2;
679: case 0x4000:
680: bpl4dat = mem.get_word(bpl4pt); bpl4pt += 2;
681: case 0x3000:
682: bpl3dat = mem.get_word(bpl3pt); bpl3pt += 2;
683: case 0x2000:
684: bpl2dat = mem.get_word(bpl2pt); bpl2pt += 2;
685: case 0x1000:
686: bpl1dat = mem.get_word(bpl1pt); bpl1pt += 2;
687: }
688: }
689: }
690:
691: static void pfield_hsync()
692: {
693: if (/*dmaen(0x100)*/ 1) {
694: switch(bplcon0 & 0x7000){
695: case 0x6000:
696: bpl6pt += bpl2mod;
697: case 0x5000:
698: bpl5pt += bpl1mod;
699: case 0x4000:
700: bpl4pt += bpl2mod;
701: case 0x3000:
702: bpl3pt += bpl1mod;
703: case 0x2000:
704: bpl2pt += bpl2mod;
705: case 0x1000:
706: bpl1pt += bpl1mod;
707: }
708: }
709: }
710:
711: static UWORD pfield_nextpixel()
712: {
713: UWORD tmp = 0;
714: switch(bplcon0 & 0x7000){
715: case 0x6000:
716: tmp = (bpl6dat >> 15); bpl6dat <<= 1;
717: case 0x5000:
718: tmp = (tmp << 1) | (bpl5dat >> 15); bpl5dat <<= 1;
719: case 0x4000:
720: tmp = (tmp << 1) | (bpl4dat >> 15); bpl4dat <<= 1;
721: case 0x3000:
722: tmp = (tmp << 1) | (bpl3dat >> 15); bpl3dat <<= 1;
723: case 0x2000:
724: tmp = (tmp << 1) | (bpl2dat >> 15); bpl2dat <<= 1;
725: case 0x1000:
726: tmp = (tmp << 1) | (bpl1dat >> 15); bpl1dat <<= 1;
727: }
728: return tmp;
729: }
730:
731: static void do_playfield()
732: {
733: int xpos = hpos * 4;
734: if (vpos >= plffirstline && vpos < plflastline){
735: if (xpos >= plffirstword && xpos < plflastword){
736: if (bplcon0 & 0x8000){
737: if ((xpos & 0xF) == 0){
738: pfield_fetchdata();
739: for(int i=0;i<16;i++){
740: UWORD pixel = pfield_nextpixel() & 3;
741: int col;
742: if (pixel == 3) col = 1;
743: else if (pixel == 0) col = 0;
744: else col = (pixel & 1) == ((xpos ^ vpos) & 1);
745: DrawPixel(xpos+i,vpos,col);
746: }
747: }
748: } else {
749: if ((xpos & 0x1F) == 0){
750: pfield_fetchdata();
751: for(int i=0;i<16;i++){
752: UWORD pixel = pfield_nextpixel() & 3;
753: int col;
754: if (pixel == 3) col = 1;
755: else if (pixel == 0) col = 0;
756: else col = (pixel & 1) == ((xpos ^ vpos) & 1);
757: DrawPixel(xpos+i*2,vpos,col);
758: DrawPixel(xpos+i*2+1,vpos,col);
759: }
760: }
761: }
762: }
763: }
764: }
765:
766: static void do_disk()
767: {
768: if (dskdmaen > 1 && dmaen(0x10)){
769: if (--dsktime == 0) {
770: dsktime = dskdelay;
771: if (dsklen & 0x4000){
772: // write
773: } else {
774: DISK_GetData(dskmfm,dskbyte);
775: dskbyte |= 0x8000;
776: if (dskmfm == dsksync) {
777: mem.put_word(0xDFF09C,0x9000);
778: dsksynced = true;
779: }
780: if (dsksynced || !(adkcon & 0x400)){
781: mem.put_word(dskpt,dskmfm); dskpt+=2;
782: }
783: }
784: }
785: }
786: }
787:
788: static void do_vsync()
789: {
790: // intreq |= 1 << i_vertb;
791: mem.put_word(0xDFF09C,0x8020);
792: lof ^= 1;
793: // if (copstate != COP_stop)
794: mem.put_word(0xDFF088,0); // restart copper
795: CIA_vsync();
796: }
797:
798: void clockcycle()
799: {
800: if (++hpos == maxhpos){
801: hpos = 0; CIA_hsync();
802: pfield_hsync();
803: if (++vpos == maxvpos) {
804: vpos = 0;
805: do_vsync();
806: }
807: }
808: do_copper();
809: do_playfield();
810: do_blitter();
811: do_disk();
812: CIA_cycle();
813: }
814:
815: void dumpcustom()
816: {
817: cout << "DMACON: " << DMACONR() << " INTENA: " << intena << " INTREQ: "
818: << intreq << " VPOS: " << vpos << " HPOS: " << hpos << "\n";
819: }
820:
821: int intlev()
822: {
823: UWORD imask = intreq & intena;
824: if (imask && (intena & 0x4000)){
825: // cout << hex << "intreq " << intreq << " intena " << intena <<"\n";
826: if (imask & 0x2000) return 6;
827: if (imask & 0x1800) return 5;
828: if (imask & 0x0780) return 4;
829: if (imask & 0x0070) return 3;
830: if (imask & 0x0008) return 2;
831: if (imask & 0x0007) return 1;
832: }
833: return -1;
834: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.