|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Custom chip emulation
5: *
6: * (c) 1995 Bernd Schmidt, Alessandro Bissacco
7: */
8:
9: #include <ctype.h>
10: #ifdef __unix
11: #include <sys/time.h>
12: #include <unistd.h>
13: #endif
14: #include <stdio.h>
15: #include <string.h>
16: #include <stdlib.h>
17: #include <assert.h>
18:
19: #include "config.h"
20: #include "amiga.h"
21: #include "options.h"
22: #include "events.h"
23: #include "memory.h"
24: #include "custom.h"
25: #include "cia.h"
26: #include "disk.h"
27: #include "blit.h"
28: #include "xwin.h"
29: #include "os.h"
30:
31: #define DMA_AUD0 0x0001
32: #define DMA_AUD1 0x0002
33: #define DMA_AUD2 0x0004
34: #define DMA_AUD3 0x0008
35: #define DMA_DISK 0x0010
36: #define DMA_SPRITE 0x0020
37: #define DMA_BLITTER 0x0040
38: #define DMA_COPPER 0x0080
39: #define DMA_BITPLANE 0x0100
40: #define DMA_BLITPRI 0x0400
41:
42: /* These are default values for mouse emulation.
43: * The first two are default values for mstepx and mstepy.
44: * The second line set the orizontal and vertical offset for amiga and X
45: * pointer matching
46: */
47:
48: #define defstepx (1<<16)
49: #define defstepy (1<<16)
50: #ifndef __mac__
51: #define defxoffs 0
52: #define defyoffs 0
53: #else
54: #define defxoffs 210
55: #define defyoffs 85
56: #endif
57:
58: /* Values below define mouse auto calibration process.
59: * They are not critical, change them if you want.
60: * The most important is calweight, which sets mouse adjustement rate */
61:
62: static const int docal = 60, xcaloff = 40, ycaloff = 20;
63: static const int calweight = 3;
64:
65: static int lastsampledmx, lastsampledmy;
66:
67: /*
68: * Events
69: */
70:
71: unsigned long int cycles, nextevent, nextev_count, specialflags;
72: int vpos;
73: UWORD lof;
74:
75: struct ev eventtab[ev_max];
76:
77: bool copper_active;
78:
79: static const int maxhpos = 227,maxvpos = 312;
80: static const int dskdelay = 2; /* FIXME: ??? */
81: static const int minfirstline = 29;
82:
83: /*
84: * hardware register values that are visible/can be written to by someone
85: */
86:
87: static UWORD cregs[256];
88:
89: static UWORD dmacon,intena,intreq,adkcon;
90:
91: static ULONG cop1lc,cop2lc,copcon;
92:
93: static CPTR bpl1pt,bpl2pt,bpl3pt,bpl4pt,bpl5pt,bpl6pt;
94: static ULONG bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat;
95: static UWORD bplcon0,bplcon1,bplcon2,bplcon3;
96: static UWORD diwstrt,diwstop,ddfstrt,ddfstop;
97: static WORD bpl1mod,bpl2mod;
98:
99: static UWORD sprdata[8], sprdatb[8], sprctl[8], sprpos[8];
100: static ULONG sprpt[8];
101: static bool sprarmed[8], sprptset[8];
102: /* Kludge. FIXME: How does sprite restart after vsync work? */
103: static int spron[8];
104:
105: static UWORD bltadat,bltbdat,bltcdat,bltddat,bltafwm,bltalwm,bltsize;
106: static WORD bltamod,bltbmod,bltcmod,bltdmod;
107: static UWORD bltcon0,bltcon1;
108: static ULONG bltapt,bltbpt,bltcpt,bltdpt,bltcnxlpt,bltdnxlpt;
109:
110: static ULONG dskpt;
111: static UWORD dsklen,dsksync;
112:
113: static int joy0x, joy1x, joy0y, joy1y;
114: static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl;
115: static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs;
116: static int sprvbfl;
117:
118: static enum { normal_mouse, dont_care_mouse, follow_mouse} mousestate;
119:
120: xcolnr acolors[64];
121: UWORD color_regs[32];
122:
123: /*
124: * "hidden" hardware registers
125: */
126:
127: static int dblpf_ind1[64], dblpf_ind2[64];
128:
129: static ULONG coplc;
130: static UWORD copi1,copi2;
131:
132: static enum {
133: COP_stop, COP_read, COP_wait, COP_move, COP_skip
134: } copstate;
135:
136: static UWORD vblitsize,hblitsize,blitpreva,blitprevb;
137: static UWORD blitlpos,blitashift,blitbshift,blinea,blineb;
138: static bool blitline,blitfc,blitzero,blitfill,blitife,blitdesc,blitsing;
139: static bool blitonedot,blitsign;
140: static long int bltwait;
141:
142: static int dsklength;
143:
144: static enum {
145: BLT_done, BLT_init, BLT_read, BLT_work, BLT_write, BLT_next
146: } bltstate;
147:
148: static int plffirstline,plflastline,plfstrt,plfstop,plflinelen;
149: static int diwfirstword,diwlastword;
150: static int plf1pri, plf2pri;
151:
152: int dskdmaen; /* used in cia.c */
153: static UWORD dskmfm,dskbyte,dsktime;
154: static bool dsksynced;
155:
156: static int bpldelay1;
157: static int bpldelay2;
158: static bool bplhires;
159: static int bplplanecnt;
160:
161: static bool pfield_fullline,pfield_linedone;
162: static bool pfield_linedmaon;
163: static int pfield_lastpart_hpos;
164:
165: unsigned char apixels[1000]; /* includes a lot of safety padding */
166: char spixels[1000]; /* for sprites */
167: char spixstate[1000]; /* more sprites */
168:
169: /*
170: * Statistics
171: */
172:
173: static unsigned long int msecs = 0, frametime = 0, timeframes = 0;
174: static unsigned long int seconds_base;
175: bool bogusframe;
176:
177: /*
178: * helper functions
179: */
180:
181: static void pfield_doline_slow(int);
182: static void pfield_doline(void);
183: static void pfield_hsync(int);
184:
185: bool inhibit_frame;
186: static int framecnt = 0;
187:
188: static __inline__ void count_frame(void)
189: {
190: if (inhibit_frame)
191: framecnt = 1;
192: else {
193: framecnt++;
194: if (framecnt == framerate)
195: framecnt = 0;
196: }
197: }
198:
199: static __inline__ void setclr(UWORD *p, UWORD val)
200: {
201: if (val & 0x8000) {
202: *p |= val & 0x7FFF;
203: } else {
204: *p &= ~val;
205: }
206: }
207:
208: bool dmaen(UWORD dmamask)
209: {
210: return (dmamask & dmacon) && (dmacon & 0x200);
211: }
212:
213: static __inline__ int current_hpos(void)
214: {
215: return cycles - eventtab[ev_hsync].oldcycles;
216: }
217:
218: static void calcdiw(void)
219: {
220: diwfirstword = (diwstrt & 0xFF) * 2 - 0x60;
221: diwlastword = (diwstop & 0xFF) * 2 + 0x200 - 0x60;
222: if (diwfirstword < 0) diwfirstword = 0;
223:
224: plffirstline = diwstrt >> 8;
225: plflastline = diwstop >> 8;
226: #if 0
227: /* This happens far too often. */
228: if (plffirstline < minfirstline) {
229: fprintf(stderr, "Warning: Playfield begins before line %d!\n", minfirstline);
230: plffirstline = minfirstline;
231: }
232: #endif
233: if ((plflastline & 0x80) == 0) plflastline |= 0x100;
234: #if 0 /* Turrican does this */
235: if (plflastline > 313) {
236: fprintf(stderr, "Warning: Playfield out of range!\n");
237: plflastline = 313;
238: }
239: #endif
240: plfstrt = ddfstrt;
241: plfstop = ddfstop;
242: if (plfstrt < 0x18) plfstrt = 0x18;
243: if (plfstop > 0xD8) plfstop = 0xD8;
244: if (plfstrt > plfstop) plfstrt = plfstop;
245:
246: /*
247: * Prize question: What are the next lines supposed to be?
248: * I can't seem to get it right.
249: */
250: #if 0
251: /* Pretty good guess, but wrong. */
252: plflinelen = (plfstop-plfstrt+15) & ~7;
253: plfstrt &= ~(bplhires ? 3 : 7);
254: plfstop &= ~(bplhires ? 3 : 7);
255: #endif
256: plfstrt &= ~(bplhires ? 3 : 3);
257: plfstop &= ~(bplhires ? 3 : 3);
258: plflinelen = (plfstop-plfstrt+15) & ~7;
259: }
260:
261: static void pfield_may_need_update(bool colreg)
262: {
263: int i;
264:
265: /* Ignore, if this happened before or after the DDF window */
266: if (framecnt != 0 || !pfield_linedmaon || current_hpos() <= plfstrt
267: || vpos < plffirstline || vpos >= plflastline)
268: {
269: return;
270: }
271: /*
272: * If a color reg was modified, it is only important if we are within
273: * the DIW.
274: */
275: if (current_hpos() <= (diwfirstword+0x60)/4 && colreg)
276: return;
277:
278: /*
279: * If we are past the DDF window, me might as well draw the complete
280: * line now.
281: */
282: if (current_hpos() > plfstrt + plflinelen && pfield_fullline) {
283: if (!pfield_linedone)
284: pfield_doline();
285: pfield_linedone = true;
286: return;
287: }
288:
289: if (pfield_fullline) {
290: pfield_lastpart_hpos = 0;
291: memset(apixels, 0, sizeof(apixels));
292: pfield_fullline = false;
293: } else {
294: assert(pfield_lastpart_hpos <= current_hpos());
295: }
296: for (i = pfield_lastpart_hpos; i < current_hpos(); i++) {
297: pfield_doline_slow(i);
298: }
299: pfield_lastpart_hpos = current_hpos();
300: }
301:
302: /* Apparently, the DMA bit is tested by the hardware at some point,
303: * presumably at the ddfstart position, to determine whether it
304: * ought to draw the line.
305: * This is probably not completely correct, but should not matter
306: * very much.
307: */
308: static void pfield_calclinedma(void)
309: {
310: if (current_hpos() >= plfstrt)
311: return;
312:
313: pfield_linedmaon = dmaen(DMA_BITPLANE);
314: }
315:
316: /*
317: * register functions
318: */
319:
320: static UWORD DMACONR(void)
321: {
322: return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
323: | (blitzero ? 0x2000 : 0));
324: }
325: static UWORD INTENAR(void) { return intena; }
326: static UWORD INTREQR(void) { return intreq; }
327: static UWORD ADKCONR(void) { return adkcon; }
328: static UWORD VPOSR(void) { return (vpos >> 8) | lof; }
329: static void VPOSW(UWORD v) { lof = v & 0x8000; }
330: static UWORD VHPOSR(void) { return (vpos << 8) | current_hpos(); }
331:
332: static void COP1LCH(UWORD v) { cop1lc= (cop1lc & 0xffff) | ((ULONG)v << 16); }
333: static void COP1LCL(UWORD v) { cop1lc= (cop1lc & ~0xffff) | v; }
334: static void COP2LCH(UWORD v) { cop2lc= (cop2lc & 0xffff) | ((ULONG)v << 16); }
335: static void COP2LCL(UWORD v) { cop2lc= (cop2lc & ~0xffff) | v; }
336:
337: static void COPJMP1(UWORD a)
338: {
339: coplc = cop1lc; copstate = COP_read;
340: eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
341: eventtab[ev_copper].evtime = 4; events_schedule();
342: copper_active = true;
343: }
344: static void COPJMP2(UWORD a)
345: {
346: coplc = cop2lc; copstate = COP_read;
347: eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
348: eventtab[ev_copper].evtime = 4; events_schedule();
349: copper_active = true;
350: }
351:
352: static void DMACON(UWORD v)
353: {
354: UWORD oldcon = dmacon;
355: setclr(&dmacon,v); dmacon &= 0x1FFF;
356: pfield_calclinedma();
357:
358: if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) {
359: COPJMP1(0); /* @@@ not sure how this works */
360: }
361: if (copper_active && !eventtab[ev_copper].active) {
362: eventtab[ev_copper].active = true;
363: eventtab[ev_copper].oldcycles = cycles;
364: eventtab[ev_copper].evtime = 1;
365: events_schedule();
366: }
367: }
368: static void INTENA(UWORD v) { setclr(&intena,v); specialflags |= SPCFLAG_INT; }
369: static void INTREQ(UWORD v) { setclr(&intreq,v); specialflags |= SPCFLAG_INT; }
370: static void ADKCON(UWORD v) { setclr(&adkcon,v); }
371:
372: static void BPL1PTH(UWORD v) { bpl1pt= (bpl1pt & 0xffff) | ((ULONG)v << 16); }
373: static void BPL1PTL(UWORD v) { bpl1pt= (bpl1pt & ~0xffff) | v; }
374: static void BPL2PTH(UWORD v) { bpl2pt= (bpl2pt & 0xffff) | ((ULONG)v << 16); }
375: static void BPL2PTL(UWORD v) { bpl2pt= (bpl2pt & ~0xffff) | v; }
376: static void BPL3PTH(UWORD v) { bpl3pt= (bpl3pt & 0xffff) | ((ULONG)v << 16); }
377: static void BPL3PTL(UWORD v) { bpl3pt= (bpl3pt & ~0xffff) | v; }
378: static void BPL4PTH(UWORD v) { bpl4pt= (bpl4pt & 0xffff) | ((ULONG)v << 16); }
379: static void BPL4PTL(UWORD v) { bpl4pt= (bpl4pt & ~0xffff) | v; }
380: static void BPL5PTH(UWORD v) { bpl5pt= (bpl5pt & 0xffff) | ((ULONG)v << 16); }
381: static void BPL5PTL(UWORD v) { bpl5pt= (bpl5pt & ~0xffff) | v; }
382: static void BPL6PTH(UWORD v) { bpl6pt= (bpl6pt & 0xffff) | ((ULONG)v << 16); }
383: static void BPL6PTL(UWORD v) { bpl6pt= (bpl6pt & ~0xffff) | v; }
384:
385: /*
386: * I've seen the listing of an example program that changes
387: * from lo- to hires while a line is being drawn. That's
388: * awful, but we want to emulate it.
389: */
390: static void BPLCON0(UWORD v)
391: {
392: pfield_may_need_update(false);
393: bplcon0 = v;
394: bplhires = (bplcon0 & 0x8000) == 0x8000;
395: bplplanecnt = (bplcon0 & 0x7000) >> 12;
396: calcdiw(); /* This should go away. */
397: }
398: static void BPLCON1(UWORD v)
399: {
400: pfield_may_need_update(false);
401: bplcon1 = v;
402: bpldelay1 = bplcon1 & 0xF;
403: bpldelay2 = (bplcon1 >> 4) & 0xF;
404: }
405: static void BPLCON2(UWORD v)
406: {
407: pfield_may_need_update(false);
408: bplcon2 = v;
409: plf1pri = 1 << 2*(v & 7);
410: plf2pri = 1 << 2*((v>>3) & 7);
411: }
412: static void BPLCON3(UWORD v) { pfield_may_need_update(false); bplcon3 = v; }
413:
414: static void BPL1MOD(UWORD v) { pfield_may_need_update(false); bpl1mod = v; }
415: static void BPL2MOD(UWORD v) { pfield_may_need_update(false); bpl2mod = v; }
416:
417: static void BPL1DAT(UWORD v) { bpl1dat = v; }
418: static void BPL2DAT(UWORD v) { bpl2dat = v; }
419: static void BPL3DAT(UWORD v) { bpl3dat = v; }
420: static void BPL4DAT(UWORD v) { bpl4dat = v; }
421: static void BPL5DAT(UWORD v) { bpl5dat = v; }
422: static void BPL6DAT(UWORD v) { bpl6dat = v; }
423:
424: /* We call pfield_may_need_update() from here. Actually,
425: * I have no idea what happens if someone changes ddf or
426: * diw mid-line, and I don't really want to know. I doubt
427: * that this sort of thing was ever used to create a
428: * useful effect.
429: */
430: static void DIWSTRT(UWORD v) { pfield_may_need_update(false); diwstrt = v; calcdiw(); }
431: static void DIWSTOP(UWORD v) { pfield_may_need_update(false); diwstop = v; calcdiw(); }
432: static void DDFSTRT(UWORD v) { pfield_may_need_update(false); ddfstrt = v; calcdiw(); }
433: static void DDFSTOP(UWORD v) { pfield_may_need_update(false); ddfstop = v; calcdiw(); }
434:
435: static void BLTADAT(UWORD v) { bltadat = v; }
436: static void BLTBDAT(UWORD v) { bltbdat = v; }
437: static void BLTCDAT(UWORD v) { bltcdat = v; }
438:
439: static void BLTAMOD(UWORD v) { bltamod = v; }
440: static void BLTBMOD(UWORD v) { bltbmod = v; }
441: static void BLTCMOD(UWORD v) { bltcmod = v; }
442: static void BLTDMOD(UWORD v) { bltdmod = v; }
443:
444: static void BLTCON0(UWORD v) { bltcon0 = v; }
445: static void BLTCON1(UWORD v) { bltcon1 = v; }
446:
447: static void BLTAFWM(UWORD v) { bltafwm = v; }
448: static void BLTALWM(UWORD v) { bltalwm = v; }
449:
450: static void BLTAPTH(UWORD v) { bltapt= (bltapt & 0xffff) | ((ULONG)v << 16); }
451: static void BLTAPTL(UWORD v) { bltapt= (bltapt & ~0xffff) | (v); }
452: static void BLTBPTH(UWORD v) { bltbpt= (bltbpt & 0xffff) | ((ULONG)v << 16); }
453: static void BLTBPTL(UWORD v) { bltbpt= (bltbpt & ~0xffff) | (v); }
454: static void BLTCPTH(UWORD v) { bltcpt= (bltcpt & 0xffff) | ((ULONG)v << 16); }
455: static void BLTCPTL(UWORD v) { bltcpt= (bltcpt & ~0xffff) | (v); }
456: static void BLTDPTH(UWORD v) { bltdpt= (bltdpt & 0xffff) | ((ULONG)v << 16); }
457: static void BLTDPTL(UWORD v) { bltdpt= (bltdpt & ~0xffff) | (v); }
458: static void BLTSIZE(UWORD v) { bltsize = v; bltstate = BLT_init; specialflags |= SPCFLAG_BLIT; }
459:
460: static void SPRxCTL(UWORD v, int num) { pfield_may_need_update(false); sprctl[num] = v; sprarmed[num] = false; spron[num] |= 2; }
461: static void SPRxPOS(UWORD v, int num) { pfield_may_need_update(false); sprpos[num] = v; }
462: static void SPRxDATA(UWORD v, int num) { pfield_may_need_update(false); sprdata[num] = v; sprarmed[num] = true; }
463: static void SPRxDATB(UWORD v, int num) { pfield_may_need_update(false); sprdatb[num] = v; }
464: static void SPRxPTH(UWORD v, int num) { sprpt[num] &= 0xffff; sprpt[num] |= (ULONG)v << 16; spron[num] |= 1; }
465: static void SPRxPTL(UWORD v, int num) { sprpt[num] &= ~0xffff; sprpt[num] |= v; spron[num] |= 1; }
466:
467: static void COLOR(UWORD v, int num)
468: {
469: pfield_may_need_update(true);
470: color_regs[num] = v;
471: acolors[num] = xcolors[v];
472: acolors[num+32] = xcolors[(v >> 1) & 0x777];
473: }
474:
475: static void DSKSYNC(UWORD v) { dsksync = v; }
476: static void DSKDAT(UWORD v) { dskmfm = v; }
477: static void DSKPTH(UWORD v) { dskpt = (dskpt & 0xffff) | ((ULONG)v << 16); }
478: static void DSKPTL(UWORD v) { dskpt = (dskpt & ~0xffff) | (v); }
479:
480: static void DSKLEN(UWORD v)
481: {
482: if (v & 0x8000) { dskdmaen++; } else { dskdmaen = 0; }
483: dsktime = dskdelay; dsksynced = false;
484: dsklen = dsklength = v; dsklength &= 0x3fff;
485: if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) {
486: printf("Non-standard sync: %04x len: %x\n", dsksync, dsklength);
487: }
488: if (dsklen & 0x4000) DISK_InitWrite();
489: if (dskdmaen) specialflags |= SPCFLAG_DISK;
490: }
491:
492: static UWORD DSKBYTR(void)
493: {
494: UWORD v = (dsklen >> 1) & 0x6000;
495: v |= dskbyte;
496: dskbyte &= ~0x8000;
497: if (dsksync == dskmfm) v |= 0x1000;
498: return v;
499: }
500:
501: static UWORD DSKDATR(void) { return dskmfm; }
502: static UWORD POTGOR(void)
503: {
504: if (!buttonstate[2]) {
505: return 0xffff;
506: } else {
507: return 0xbbff;
508: }
509: }
510:
511: static UWORD JOY0DAT(void) { return joy0x + (joy0y << 8); }
512: static UWORD JOY1DAT(void)
513: {
514: #ifdef HAVE_JOYSTICK
515: UWORD dir;
516: bool button;
517: read_joystick(&dir, &button);
518: buttonstate[1] = button;
519: return dir;
520: #else
521: return joy1x + (joy1y << 8);
522: #endif
523: }
524: static void JOYTEST(UWORD v)
525: {
526: joy0x = joy1x = v & 0xFC;
527: joy0y = joy1y = (v >> 8) & 0xFC;
528: }
529: static void AUD0LCH(UWORD v) { audlc[0] = (audlc[0] & 0xffff) | ((ULONG)v << 16); }
530: static void AUD0LCL(UWORD v) { audlc[0] = (audlc[0] & ~0xffff) | v; }
531: static void AUD1LCH(UWORD v) { audlc[1] = (audlc[1] & 0xffff) | ((ULONG)v << 16); }
532: static void AUD1LCL(UWORD v) { audlc[1] = (audlc[1] & ~0xffff) | v; }
533: static void AUD2LCH(UWORD v) { audlc[2] = (audlc[2] & 0xffff) | ((ULONG)v << 16); }
534: static void AUD2LCL(UWORD v) { audlc[2] = (audlc[2] & ~0xffff) | v; }
535: static void AUD3LCH(UWORD v) { audlc[3] = (audlc[3] & 0xffff) | ((ULONG)v << 16); }
536: static void AUD3LCL(UWORD v) { audlc[3] = (audlc[3] & ~0xffff) | v; }
537: static void AUD0PER(UWORD v) { audper[0] = v; }
538: static void AUD1PER(UWORD v) { audper[1] = v; }
539: static void AUD2PER(UWORD v) { audper[2] = v; }
540: static void AUD3PER(UWORD v) { audper[3] = v; }
541: static void AUD0VOL(UWORD v) { audvol[0] = v; }
542: static void AUD1VOL(UWORD v) { audvol[1] = v; }
543: static void AUD2VOL(UWORD v) { audvol[2] = v; }
544: static void AUD3VOL(UWORD v) { audvol[3] = v; }
545: static void AUD0LEN(UWORD v) { audlen[0] = v; }
546: static void AUD1LEN(UWORD v) { audlen[1] = v; }
547: static void AUD2LEN(UWORD v) { audlen[2] = v; }
548: static void AUD3LEN(UWORD v) { audlen[3] = v; }
549:
550: /* Custom chip memory bank */
551:
552: static ULONG custom_lget(CPTR) REGPARAM;
553: static UWORD custom_wget(CPTR) REGPARAM;
554: static UBYTE custom_bget(CPTR) REGPARAM;
555: static void custom_lput(CPTR, ULONG) REGPARAM;
556: static void custom_wput(CPTR, UWORD) REGPARAM;
557: static void custom_bput(CPTR, UBYTE) REGPARAM;
558:
559: addrbank custom_bank = {
560: custom_lget, custom_wget, custom_bget,
561: custom_lput, custom_wput, custom_bput,
562: default_xlate, default_check
563: };
564:
565: UWORD custom_wget(CPTR addr)
566: {
567: #ifdef DUALCPU
568: customacc = true;
569: #endif
570: switch(addr & 0x1FE) {
571: case 0x002: return DMACONR();
572: case 0x004: return VPOSR();
573: case 0x006: return VHPOSR();
574:
575: case 0x008: return DSKDATR();
576: case 0x016: return POTGOR();
577: case 0x01A: return DSKBYTR();
578: case 0x01C: return INTENAR();
579: case 0x01E: return INTREQR();
580: case 0x010: return ADKCONR();
581: case 0x00A: return JOY0DAT();
582: case 0x00C: return JOY1DAT();
583: default:
584: custom_wput(addr,0);
585: return 0xffff;
586: }
587: }
588:
589: UBYTE custom_bget(CPTR addr)
590: {
591: return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
592: }
593:
594: ULONG custom_lget(CPTR addr)
595: {
596: return ((ULONG)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe);
597: }
598:
599: void custom_wput(CPTR addr, UWORD value)
600: {
601: #ifdef DUALCPU
602: customacc = true;
603: #endif
604: addr &= 0x1FE;
605: cregs[addr>>1] = value;
606: switch(addr) {
607: case 0x020: DSKPTH(value); break;
608: case 0x022: DSKPTL(value); break;
609: case 0x024: DSKLEN(value); break;
610: case 0x026: DSKDAT(value); break;
611:
612: case 0x02A: VPOSW(value); break;
613:
614: case 0x040: BLTCON0(value); break;
615: case 0x042: BLTCON1(value); break;
616:
617: case 0x044: BLTAFWM(value); break;
618: case 0x046: BLTALWM(value); break;
619:
620: case 0x050: BLTAPTH(value); break;
621: case 0x052: BLTAPTL(value); break;
622: case 0x04C: BLTBPTH(value); break;
623: case 0x04E: BLTBPTL(value); break;
624: case 0x048: BLTCPTH(value); break;
625: case 0x04A: BLTCPTL(value); break;
626: case 0x054: BLTDPTH(value); break;
627: case 0x056: BLTDPTL(value); break;
628:
629: case 0x058: BLTSIZE(value); break;
630:
631: case 0x064: BLTAMOD(value); break;
632: case 0x062: BLTBMOD(value); break;
633: case 0x060: BLTCMOD(value); break;
634: case 0x066: BLTDMOD(value); break;
635:
636: case 0x070: BLTCDAT(value); break;
637: case 0x072: BLTBDAT(value); break;
638: case 0x074: BLTADAT(value); break;
639:
640: case 0x07E: DSKSYNC(value); break;
641:
642: case 0x080: COP1LCH(value); break;
643: case 0x082: COP1LCL(value); break;
644: case 0x084: COP2LCH(value); break;
645: case 0x086: COP2LCL(value); break;
646:
647: case 0x088: COPJMP1(value); break;
648: case 0x08A: COPJMP2(value); break;
649:
650: case 0x08E: DIWSTRT(value); break;
651: case 0x090: DIWSTOP(value); break;
652: case 0x092: DDFSTRT(value); break;
653: case 0x094: DDFSTOP(value); break;
654:
655: case 0x096: DMACON(value); break;
656: case 0x09A: INTENA(value); break;
657: case 0x09C: INTREQ(value); break;
658: case 0x09E: ADKCON(value); break;
659:
660: case 0x0A0: AUD0LCH(value); break;
661: case 0x0A2: AUD0LCL(value); break;
662: case 0x0A4: AUD0LEN(value); break;
663: case 0x0A6: AUD0PER(value); break;
664: case 0x0A8: AUD0VOL(value); break;
665:
666: case 0x0B0: AUD1LCH(value); break;
667: case 0x0B2: AUD1LCL(value); break;
668: case 0x0B4: AUD1LEN(value); break;
669: case 0x0B6: AUD1PER(value); break;
670: case 0x0B8: AUD1VOL(value); break;
671:
672: case 0x0C0: AUD2LCH(value); break;
673: case 0x0C2: AUD2LCL(value); break;
674: case 0x0C4: AUD2LEN(value); break;
675: case 0x0C6: AUD2PER(value); break;
676: case 0x0C8: AUD2VOL(value); break;
677:
678: case 0x0D0: AUD3LCH(value); break;
679: case 0x0D2: AUD3LCL(value); break;
680: case 0x0D4: AUD3LEN(value); break;
681: case 0x0D6: AUD3PER(value); break;
682: case 0x0D8: AUD3VOL(value); break;
683:
684: case 0x0E0: BPL1PTH(value); break;
685: case 0x0E2: BPL1PTL(value); break;
686: case 0x0E4: BPL2PTH(value); break;
687: case 0x0E6: BPL2PTL(value); break;
688: case 0x0E8: BPL3PTH(value); break;
689: case 0x0EA: BPL3PTL(value); break;
690: case 0x0EC: BPL4PTH(value); break;
691: case 0x0EE: BPL4PTL(value); break;
692: case 0x0F0: BPL5PTH(value); break;
693: case 0x0F2: BPL5PTL(value); break;
694: case 0x0F4: BPL6PTH(value); break;
695: case 0x0F6: BPL6PTL(value); break;
696:
697: case 0x100: BPLCON0(value); break;
698: case 0x102: BPLCON1(value); break;
699: case 0x104: BPLCON2(value); break;
700: case 0x106: BPLCON3(value); break;
701:
702: case 0x108: BPL1MOD(value); break;
703: case 0x10A: BPL2MOD(value); break;
704:
705: case 0x110: BPL1DAT(value); break;
706: case 0x112: BPL2DAT(value); break;
707: case 0x114: BPL3DAT(value); break;
708: case 0x116: BPL4DAT(value); break;
709: case 0x118: BPL5DAT(value); break;
710: case 0x11A: BPL6DAT(value); break;
711:
712: case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
713: case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
714: case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
715: case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
716: case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
717: case 0x1BC: case 0x1BE:
718: COLOR(value & 0xFFF, (addr & 0x3E) / 2);
719: break;
720: case 0x120: case 0x124: case 0x128: case 0x12C:
721: case 0x130: case 0x134: case 0x138: case 0x13C:
722: SPRxPTH(value, (addr - 0x120) / 4);
723: break;
724: case 0x122: case 0x126: case 0x12A: case 0x12E:
725: case 0x132: case 0x136: case 0x13A: case 0x13E:
726: SPRxPTL(value, (addr - 0x122) / 4);
727: break;
728: case 0x140: case 0x148: case 0x150: case 0x158:
729: case 0x160: case 0x168: case 0x170: case 0x178:
730: SPRxPOS(value, (addr - 0x140) / 8);
731: break;
732: case 0x142: case 0x14A: case 0x152: case 0x15A:
733: case 0x162: case 0x16A: case 0x172: case 0x17A:
734: SPRxCTL(value, (addr - 0x142) / 8);
735: break;
736: case 0x144: case 0x14C: case 0x154: case 0x15C:
737: case 0x164: case 0x16C: case 0x174: case 0x17C:
738: SPRxDATA(value, (addr - 0x144) / 8);
739: break;
740: case 0x146: case 0x14E: case 0x156: case 0x15E:
741: case 0x166: case 0x16E: case 0x176: case 0x17E:
742: SPRxDATB(value, (addr - 0x146) / 8);
743: break;
744:
745: case 0x36: JOYTEST(value); break;
746: }
747: }
748:
749: void custom_bput(CPTR addr, UBYTE value)
750: {
751: /* Yes, there are programs that do this. The programmers should be shot.
752: * This might actually work sometimes. */
753: UWORD rval = value;
754: CPTR raddr = addr & 0x1FE;
755: if (addr & 1) {
756: rval |= cregs[raddr >> 1] & 0xFF00;
757: } else {
758: rval <<= 8;
759: rval |= cregs[raddr >> 1] & 0xFF;
760: }
761: custom_wput(raddr, rval);
762: }
763:
764: void custom_lput(CPTR addr, ULONG value)
765: {
766: custom_wput(addr & 0xfffe, value >> 16);
767: custom_wput((addr+2) & 0xfffe, (UWORD)value);
768: }
769:
770: static bool copcomp(void)
771: {
772: UWORD vp = vpos & (((copi2 >> 8) & 0x7F) | 0x80);
773: UWORD hp = current_hpos() & (copi2 & 0xFE);
774: UWORD vcmp = copi1 >> 8;
775: UWORD hcmp = copi1 & 0xFE;
776: return (vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000));
777: }
778:
779: /*
780: * Calculate the minimum number of cycles after which the
781: * copper comparison becomes true. This is quite tricky. I hope it works.
782: */
783: static int calc_copcomp_true(int currvpos, int currhpos)
784: {
785: UWORD vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
786: UWORD hp = currhpos & (copi2 & 0xFE);
787: UWORD vcmp = copi1 >> 8;
788: UWORD hcmp = copi1 & 0xFE;
789:
790: int cycleadd = maxhpos - currhpos;
791: int coptime = 0;
792:
793: if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
794: return 0;
795:
796: try_again:
797:
798: while (vp < vcmp) {
799: currvpos++;
800: if (currvpos > maxvpos + 1)
801: return -1;
802: currhpos = 0;
803: coptime += cycleadd;
804: cycleadd = maxhpos;
805: vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
806: }
807: hp = currhpos & (copi2 & 0xFE);
808: if (!(vp > vcmp)) {
809: while (hp < hcmp) {
810: currhpos++;
811: if (currhpos > maxhpos) {
812: /* Now, what? There might be a good position on the
813: * next line. But it can also be the FFFF FFFE
814: * case.
815: */
816: currhpos = 0;
817: currvpos++;
818: vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
819: goto try_again;
820: }
821: coptime++;
822: hp = currhpos & (copi2 & 0xFE);
823: }
824: }
825: if (coptime == 0) /* waiting for the blitter */
826: return 1;
827:
828: return coptime;
829: }
830:
831: static void copper_read(void)
832: {
833: if (dmaen(DMA_COPPER)){
834: copi1 = chipmem_bank.wget(coplc);
835: copi2 = chipmem_bank.wget(coplc+2);
836: coplc += 4;
837: eventtab[ev_copper].oldcycles = cycles;
838: eventtab[ev_copper].evtime = (copi1 & 1) ? (copi2 & 1) ? 4 : 6 : 4;
839: copstate = (copi1 & 1) ? (copi2 & 1) ? COP_skip : COP_wait : COP_move;
840: } else {
841: copstate = COP_read;
842: eventtab[ev_copper].active = false;
843: }
844: }
845:
846: static void do_copper(void)
847: {
848: switch(copstate){
849: case COP_read:
850: copper_read();
851: break;
852: case COP_move:
853: if (copi1 >= (copcon & 2 ? 0x40 : 0x80))
854: custom_bank.wput(copi1,copi2);
855: copper_read();
856: break;
857: case COP_skip:
858: if (copcomp())
859: coplc += 4;
860: copper_read();
861: break;
862: case COP_wait: {
863: int coptime = calc_copcomp_true(vpos, current_hpos());
864: if (coptime < 0) {
865: copstate = COP_stop;
866: eventtab[ev_copper].active = false;
867: copper_active = false;
868: } else {
869: if (!coptime)
870: copper_read();
871: else {
872: eventtab[ev_copper].evtime = coptime;
873: eventtab[ev_copper].oldcycles = cycles;
874: }
875: }
876: break;
877: }
878: case COP_stop:
879: eventtab[ev_copper].active = false;
880: copper_active = false;
881: break;
882: }
883: }
884:
885: static __inline__ bool blitter_read(void)
886: {
887: if (bltcon0 & 0xe00){
888: if (!dmaen(DMA_BLITTER)) return true; /* blitter stopped */
889: if (!blitline){
890: if (bltcon0 & 0x800) bltadat = chipmem_bank.wget(bltapt);
891: if (bltcon0 & 0x400) bltbdat = chipmem_bank.wget(bltbpt);
892: }
893: if (bltcon0 & 0x200) bltcdat = chipmem_bank.wget(bltcpt);
894: }
895: bltstate = BLT_work;
896: return (bltcon0 & 0xE00) != 0;
897: }
898:
899: static __inline__ bool blitter_write(void)
900: {
901: if (bltddat) blitzero = false;
902: if ((bltcon0 & 0x100) || blitline){
903: if (!dmaen(DMA_BLITTER)) return true;
904: chipmem_bank.wput(bltdpt,bltddat);
905: }
906: bltstate = BLT_next;
907: return (bltcon0 & 0x100) != 0;
908: }
909:
910: static void blitter_blit(void)
911: {
912: UWORD blitahold,blitbhold,blitchold;
913: UWORD bltaold;
914:
915: if (blitdesc) {
916: UWORD bltamask = 0xffff;
917:
918: if (!blitlpos) { bltamask &= bltafwm; }
919: if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }
920: bltaold = bltadat & bltamask;
921:
922: blitahold = (((ULONG)bltaold << 16) | blitpreva) >> (16-blitashift);
923: blitbhold = (((ULONG)bltbdat << 16) | blitprevb) >> (16-blitbshift);
924: blitchold = bltcdat;
925: } else {
926: UWORD bltamask = 0xffff;
927:
928: if (!blitlpos) { bltamask &= bltafwm; }
929: if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }
930: bltaold = bltadat & bltamask;
931:
932: blitahold = (((ULONG)blitpreva << 16) | bltaold) >> blitashift;
933: blitbhold = (((ULONG)blitprevb << 16) | bltbdat) >> blitbshift;
934: blitchold = bltcdat;
935: }
936: bltddat = 0;
937: bltddat = blit_func(blitahold, blitbhold, blitchold, bltcon0 & 0xFF);
938: if (blitfill){
939: UWORD fillmask;
940: for (fillmask = 1; fillmask; fillmask <<= 1){
941: UWORD tmp = bltddat;
942: if (blitfc) {
943: if (blitife)
944: bltddat |= fillmask;
945: else
946: bltddat ^= fillmask;
947: }
948: if (tmp & fillmask) blitfc = !blitfc;
949: }
950: }
951: bltstate = BLT_write;
952: blitpreva = bltaold; blitprevb = bltbdat;
953: }
954:
955: static void blitter_nxblit(void)
956: {
957: bltstate = BLT_read;
958: if (blitdesc){
959: if (++blitlpos == hblitsize) {
960: if (--vblitsize == 0) {
961: bltstate = BLT_done;
962: #ifdef NO_FAST_BLITTER
963: custom_bank.wput(0xDFF09C,0x8040);
964: #endif
965: }
966: blitfc = bltcon1 & 0x4;
967:
968: blitlpos = 0;
969: if (bltcon0 & 0x800) bltapt -= 2+bltamod;
970: if (bltcon0 & 0x400) bltbpt -= 2+bltbmod;
971: if (bltcon0 & 0x200) bltcpt -= 2+bltcmod;
972: if (bltcon0 & 0x100) bltdpt -= 2+bltdmod;
973: } else {
974: if (bltcon0 & 0x800) bltapt -= 2;
975: if (bltcon0 & 0x400) bltbpt -= 2;
976: if (bltcon0 & 0x200) bltcpt -= 2;
977: if (bltcon0 & 0x100) bltdpt -= 2;
978: }
979: } else {
980: if (++blitlpos == hblitsize) {
981: if (--vblitsize == 0) {
982: bltstate = BLT_done;
983: #ifdef NO_FAST_BLITTER
984: custom_bank.wput(0xDFF09C,0x8040);
985: #endif
986: }
987: blitlpos = 0;
988: if (bltcon0 & 0x800) bltapt += 2+bltamod;
989: if (bltcon0 & 0x400) bltbpt += 2+bltbmod;
990: if (bltcon0 & 0x200) bltcpt += 2+bltcmod;
991: if (bltcon0 & 0x100) bltdpt += 2+bltdmod;
992: } else {
993: if (bltcon0 & 0x800) bltapt += 2;
994: if (bltcon0 & 0x400) bltbpt += 2;
995: if (bltcon0 & 0x200) bltcpt += 2;
996: if (bltcon0 & 0x100) bltdpt += 2;
997: }
998: }
999: }
1000:
1001: static __inline__ void blitter_line_incx(int a)
1002: {
1003: blinea >>= 1;
1004: if (!blinea) {
1005: blinea = 0x8000;
1006: bltcnxlpt += 2;
1007: bltdnxlpt += 2;
1008: }
1009: }
1010:
1011: static __inline__ void blitter_line_decx(int shm)
1012: {
1013: if (shm) blineb = (blineb << 2) | (blineb >> 14);
1014: blinea <<= 1;
1015: if (!blinea) {
1016: blinea = 1;
1017: bltcnxlpt -= 2;
1018: bltdnxlpt -= 2;
1019: }
1020: }
1021:
1022: static __inline__ void blitter_line_decy(int shm)
1023: {
1024: if (shm) blineb = (blineb >> 1) | (blineb << 15);
1025: bltcnxlpt -= bltcmod;
1026: bltdnxlpt -= bltcmod; /* ??? am I wrong or doesn't KS1.3 set bltdmod? */
1027: blitonedot = 0;
1028: }
1029:
1030: static __inline__ void blitter_line_incy(int shm)
1031: {
1032: if (shm) blineb = (blineb >> 1) | (blineb << 15);
1033: bltcnxlpt += bltcmod;
1034: bltdnxlpt += bltcmod; /* ??? */
1035: blitonedot = 0;
1036: }
1037:
1038: static void blitter_line(void)
1039: {
1040: UWORD blitahold = blinea, blitbhold = blineb, blitchold = bltcdat;
1041: bltddat = 0;
1042:
1043: if (blitsing && blitonedot) blitahold = 0;
1044: blitonedot = 1;
1045: bltddat = blit_func(blitahold, blitbhold, blitchold, bltcon0 & 0xFF);
1046: if (!blitsign){
1047: bltapt += (WORD)bltamod;
1048: if (bltcon1 & 0x10){
1049: if (bltcon1 & 0x8)
1050: blitter_line_decy(0);
1051: else
1052: blitter_line_incy(0);
1053: } else {
1054: if (bltcon1 & 0x8)
1055: blitter_line_decx(0);
1056: else
1057: blitter_line_incx(0);
1058: }
1059: } else {
1060: bltapt += (WORD)bltbmod;
1061: }
1062: if (bltcon1 & 0x10){
1063: if (bltcon1 & 0x4)
1064: blitter_line_decx(1);
1065: else
1066: blitter_line_incx(1);
1067: } else {
1068: if (bltcon1 & 0x4)
1069: blitter_line_decy(1);
1070: else
1071: blitter_line_incy(1);
1072: }
1073: blitsign = 0 > (WORD)bltapt;
1074: bltstate = BLT_write;
1075: }
1076:
1077: static __inline__ void blitter_nxline(void)
1078: {
1079: if (--vblitsize == 0) {
1080: bltstate = BLT_done;
1081: #ifdef NO_FAST_BLITTER
1082: custom_bank.wput(0xDFF09C,0x8040);
1083: #endif
1084: } else {
1085: bltstate = BLT_read;
1086: bltcpt = bltcnxlpt;
1087: bltdpt = bltdnxlpt;
1088: }
1089: }
1090:
1091: static void blit_init(void)
1092: {
1093: vblitsize = bltsize >> 6;
1094: hblitsize = bltsize & 0x3F;
1095: if (!vblitsize) vblitsize = 1024;
1096: if (!hblitsize) hblitsize = 64;
1097: blitlpos = 0;
1098: blitzero = true; blitpreva = blitprevb = 0;
1099: blitline = bltcon1 & 1;
1100: blitashift = bltcon0 >> 12; blitbshift = bltcon1 >> 12;
1101:
1102: if (blitline) {
1103: bltcnxlpt = bltcpt;
1104: bltdnxlpt = bltdpt;
1105: blitsing = bltcon1 & 0x2;
1106: blinea = bltadat >> blitashift;
1107: blineb = (bltbdat >> blitbshift) | (bltbdat << (16-blitbshift));
1108: blitsign = bltcon1 & 0x40;
1109: blitonedot = false;
1110: bltamod &= 0xfffe; bltbmod &= 0xfffe; bltapt &= 0xfffe;
1111: } else {
1112: blitfc = bltcon1 & 0x4;
1113: blitife = bltcon1 & 0x8;
1114: blitfill = bltcon1 & 0x18;
1115:
1116: if ((bltcon1 & 0x18) == 0x18) {
1117: /* Digital "Trash" demo does this; others too. Apparently, no
1118: * negative effects. */
1119: static bool warn = true;
1120: if (warn)
1121: fprintf(stderr, "warning: weird fill mode (further messages suppressed)\n");
1122: warn = false;
1123: }
1124: blitdesc = bltcon1 & 0x2;
1125: if (blitfill && !blitdesc)
1126: fprintf(stderr, "warning: blitter fill without desc\n");
1127: }
1128: }
1129:
1130: #ifdef DEFERRED_INT
1131:
1132: static UWORD deferred_bits;
1133:
1134: static void defer_int_handler(void)
1135: {
1136: INTREQ(0x8000 | deferred_bits);
1137: deferred_bits = 0;
1138: eventtab[ev_deferint].active = false;
1139: }
1140: #endif
1141:
1142: void do_blitter(void)
1143: {
1144: #ifdef NO_FAST_BLITTER
1145: /* I'm not sure all this bltstate stuff is really necessary.
1146: * Most programs should be OK if the blit is done as soon as BLTSIZE is
1147: * written to, and the BLTFINISH bit is set some time after that.
1148: * This code here is nowhere near exact.
1149: */
1150: do {
1151: switch(bltstate) {
1152: case BLT_init:
1153: blit_init();
1154: bltstate = BLT_read;
1155: /* fall through */
1156: case BLT_read:
1157: if (blitter_read())
1158: break;
1159: /* fall through */
1160: case BLT_work:
1161: if (blitline)
1162: blitter_line();
1163: else
1164: blitter_blit();
1165: /* fall through */
1166: case BLT_write:
1167: if (blitter_write())
1168: break;
1169: /* fall through */
1170: case BLT_next:
1171: if (blitline)
1172: blitter_nxline();
1173: else
1174: blitter_nxblit();
1175: break;
1176: case BLT_done:
1177: specialflags &= ~SPCFLAG_BLIT;
1178: break;
1179: }
1180: } while(bltstate != BLT_done && dmaen(DMA_BLITTER)
1181: && dmaen(DMA_BLITPRI)); /* blitter nasty -> no time for CPU */
1182: #else
1183: if (bltstate == BLT_init) {
1184: blit_init();
1185: bltstate = BLT_read;
1186: }
1187: if (!dmaen(DMA_BLITTER))
1188: return; /* gotta come back later. */
1189:
1190: if (blitline) {
1191: do {
1192: blitter_read();
1193: blitter_line();
1194: blitter_write();
1195: blitter_nxline();
1196: } while (bltstate != BLT_done);
1197: } else {
1198: do {
1199: blitter_read();
1200: blitter_blit();
1201: blitter_write();
1202: blitter_nxblit();
1203: } while (bltstate != BLT_done);
1204: }
1205: eventtab[ev_deferint].active = true;
1206: eventtab[ev_deferint].oldcycles = cycles;
1207: eventtab[ev_deferint].evtime = 10; /* whatever */
1208: deferred_bits |= 0x40;
1209: events_schedule();
1210:
1211: specialflags &= ~SPCFLAG_BLIT;
1212: #endif
1213: }
1214:
1215: void do_disk(void)
1216: {
1217: #ifdef NO_FAST_FLOPPY
1218: if (dskdmaen > 1 && dmaen(0x10)){
1219: if (--dsktime == 0) {
1220: dsktime = dskdelay;
1221: if (dsklen & 0x4000){
1222: UWORD dsksync_check;
1223: DISK_GetData(&dsksync_check, &dskbyte);
1224: dskbyte |= 0x8000;
1225: if (dsksynced || !(adkcon & 0x400)) {
1226: *mfmwrite++ = chipmem_bank.wget(dskpt); dskpt += 2;
1227: if (--dsklength == 0) {
1228: DISK_WriteData();
1229: custom_bank.wput(0xDFF09C, 0x8002); /*INTREQ->DSKBLK */
1230: dskdmaen = 0;
1231: specialflags &= ~SPCFLAG_DISK;
1232: }
1233: }
1234: if (dsksync_check == dsksync) {
1235: custom_bank.wput(0xDFF09C, 0x9000);
1236: dsksynced = true;
1237: }
1238: } else {
1239: DISK_GetData(&dskmfm, &dskbyte);
1240: dskbyte |= 0x8000;
1241: if (dsksynced || !(adkcon & 0x400)){
1242: chipmem_bank.wput(dskpt, dskmfm); dskpt += 2;
1243: if (--dsklength == 0) {
1244: custom_bank.wput(0xDFF09C, 0x8002);
1245: dskdmaen = 0;
1246: specialflags &= ~SPCFLAG_DISK;
1247: }
1248: }
1249: if (dskmfm == dsksync) {
1250: custom_bank.wput(0xDFF09C,0x9000);
1251: dsksynced = true;
1252: }
1253: }
1254: }
1255: }
1256: #else
1257: if (dskdmaen > 1 && dmaen(0x10)){
1258: /* Just don't get into an infinite loop if the code below screws up */
1259: int ntries = 100000;
1260:
1261: while (--ntries > 0 && (specialflags & SPCFLAG_DISK)) {
1262: if (dsklen & 0x4000){
1263: UWORD dsksync_check;
1264: DISK_GetData(&dsksync_check, &dskbyte);
1265: dskbyte |= 0x8000;
1266: if (dsksynced || !(adkcon & 0x400)) {
1267: *mfmwrite++ = chipmem_bank.wget(dskpt); dskpt += 2;
1268: if (--dsklength == 0) {
1269: DISK_WriteData();
1270: dskdmaen = 0;
1271: specialflags &= ~SPCFLAG_DISK;
1272: eventtab[ev_deferint].active = true;
1273: eventtab[ev_deferint].oldcycles = cycles;
1274: eventtab[ev_deferint].evtime = 10; /* whatever */
1275: events_schedule ();
1276: deferred_bits |= 0x0002;
1277: }
1278: }
1279: if (dsksync_check == dsksync) {
1280: /* This is pretty pointless... */
1281: custom_bank.wput(0xDFF09C, 0x9000);
1282: dsksynced = true;
1283: }
1284: } else {
1285: DISK_GetData(&dskmfm, &dskbyte);
1286: dskbyte |= 0x8000;
1287: if (dsksynced || !(adkcon & 0x400)){
1288: chipmem_bank.wput(dskpt, dskmfm); dskpt += 2;
1289: if (--dsklength == 0) {
1290: eventtab[ev_deferint].active = true;
1291: eventtab[ev_deferint].oldcycles = cycles;
1292: eventtab[ev_deferint].evtime = 10; /* whatever */
1293: events_schedule ();
1294: deferred_bits |= 0x0002;
1295: dskdmaen = 0;
1296: specialflags &= ~SPCFLAG_DISK;
1297: }
1298: }
1299: if (dskmfm == dsksync) {
1300: /* This is pretty pointless... */
1301: custom_bank.wput(0xDFF09C,0x9000);
1302: dsksynced = true;
1303: }
1304: }
1305: }
1306: }
1307: #endif
1308: }
1309:
1310: static __inline__ void pfield_fetchdata(void)
1311: {
1312: if (dmaen(0x100) && pfield_linedmaon) {
1313: switch(bplplanecnt){
1314: case 6:
1315: bpl6dat = chipmem_bank.wget(bpl6pt); bpl6pt += 2; bpl6dat <<= 5;
1316: case 5:
1317: bpl5dat = chipmem_bank.wget(bpl5pt); bpl5pt += 2; bpl5dat <<= 4;
1318: case 4:
1319: bpl4dat = chipmem_bank.wget(bpl4pt); bpl4pt += 2; bpl4dat <<= 3;
1320: case 3:
1321: bpl3dat = chipmem_bank.wget(bpl3pt); bpl3pt += 2; bpl3dat <<= 2;
1322: case 2:
1323: bpl2dat = chipmem_bank.wget(bpl2pt); bpl2pt += 2; bpl2dat <<= 1;
1324: case 1:
1325: bpl1dat = chipmem_bank.wget(bpl1pt); bpl1pt += 2;
1326: }
1327: }
1328: }
1329:
1330: static void pfield_hsync(int plfline)
1331: {
1332: }
1333:
1334: static void do_sprites(int currvp)
1335: {
1336: int spr;
1337: for(spr = 0; spr < 8; spr++) {
1338: int vstart = (sprpos[spr] >> 8) | ((sprctl[spr] << 6) & 0x100);
1339: int vstop = (sprctl[spr] >> 8) | ((sprctl[spr] << 7) & 0x100);
1340: if ((vstart <= currvp && vstop >= currvp) || spron[spr] == 1) {
1341: if (dmaen(0x20)) {
1342: UWORD data1 = chipmem_bank.wget(sprpt[spr]);
1343: UWORD data2 = chipmem_bank.wget(sprpt[spr]+2);
1344: sprpt[spr] += 4;
1345:
1346: if (vstop != currvp && spron[spr] != 1) {
1347: SPRxDATB(data2, spr);
1348: SPRxDATA(data1, spr);
1349: if (!spr && !sprvbfl && ((sprpos[0]&0xff)<<2)>0x60) {
1350: sprvbfl=2;
1351: spr0ctl=sprctl[0];
1352: spr0pos=sprpos[0];
1353: }
1354: } else {
1355: SPRxPOS(data1, spr);
1356: SPRxCTL(data2, spr);
1357: }
1358:
1359: #if 0
1360: if (vstop != currvp && !sprptset[spr]) {
1361: SPRxDATB(data2, spr);
1362: SPRxDATA(data1, spr);
1363: if (!spr && !sprvbfl && ((sprpos[0]&0xff)<<2)>0x60) {
1364: sprvbfl=2;
1365: spr0ctl=sprctl[0];
1366: spr0pos=sprpos[0];
1367: }
1368: } else {
1369: SPRxPOS(data1, spr);
1370: SPRxCTL(data2, spr);
1371: sprptset[spr] = false;
1372: }
1373: #endif
1374: }
1375: }
1376: }
1377: }
1378:
1379: static void pfield_modulos(void)
1380: {
1381: switch(bplplanecnt){
1382: case 6:
1383: bpl6pt += bpl2mod;
1384: case 5:
1385: bpl5pt += bpl1mod;
1386: case 4:
1387: bpl4pt += bpl2mod;
1388: case 3:
1389: bpl3pt += bpl1mod;
1390: case 2:
1391: bpl2pt += bpl2mod;
1392: case 1:
1393: bpl1pt += bpl1mod;
1394: }
1395: }
1396:
1397: static void pfield_linetoscr(int pix, int stoppos)
1398: {
1399: if (bplcon0 & 0x800 && bplplanecnt == 6) {
1400: /* HAM */
1401: static UWORD lastcolor;
1402: while (pix < diwfirstword && pix < stoppos) {
1403: DrawPixel((pix++)-16, acolors[0]);
1404: lastcolor = color_regs[0];
1405: }
1406: while (pix < diwlastword && pix < stoppos) {
1407: int pv = apixels[pix];
1408: switch(pv & 0x30) {
1409: case 0x00: lastcolor = color_regs[pv]; break;
1410: case 0x10: lastcolor &= 0xFF0; lastcolor |= (pv & 0xF); break;
1411: case 0x20: lastcolor &= 0x0FF; lastcolor |= (pv & 0xF) << 8; break;
1412: case 0x30: lastcolor &= 0xF0F; lastcolor |= (pv & 0xF) << 4; break;
1413: }
1414:
1415: if (spixstate[pix]) {
1416: DrawPixel(pix-16, acolors[spixels[pix]+16]);
1417: spixels[pix] = spixstate[pix] = 0;
1418: } else {
1419: DrawPixel(pix-16, xcolors[lastcolor]);
1420: }
1421: pix++;
1422: }
1423: while (pix < stoppos) {
1424: DrawPixel((pix++)-16, acolors[0]);
1425: }
1426: } else {
1427: if (bplcon0 & 0x400) {
1428: int *lookup = (bplcon2 & 0x40) ? dblpf_ind2 : dblpf_ind1;
1429: /* Dual playfield */
1430: while (pix < diwfirstword && pix < stoppos) {
1431: DrawPixel((pix++)-16, acolors[0]);
1432: }
1433: while (pix < diwlastword && pix < stoppos) {
1434: if (spixstate[pix]) {
1435: DrawPixel(pix-16, acolors[spixels[pix]+16]);
1436: spixels[pix] = spixstate[pix] = 0;
1437: } else {
1438: DrawPixel(pix-16, acolors[lookup[apixels[pix]]]);
1439: }
1440: pix++;
1441: }
1442: while (pix < stoppos) {
1443: DrawPixel((pix++)-16, acolors[0]);
1444: }
1445: } else {
1446: while (pix < diwfirstword && pix < stoppos) {
1447: DrawPixel((pix++)-16, acolors[0]);
1448: }
1449: while (pix < diwlastword && pix < stoppos) {
1450: if (spixstate[pix]) {
1451: if (apixels[pix] == 0 || spixstate[pix] < plf2pri)
1452: DrawPixel(pix-16, acolors[spixels[pix]+16]);
1453: else
1454: DrawPixel(pix-16, acolors[apixels[pix]]);
1455: spixels[pix] = spixstate[pix] = 0;
1456: } else {
1457: DrawPixel(pix-16, acolors[apixels[pix]]);
1458: }
1459: pix++;
1460: }
1461: while (pix < stoppos) {
1462: DrawPixel((pix++)-16, acolors[0]);
1463: }
1464: }
1465: }
1466: }
1467:
1468: static void pfield_sprite (int num, int sprxp, UWORD data, UWORD datb)
1469: {
1470: int i;
1471: for(i = 15; i >= 0; i--) {
1472: int sprxpos = sprxp + i*2;
1473: if ((sprctl[num] & 0x80) && (num & 1)) {
1474: /* Attached sprite */
1475: int col = ((data << 2) & 4) + ((datb << 3) & 8);
1476: if (col) {
1477: spixels[sprxpos] = col;
1478: spixels[sprxpos+1] = col;
1479: spixstate[sprxpos] = 1 << num;
1480: spixstate[sprxpos+1] = 1 << num;
1481: }
1482: spixstate[sprxpos] |= 1 << (num-1);
1483: spixstate[sprxpos+1] |= 1 << (num-1);
1484: } else {
1485: int col = (data & 1) | ((datb << 1) & 2);
1486: if (spixstate[sprxpos] & (1 << num)) {
1487: /* finish attached sprite */
1488: /* Did the upper half of the sprite have any bits set? */
1489: if (spixstate[sprxpos] & (1 << (num+1)))
1490: col += spixels[sprxpos];
1491: if (!col) {
1492: spixstate[sprxpos] = spixstate[sprxpos+1] &= ~(3 << num);
1493: }
1494: } else {
1495: if (col) {
1496: col |= (num & 6) << 1;
1497: }
1498: }
1499: if (col) {
1500: spixels[sprxpos] = col;
1501: spixels[sprxpos+1] = col;
1502: spixstate[sprxpos] = 1<<num;
1503: spixstate[sprxpos+1] = 1<<num;
1504: }
1505: }
1506: data >>= 1;
1507: datb >>= 1;
1508: }
1509: }
1510:
1511: void pfield_doline_slow(int currhpos)
1512: {
1513: int xpos = currhpos * 4 - 0x60;
1514: static int nextpos = -1;
1515: static int linepos;
1516: static bool paststop = false;
1517:
1518: if (vpos < plffirstline || vpos >= plflastline)
1519: return;
1520:
1521: if (currhpos == plfstrt) {
1522: nextpos = currhpos;
1523: linepos = 0;
1524: paststop = false;
1525: }
1526: if (currhpos == nextpos) {
1527: if (linepos >= plflinelen) {
1528: nextpos = -1;
1529: pfield_modulos();
1530: } else {
1531: nextpos += bplhires ? 4 : 8;
1532: linepos += bplhires ? 4 : 8;
1533:
1534: pfield_fetchdata();
1535:
1536: if (bplhires) {
1537: int offs1 = 2 + xpos + 16 + bpldelay1*2; /* Never trust compilers, kids! */
1538: int offs2 = 2 + xpos + 16 + bpldelay2*2;
1539:
1540: int pix;
1541: for(pix = 15; pix >= 0; pix--) {
1542: switch(bplplanecnt) {
1543: case 4:
1544: apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 1;
1545: case 3:
1546: apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 1;
1547: case 2:
1548: apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 1;
1549: case 1:
1550: apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 1;
1551: }
1552: }
1553: } else {
1554: int offs1 = 2 + xpos + 32 + bpldelay1*2;
1555: int offs2 = 2 + xpos + 32 + bpldelay2*2;
1556:
1557: int pix;
1558: for(pix = 30; pix >= 0; pix -= 2) {
1559: switch(bplplanecnt) {
1560: case 6:
1561: apixels[pix + offs2] |= bpl6dat & 0x20;
1562: apixels[pix + offs2 + 1] |= bpl6dat & 0x20; bpl6dat >>= 1;
1563: case 5:
1564: apixels[pix + offs1] |= bpl5dat & 0x10;
1565: apixels[pix + offs1 + 1] |= bpl5dat & 0x10; bpl5dat >>= 1;
1566: case 4:
1567: apixels[pix + offs2] |= bpl4dat & 0x8;
1568: apixels[pix + offs2 + 1] |= bpl4dat & 0x8; bpl4dat >>= 1;
1569: case 3:
1570: apixels[pix + offs1] |= bpl3dat & 0x4;
1571: apixels[pix + offs1 + 1] |= bpl3dat & 0x4; bpl3dat >>= 1;
1572: case 2:
1573: apixels[pix + offs2] |= bpl2dat & 0x2;
1574: apixels[pix + offs2 + 1] |= bpl2dat & 0x2; bpl2dat >>= 1;
1575: case 1:
1576: apixels[pix + offs1] |= bpl1dat & 0x1;
1577: apixels[pix + offs1 + 1] |= bpl1dat & 0x1; bpl1dat >>= 1;
1578: }
1579: }
1580: }
1581: }
1582: }
1583: if (xpos > 0x60) { /* sprites can't appear that far to the left */
1584: int spr;
1585: for(spr = 7; spr >= 0; spr--) {
1586: if (sprarmed[spr] && xpos == ((sprpos[spr] & 0xFF) * 4) - 0x60) {
1587: int sprxp = xpos + 2 + (sprctl[spr] & 1)*2;
1588: pfield_sprite (spr, sprxp, sprdata[spr], sprdatb[spr]);
1589: }
1590: }
1591: }
1592:
1593: if (xpos >= 16 && xpos <= 812) {
1594: pfield_linetoscr (xpos, xpos+4);
1595: }
1596: }
1597:
1598: static __inline__ UWORD *pfield_xlateptr(CPTR plpt, int bytecount)
1599: {
1600: if (!chipmem_bank.check(plpt,bytecount)) {
1601: fprintf(stderr, "Warning: Bad playfield pointer\n");
1602: return NULL;
1603: }
1604: return chipmem_bank.xlateaddr(plpt);
1605: }
1606:
1607: /*
1608: * A few hand-unrolled loops...
1609: */
1610: static __inline__ void pfield_orword_hires(UWORD **plfptr,
1611: unsigned char **dataptr, int bit)
1612: {
1613: UWORD data = *(*plfptr)++;
1614: unsigned char *pixptr = *dataptr;
1615:
1616: if (data & 0x8000) *pixptr |= bit;
1617: pixptr++;
1618: if (data & 0x4000) *pixptr |= bit;
1619: pixptr++;
1620: if (data & 0x2000) *pixptr |= bit;
1621: pixptr++;
1622: if (data & 0x1000) *pixptr |= bit;
1623: pixptr++;
1624: if (data & 0x800) *pixptr |= bit;
1625: pixptr++;
1626: if (data & 0x400) *pixptr |= bit;
1627: pixptr++;
1628: if (data & 0x200) *pixptr |= bit;
1629: pixptr++;
1630: if (data & 0x100) *pixptr |= bit;
1631: pixptr++;
1632: if (data & 0x80) *pixptr |= bit;
1633: pixptr++;
1634: if (data & 0x40) *pixptr |= bit;
1635: pixptr++;
1636: if (data & 0x20) *pixptr |= bit;
1637: pixptr++;
1638: if (data & 0x10) *pixptr |= bit;
1639: pixptr++;
1640: if (data & 0x8) *pixptr |= bit;
1641: pixptr++;
1642: if (data & 0x4) *pixptr |= bit;
1643: pixptr++;
1644: if (data & 0x2) *pixptr |= bit;
1645: pixptr++;
1646: if (data & 0x1) *pixptr |= bit;
1647: pixptr++;
1648: *dataptr = pixptr;
1649: }
1650:
1651: static __inline__ void pfield_orword_lores(UWORD **plfptr,
1652: unsigned char **dataptr, int bit)
1653: {
1654: UWORD data = *(*plfptr)++;
1655: unsigned char *pixptr = *dataptr;
1656: if (data & 0x8000) { *pixptr |= bit; *(pixptr+1) |= bit; }
1657: pixptr+=2;
1658: if (data & 0x4000) { *pixptr |= bit; *(pixptr+1) |= bit; }
1659: pixptr+=2;
1660: if (data & 0x2000) { *pixptr |= bit; *(pixptr+1) |= bit; }
1661: pixptr+=2;
1662: if (data & 0x1000) { *pixptr |= bit; *(pixptr+1) |= bit; }
1663: pixptr+=2;
1664: if (data & 0x800) { *pixptr |= bit; *(pixptr+1) |= bit; }
1665: pixptr+=2;
1666: if (data & 0x400) { *pixptr |= bit; *(pixptr+1) |= bit; }
1667: pixptr+=2;
1668: if (data & 0x200) { *pixptr |= bit; *(pixptr+1) |= bit; }
1669: pixptr+=2;
1670: if (data & 0x100) { *pixptr |= bit; *(pixptr+1) |= bit; }
1671: pixptr+=2;
1672: if (data & 0x80) { *pixptr |= bit; *(pixptr+1) |= bit; }
1673: pixptr+=2;
1674: if (data & 0x40) { *pixptr |= bit; *(pixptr+1) |= bit; }
1675: pixptr+=2;
1676: if (data & 0x20) { *pixptr |= bit; *(pixptr+1) |= bit; }
1677: pixptr+=2;
1678: if (data & 0x10) { *pixptr |= bit; *(pixptr+1) |= bit; }
1679: pixptr+=2;
1680: if (data & 0x8) { *pixptr |= bit; *(pixptr+1) |= bit; }
1681: pixptr+=2;
1682: if (data & 0x4) { *pixptr |= bit; *(pixptr+1) |= bit; }
1683: pixptr+=2;
1684: if (data & 0x2) { *pixptr |= bit; *(pixptr+1) |= bit; }
1685: pixptr+=2;
1686: if (data & 0x1) { *pixptr |= bit; *(pixptr+1) |= bit; }
1687: pixptr+=2;
1688: *dataptr = pixptr;
1689: }
1690:
1691: static __inline__ void pfield_setword_hires(UWORD **plfptr,
1692: unsigned char **dataptr, int bit)
1693: {
1694: UWORD data = *(*plfptr)++;
1695: unsigned char *pixptr = *dataptr;
1696: if (data & 0x8000) *pixptr++ = bit;
1697: else *pixptr++ = 0;
1698: if (data & 0x4000) *pixptr++ = bit;
1699: else *pixptr++ = 0;
1700: if (data & 0x2000) *pixptr++ = bit;
1701: else *pixptr++ = 0;
1702: if (data & 0x1000) *pixptr++ = bit;
1703: else *pixptr++ = 0;
1704: if (data & 0x800) *pixptr++ = bit;
1705: else *pixptr++ = 0;
1706: if (data & 0x400) *pixptr++ = bit;
1707: else *pixptr++ = 0;
1708: if (data & 0x200) *pixptr++ = bit;
1709: else *pixptr++ = 0;
1710: if (data & 0x100) *pixptr++ = bit;
1711: else *pixptr++ = 0;
1712: if (data & 0x80) *pixptr++ = bit;
1713: else *pixptr++ = 0;
1714: if (data & 0x40) *pixptr++ = bit;
1715: else *pixptr++ = 0;
1716: if (data & 0x20) *pixptr++ = bit;
1717: else *pixptr++ = 0;
1718: if (data & 0x10) *pixptr++ = bit;
1719: else *pixptr++ = 0;
1720: if (data & 0x8) *pixptr++ = bit;
1721: else *pixptr++ = 0;
1722: if (data & 0x4) *pixptr++ = bit;
1723: else *pixptr++ = 0;
1724: if (data & 0x2) *pixptr++ = bit;
1725: else *pixptr++ = 0;
1726: if (data & 0x1) *pixptr++ = bit;
1727: else *pixptr++ = 0;
1728: *dataptr = pixptr;
1729: }
1730:
1731: static __inline__ void pfield_setword_lores(UWORD **plfptr,
1732: unsigned char **dataptr, int bit)
1733: {
1734: UWORD data = *(*plfptr)++;
1735: unsigned char *pixptr = *dataptr;
1736:
1737: if (data & 0x8000) { *pixptr++ = bit; *pixptr++ = bit; }
1738: else { *pixptr++ = 0; *pixptr++ = 0; }
1739: if (data & 0x4000) { *pixptr++ = bit; *pixptr++ = bit; }
1740: else { *pixptr++ = 0; *pixptr++ = 0; }
1741: if (data & 0x2000) { *pixptr++ = bit; *pixptr++ = bit; }
1742: else { *pixptr++ = 0; *pixptr++ = 0; }
1743: if (data & 0x1000) { *pixptr++ = bit; *pixptr++ = bit; }
1744: else { *pixptr++ = 0; *pixptr++ = 0; }
1745: if (data & 0x800) { *pixptr++ = bit; *pixptr++ = bit; }
1746: else { *pixptr++ = 0; *pixptr++ = 0; }
1747: if (data & 0x400) { *pixptr++ = bit; *pixptr++ = bit; }
1748: else { *pixptr++ = 0; *pixptr++ = 0; }
1749: if (data & 0x200) { *pixptr++ = bit; *pixptr++ = bit; }
1750: else { *pixptr++ = 0; *pixptr++ = 0; }
1751: if (data & 0x100) { *pixptr++ = bit; *pixptr++ = bit; }
1752: else { *pixptr++ = 0; *pixptr++ = 0; }
1753: if (data & 0x80) { *pixptr++ = bit; *pixptr++ = bit; }
1754: else { *pixptr++ = 0; *pixptr++ = 0; }
1755: if (data & 0x40) { *pixptr++ = bit; *pixptr++ = bit; }
1756: else { *pixptr++ = 0; *pixptr++ = 0; }
1757: if (data & 0x20) { *pixptr++ = bit; *pixptr++ = bit; }
1758: else { *pixptr++ = 0; *pixptr++ = 0; }
1759: if (data & 0x10) { *pixptr++ = bit; *pixptr++ = bit; }
1760: else { *pixptr++ = 0; *pixptr++ = 0; }
1761: if (data & 0x8) { *pixptr++ = bit; *pixptr++ = bit; }
1762: else { *pixptr++ = 0; *pixptr++ = 0; }
1763: if (data & 0x4) { *pixptr++ = bit; *pixptr++ = bit; }
1764: else { *pixptr++ = 0; *pixptr++ = 0; }
1765: if (data & 0x2) { *pixptr++ = bit; *pixptr++ = bit; }
1766: else { *pixptr++ = 0; *pixptr++ = 0; }
1767: if (data & 0x1) { *pixptr++ = bit; *pixptr++ = bit; }
1768: else { *pixptr++ = 0; *pixptr++ = 0; }
1769:
1770: *dataptr = pixptr;
1771: }
1772:
1773: static void pfield_doline(void)
1774: {
1775: int xpos = plfstrt * 4 - 0x60;
1776: int spr;
1777: int linelen;
1778:
1779: if (vpos < plffirstline || vpos >= plflastline)
1780: return;
1781:
1782: if (dmaen(0x100) && pfield_linedmaon) {
1783: /*
1784: * We want to use real pointers, but we don't want to get segfaults
1785: * because of them.
1786: */
1787: UWORD *r_bpl1pt,*r_bpl2pt,*r_bpl3pt,*r_bpl4pt,*r_bpl5pt,*r_bpl6pt;
1788: int bytecount = plflinelen / (bplhires ? 4 : 8) * 2;
1789: switch (bplplanecnt) {
1790: case 6:
1791: r_bpl6pt = pfield_xlateptr(bpl6pt, bytecount);
1792: if (r_bpl6pt == NULL)
1793: return;
1794: case 5:
1795: r_bpl5pt = pfield_xlateptr(bpl5pt, bytecount);
1796: if (r_bpl5pt == NULL)
1797: return;
1798: case 4:
1799: r_bpl4pt = pfield_xlateptr(bpl4pt, bytecount);
1800: if (r_bpl4pt == NULL)
1801: return;
1802: case 3:
1803: r_bpl3pt = pfield_xlateptr(bpl3pt, bytecount);
1804: if (r_bpl3pt == NULL)
1805: return;
1806: case 2:
1807: r_bpl2pt = pfield_xlateptr(bpl2pt, bytecount);
1808: if (r_bpl2pt == NULL)
1809: return;
1810: case 1:
1811: r_bpl1pt = pfield_xlateptr(bpl1pt, bytecount);
1812: if (r_bpl1pt == NULL)
1813: return;
1814: }
1815: switch (bplplanecnt) {
1816: case 6: bpl6pt += bytecount + bpl2mod;
1817: case 5: bpl5pt += bytecount + bpl1mod;
1818: case 4: bpl4pt += bytecount + bpl2mod;
1819: case 3: bpl3pt += bytecount + bpl1mod;
1820: case 2: bpl2pt += bytecount + bpl2mod;
1821: case 1: bpl1pt += bytecount + bpl1mod;
1822: }
1823:
1824: if (bplhires) {
1825: int xpos1 = 2 + xpos + 16 + bpldelay1*2;
1826: int xpos2 = 2 + xpos + 16 + bpldelay2*2;
1827: unsigned char *xp1ptr = apixels+xpos1;
1828: unsigned char *xp2ptr = apixels+xpos2;
1829:
1830: if (bplplanecnt > 0) {
1831: unsigned char *app = xp1ptr;
1832: for (linelen = plflinelen; linelen > 0; linelen-=4) {
1833: pfield_setword_hires(&r_bpl1pt, &app, 1);
1834: }
1835: if (bplplanecnt > 2) {
1836: unsigned char *app = xp1ptr;
1837: for (linelen = plflinelen; linelen > 0; linelen-=4) {
1838: pfield_orword_hires(&r_bpl3pt, &app, 4);
1839: }
1840: }
1841: if (bplplanecnt > 1) {
1842: unsigned char *app = xp2ptr;
1843: for (linelen = plflinelen; linelen > 0; linelen-=4) {
1844: pfield_orword_hires(&r_bpl2pt, &app, 2);
1845: }
1846: }
1847: if (bplplanecnt > 3) {
1848: unsigned char *app = xp2ptr;
1849: for (linelen = plflinelen; linelen > 0; linelen-=4) {
1850: pfield_orword_hires(&r_bpl4pt, &app, 8);
1851: }
1852: }
1853: } else {
1854: memset(apixels, 0, sizeof(apixels));
1855: }
1856: } else {
1857: int xpos1 = 2 + xpos + 32 + bpldelay1*2;
1858: int xpos2 = 2 + xpos + 32 + bpldelay2*2;
1859: unsigned char *xp1ptr = apixels+xpos1;
1860: unsigned char *xp2ptr = apixels+xpos2;
1861: if (bplplanecnt > 0) {
1862: unsigned char *app = xp1ptr;
1863: for (linelen = plflinelen; linelen > 0; linelen-=8) {
1864: pfield_setword_lores(&r_bpl1pt, &app, 1);
1865: }
1866: if (bplplanecnt > 2) {
1867: unsigned char *app = xp1ptr;
1868: for (linelen = plflinelen; linelen > 0; linelen-=8) {
1869: pfield_orword_lores(&r_bpl3pt, &app, 4);
1870: }
1871: }
1872: if (bplplanecnt > 4) {
1873: unsigned char *app = xp1ptr;
1874: for (linelen = plflinelen; linelen > 0; linelen-=8) {
1875: pfield_orword_lores(&r_bpl5pt, &app, 16);
1876: }
1877: }
1878: if (bplplanecnt > 1) {
1879: unsigned char *app = xp2ptr;
1880: for (linelen = plflinelen; linelen > 0; linelen-=8) {
1881: pfield_orword_lores(&r_bpl2pt, &app, 2);
1882: }
1883: }
1884: if (bplplanecnt > 3) {
1885: unsigned char *app = xp2ptr;
1886: for (linelen = plflinelen; linelen > 0; linelen-=8) {
1887: pfield_orword_lores(&r_bpl4pt, &app, 8);
1888: }
1889: }
1890: if (bplplanecnt > 5) {
1891: unsigned char *app = xp2ptr;
1892: for (linelen = plflinelen; linelen > 0; linelen-=8) {
1893: pfield_orword_lores(&r_bpl6pt, &app, 32);
1894: }
1895: }
1896: } else {
1897: memset(apixels, 0, sizeof(apixels));
1898: }
1899: }
1900: }
1901: for(spr = 7; spr >= 0; spr--) {
1902: if (sprarmed[spr]) {
1903: int sprxp = ((sprpos[spr] & 0xFF) * 4) - 0x60 + 2 + (sprctl[spr] & 1)*2;
1904: int i;
1905: /* Ugh. Nasty bug. Let's rather lose some sprites than trash
1906: * memory. */
1907: if (sprxp < 0)
1908: continue;
1909: pfield_sprite (spr, sprxp, sprdata[spr], sprdatb[spr]);
1910: }
1911: }
1912:
1913: pfield_linetoscr (16, 812);
1914: }
1915:
1916: static void setdontcare(void)
1917: {
1918: printf("Don't care mouse mode set\n");
1919: mousestate=dont_care_mouse;
1920: lastspr0x=lastmx; lastspr0y=lastmy;
1921: mstepx=defstepx; mstepy=defstepy;
1922: }
1923:
1924: static void setfollow(void)
1925: {
1926: printf("Follow sprite mode set\n");
1927: mousestate=follow_mouse;
1928: lastdiffx=lastdiffy=0;
1929: sprvbfl=0;
1930: spr0ctl=spr0pos=0;
1931: mstepx=defstepx; mstepy=defstepy;
1932: }
1933:
1934: void togglemouse(void)
1935: {
1936: switch(mousestate) {
1937: case dont_care_mouse: setfollow(); break;
1938: case follow_mouse: setdontcare(); break;
1939: }
1940: }
1941:
1942: #if 0 /* Mouse calibrations works well enough without this. */
1943: void mousesetup(void)
1944: {
1945: if (mousestate != follow_mouse) return;
1946: char buf[80];
1947: printf("\nMouse pointer centering.\n\n");
1948: printf("Current values: xoffs=0x%x yoffs=0x%x\n", xoffs, yoffs);
1949: printf("New values (y/n)?";
1950: cin.get(buf,80,'\n');
1951: if (toupper(buf[0]) != 'Y') return;
1952: cout << "\nxoffs= "; cin>>xoffs;
1953: cout << "yoffs= "; cin>>yoffs;
1954: cout << "\n";
1955: }
1956: #endif
1957:
1958: static __inline__ int adjust(int val)
1959: {
1960: if (val>127)
1961: return 127;
1962: else if (val<-127)
1963: return -127;
1964: return val;
1965: }
1966:
1967: static void vsync_handler(void)
1968: {
1969: int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
1970: int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
1971: int diffx, diffy;
1972: int i;
1973:
1974: handle_events();
1975: #ifdef HAVE_JOYSTICK
1976: {
1977: UWORD dir;
1978: bool button;
1979: read_joystick(&dir, &button);
1980: buttonstate[1] = button;
1981: }
1982: #endif
1983:
1984: if (produce_sound)
1985: flush_sound ();
1986:
1987: switch (mousestate) {
1988: case normal_mouse:
1989: diffx = lastmx - lastsampledmx;
1990: diffy = lastmy - lastsampledmy;
1991: if (!newmousecounters) {
1992: if (diffx > 127) diffx = 127;
1993: if (diffx < -127) diffx = -127;
1994: joy0x += diffx;
1995: if (diffy > 127) diffy = 127;
1996: if (diffy < -127) diffy = -127;
1997: joy0y += diffy;
1998: }
1999: lastsampledmx += diffx; lastsampledmy += diffy;
2000: break;
2001:
2002: case dont_care_mouse:
2003: diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16);
2004: diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16);
2005: lastspr0x=lastmx; lastspr0y=lastmy;
2006: joy0x+=diffx; joy0y+=diffy;
2007: break;
2008:
2009: case follow_mouse:
2010: if (sprvbfl && sprvbfl-- >1) {
2011: int mouseypos;
2012:
2013: if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x
2014: && spr0x > plfstrt*4+34+xcaloff && spr0x < plfstop*4-xcaloff)
2015: {
2016: int val = (lastdiffx << 16) / (spr0x - lastspr0x);
2017: if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight;
2018: }
2019: if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y
2020: && spr0y>plffirstline+ycaloff && spr0y<plflastline-ycaloff)
2021: {
2022: int val = (lastdiffy<<16) / (spr0y-lastspr0y);
2023: if (val>=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight;
2024: }
2025: mouseypos = lastmy;
2026:
2027: /* Calculations might be incorrect */
2028: if(dont_want_aspect)
2029: mouseypos *= 2;
2030:
2031: /* cout<<" mstepx= "<<mstepx<<" mstepy= "<<mstepy<<"\n";*/
2032: diffx = adjust ((((lastmx + 0x70 + xoffs - spr0x) & ~1) * mstepx) >> 16);
2033: diffy = adjust ((((mouseypos + yoffs - spr0y+minfirstline*2) & ~1) * mstepy) >> 16);
2034: lastspr0x=spr0x; lastspr0y=spr0y;
2035: lastdiffx=diffx; lastdiffy=diffy;
2036: joy0x+=diffx; joy0y+=diffy;
2037: }
2038: break;
2039: }
2040:
2041: INTREQ(0x8020);
2042: if (bplcon0 & 4) lof ^= 0x8000;
2043: COPJMP1(0);
2044:
2045: for (i = 0; i < 8; i++)
2046: spron[i] = 0;
2047:
2048: if (framecnt == 0)
2049: flush_screen ();
2050: count_frame();
2051: #ifdef __unix
2052: {
2053: struct timeval tv;
2054: unsigned long int newtime;
2055:
2056: gettimeofday(&tv,NULL);
2057: newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
2058:
2059: if (!bogusframe) {
2060: frametime += newtime - msecs;
2061: timeframes++;
2062: }
2063: msecs = newtime;
2064: bogusframe = false;
2065: }
2066: #endif
2067: CIA_vsync_handler();
2068: }
2069:
2070: static void hsync_handler(void)
2071: {
2072: eventtab[ev_hsync].oldcycles = cycles;
2073: CIA_hsync_handler();
2074:
2075: if(produce_sound)
2076: do_sound ();
2077:
2078: if (framecnt == 0 && vpos >= plffirstline && vpos < plflastline
2079: && vpos >= minfirstline)
2080: {
2081: /* Finish the line, if we started doing it with the slow update.
2082: * Otherwise, draw it entirely. */
2083: if (pfield_fullline) {
2084: if (!pfield_linedone) {
2085: pfield_doline();
2086: }
2087: } else {
2088: int i;
2089: for(i = pfield_lastpart_hpos; i < maxhpos; i++)
2090: pfield_doline_slow(i);
2091: }
2092: flush_line ();
2093: }
2094: pfield_calclinedma();
2095: pfield_fullline = true;
2096: pfield_linedone = false;
2097: pfield_lastpart_hpos = 0;
2098:
2099: if (++vpos == (maxvpos + (lof != 0))) {
2100: vpos = 0;
2101: vsync_handler();
2102: }
2103:
2104: /* Tell the graphics code about the next line. */
2105: if (framecnt == 0 && vpos >= plffirstline && vpos < plflastline
2106: && vpos >= minfirstline)
2107: {
2108: if (dont_want_aspect) {
2109: prepare_line(vpos - minfirstline, false);
2110: } else {
2111: if (bplcon0 & 4) {
2112: if(lof) {
2113: prepare_line((vpos-minfirstline)*2, false);
2114: } else {
2115: prepare_line((vpos-minfirstline)*2+1, false);
2116: }
2117: } else {
2118: prepare_line((vpos-minfirstline)*2, true);
2119: }
2120: }
2121: }
2122:
2123: /* do_sprites must be called after pfield_lastpart_hpos
2124: * is set to 0. */
2125: if (vpos > 0) do_sprites(vpos);
2126: }
2127:
2128: void customreset(void)
2129: {
2130: int i;
2131: #ifdef __unix
2132: struct timeval tv;
2133: #endif
2134: inhibit_frame = 0;
2135: CIA_reset();
2136: cycles = 0; specialflags = 0;
2137:
2138: vpos = 0; lof = 0;
2139:
2140: if (needmousehack()) {
2141: if (mousestate != follow_mouse) setfollow();
2142: } else {
2143: mousestate = normal_mouse;
2144: }
2145:
2146: memset(spixels, 0, sizeof(spixels));
2147: memset(spixstate, 0, sizeof(spixstate));
2148:
2149: prepare_line(0, false); /* Get the graphics stuff in a sane state */
2150:
2151: dmacon = intena = 0;
2152: bltstate = BLT_done;
2153: copstate = COP_stop;
2154: copcon = 0;
2155: dskdmaen = 0;
2156: cycles = 0;
2157: for(i = ev_copper; i < ev_max; i++) {
2158: eventtab[i].active = false;
2159: eventtab[i].oldcycles = 0;
2160: }
2161: copper_active = false;
2162: eventtab[ev_cia].handler = CIA_handler;
2163: eventtab[ev_copper].handler = do_copper;
2164: eventtab[ev_hsync].handler = hsync_handler;
2165: eventtab[ev_hsync].evtime = maxhpos;
2166: eventtab[ev_hsync].active = true;
2167: #ifdef DEFERRED_INT
2168: eventtab[ev_deferint].handler = defer_int_handler;
2169: eventtab[ev_deferint].active = false;
2170: deferred_bits = 0;
2171: #endif
2172: events_schedule();
2173:
2174: #ifdef __unix
2175: gettimeofday(&tv,NULL);
2176: seconds_base = tv.tv_sec;
2177: bogusframe = true;
2178: #endif
2179: }
2180:
2181: void dumpcustom(void)
2182: {
2183:
2184: printf("DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
2185: intena, intreq, vpos, current_hpos());
2186: if (timeframes) {
2187: printf("Average frame time: %d ms [frames: %d time: %d]\n",
2188: frametime/timeframes, timeframes, frametime);
2189: }
2190: }
2191:
2192: int intlev(void)
2193: {
2194: UWORD imask = intreq & intena;
2195: if (imask && (intena & 0x4000)){
2196: if (imask & 0x2000) return 6;
2197: if (imask & 0x1800) return 5;
2198: if (imask & 0x0780) return 4;
2199: if (imask & 0x0070) return 3;
2200: if (imask & 0x0008) return 2;
2201: if (imask & 0x0007) return 1;
2202: }
2203: return -1;
2204: }
2205:
2206: void custom_init(void)
2207: {
2208: int num;
2209: setfollow();
2210: customreset();
2211: for (num = 0; num < 64; num++) {
2212: int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4);
2213: int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4);
2214: if (plane2 > 0) plane2 += 8;
2215: dblpf_ind1[num] = plane1 == 0 ? plane2 : plane1;
2216: dblpf_ind2[num] = plane2 == 0 ? plane1 : plane2;
2217: }
2218: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.