X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fblitter.cpp;h=d3741948b5fcfcb15ff0c8678fa471b1ccf41c62;hb=d2870630b5d9154a70dfb9005768e882c265a969;hp=888abea7b4fcd8f62c6a1470de376e050846e116;hpb=d6a71ac785c82ec13d802cd0f8c5d758203d7c1e;p=virtualjaguar diff --git a/src/blitter.cpp b/src/blitter.cpp index 888abea..d374194 100644 --- a/src/blitter.cpp +++ b/src/blitter.cpp @@ -6,6 +6,8 @@ // Cleanups/fixes by James L. Hammons // bool specialLog = false; +extern int effect_start; +extern int blit_start_log; #include "jaguar.h" @@ -41,14 +43,14 @@ bool specialLog = false; #define INTENSITYINC ((UINT32)0x70) #define ZINC ((UINT32)0x74) #define COLLISIONCTRL ((UINT32)0x78) -#define PHRASEINT3 ((UINT32)0x7C) -#define PHRASEINT2 ((UINT32)0x80) -#define PHRASEINT1 ((UINT32)0x84) -#define PHRASEINT0 ((UINT32)0x88) -#define PHRASEZ3 ((UINT32)0x8C) -#define PHRASEZ2 ((UINT32)0x90) -#define PHRASEZ1 ((UINT32)0x94) -#define PHRASEZ0 ((UINT32)0x98) +#define PHRASEINT0 ((UINT32)0x7C) +#define PHRASEINT1 ((UINT32)0x80) +#define PHRASEINT2 ((UINT32)0x84) +#define PHRASEINT3 ((UINT32)0x88) +#define PHRASEZ0 ((UINT32)0x8C) +#define PHRASEZ1 ((UINT32)0x90) +#define PHRASEZ2 ((UINT32)0x94) +#define PHRASEZ3 ((UINT32)0x98) // Blitter command bits @@ -80,7 +82,7 @@ bool specialLog = false; #define DCOMPEN (cmd & 0x08000000) #define PATDSEL (cmd & 0x00010000) -#define INTADD (cmd & 0x00020000) +#define ADDDSEL (cmd & 0x00020000) #define TOPBEN (cmd & 0x00004000) #define TOPNEN (cmd & 0x00008000) #define BKGWREN (cmd & 0x10000000) @@ -162,22 +164,22 @@ bool specialLog = false; #define WRITE_ZDATA(a,f,d) WRITE_ZDATA_16(a,d); // 1 bpp r data read -#define READ_RDATA_1(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x>>19)&4)))>>(((UINT32)a##_x>>16)&0x1f))& 0x1 : (REG(r) & 0x1)) +#define READ_RDATA_1(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 19) & 0x04))) >> (((UINT32)a##_x >> 16) & 0x1F)) & 0x0001 : (REG(r) & 0x0001)) // 2 bpp r data read -#define READ_RDATA_2(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x>>18)&4)))>>(((UINT32)a##_x>>15)&0x3e))& 0x3 : (REG(r) & 0x3)) +#define READ_RDATA_2(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 18) & 0x04))) >> (((UINT32)a##_x >> 15) & 0x3E)) & 0x0003 : (REG(r) & 0x0003)) // 4 bpp r data read -#define READ_RDATA_4(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x>>17)&4)))>>(((UINT32)a##_x>>14)&0x28))& 0xf : (REG(r) & 0xf)) +#define READ_RDATA_4(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 17) & 0x04))) >> (((UINT32)a##_x >> 14) & 0x28)) & 0x000F : (REG(r) & 0x000F)) // 8 bpp r data read -#define READ_RDATA_8(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x>>16)&4)))>>(((UINT32)a##_x>>13)&0x18))& 0xff : (REG(r) & 0xff)) +#define READ_RDATA_8(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 16) & 0x04))) >> (((UINT32)a##_x >> 13) & 0x18)) & 0x00FF : (REG(r) & 0x00FF)) // 16 bpp r data read -#define READ_RDATA_16(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x>>15)&4)))>>(((UINT32)a##_x>>12)&0x10))&0xffff : (REG(r) & 0xffff)) +#define READ_RDATA_16(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 15) & 0x04))) >> (((UINT32)a##_x >> 12) & 0x10)) & 0xFFFF : (REG(r) & 0xFFFF)) // 32 bpp r data read -#define READ_RDATA_32(r,a,p) ((p) ? REG(r+(((UINT32)a##_x>>14)&4)) : REG(r)) +#define READ_RDATA_32(r,a,p) ((p) ? REG(r+(((UINT32)a##_x >> 14) & 0x04)) : REG(r)) // register data read #define READ_RDATA(r,a,f,p) (\ @@ -244,7 +246,7 @@ static uint8 blitter_ram[0x100]; // as a floating point bit pattern being followed by a number of zeroes. So, e.g., 001101 translates to // 1.01 (the "1." being implied) x (2 ^ 3) or 1010 -> 10 in base 10 (i.e., 1.01 with the decimal place // being shifted to the right 3 places). -static uint32 blitter_scanline_width[48] = +/*static uint32 blitter_scanline_width[48] = { 0, 0, 0, 0, // Note: This would really translate to 1, 1, 1, 1 2, 0, 0, 0, @@ -258,7 +260,7 @@ static uint32 blitter_scanline_width[48] = 512, 640, 768, 896, 1024, 1280, 1536, 1792, 2048, 2560, 3072, 3584 -}; +};//*/ //static uint8 * tom_ram_8; //static uint8 * paletteRam; @@ -326,21 +328,53 @@ static int32 a1_clip_x, a1_clip_y; // void blitter_generic(uint32 cmd) { +/* +Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C] + CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN + A1 step values: -2 (X), 1 (Y) + A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000 +*/ +//if (effect_start) +// specialLog = true; +/*if (cmd == 0x1401060C && blit_start_log) + specialLog = true;//*/ //Testing only! //uint32 logGo = ((cmd == 0x01800E01 && REG(A1_BASE) == 0x898000) ? 1 : 0); uint32 srcdata, srczdata, dstdata, dstzdata, writedata, inhibit; + uint32 bppSrc = (DSTA2 ? 1 << ((REG(A1_FLAGS) >> 3) & 0x07) : 1 << ((REG(A2_FLAGS) >> 3) & 0x07)); if (specialLog) { - WriteLog("About to do 8x8 blit (BM width is 448 pixels)...\n"); + WriteLog("About to do n x m blit (BM width is ? pixels)...\n"); + WriteLog("A1_STEP_X/Y = %08X/%08X, A2_STEP_X/Y = %08X/%08X\n", a1_step_x, a1_step_y, a2_step_x, a2_step_y); } +/* if (BCOMPEN) + { + if (DSTA2) + a1_xadd = 0; + else + a2_xadd = 0; + }//*/ + while (outer_loop--) { if (specialLog) { WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y); } - uint32 a1_start = a1_x, a2_start = a2_x; + uint32 a1_start = a1_x, a2_start = a2_x, bitPos = 0; + + //Kludge for Hover Strike... + //I wonder if this kludge is in conjunction with the SRCENX down below... + // This isn't so much a kludge but the way things work in BCOMPEN mode...! + if (BCOMPEN && SRCENX) + { + if (n_pixels < bppSrc) + bitPos = bppSrc - n_pixels; + } inner_loop = n_pixels; while (inner_loop--) @@ -351,21 +385,22 @@ if (specialLog) } srcdata = srczdata = dstdata = dstzdata = writedata = inhibit = 0; - if (!DSTA2) + if (!DSTA2) // Data movement: A1 <- A2 { // load src data and Z - if (SRCEN) +// if (SRCEN) + if (SRCEN || SRCENX) // Not sure if this is correct... (seems to be...!) { srcdata = READ_PIXEL(a2, REG(A2_FLAGS)); if (SRCENZ) srczdata = READ_ZDATA(a2, REG(A2_FLAGS)); - else if (cmd & 0x0001C020) + else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode); } - else + else // Use SRCDATA register... { srcdata = READ_RDATA(SRCDATA, a2, REG(A2_FLAGS), a2_phrase_mode); - if (cmd & 0x0001C020) + if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode); } @@ -404,8 +439,81 @@ if (specialLog) // apply data comparator // Note: DCOMPEN only works in 8/16 bpp modes! !!! FIX !!! // Does BCOMPEN only work in 1 bpp mode??? +// No, but it always does a 1 bit expansion no matter what the BPP of the channel is set to. !!! FIX !!! +// This is bit tricky... We need to fix the XADD value so that it acts like a 1BPP value while inside +// an 8BPP space. if (DCOMPEN | BCOMPEN) { +//Temp, for testing Hover Strike +//Doesn't seem to do it... Why? +//What needs to happen here is twofold. First, the address generator in the outer loop has +//to honor the BPP when calculating the start address (which it kinda does already). Second, +//it has to step bit by bit when using BCOMPEN. How to do this??? + if (BCOMPEN) +//small problem with this approach: it's not accurate... We need a proper address to begin with +//and *then* we can do the bit stepping from there the way it's *supposed* to be done... !!! FIX !!! +//[DONE] + { + uint32 pixShift = (~bitPos) & (bppSrc - 1); + srcdata = (srcdata >> pixShift) & 0x01; + + bitPos++; +// if (bitPos % bppSrc == 0) +// a2_x += 0x00010000; + } +/* +Interesting (Hover Strike--large letter): + +Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C] + CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN + A1 step values: -2 (X), 1 (Y) + A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000 + +Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C] + CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN + A1 step values: -8 (X), 1 (Y) + A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 102/12, A2 x/y: 107/0 Pattern: 000000F300000000 + +Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C] + CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN + A1 step values: -1 (X), 1 (Y) + A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 118/12, A2 x/y: 70/0 Pattern: 000000F300000000 + +Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C] + CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN + A1 step values: -8 (X), 1 (Y) + A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 119/12, A2 x/y: 71/0 Pattern: 000000F300000000 + +Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C] + CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN + A1 step values: -1 (X), 1 (Y) + A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 127/12, A2 x/y: 66/0 Pattern: 000000F300000000 + +Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C] + CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN + A1 step values: -8 (X), 1 (Y) + A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 128/12, A2 x/y: 67/0 Pattern: 000000F300000000 +*/ + + if (!CMPDST) { //WriteLog("Blitter: BCOMPEN set on command %08X inhibit prev:%u, now:", cmd, inhibit); @@ -434,6 +542,7 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: else WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A2bpp);//*/ // What it boils down to is this: + if (srcdata == 0) inhibit = 1;//*/ } @@ -459,20 +568,74 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: // compute the write data and store if (!inhibit) { +// Houston, we have a problem... +// Look here, at PATDSEL and GOURD. If both are active (as they are on the BIOS intro), then there's +// a conflict! E.g.: +//Blit! (00100000 <- 000095D0) count: 3 x 1, A1/2_FLAGS: 00014220/00004020 [cmd: 00011008] +// CMD -> src: dst: DSTEN misc: a1ctl: mode: GOURD ity: PATDSEL z-op: op: LFU_CLEAR ctrl: +// A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD +// A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD +// A1 x/y: 90/171, A2 x/y: 808/0 Pattern: 776D770077007700 + if (PATDSEL) { // use pattern data for write data writedata = READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode); } - else if (INTADD) + else if (ADDDSEL) { +/*if (blit_start_log) + WriteLog("BLIT: ADDDSEL srcdata: %08X\, dstdata: %08X, ", srcdata, dstdata);//*/ + // intensity addition - writedata = (srcdata & 0xFF) + (dstdata & 0xFF); +//Ok, this is wrong... Or is it? Yes, it's wrong! !!! FIX !!! +/* writedata = (srcdata & 0xFF) + (dstdata & 0xFF); if (!(TOPBEN) && writedata > 0xFF) - writedata = 0xFF; +// writedata = 0xFF; + writedata &= 0xFF; writedata |= (srcdata & 0xF00) + (dstdata & 0xF00); if (!(TOPNEN) && writedata > 0xFFF) - writedata = 0xFFF; +// writedata = 0xFFF; + writedata &= 0xFFF; + writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);//*/ +//notneeded--writedata &= 0xFFFF; +/*if (blit_start_log) + WriteLog("writedata: %08X\n", writedata);//*/ +/* +Hover Strike ADDDSEL blit: + +Blit! (00098D90 <- 0081DDC0) count: 320 x 287, A1/2_FLAGS: 00004220/00004020 [cmd: 00020208] + CMD -> src: dst: DSTEN misc: a1ctl: UPDA1 mode: ity: ADDDSEL z-op: op: LFU_CLEAR ctrl: + A1 step values: -320 (X), 1 (Y) + A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A1 x/y: 0/0, A2 x/y: 3288/0 Pattern: 0000000000000000 SRCDATA: 00FD00FD00FD00FD +*/ + writedata = (srcdata & 0xFF) + (dstdata & 0xFF); + + if (!TOPBEN) + { +//This is correct now, but slow... + int16 s = (srcdata & 0xFF) | (srcdata & 0x80 ? 0xFF00 : 0x0000), + d = dstdata & 0xFF; + int16 sum = s + d; + + if (sum < 0) + writedata = 0x00; + else if (sum > 0xFF) + writedata = 0xFF; + else + writedata = (uint32)sum; + } + +//This doesn't seem right... Looks like it would muck up the low byte... !!! FIX !!! + writedata |= (srcdata & 0xF00) + (dstdata & 0xF00); + + if (!TOPNEN && writedata > 0xFFF) + { + writedata &= 0xFFF; + } + writedata |= (srcdata & 0xF000) + (dstdata & 0xF000); } else @@ -483,6 +646,10 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: if (LFU_A) writedata |= srcdata & dstdata; } +//Although, this looks like it's OK... (even if it is shitty!) +//According to JTRM, this is part of the four things the blitter does with the write data (the other +//three being PATDSEL, ADDDSEL, and LFU (default). I'm not sure which gets precedence, this or PATDSEL +//(see above blit example)... if (GOURD) writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16); @@ -506,7 +673,9 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: srczdata = dstzdata; } +//Tried 2nd below for Hover Strike: No dice. if (/*a1_phrase_mode || */BKGWREN || !inhibit) +// if (/*a1_phrase_mode || BKGWREN ||*/ !inhibit) { /*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5) { @@ -521,7 +690,7 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: WRITE_ZDATA(a1, REG(A1_FLAGS), srczdata); } } - else // if (DSTA2) + else // if (DSTA2) // Data movement: A1 -> A2 { // load src data and Z if (SRCEN) @@ -529,13 +698,13 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: srcdata = READ_PIXEL(a1, REG(A1_FLAGS)); if (SRCENZ) srczdata = READ_ZDATA(a1, REG(A1_FLAGS)); - else if (cmd & 0x0001C020) + else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode); } else { srcdata = READ_RDATA(SRCDATA, a1, REG(A1_FLAGS), a1_phrase_mode); - if (cmd & 0x001C020) + if (cmd & 0x001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode); } @@ -616,7 +785,7 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: // use pattern data for write data writedata= READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode); } - else if (INTADD) + else if (ADDDSEL) { // intensity addition writedata = (srcdata & 0xFF) + (dstdata & 0xFF); @@ -672,16 +841,36 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: }//*/ // write to the destination WRITE_PIXEL(a2, REG(A2_FLAGS), writedata); + if (DSTWRZ) WRITE_ZDATA(a2, REG(A2_FLAGS), srczdata); } } - // update x and y - a1_x += a1_xadd; - a1_y += a1_yadd; - a2_x = (a2_x + a2_xadd) & a2_mask_x; - a2_y = (a2_y + a2_yadd) & a2_mask_y; + // Update x and y (inner loop) +//Now it does! But crappy, crappy, crappy! !!! FIX !!! [DONE] +//This is less than ideal, but it works... + if (!BCOMPEN) + {//*/ + a1_x += a1_xadd, a1_y += a1_yadd; + a2_x = (a2_x + a2_xadd) & a2_mask_x, a2_y = (a2_y + a2_yadd) & a2_mask_y; + } + else + { + a1_y += a1_yadd, a2_y = (a2_y + a2_yadd) & a2_mask_y; + if (!DSTA2) + { + a1_x += a1_xadd; + if (bitPos % bppSrc == 0) + a2_x = (a2_x + a2_xadd) & a2_mask_x; + } + else + { + a2_x = (a2_x + a2_xadd) & a2_mask_x; + if (bitPos % bppSrc == 0) + a1_x += a1_xadd; + } + }//*/ if (GOURZ) z_i[colour_index] += zadd; @@ -689,17 +878,66 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: if (GOURD || SRCSHADE) { gd_i[colour_index] += gd_ia; +//Hmm, this doesn't seem to do anything... +//But it is correct according to the JTRM...! +if ((int32)gd_i[colour_index] < 0) + gd_i[colour_index] = 0; +if (gd_i[colour_index] > 0x00FFFFFF) + gd_i[colour_index] = 0x00FFFFFF;//*/ + gd_c[colour_index] += gd_ca; +if ((int32)gd_c[colour_index] < 0) + gd_c[colour_index] = 0; +if (gd_c[colour_index] > 0x000000FF) + gd_c[colour_index] = 0x000000FF;//*/ } + if (GOURD || SRCSHADE || GOURZ) { if (a1_phrase_mode) +//This screws things up WORSE (for the BIOS opening screen) +// if (a1_phrase_mode || a2_phrase_mode) colour_index = (colour_index + 1) & 0x03; } } +/* +Here's the problem... The phrase mode code! +Blit! (00100000 -> 00148000) count: 327 x 267, A1/2_FLAGS: 00004420/00004420 [cmd: 41802E01] + CMD -> src: SRCEN dst: misc: a1ctl: UPDA1 UPDA2 mode: DSTA2 GOURZ ity: z-op: op: LFU_REPLACE ctrl: SRCSHADE + A1 step values: -327 (X), 1 (Y) + A2 step values: -327 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A1 x/y: 28/58, A2 x/y: 28/58 Pattern: 00EA7BEA77EA77EA SRCDATA: 7BFF7BFF7BFF7BFF + +Below fixes it, but then borks: +; O + +Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609] + CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN + A1 step values: -15 (X), 1 (Y) + A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A1 x/y: 173/144, A2 x/y: 4052/0 + +Lesse, with pre-add we'd have: + + oooooooooooo +00001111222233334444555566667777 + ^ ^starts here... + | ^ends here. + |rolls back to here. Hmm. + +*/ + a1_x += a1_step_x; + a1_y += a1_step_y; + a2_x += a2_step_x; + a2_y += a2_step_y;//*/ + //New: Phrase mode taken into account! :-p - if (a1_phrase_mode) +/* if (a1_phrase_mode) // v1 { // Bump the pointer to the next phrase boundary // Even though it works, this is crappy... Clean it up! @@ -716,16 +954,32 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: uint32 newxrem = (a1_x >> 16) % size; a1_x &= 0x0000FFFF; a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16; + }//*/ + if (a1_phrase_mode) // v2 + { + // Bump the pointer to the next phrase boundary + // Even though it works, this is crappy... Clean it up! + uint32 size = 64 / a1_psize; + + // Crappy kludge... ('aligning' source to destination) + if (a2_phrase_mode && DSTA2) + { + uint32 extra = (a2_start >> 16) % size; + a1_x += extra << 16; + } + + uint32 pixelSize = (size - 1) << 16; + a1_x = (a1_x + pixelSize) & ~pixelSize; } - if (a2_phrase_mode) +/* if (a2_phrase_mode) // v1 { // Bump the pointer to the next phrase boundary // Even though it works, this is crappy... Clean it up! uint32 size = 64 / a2_psize; // Crappy kludge... ('aligning' source to destination) - // Prolly should do this for A1 channel as well... + // Prolly should do this for A1 channel as well... [DONE] if (a1_phrase_mode && !DSTA2) { uint32 extra = (a1_start >> 16) % size; @@ -735,25 +989,33 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: uint32 newx = (a2_x >> 16) / size; uint32 newxrem = (a2_x >> 16) % size; a2_x &= 0x0000FFFF; - a2_x |= (((newx + (newxrem == 0 ? 0 : 1) /*+ extra*/) * size) & 0xFFFF) << 16; + a2_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16; + }//*/ + if (a2_phrase_mode) // v1 + { + // Bump the pointer to the next phrase boundary + // Even though it works, this is crappy... Clean it up! + uint32 size = 64 / a2_psize; + + // Crappy kludge... ('aligning' source to destination) + // Prolly should do this for A1 channel as well... [DONE] + if (a1_phrase_mode && !DSTA2) + { + uint32 extra = (a1_start >> 16) % size; + a2_x += extra << 16; + } + + uint32 pixelSize = (size - 1) << 16; + a2_x = (a2_x + pixelSize) & ~pixelSize; } //Not entirely: This still mucks things up... !!! FIX !!! - a1_x += a1_step_x; + //Should this go before or after the phrase mode mucking around? +/* a1_x += a1_step_x; a1_y += a1_step_y; a2_x += a2_step_x; a2_y += a2_step_y;//*/ - -/* if (a2_phrase_mode) - { - a1_x+=(64/a1_psize)*a1_xadd; - } - if (a2_phrase_mode) - { - for (int nb=0;nb<(64/a2_psize)+1;nb++) - a2_x = (a2_x + a2_xadd) & a2_mask_x; - } -*/ } + } // write values back to registers WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF)); @@ -764,6 +1026,14 @@ specialLog = false; void blitter_blit(uint32 cmd) { +//Apparently this is doing *something*, just not sure exactly what... +/*if (cmd == 0x41802E01) +{ + WriteLog("BLIT: Found our blit. Was: %08X ", cmd); + cmd = 0x01800E01; + WriteLog("Is: %08X\n", cmd); +}//*/ + uint32 pitchValue[4] = { 0, 1, 3, 2 }; colour_index = 0; src = cmd & 0x07; @@ -800,6 +1070,8 @@ void blitter_blit(uint32 cmd) //But it seems to fuck up T2K! !!! FIX !!! //Could it be sign extended??? Doesn't seem to be so according to JTRM // a1_x &= 0x7FFFFFFF, a1_y &= 0x0FFFFFFF; +//Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12... +// a1_y &= 0x0FFFFFFF; // a1_width = blitter_scanline_width[((REG(A1_FLAGS) & 0x00007E00) >> 9)]; // According to JTRM, this must give a *whole number* of phrases in the current @@ -812,6 +1084,8 @@ void blitter_blit(uint32 cmd) //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12. //But it seems to fuck up T2K! !!! FIX !!! // a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF; +//Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12... +// a2_y &= 0x0FFFFFFF; // a2_width = blitter_scanline_width[((REG(A2_FLAGS) & 0x00007E00) >> 9)]; // According to JTRM, this must give a *whole number* of phrases in the current @@ -855,10 +1129,24 @@ void blitter_blit(uint32 cmd) break; case XADDINC: // add the contents of the increment register - a1_xadd = (REG(A1_INC) << 16) | (REG(A1_FINC) & 0xFFFF); + a1_xadd = (REG(A1_INC) << 16) | (REG(A1_FINC) & 0x0000FFFF); a1_yadd = (REG(A1_INC) & 0xFFFF0000) | (REG(A1_FINC) >> 16); break; } + + +//Blit! (0011D000 -> 000B9600) count: 228 x 1, A1/2_FLAGS: 00073820/00064220 [cmd: 41802801] +// A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 128 (1C), addctl: XADDINC YADD1 XSIGNADD YSIGNADD +// A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADD0 YADD1 XSIGNADD YSIGNADD +//if (YADD1_A1 && YADD1_A2 && xadd_a2_control == XADD0 && xadd_a1_control == XADDINC)// && +// UINT32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS); +//Ok, so this ISN'T it... Prolly the XADDPHR code above that's doing it... +//if (REG(A1_FLAGS) == 0x00073820 && REG(A2_FLAGS) == 0x00064220 && cmd == 0x41802801) +// A1 x/y: 14368/7, A2 x/y: 150/36 +//This is it... The problem... +//if ((a1_x >> 16) == 14368) // 14368 = $3820 +// return; //Lesse what we got... + if (XSIGNSUB_A1) a1_xadd = -a1_xadd; @@ -892,6 +1180,7 @@ WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n"); // a2_xadd = 1 << 16; break; } + if (XSIGNSUB_A2) a2_xadd = -a2_xadd; @@ -922,129 +1211,64 @@ WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n"); a1_clip_x = REG(A1_CLIP) & 0x7FFF, a1_clip_y = (REG(A1_CLIP) >> 16) & 0x7FFF; -// This phrase sizing is incorrect as well... !!! FIX !!! +// This phrase sizing is incorrect as well... !!! FIX !!! [NOTHING TO FIX] // Err, this is pixel size... (and it's OK) a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07); a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07); - // zbuffering + // Z-buffering if (GOURZ) { - zadd = JaguarReadLong(0xF02274, BLITTER); + zadd = REG(ZINC); - for(int v=0; v<4; v++) - z_i[v] = (int32)JaguarReadLong(0xF0228C + (v << 2), BLITTER); + for(int v=0; v<4; v++) + z_i[v] = REG(PHRASEZ0 + v*4); } + + // Gouraud shading if (GOURD || GOURZ || SRCSHADE) { - // gouraud shading - gouraud_add = JaguarReadLong(0xF02270, BLITTER); + gd_c[0] = blitter_ram[PATTERNDATA + 0]; + gd_i[0] = ((uint32)blitter_ram[PATTERNDATA + 1] << 16) + | ((uint32)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 1]; + + gd_c[1] = blitter_ram[PATTERNDATA + 2]; + gd_i[1] = ((uint32)blitter_ram[PATTERNDATA + 3] << 16) + | ((uint32)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 3]; + + gd_c[2] = blitter_ram[PATTERNDATA + 4]; + gd_i[2] = ((uint32)blitter_ram[PATTERNDATA + 5] << 16) + | ((uint32)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 5]; + + gd_c[3] = blitter_ram[PATTERNDATA + 6]; + gd_i[3] = ((uint32)blitter_ram[PATTERNDATA + 7] << 16) + | ((uint32)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 7]; + + gouraud_add = REG(INTENSITYINC); - gd_c[0] = JaguarReadByte(0xF02268, BLITTER); - gd_i[0] = JaguarReadByte(0xF02269, BLITTER); - gd_i[0] <<= 16; - gd_i[0] |= JaguarReadWord(0xF02240, BLITTER); - - gd_c[1] = JaguarReadByte(0xF0226A, BLITTER); - gd_i[1] = JaguarReadByte(0xF0226B, BLITTER); - gd_i[1] <<= 16; - gd_i[1] |= JaguarReadWord(0xF02242, BLITTER); - - gd_c[2] = JaguarReadByte(0xF0226C, BLITTER); - gd_i[2] = JaguarReadByte(0xF0226D, BLITTER); - gd_i[2] <<= 16; - gd_i[2] |= JaguarReadWord(0xF02244, BLITTER); - - gd_c[3] = JaguarReadByte(0xF0226E, BLITTER); - gd_i[3] = JaguarReadByte(0xF0226F, BLITTER); - gd_i[3] <<= 16; - gd_i[3] |= JaguarReadWord(0xF02246, BLITTER); - - gd_ia = gouraud_add & 0xFFFFFF; - if (gd_ia & 0x800000) + gd_ia = gouraud_add & 0x00FFFFFF; + if (gd_ia & 0x00800000) gd_ia = 0xFF000000 | gd_ia; - gd_ca = (gouraud_add>>24) & 0xFF; - if (gd_ca & 0x80) + gd_ca = (gouraud_add >> 24) & 0xFF; + if (gd_ca & 0x00000080) gd_ca = 0xFFFFFF00 | gd_ca; } - // fix for zoop! and syndicate -/* if ((jaguar_mainRom_crc32==0x501be17c)|| - (jaguar_mainRom_crc32==0x70895c51)|| - (jaguar_mainRom_crc32==0x0f1f1497)|| - (jaguar_mainRom_crc32==0xfc8f0dcd) - ) - { - if (a1_step_x < 0) - a1_step_x = (-n_pixels) * 65536; - - if (a2_step_x < 0) - a2_step_x = (-n_pixels) * 65536;; - } - else - // fix for wolfenstein 3d - if (jaguar_mainRom_crc32==0x3966698f) + // Bit comparitor fixing... +/* if (BCOMPEN) { - if (n_pixels==24) - { - if ((a1_step_x / 65536)==-28) - { - a1_step_x=-24*65536; // au lieu de -28 - a2_step_x= 0*65536; // au lieu de -8 - } - } - } - else - // fix for Tempest 2000 - if (jaguar_mainRom_crc32==0x32816d44) + // Determine the data flow direction... + if (!DSTA2) + a2_step_x /= (1 << ((REG(A2_FLAGS) >> 3) & 0x07)); + else + ;//add this later + }//*/ +/* if (BCOMPEN)//Kludge for Hover Strike... !!! FIX !!! { - - if ((n_lines!=1)&&((n_pixels==288)||(n_pixels==384))) - { - WriteLog("Blit!\n"); - WriteLog(" cmd = 0x%.8x\n",cmd); - WriteLog(" a1_base = %08X\n", a1_addr); - WriteLog(" a1_pitch = %d\n", a1_pitch); - WriteLog(" a1_psize = %d\n", a1_psize); - WriteLog(" a1_width = %d\n", a1_width); - WriteLog(" a1_xadd = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode); - WriteLog(" a1_yadd = %f\n", (float)a1_yadd / 65536.0); - WriteLog(" a1_xstep = %f\n", (float)a1_step_x / 65536.0); - WriteLog(" a1_ystep = %f\n", (float)a1_step_y / 65536.0); - WriteLog(" a1_x = %f\n", (float)a1_x / 65536.0); - WriteLog(" a1_y = %f\n", (float)a1_y / 65536.0); - WriteLog(" a1_zoffs = %i\n",a1_zoffs); - - WriteLog(" a2_base = %08X\n", a2_addr); - WriteLog(" a2_pitch = %d\n", a2_pitch); - WriteLog(" a2_psize = %d\n", a2_psize); - WriteLog(" a2_width = %d\n", a2_width); - WriteLog(" a2_xadd = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode); - WriteLog(" a2_yadd = %f\n", (float)a2_yadd / 65536.0); - WriteLog(" a2_xstep = %f\n", (float)a2_step_x / 65536.0); - WriteLog(" a2_ystep = %f\n", (float)a2_step_y / 65536.0); - WriteLog(" a2_x = %f\n", (float)a2_x / 65536.0); - WriteLog(" a2_y = %f\n", (float)a2_y / 65536.0); - WriteLog(" a2_mask_x= 0x%.4x\n",a2_mask_x); - WriteLog(" a2_mask_y= 0x%.4x\n",a2_mask_y); - WriteLog(" a2_zoffs = %i\n",a2_zoffs); - - WriteLog(" count = %d x %d\n", n_pixels, n_lines); - - WriteLog(" command = %08X\n", cmd); - WriteLog(" dsten = %i\n",DSTEN); - WriteLog(" srcen = %i\n",SRCEN); - WriteLog(" patdsel = %i\n",PATDSEL); - WriteLog(" color = 0x%.8x\n",REG(PATTERNDATA)); - WriteLog(" dcompen = %i\n",DCOMPEN); - WriteLog(" bcompen = %i\n",BCOMPEN); - WriteLog(" cmpdst = %i\n",CMPDST); - WriteLog(" GOURZ = %i\n",GOURZ); - WriteLog(" GOURD = %i\n",GOURD); - WriteLog(" SRCSHADE = %i\n",SRCSHADE); - WriteLog(" DSTDATA = 0x%.8x%.8x\n",REG(DSTDATA),REG(DSTDATA+4)); - } + // Determine the data flow direction... + if (!DSTA2) + a2_x <<= 3; }//*/ #ifdef LOG_BLITS @@ -1193,17 +1417,16 @@ Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: A1 x/y: 173/144, A2 x/y: 4052/0 */ -extern int blit_start_log; -extern int op_start_log; +//extern int op_start_log; if (blit_start_log) { char * ctrlStr[4] = { "XADDPHR\0", "XADDPIX\0", "XADD0\0", "XADDINC\0" }; char * bppStr[8] = { "1bpp\0", "2bpp\0", "4bpp\0", "8bpp\0", "16bpp\0", "32bpp\0", "???\0", "!!!\0" }; char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND", "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" }; - uint32 src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03, - a1ctl = (cmd >> 8) & 0x07, mode = (cmd >> 11) & 0x07, ity = (cmd >> 14) & 0x0F, - zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F; + uint32 /*src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03, + a1ctl = (cmd >> 8) & 0x07,*/ mode = (cmd >> 11) & 0x07/*, ity = (cmd >> 14) & 0x0F, + zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F*/; UINT32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS); uint32 p1 = a1f & 0x07, p2 = a2f & 0x07, d1 = (a1f >> 3) & 0x07, d2 = (a2f >> 3) & 0x07, @@ -1219,8 +1442,8 @@ if (blit_start_log) WriteLog("dst: %s%s%s ", (cmd & 0x0008 ? "DSTEN " : ""), (cmd & 0x0010 ? "DSTENZ " : ""), (cmd & 0x0020 ? "DSTWRZ" : "")); WriteLog("misc: %s%s ", (cmd & 0x0040 ? "CLIP_A1 " : ""), (cmd & 0x0080 ? "???" : "")); WriteLog("a1ctl: %s%s%s ", (cmd & 0x0100 ? "UPDA1F " : ""), (cmd & 0x0200 ? "UPDA1 " : ""), (cmd & 0x0400 ? "UPDA2" : "")); - WriteLog("mode: %s%s%s ", (cmd & 0x0800 ? "DSTA2 " : ""), (cmd & 0x1000 ? "GOURD " : ""), (cmd & 0x2000 ? "ZBUFF" : "")); - WriteLog("ity: %s%s%s ", (cmd & 0x4000 ? "TOPBEN " : ""), (cmd & 0x8000 ? "TOPNEN " : ""), (cmd & 0x00010000 ? "PATDSEL" : "")); + WriteLog("mode: %s%s%s ", (cmd & 0x0800 ? "DSTA2 " : ""), (cmd & 0x1000 ? "GOURD " : ""), (cmd & 0x2000 ? "GOURZ" : "")); + WriteLog("ity: %s%s%s%s ", (cmd & 0x4000 ? "TOPBEN " : ""), (cmd & 0x8000 ? "TOPNEN " : ""), (cmd & 0x00010000 ? "PATDSEL" : ""), (cmd & 0x00020000 ? "ADDDSEL" : "")); WriteLog("z-op: %s%s%s ", (cmd & 0x00040000 ? "ZMODELT " : ""), (cmd & 0x00080000 ? "ZMODEEQ " : ""), (cmd & 0x00100000 ? "ZMODEGT" : "")); WriteLog("op: %s ", opStr[(cmd >> 21) & 0x0F]); WriteLog("ctrl: %s%s%s%s%s%s\n", (cmd & 0x02000000 ? "CMPDST " : ""), (cmd & 0x04000000 ? "BCOMPEN " : ""), (cmd & 0x08000000 ? "DCOMPEN " : ""), (cmd & 0x10000000 ? "BKGWREN " : ""), (cmd & 0x20000000 ? "BUSHI " : ""), (cmd & 0x40000000 ? "SRCSHADE" : "")); @@ -1233,7 +1456,7 @@ if (blit_start_log) WriteLog(" A1 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p1, bppStr[d1], zo1, iw1, w1, ctrlStr[ac1&0x03], (ac1&0x04 ? "YADD1" : "YADD0"), (ac1&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac1&0x10 ? "YSIGNSUB" : "YSIGNADD")); WriteLog(" A2 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p2, bppStr[d2], zo2, iw2, w2, ctrlStr[ac2&0x03], (ac2&0x04 ? "YADD1" : "YADD0"), (ac2&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac2&0x10 ? "YSIGNSUB" : "YSIGNADD")); - WriteLog(" A1 x/y: %d/%d, A2 x/y: %d/%d\n", a1_x >> 16, a1_y >> 16, a2_x >> 16, a2_y >> 16); + WriteLog(" A1 x/y: %d/%d, A2 x/y: %d/%d Pattern: %08X%08X SRCDATA: %08X%08X\n", a1_x >> 16, a1_y >> 16, a2_x >> 16, a2_y >> 16, REG(PATTERNDATA), REG(PATTERNDATA + 4), REG(SRCDATA), REG(SRCDATA + 4)); // blit_start_log = 0; // op_start_log = 1; } @@ -1281,17 +1504,27 @@ uint8 BlitterReadByte(uint32 offset, uint32 who/*=UNKNOWN*/) offset &= 0xFF; // status register +//This isn't cycle accurate--how to fix? !!! FIX !!! if (offset == (0x38 + 3)) return 0x01; // always idle +//Attempted fix for AvP: + if (offset >= 0x04 && offset <= 0x07) +// return (offset > 0x05 ? blitter_ram[PIXLINECOUNTER + offset - 0x04] : 0x00); +// return 0x00; // WO register! What does it expect to see here??? +//This is it. I wonder if it just ignores the lower three bits? + return blitter_ram[A1_PIXEL + offset - 0x04]; + return blitter_ram[offset]; } +//Crappy! uint16 BlitterReadWord(uint32 offset, uint32 who/*=UNKNOWN*/) { return ((uint16)BlitterReadByte(offset, who) << 8) | (uint16)BlitterReadByte(offset+1, who); } +//Crappy! uint32 BlitterReadLong(uint32 offset, uint32 who/*=UNKNOWN*/) { return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who); @@ -1304,32 +1537,53 @@ void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/) offset &= 0xFF; // if ((offset >= 0x7C) && (offset <= 0x9B)) - if ((offset >= 0x7C) && (offset <= 0x8B)) + // This handles writes to INTENSITY0-3 by also writing them to their proper places in + // PATTERNDATA & SOURCEDATA (should do the same for the Z registers! !!! FIX !!! [DONE]) + if ((offset >= 0x7C) && (offset <= 0x9B))//8B)) { switch (offset) { + // INTENSITY registers 0-3 case 0x7C: break; - case 0x7D: blitter_ram[0x69] = data; break; - case 0x7E: blitter_ram[0x40] = data; break; - case 0x7F: blitter_ram[0x41] = data; break; + case 0x7D: blitter_ram[PATTERNDATA + 1] = data; break; + case 0x7E: blitter_ram[SRCDATA + 0] = data; break; + case 0x7F: blitter_ram[SRCDATA + 1] = data; break; case 0x80: break; - case 0x81: blitter_ram[0x6B] = data; break; - case 0x82: blitter_ram[0x42] = data; break; - case 0x83: blitter_ram[0x43] = data; break; + case 0x81: blitter_ram[PATTERNDATA + 3] = data; break; + case 0x82: blitter_ram[SRCDATA + 2] = data; break; + case 0x83: blitter_ram[SRCDATA + 3] = data; break; case 0x84: break; - case 0x85: blitter_ram[0x6D] = data; break; - case 0x86: blitter_ram[0x44] = data; break; - case 0x87: blitter_ram[0x45] = data; break; + case 0x85: blitter_ram[PATTERNDATA + 5] = data; break; + case 0x86: blitter_ram[SRCDATA + 4] = data; break; + case 0x87: blitter_ram[SRCDATA + 5] = data; break; case 0x88: break; - case 0x89: blitter_ram[0x6F] = data; break; -//Mistyped? -// case 0x9A: blitter_ram[0x46] = data; break; -// case 0x9B: blitter_ram[0x47] = data; break; - case 0x8A: blitter_ram[0x46] = data; break; - case 0x8B: blitter_ram[0x47] = data; break; + case 0x89: blitter_ram[PATTERNDATA + 7] = data; break; + case 0x8A: blitter_ram[SRCDATA + 6] = data; break; + case 0x8B: blitter_ram[SRCDATA + 7] = data; break; + + // Z registers 0-3 + case 0x8C: blitter_ram[SRCZINT + 0] = data; break; + case 0x8D: blitter_ram[SRCZINT + 1] = data; break; + case 0x8E: blitter_ram[SRCZFRAC + 0] = data; break; + case 0x8F: blitter_ram[SRCZFRAC + 1] = data; break; + + case 0x90: blitter_ram[SRCZINT + 2] = data; break; + case 0x91: blitter_ram[SRCZINT + 3] = data; break; + case 0x92: blitter_ram[SRCZFRAC + 2] = data; break; + case 0x93: blitter_ram[SRCZFRAC + 3] = data; break; + + case 0x94: blitter_ram[SRCZINT + 4] = data; break; + case 0x95: blitter_ram[SRCZINT + 5] = data; break; + case 0x96: blitter_ram[SRCZFRAC + 4] = data; break; + case 0x97: blitter_ram[SRCZFRAC + 5] = data; break; + + case 0x98: blitter_ram[SRCZINT + 6] = data; break; + case 0x99: blitter_ram[SRCZINT + 7] = data; break; + case 0x9A: blitter_ram[SRCZFRAC + 6] = data; break; + case 0x9B: blitter_ram[SRCZFRAC + 7] = data; break; } } @@ -1338,21 +1592,98 @@ void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/) void BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/) { +//#if 1 +/* if (offset & 0xFF == A1_PIXEL && data == 14368) + { + WriteLog("\n1\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data); +extern bool doGPUDis; +doGPUDis = true; + } + if ((offset & 0xFF) == (A1_PIXEL + 2) && data == 14368) + { + WriteLog("\n2\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data); +extern bool doGPUDis; +doGPUDis = true; + }//*/ +//#endif + BlitterWriteByte(offset+0, (data>>8) & 0xFF, who); BlitterWriteByte(offset+1, data & 0xFF, who); if ((offset & 0xFF) == 0x3A) // I.e., the second write of 32-bit value--not convinced this is the best way to do this! // But then again, according to the Jaguar docs, this is correct...! +{ +/*extern int blit_start_log; +extern bool doGPUDis; +if (blit_start_log) +{ + WriteLog("BLIT: Blitter started by %s...\n", whoName[who]); + doGPUDis = true; +}//*/ blitter_blit(GET32(blitter_ram, 0x38)); -// Testing purposes only! -//This does the clipping correctly, but not the Gouraud shading... -// blitter2_exec(GET32(blitter_ram, 0x38)); +} } //F02278,9,A,B void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/) { +//#if 1 +/* if ((offset & 0xFF) == A1_PIXEL && (data & 0xFFFF) == 14368) + { + WriteLog("\n3\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data); +extern bool doGPUDis; +doGPUDis = true; + }//*/ +//#endif + BlitterWriteWord(offset, data >> 16, who); BlitterWriteWord(offset+2, data & 0xFFFF, who); } + +void LogBlit(void) +{ + uint32 cmd = GET32(blitter_ram, 0x38); + + WriteLog("Blit!\n"); + WriteLog(" cmd = %08X\n", cmd); + WriteLog(" a1_base = %08X\n", a1_addr); + WriteLog(" a1_pitch = %d\n", a1_pitch); + WriteLog(" a1_psize = %d\n", a1_psize); + WriteLog(" a1_width = %d\n", a1_width); + WriteLog(" a1_xadd = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode); + WriteLog(" a1_yadd = %f\n", (float)a1_yadd / 65536.0); + WriteLog(" a1_xstep = %f\n", (float)a1_step_x / 65536.0); + WriteLog(" a1_ystep = %f\n", (float)a1_step_y / 65536.0); + WriteLog(" a1_x = %f\n", (float)a1_x / 65536.0); + WriteLog(" a1_y = %f\n", (float)a1_y / 65536.0); + WriteLog(" a1_zoffs = %i\n",a1_zoffs); + + WriteLog(" a2_base = %08X\n", a2_addr); + WriteLog(" a2_pitch = %d\n", a2_pitch); + WriteLog(" a2_psize = %d\n", a2_psize); + WriteLog(" a2_width = %d\n", a2_width); + WriteLog(" a2_xadd = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode); + WriteLog(" a2_yadd = %f\n", (float)a2_yadd / 65536.0); + WriteLog(" a2_xstep = %f\n", (float)a2_step_x / 65536.0); + WriteLog(" a2_ystep = %f\n", (float)a2_step_y / 65536.0); + WriteLog(" a2_x = %f\n", (float)a2_x / 65536.0); + WriteLog(" a2_y = %f\n", (float)a2_y / 65536.0); + WriteLog(" a2_mask_x= 0x%.4x\n",a2_mask_x); + WriteLog(" a2_mask_y= 0x%.4x\n",a2_mask_y); + WriteLog(" a2_zoffs = %i\n",a2_zoffs); + + WriteLog(" count = %d x %d\n", n_pixels, n_lines); + + WriteLog(" COMMAND = %08X\n", cmd); + WriteLog(" DSTEN = %s\n", (DSTEN ? "1" : "0")); + WriteLog(" SRCEN = %s\n", (SRCEN ? "1" : "0")); + WriteLog(" PATDSEL = %s\n", (PATDSEL ? "1" : "0")); + WriteLog(" COLOR = %08X\n", REG(PATTERNDATA)); + WriteLog(" DCOMPEN = %s\n", (DCOMPEN ? "1" : "0")); + WriteLog(" BCOMPEN = %s\n", (BCOMPEN ? "1" : "0")); + WriteLog(" CMPDST = %s\n", (CMPDST ? "1" : "0")); + WriteLog(" GOURZ = %s\n", (GOURZ ? "1" : "0")); + WriteLog(" GOURD = %s\n", (GOURD ? "1" : "0")); + WriteLog(" SRCSHADE = %s\n", (SRCSHADE ? "1" : "0")); +}