|
|
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 "sysconfig.h"
10: #include "sysdeps.h"
11:
12: #include "config.h"
13: #include "options.h"
14: #include "events.h"
15: #include "memory.h"
16: #include "custom.h"
17: #include "newcpu.h"
18: #include "blitter.h"
19: #include "blit.h"
20:
21: UWORD bltsize, oldvblts;
22: UWORD bltcon0,bltcon1;
23: ULONG bltapt,bltbpt,bltcpt,bltdpt;
24:
25: int blinea_shift;
26: static UWORD blitlpos, blinea, blineb;
27: static CPTR bltcnxlpt,bltdnxlpt;
28: static int blitline,blitfc,blitfill,blitife,blitdesc,blitsing;
29: static int blitonedot,blitsign;
30: static long int bltwait;
31:
32: struct bltinfo blt_info;
33:
34: static UBYTE blit_filltable[256][4][2];
35:
36: enum blitter_states bltstate;
37:
38: void build_blitfilltable(void)
39: {
40: unsigned int d, fillmask;
41: int i;
42: for (d = 0; d < 256; d++) {
43: for (i = 0; i < 4; i++) {
44: int fc = i & 1;
45: UBYTE data = d;
46: for (fillmask = 1; fillmask != 0x100; fillmask <<= 1) {
47: UWORD tmp = data;
48: if (fc) {
49: if (i & 2)
50: data |= fillmask;
51: else
52: data ^= fillmask;
53: }
54: if (tmp & fillmask) fc = !fc;
55: }
56: blit_filltable[d][i][0] = data;
57: blit_filltable[d][i][1] = fc;
58: }
59: }
60: }
61:
62: static __inline__ UBYTE *blit_xlateptr(CPTR bltpt, int bytecount)
63: {
64: if (!chipmem_bank.check(bltpt,bytecount)) return NULL;
65: return chipmem_bank.xlateaddr(bltpt);
66: }
67:
68: static __inline__ UBYTE *blit_xlateptr_desc(CPTR bltpt, int bytecount)
69: {
70: if (!chipmem_bank.check(bltpt-bytecount, bytecount)) return NULL;
71: return chipmem_bank.xlateaddr(bltpt);
72: }
73:
74: static void blitter_dofast(void)
75: {
76: int i,j;
77: UBYTE *bltadatpt = 0, *bltbdatpt = 0, *bltcdatpt = 0, *bltddatpt = 0;
78: UWORD blitahold, blitbhold, bltaold;
79: UBYTE mt = bltcon0 & 0xFF;
80:
81: if (bltcon0 & 0x800) {
82: bltadatpt = blit_xlateptr(bltapt, (blt_info.hblitsize*2+blt_info.bltamod)*blt_info.vblitsize);
83: bltapt += (blt_info.hblitsize*2+blt_info.bltamod)*blt_info.vblitsize;
84: }
85: if (bltcon0 & 0x400) {
86: bltbdatpt = blit_xlateptr(bltbpt, (blt_info.hblitsize*2+blt_info.bltbmod)*blt_info.vblitsize);
87: bltbpt += (blt_info.hblitsize*2+blt_info.bltbmod)*blt_info.vblitsize;
88: }
89: if (bltcon0 & 0x200) {
90: bltcdatpt = blit_xlateptr(bltcpt, (blt_info.hblitsize*2+blt_info.bltcmod)*blt_info.vblitsize);
91: bltcpt += (blt_info.hblitsize*2+blt_info.bltcmod)*blt_info.vblitsize;
92: }
93: if (bltcon0 & 0x100) {
94: bltddatpt = blit_xlateptr(bltdpt, (blt_info.hblitsize*2+blt_info.bltdmod)*blt_info.vblitsize);
95: bltdpt += (blt_info.hblitsize*2+blt_info.bltdmod)*blt_info.vblitsize;
96: }
97:
98: if (blitfunc_dofast[mt] && !blitfill)
99: (*blitfunc_dofast[mt])(bltadatpt,bltbdatpt,bltcdatpt,bltddatpt,&blt_info);
100: else {
101: /*if (!blitfill) fprintf(stderr, "minterm %x not present\n",mt); */
102: for (j = 0; j < blt_info.vblitsize; j++) {
103: blitfc = !!(bltcon1 & 0x4);
104: for (i = 0; i < blt_info.hblitsize; i++) {
105: if (bltadatpt) { blt_info.bltadat = (*bltadatpt << 8) | *(bltadatpt + 1); bltadatpt += 2; }
106: if (bltbdatpt) { blt_info.bltbdat = (*bltbdatpt << 8) | *(bltbdatpt + 1); bltbdatpt += 2; }
107: if (bltcdatpt) { blt_info.bltcdat = (*bltcdatpt << 8) | *(bltcdatpt + 1); bltcdatpt += 2; }
108: bltaold = blt_info.bltadat;
109: if (i == 0) bltaold &= blt_info.bltafwm;
110: if (i== blt_info.hblitsize-1) bltaold &= blt_info.bltalwm;
111: blitahold = (((ULONG)blt_info.blitpreva << 16) | bltaold) >> blt_info.blitashift;
112: blitbhold = (((ULONG)blt_info.blitprevb << 16) | blt_info.bltbdat) >> blt_info.blitbshift;
113: blt_info.bltddat = blit_func(blitahold, blitbhold, blt_info.bltcdat, mt);
114: if (blitfill) {
115: UWORD d = blt_info.bltddat;
116: int ifemode = blitife ? 2 : 0;
117: int fc1 = blit_filltable[d & 255][ifemode + blitfc][1];
118: blt_info.bltddat = (blit_filltable[d & 255][ifemode + blitfc][0]
119: + (blit_filltable[d >> 8][ifemode + fc1][0] << 8));
120: blitfc = blit_filltable[d >> 8][ifemode + fc1][1];
121: }
122: blt_info.blitpreva = bltaold; blt_info.blitprevb = blt_info.bltbdat;
123: if (blt_info.bltddat) blt_info.blitzero = 0;
124: if (bltddatpt) { *bltddatpt = blt_info.bltddat >> 8; *(bltddatpt+1) = blt_info.bltddat; bltddatpt += 2; }
125: }
126: if (bltadatpt) bltadatpt += blt_info.bltamod;
127: if (bltbdatpt) bltbdatpt += blt_info.bltbmod;
128: if (bltcdatpt) bltcdatpt += blt_info.bltcmod;
129: if (bltddatpt) bltddatpt += blt_info.bltdmod;
130: }
131: }
132: bltstate = BLT_done;
133: }
134:
135: static void blitter_dofast_desc(void)
136: {
137: int i,j;
138: UBYTE *bltadatpt = 0, *bltbdatpt = 0, *bltcdatpt = 0, *bltddatpt = 0;
139: UWORD blitahold, blitbhold, bltaold;
140: UBYTE mt = bltcon0 & 0xFF;
141:
142: if (bltcon0 & 0x800) {
143: bltadatpt = blit_xlateptr_desc(bltapt, (blt_info.hblitsize*2+blt_info.bltamod)*blt_info.vblitsize);
144: bltapt -= (blt_info.hblitsize*2+blt_info.bltamod)*blt_info.vblitsize;
145: }
146: if (bltcon0 & 0x400) {
147: bltbdatpt = blit_xlateptr_desc(bltbpt, (blt_info.hblitsize*2+blt_info.bltbmod)*blt_info.vblitsize);
148: bltbpt -= (blt_info.hblitsize*2+blt_info.bltbmod)*blt_info.vblitsize;
149: }
150: if (bltcon0 & 0x200) {
151: bltcdatpt = blit_xlateptr_desc(bltcpt, (blt_info.hblitsize*2+blt_info.bltcmod)*blt_info.vblitsize);
152: bltcpt -= (blt_info.hblitsize*2+blt_info.bltcmod)*blt_info.vblitsize;
153: }
154: if (bltcon0 & 0x100) {
155: bltddatpt = blit_xlateptr_desc(bltdpt, (blt_info.hblitsize*2+blt_info.bltdmod)*blt_info.vblitsize);
156: bltdpt -= (blt_info.hblitsize*2+blt_info.bltdmod)*blt_info.vblitsize;
157: }
158: if (blitfunc_dofast_desc[mt] && !blitfill)
159: (*blitfunc_dofast_desc[mt])(bltadatpt,bltbdatpt,bltcdatpt,bltddatpt,&blt_info);
160: else {
161: /* if (!blitfill) fprintf(stderr, "minterm %x not present\n",mt);*/
162: for (j = 0; j < blt_info.vblitsize; j++) {
163: blitfc = !!(bltcon1 & 0x4);
164: for (i = 0; i < blt_info.hblitsize; i++) {
165: if (bltadatpt) { blt_info.bltadat = (*bltadatpt << 8) | *(bltadatpt + 1); bltadatpt -= 2; }
166: if (bltbdatpt) { blt_info.bltbdat = (*bltbdatpt << 8) | *(bltbdatpt + 1); bltbdatpt -= 2; }
167: if (bltcdatpt) { blt_info.bltcdat = (*bltcdatpt << 8) | *(bltcdatpt + 1); bltcdatpt -= 2; }
168: bltaold = blt_info.bltadat;
169: if (i == 0) bltaold &= blt_info.bltafwm;
170: if (i== blt_info.hblitsize-1) bltaold &= blt_info.bltalwm;
171: blitahold = (((ULONG)bltaold << 16) | blt_info.blitpreva) >> (16-blt_info.blitashift);
172: blitbhold = (((ULONG)blt_info.bltbdat << 16) | blt_info.blitprevb) >> (16-blt_info.blitbshift);
173: blt_info.bltddat = blit_func(blitahold, blitbhold, blt_info.bltcdat, mt);
174: if (blitfill) {
175: UWORD d = blt_info.bltddat;
176: int ifemode = blitife ? 2 : 0;
177: int fc1 = blit_filltable[d & 255][ifemode + blitfc][1];
178: blt_info.bltddat = (blit_filltable[d & 255][ifemode + blitfc][0]
179: + (blit_filltable[d >> 8][ifemode + fc1][0] << 8));
180: blitfc = blit_filltable[d >> 8][ifemode + fc1][1];
181: }
182: blt_info.blitpreva = bltaold; blt_info.blitprevb = blt_info.bltbdat;
183: if (blt_info.bltddat) blt_info.blitzero = 0;
184: if (bltddatpt) { *bltddatpt = blt_info.bltddat >> 8; *(bltddatpt + 1) = blt_info.bltddat; bltddatpt -= 2; }
185: }
186: if (bltadatpt) bltadatpt -= blt_info.bltamod;
187: if (bltbdatpt) bltbdatpt -= blt_info.bltbmod;
188: if (bltcdatpt) bltcdatpt -= blt_info.bltcmod;
189: if (bltddatpt) bltddatpt -= blt_info.bltdmod;
190: }
191: }
192: bltstate = BLT_done;
193: }
194:
195: static __inline__ int blitter_read(void)
196: {
197: if (bltcon0 & 0xe00){
198: if (!dmaen(DMA_BLITTER)) return 1; /* blitter stopped */
199: if (!blitline){
200: if (bltcon0 & 0x800) blt_info.bltadat = chipmem_bank.wget(bltapt);
201: if (bltcon0 & 0x400) blt_info.bltbdat = chipmem_bank.wget(bltbpt);
202: }
203: if (bltcon0 & 0x200) blt_info.bltcdat = chipmem_bank.wget(bltcpt);
204: }
205: bltstate = BLT_work;
206: return (bltcon0 & 0xE00) != 0;
207: }
208:
209: static __inline__ int blitter_write(void)
210: {
211: if (blt_info.bltddat) blt_info.blitzero = 0;
212: if ((bltcon0 & 0x100) || blitline){
213: if (!dmaen(DMA_BLITTER)) return 1;
214: chipmem_bank.wput(bltdpt, blt_info.bltddat);
215: }
216: bltstate = BLT_next;
217: return (bltcon0 & 0x100) != 0;
218: }
219:
220: static void blitter_blit(void)
221: {
222: UWORD blitahold,blitbhold,blitchold;
223: UWORD bltaold;
224:
225: if (blitdesc) {
226: UWORD bltamask = 0xffff;
227:
228: if (!blitlpos) { bltamask &= blt_info.bltafwm; }
229: if (blitlpos == (blt_info.hblitsize - 1)) { bltamask &= blt_info.bltalwm; }
230: bltaold = blt_info.bltadat & bltamask;
231:
232: blitahold = (((ULONG)bltaold << 16) | blt_info.blitpreva) >> (16-blt_info.blitashift);
233: blitbhold = (((ULONG)blt_info.bltbdat << 16) | blt_info.blitprevb) >> (16-blt_info.blitbshift);
234: blitchold = blt_info.bltcdat;
235: } else {
236: UWORD bltamask = 0xffff;
237:
238: if (!blitlpos) { bltamask &= blt_info.bltafwm; }
239: if (blitlpos == (blt_info.hblitsize - 1)) { bltamask &= blt_info.bltalwm; }
240: bltaold = blt_info.bltadat & bltamask;
241:
242: blitahold = (((ULONG)blt_info.blitpreva << 16) | bltaold) >> blt_info.blitashift;
243: blitbhold = (((ULONG)blt_info.blitprevb << 16) | blt_info.bltbdat) >> blt_info.blitbshift;
244: blitchold = blt_info.bltcdat;
245: }
246: blt_info.bltddat = 0;
247: blt_info.bltddat = blit_func(blitahold, blitbhold, blitchold, bltcon0 & 0xFF);
248: if (blitfill){
249: UWORD fillmask;
250: for (fillmask = 1; fillmask; fillmask <<= 1){
251: UWORD tmp = blt_info.bltddat;
252: if (blitfc) {
253: if (blitife)
254: blt_info.bltddat |= fillmask;
255: else
256: blt_info.bltddat ^= fillmask;
257: }
258: if (tmp & fillmask) blitfc = !blitfc;
259: }
260: }
261: bltstate = BLT_write;
262: blt_info.blitpreva = bltaold; blt_info.blitprevb = blt_info.bltbdat;
263: }
264:
265: static void blitter_nxblit(void)
266: {
267: bltstate = BLT_read;
268: if (blitdesc){
269: if (++blitlpos == blt_info.hblitsize) {
270: if (--blt_info.vblitsize == 0) {
271: bltstate = BLT_done;
272: #if FAST_BLITTER == 0
273: custom_bank.wput(0xDFF09C,0x8040);
274: #endif
275: }
276: blitfc = bltcon1 & 0x4;
277:
278: blitlpos = 0;
279: if (bltcon0 & 0x800) bltapt -= 2+blt_info.bltamod;
280: if (bltcon0 & 0x400) bltbpt -= 2+blt_info.bltbmod;
281: if (bltcon0 & 0x200) bltcpt -= 2+blt_info.bltcmod;
282: if (bltcon0 & 0x100) bltdpt -= 2+blt_info.bltdmod;
283: } else {
284: if (bltcon0 & 0x800) bltapt -= 2;
285: if (bltcon0 & 0x400) bltbpt -= 2;
286: if (bltcon0 & 0x200) bltcpt -= 2;
287: if (bltcon0 & 0x100) bltdpt -= 2;
288: }
289: } else {
290: if (++blitlpos == blt_info.hblitsize) {
291: if (--blt_info.vblitsize == 0) {
292: bltstate = BLT_done;
293: #if FAST_BLITTER == 0
294: custom_bank.wput(0xDFF09C,0x8040);
295: #endif
296: }
297: blitlpos = 0;
298: if (bltcon0 & 0x800) bltapt += 2+blt_info.bltamod;
299: if (bltcon0 & 0x400) bltbpt += 2+blt_info.bltbmod;
300: if (bltcon0 & 0x200) bltcpt += 2+blt_info.bltcmod;
301: if (bltcon0 & 0x100) bltdpt += 2+blt_info.bltdmod;
302: } else {
303: if (bltcon0 & 0x800) bltapt += 2;
304: if (bltcon0 & 0x400) bltbpt += 2;
305: if (bltcon0 & 0x200) bltcpt += 2;
306: if (bltcon0 & 0x100) bltdpt += 2;
307: }
308: }
309: }
310:
311: static __inline__ void blitter_line_incx(void)
312: {
313: if (++blinea_shift == 16) {
314: blinea_shift = 0;
315: bltcnxlpt += 2;
316: bltdnxlpt += 2;
317: }
318: }
319:
320: static __inline__ void blitter_line_decx(void)
321: {
322: if (blinea_shift-- == 0) {
323: blinea_shift = 15;
324: bltcnxlpt -= 2;
325: bltdnxlpt -= 2;
326: }
327: }
328:
329: static __inline__ void blitter_line_decy(void)
330: {
331: bltcnxlpt -= blt_info.bltcmod;
332: bltdnxlpt -= blt_info.bltcmod; /* ??? am I wrong or doesn't KS1.3 set bltdmod? */
333: blitonedot = 0;
334: }
335:
336: static __inline__ void blitter_line_incy(void)
337: {
338: bltcnxlpt += blt_info.bltcmod;
339: bltdnxlpt += blt_info.bltcmod; /* ??? */
340: blitonedot = 0;
341: }
342:
343: static void blitter_line(void)
344: {
345: UWORD blitahold = blinea >> blinea_shift, blitbhold = blineb & 1 ? 0xFFFF : 0, blitchold = blt_info.bltcdat;
346: blt_info.bltddat = 0;
347:
348: if (blitsing && blitonedot) blitahold = 0;
349: blitonedot = 1;
350: blt_info.bltddat = blit_func(blitahold, blitbhold, blitchold, bltcon0 & 0xFF);
351: if (!blitsign){
352: bltapt += (WORD)blt_info.bltamod;
353: if (bltcon1 & 0x10){
354: if (bltcon1 & 0x8)
355: blitter_line_decy();
356: else
357: blitter_line_incy();
358: } else {
359: if (bltcon1 & 0x8)
360: blitter_line_decx();
361: else
362: blitter_line_incx();
363: }
364: } else {
365: bltapt += (WORD)blt_info.bltbmod;
366: }
367: if (bltcon1 & 0x10){
368: if (bltcon1 & 0x4)
369: blitter_line_decx();
370: else
371: blitter_line_incx();
372: } else {
373: if (bltcon1 & 0x4)
374: blitter_line_decy();
375: else
376: blitter_line_incy();
377: }
378: blitsign = 0 > (WORD)bltapt;
379: bltstate = BLT_write;
380: }
381:
382: static __inline__ void blitter_nxline(void)
383: {
384: bltcpt = bltcnxlpt;
385: bltdpt = bltdnxlpt;
386: blineb = (blineb << 1) | (blineb >> 15);
387: if (--blt_info.vblitsize == 0) {
388: bltstate = BLT_done;
389: #if FAST_BLITTER == 0
390: custom_bank.wput(0xDFF09C,0x8040);
391: #endif
392: } else {
393: bltstate = BLT_read;
394: }
395: }
396:
397: static void blit_init(void)
398: {
399: blitlpos = 0;
400: blt_info.blitzero = 1; blt_info.blitpreva = blt_info.blitprevb = 0;
401: blitline = bltcon1 & 1;
402: blt_info.blitashift = bltcon0 >> 12; blt_info.blitbshift = bltcon1 >> 12;
403:
404: if (blitline) {
405: if (blt_info.hblitsize != 2)
406: fprintf(stderr, "weird hblitsize in linemode: %d\n", blt_info.hblitsize);
407: bltcnxlpt = bltcpt;
408: bltdnxlpt = bltdpt;
409: blitsing = bltcon1 & 0x2;
410: blinea = blt_info.bltadat;
411: blineb = (blt_info.bltbdat >> blt_info.blitbshift) | (blt_info.bltbdat << (16-blt_info.blitbshift));
412: #if 0
413: if (blineb != 0xFFFF && blineb != 0)
414: fprintf(stderr, "%x %x %d %x\n", blineb, blt_info.bltbdat, blt_info.blitbshift, bltcon1);
415: #endif
416: blitsign = bltcon1 & 0x40;
417: blitonedot = 0;
418: } else {
419: blitfc = !!(bltcon1 & 0x4);
420: blitife = bltcon1 & 0x8;
421: blitfill = bltcon1 & 0x18;
422: if ((bltcon1 & 0x18) == 0x18) {
423: /* Digital "Trash" demo does this; others too. Apparently, no
424: * negative effects. */
425: static int warn = 1;
426: if (warn)
427: fprintf(stderr, "warning: weird fill mode (further messages suppressed)\n");
428: warn = 0;
429: }
430: blitdesc = bltcon1 & 0x2;
431: if (blitfill && !blitdesc)
432: fprintf(stderr, "warning: blitter fill without desc\n");
433: }
434: }
435:
436: static void actually_do_blit(void)
437: {
438: if (blitline) {
439: do {
440: blitter_read();
441: blitter_line();
442: blitter_write();
443: blitter_nxline();
444: } while (bltstate != BLT_done);
445: } else {
446: /*blitcount[bltcon0 & 0xff]++; blitter debug */
447: if (blitdesc) blitter_dofast_desc();
448: else blitter_dofast();
449: }
450: }
451:
452: void blitter_handler(void)
453: {
454: if (!dmaen(DMA_BLITTER)) {
455: eventtab[ev_blitter].active = 1;
456: eventtab[ev_blitter].oldcycles = cycles;
457: eventtab[ev_blitter].evtime = 10 + cycles; /* wait a little */
458: return; /* gotta come back later. */
459: }
460: actually_do_blit();
461:
462: INTREQ(0x8040);
463: eventtab[ev_blitter].active = 0;
464: regs.spcflags &= ~SPCFLAG_BLTNASTY;
465: }
466:
467: void do_blitter(void)
468: {
469: #if FAST_BLITTER == 0
470: /* I'm not sure all this bltstate stuff is really necessary.
471: * Most programs should be OK if the blit is done as soon as BLTSIZE is
472: * written to, and the BLTFINISH bit is set some time after that.
473: * This code here is nowhere near exact.
474: */
475: do {
476: switch(bltstate) {
477: case BLT_init:
478: blit_init();
479: bltstate = BLT_read;
480: /* fall through */
481: case BLT_read:
482: if (blitter_read())
483: break;
484: /* fall through */
485: case BLT_work:
486: if (blitline)
487: blitter_line();
488: else
489: blitter_blit();
490: /* fall through */
491: case BLT_write:
492: if (blitter_write())
493: break;
494: /* fall through */
495: case BLT_next:
496: if (blitline)
497: blitter_nxline();
498: else
499: blitter_nxblit();
500: break;
501: case BLT_done:
502: regs.spcflags &= ~SPCFLAG_BLIT;
503: break;
504: }
505: } while(bltstate != BLT_done && dmaen(DMA_BLITTER)
506: && dmaen(DMA_BLITPRI)); /* blitter nasty -> no time for CPU */
507: #else
508: {
509: #if FAST_BLITTER < 4
510: long int blit_cycles = 2;
511:
512: if (!blitline) {
513: if (bltcon0 & 0x400)
514: blit_cycles++;
515: if ((bltcon0 & 0x300) == 0x300)
516: blit_cycles++;
517: blit_cycles *= blt_info.vblitsize * blt_info.hblitsize;
518: }
519: #else
520: long int blit_cycles = 1;
521: #endif
522: blit_init();
523:
524: eventtab[ev_blitter].active = 1;
525: eventtab[ev_blitter].oldcycles = cycles;
526: eventtab[ev_blitter].evtime = blit_cycles + cycles;
527: events_schedule();
528:
529: regs.spcflags &= ~SPCFLAG_BLIT;
530: if (dmaen(DMA_BLITPRI))
531: regs.spcflags |= SPCFLAG_BLTNASTY;
532: }
533: #endif
534: }
535:
536: void maybe_blit(void)
537: {
538: static int warned = 0;
539: if (bltstate == BLT_done)
540: return;
541:
542: if (!warned) {
543: warned = 1;
544: fprintf(stderr, "warning: Program does not wait for blitter (no further messages)\n");
545: }
546: if (!eventtab[ev_blitter].active)
547: printf("FOO!!?\n");
548: actually_do_blit();
549: eventtab[ev_blitter].active = 0;
550: regs.spcflags &= ~SPCFLAG_BLTNASTY;
551: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.