X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fblitter.cpp;h=ce4f0d7a83f539bc337bef7171a54329334d9a95;hb=ba85b1c5daf45e9d78201fb80542b79eb6f8c92d;hp=e21834537ed0ce4f4aff85f957086945373ea9a6;hpb=fa566a2c8ec532eb5325b4d5a663fb2a7d72adc6;p=virtualjaguar diff --git a/src/blitter.cpp b/src/blitter.cpp index e218345..ce4f0d7 100644 --- a/src/blitter.cpp +++ b/src/blitter.cpp @@ -1,33 +1,23 @@ // // Blitter core // -// by cal2 +// Originally by David Raingeard // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS) -// Cleanups/fixes by James L. Hammons +// Extensive cleanups/fixes by James L. Hammons // -//#define GEN_CODE -//#define LOG_BLITS -// Generic blitter it is, until all blitter bugs are squashed! -#define USE_GENERIC_BLITTER - -#include "jaguar.h" -#include "blitter2.h" // Testing purposes only! +bool specialLog = false; +extern int effect_start; +extern int blit_start_log; -#define null 0 -extern int jaguar_active_memory_dumps; +#include "jaguar.h" +#include "blitter.h" #define REG(A) (((uint32)blitter_ram[(A)] << 24) | ((uint32)blitter_ram[(A)+1] << 16) \ | ((uint32)blitter_ram[(A)+2] << 8) | (uint32)blitter_ram[(A)+3]) #define WREG(A,D) (blitter_ram[(A)] = ((D)>>24)&0xFF, blitter_ram[(A)+1] = ((D)>>16)&0xFF, \ blitter_ram[(A)+2] = ((D)>>8)&0xFF, blitter_ram[(A)+3] = (D)&0xFF) -int start_logging = 0; - -// Blitter register RAM (most of it is hidden from the user) - -static uint8 blitter_ram[0x100]; - // Blitter registers (offsets from F02200) #define A1_BASE ((UINT32)0x00) @@ -55,14 +45,14 @@ static uint8 blitter_ram[0x100]; #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 @@ -94,7 +84,7 @@ static uint8 blitter_ram[0x100]; #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) @@ -108,41 +98,48 @@ static uint8 blitter_ram[0x100]; #define XADD0 2 #define XADDINC 3 -#define XSIGNSUB_A1 (REG(A1_FLAGS)&0x80000) -#define XSIGNSUB_A2 (REG(A2_FLAGS)&0x80000) +#define XSIGNSUB_A1 (REG(A1_FLAGS)&0x080000) +#define XSIGNSUB_A2 (REG(A2_FLAGS)&0x080000) #define YSIGNSUB_A1 (REG(A1_FLAGS)&0x100000) #define YSIGNSUB_A2 (REG(A2_FLAGS)&0x100000) -#define YADD1_A1 (REG(A1_FLAGS)&0x40000) -#define YADD1_A2 (REG(A2_FLAGS)&0x40000) +#define YADD1_A1 (REG(A1_FLAGS)&0x040000) +#define YADD1_A2 (REG(A2_FLAGS)&0x040000) +//Put 'em back, once we fix the problem!!! [KO] // 1 bpp pixel read #define PIXEL_SHIFT_1(a) (((~a##_x) >> 16) & 7) #define PIXEL_OFFSET_1(a) (((((UINT32)a##_y >> 16) * a##_width / 8) + (((UINT32)a##_x >> 19) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 19) & 7)) -#define READ_PIXEL_1(a) ((jaguar_byte_read(a##_addr+PIXEL_OFFSET_1(a)) >> PIXEL_SHIFT_1(a)) & 0x01) +#define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER) >> PIXEL_SHIFT_1(a)) & 0x01) +//#define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a)) >> PIXEL_SHIFT_1(a)) & 0x01) // 2 bpp pixel read #define PIXEL_SHIFT_2(a) (((~a##_x) >> 15) & 6) #define PIXEL_OFFSET_2(a) (((((UINT32)a##_y >> 16) * a##_width / 4) + (((UINT32)a##_x >> 18) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 18) & 7)) -#define READ_PIXEL_2(a) ((jaguar_byte_read(a##_addr+PIXEL_OFFSET_2(a)) >> PIXEL_SHIFT_2(a)) & 0x03) +#define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER) >> PIXEL_SHIFT_2(a)) & 0x03) +//#define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a)) >> PIXEL_SHIFT_2(a)) & 0x03) // 4 bpp pixel read #define PIXEL_SHIFT_4(a) (((~a##_x) >> 14) & 4) #define PIXEL_OFFSET_4(a) (((((UINT32)a##_y >> 16) * (a##_width/2)) + (((UINT32)a##_x >> 17) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 17) & 7)) -#define READ_PIXEL_4(a) ((jaguar_byte_read(a##_addr+PIXEL_OFFSET_4(a)) >> PIXEL_SHIFT_4(a)) & 0x0f) +#define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER) >> PIXEL_SHIFT_4(a)) & 0x0f) +//#define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a)) >> PIXEL_SHIFT_4(a)) & 0x0f) // 8 bpp pixel read #define PIXEL_OFFSET_8(a) (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 7)) -#define READ_PIXEL_8(a) (jaguar_byte_read(a##_addr+PIXEL_OFFSET_8(a))) +#define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a), BLITTER)) +//#define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a))) // 16 bpp pixel read #define PIXEL_OFFSET_16(a) (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~3)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 3)) -#define READ_PIXEL_16(a) (jaguar_word_read(a##_addr+(PIXEL_OFFSET_16(a)<<1))) +#define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), BLITTER)) +//#define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1))) // 32 bpp pixel read #define PIXEL_OFFSET_32(a) (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1)) -#define READ_PIXEL_32(a) (jaguar_long_read(a##_addr+(PIXEL_OFFSET_32(a)<<2))) +#define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), BLITTER)) +//#define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2))) // pixel read #define READ_PIXEL(a,f) (\ @@ -155,36 +152,36 @@ static uint8 blitter_ram[0x100]; // 16 bpp z data read #define ZDATA_OFFSET_16(a) (PIXEL_OFFSET_16(a) + a##_zoffs * 4) -#define READ_ZDATA_16(a) (jaguar_word_read(a##_addr+(ZDATA_OFFSET_16(a)<<1))) +#define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), BLITTER)) +//#define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1))) // z data read #define READ_ZDATA(a,f) (READ_ZDATA_16(a)) // 16 bpp z data write -#define WRITE_ZDATA_16(a,d) { jaguar_word_write(a##_addr+(ZDATA_OFFSET_16(a)<<1),d); } -//#define WRITE_ZDATA_16(a,d) { jaguar_word_write(a##_addr+(ZDATA_OFFSET_16(a)<<1),d); \ - WriteLog("16bpp z write --> "); } +#define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d, BLITTER); } +//#define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d); } // z data write #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) (\ @@ -196,27 +193,29 @@ static uint8 blitter_ram[0x100]; (((f>>3)&0x07) == 5) ? (READ_RDATA_32(r,a,p)) : 0) // 1 bpp pixel write -#define WRITE_PIXEL_1(a,d) { jaguar_byte_write(a##_addr+PIXEL_OFFSET_1(a),(jaguar_byte_read(a##_addr+PIXEL_OFFSET_1(a))&(~(0x01 << PIXEL_SHIFT_1(a))))|(d< "); } +//#define WRITE_PIXEL_16(a,d) { JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); } +#define WRITE_PIXEL_16(a,d) { JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), d, BLITTER); if (specialLog) WriteLog("Pixel write address: %08X\n", a##_addr+(PIXEL_OFFSET_16(a)<<1)); } +//#define WRITE_PIXEL_16(a,d) { JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), d); if (specialLog) WriteLog("Pixel write address: %08X\n", a##_addr+(PIXEL_OFFSET_16(a)<<1)); } -//This is where the bad YPOS values are being written... How to fix??? // 32 bpp pixel write -#define WRITE_PIXEL_32(a,d) { jaguar_long_write(a##_addr+(PIXEL_OFFSET_32(a)<<2),d); } -//#define WRITE_PIXEL_32(a,d) { jaguar_long_write(a##_addr+(PIXEL_OFFSET_32(a)<<2),d); \ - WriteLog("32bpp pixel write --> "); } +#define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d, BLITTER); } +//#define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d); } // pixel write #define WRITE_PIXEL(a,f,d) {\ @@ -229,6 +228,19 @@ static uint8 blitter_ram[0x100]; case 5: WRITE_PIXEL_32(a,d); break; \ }} +// External global variables + +extern int jaguar_active_memory_dumps; + +// Local global variables + +int start_logging = 0; +uint8 blitter_working = 0; + +// Blitter register RAM (most of it is hidden from the user) + +static uint8 blitter_ram[0x100]; + // Width in Pixels of a Scanline // This is a pretranslation of the value found in the A1 & A2 flags: It's really a floating point value // of the form EEEEMM where MM is the mantissa with an implied "1." in front of it and the EEEE value is @@ -236,7 +248,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, @@ -250,7 +262,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; @@ -300,473 +312,97 @@ static uint32 gouraud_add; //static uint16 gint[4]; //static uint16 gfrac[4]; //static uint8 gcolour[4]; -static int gd_i[4]; -static int gd_c[4]; -static int gd_ia, gd_ca; -static int colour_index = 0; -static int32 zadd; -static uint32 z_i[4]; - -static uint32 a1_clip_x, a1_clip_y; - -static uint8 blitter_code_cache[4096]; -static uint8 * blitter_ptr; -uint8 blitter_working = 0; - -typedef void (blitter_fn)(void); - -typedef struct s_blitter_cache -{ - uint32 hashcode; - uint8 * code; - uint32 ready; - uint8 used; - struct s_blitter_cache * next; - struct s_blitter_cache * prev; -} s_blitter_code_cache; - -s_blitter_cache * blitter_cache[256]; - -uint8 blitter_cache_init = 0; -static uint8 BPP_LUT[8] = { 1, 2, 4, 8, 16, 32, 0, 0 }; - -FILE * blitters_code_fp; -FILE * blitters_code_init_fp; - -////////////////////////////////////////////////////////////////////////////// -// build C code for the specified blitter -////////////////////////////////////////////////////////////////////////////// -// -// -// -////////////////////////////////////////////////////////////////////////////// -void blitter_gen_c_code(FILE *fp, uint32 cmd,uint32 hashcode) -{ - static uint8 inhibit_modified=0; - - fprintf(fp,"#ifndef blitter_code_0x%.8x\n",hashcode); - fprintf(fp,"#define blitter_code_0x%.8x\n",hashcode); - - fprintf(fp,"void blitter_0x%.8x(void)\n",hashcode); - fprintf(fp,"{\n"); - fprintf(fp,"\twhile (outer_loop--)\n"); - fprintf(fp,"\t{\n"); - fprintf(fp,"\t\tinner_loop=n_pixels;\n"); - fprintf(fp,"\t\twhile (inner_loop--)\n"); - fprintf(fp,"\t\t{\n"); - fprintf(fp,"\t\t\tuint32 srcdata = 0;\n"); - fprintf(fp,"\t\t\tuint32 srczdata = 0;\n"); - fprintf(fp,"\t\t\tuint32 dstdata = 0;\n"); - fprintf(fp,"\t\t\tuint32 dstzdata = 0;\n"); - fprintf(fp,"\t\t\tuint32 writedata = 0;\n"); - fprintf(fp,"\t\t\tuint32 inhibit = 0;\n"); - - char *src; - char *dst; - uint32 src_flags; - uint32 dst_flags; - - if (!DSTA2) - { - src="a2"; - dst="a1"; - src_flags=A2_FLAGS; - dst_flags=A1_FLAGS; - } - else - { - src="a1"; - dst="a2"; - src_flags=A1_FLAGS; - dst_flags=A2_FLAGS; - } - - // load src data and Z - if (SRCEN) - { - fprintf(fp, "\t\t\tsrcdata = READ_PIXEL_%i(%s);\n", BPP_LUT[(((REG(dst_flags)) >> 3) & 0x07)], src); - if (SRCENZ) - fprintf(fp,"\t\t\tsrczdata = READ_ZDATA_%i(%s);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src); - else - if (cmd & 0x001c020) - fprintf(fp,"\t\t\tsrczdata = READ_RDATA_%i(SRCZINT, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(src_flags))>>3)&0x07)],src,src); - } - else - { - fprintf(fp,"\t\t\tsrcdata = READ_RDATA_%i(SRCDATA, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src,src); - if (cmd & 0x001c020) - fprintf(fp,"\t\t\tsrczdata = READ_RDATA_%i(SRCZINT, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src,src); - } - - // load dst data and Z - if (DSTEN) - { - fprintf(fp,"\t\t\tdstdata = READ_PIXEL_%i(%s);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst); - if (DSTENZ) - fprintf(fp,"\t\t\tdstzdata = READ_ZDATA_%i(%s);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst); - else - fprintf(fp,"\t\t\tdstzdata = READ_RDATA_%i(DSTZ, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst); - } - else - { - fprintf(fp,"\t\t\tdstdata = READ_RDATA_%i(DSTDATA, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst); - - if (DSTENZ) - fprintf(fp,"\t\t\tdstzdata = READ_RDATA_%i(DSTZ, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst); - } - - // a1 clipping - if ((cmd & 0x00000040)&&(!DSTA2)) - - { - fprintf(fp,"\t\t\tif (a1_x < 0 || a1_y < 0 || (a1_x >> 16) >= (REG(A1_CLIP) & 0x7fff) || (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7fff)) inhibit = 1;\n"); - inhibit_modified=1; - } - if(GOURZ) - { - fprintf(fp,"\t\t\tsrczdata=z_i[colour_index]>>16;\n"); - } - // apply z comparator - if (Z_OP_INF) { fprintf(fp,"\t\t\tif (srczdata < dstzdata) inhibit = 1;\n"); inhibit_modified=1;} - if (Z_OP_EQU) { fprintf(fp,"\t\t\tif (srczdata == dstzdata) inhibit = 1;\n"); inhibit_modified=1;} - if (Z_OP_SUP) { fprintf(fp,"\t\t\tif (srczdata > dstzdata) inhibit = 1;\n"); inhibit_modified=1;} - - // apply data comparator - if (DCOMPEN) - { - if (!CMPDST) - { - // compare source pixel with pattern pixel - fprintf(fp,"\t\t\tif (srcdata == READ_RDATA_%i(PATTERNDATA, %s,%s_phrase_mode)) inhibit=1;\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src,src); - inhibit_modified=1; - } - else - { - // compare destination pixel with pattern pixel - fprintf(fp,"\t\t\tif (dstdata == READ_RDATA_%i(PATTERNDATA, %s,%s_phrase_mode)) inhibit=1;\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst); - inhibit_modified=1; - } - } - - // compute the write data and store - if (inhibit_modified) fprintf(fp,"\t\t\tif (!inhibit)\n\t\t\t{\n"); - if (PATDSEL) - { - // use pattern data for write data - fprintf(fp,"\t\t\t\twritedata= READ_RDATA_%i(PATTERNDATA, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst); - } - else - if (INTADD) - { - // intensity addition - fprintf(fp,"\t\t\t\twritedata = (srcdata & 0xff) + (dstdata & 0xff);\n"); - if (!(TOPBEN)) - fprintf(fp,"\t\t\t\tif (writedata > 0xff) writedata = 0xff;\n"); - - fprintf(fp,"\t\t\t\twritedata |= (srcdata & 0xf00) + (dstdata & 0xf00);\n"); - if (!(TOPNEN)) fprintf(fp,"\t\t\t\tif (writedata > 0xfff) writedata = 0xfff;\n"); - fprintf(fp,"\t\t\t\twritedata |= (srcdata & 0xf000) + (dstdata & 0xf000);\n"); - } - else - { - if (LFU_NAN) fprintf(fp,"\t\t\t\twritedata |= ~srcdata & ~dstdata;\n"); - if (LFU_NA) fprintf(fp,"\t\t\t\twritedata |= ~srcdata & dstdata;\n"); - if (LFU_AN) fprintf(fp,"\t\t\t\twritedata |= srcdata & ~dstdata;\n"); - if (LFU_A) fprintf(fp,"\t\t\t\twritedata |= srcdata & dstdata;\n"); - } - if(GOURD) - { - fprintf(fp,"\t\t\t\twritedata = ((gd_c[colour_index])<<8)|(gd_i[colour_index]>>16);\n"); - } - if(SRCSHADE) - { - fprintf(fp,"\t\t\t\t{\n"); - fprintf(fp,"\t\t\t\tint intensity = srcdata & 0xFF;\n"); - fprintf(fp,"\t\t\t\tint ia = gd_ia >> 16;\n"); - fprintf(fp,"\t\t\t\tif(ia & 0x80)\n"); - fprintf(fp,"\t\t\t\t ia = 0xFFFFFF00 | ia;\n"); - fprintf(fp,"\t\t\t\tintensity += ia;\n"); - fprintf(fp,"\t\t\t\tif(intensity < 0)\n"); - fprintf(fp,"\t\t\t\t intensity = 0;\n"); - fprintf(fp,"\t\t\t\tif(intensity > 0xFF)\n"); - fprintf(fp,"\t\t\t\t intensity = 0xFF;\n"); - fprintf(fp,"\t\t\t\twritedata = (srcdata & 0xFF00) | intensity;\n"); - fprintf(fp,"\t\t\t\t}\n"); - } - if (inhibit_modified) - { - fprintf(fp,"\t\t\t} else { srczdata=dstzdata; writedata=dstdata; }\n"); - } +static int gd_i[4]; +static int gd_c[4]; +static int gd_ia, gd_ca; +static int colour_index = 0; +static int32 zadd; +static uint32 z_i[4]; - if ((DSTA2?a2_phrase_mode:a1_phrase_mode) || BKGWREN) - { - // write to the destination - fprintf(fp,"\t\t\tWRITE_PIXEL_%i(%s, writedata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst); - if (DSTWRZ) fprintf(fp,"\t\t\tWRITE_ZDATA_%i(%s, srczdata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst); - } - else - { - if (inhibit_modified) fprintf(fp,"\t\t\tif (!inhibit)\n\t\t\t{\n"); - // write to the destination - fprintf(fp,"\t\t\t\tWRITE_PIXEL_%i(%s, writedata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst); - if (DSTWRZ) fprintf(fp,"\t\t\t\tWRITE_ZDATA_%i(%s, srczdata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst); - if (inhibit_modified) fprintf(fp,"\t\t\t}\n"); - } - // update x and y - fprintf(fp,"\t\t\ta1_x += a1_xadd;\n"); - fprintf(fp,"\t\t\ta1_y += a1_yadd;\n"); - fprintf(fp,"\t\t\ta2_x = (a2_x + a2_xadd) & a2_mask_x;\n"); - fprintf(fp,"\t\t\ta2_y = (a2_y + a2_yadd) & a2_mask_y;\n"); - if (GOURZ) - { - fprintf(fp,"\t\t\tz_i[colour_index]+=zadd;\n"); - } - if ((GOURD)||(SRCSHADE)) - { - fprintf(fp,"\t\t\tgd_i[colour_index] += gd_ia;\n"); - fprintf(fp,"\t\t\tgd_c[colour_index] += gd_ca;\n"); - } - if ((GOURD)||(SRCSHADE)||(GOURZ)) - { - if (a1_phrase_mode) - fprintf(fp,"\t\t\t colour_index=(colour_index+1)&0x3;\n"); - } - fprintf(fp,"\t\t}\n"); +static int32 a1_clip_x, a1_clip_y; - fprintf(fp,"\t\ta1_x+=a1_step_x;\n"); - fprintf(fp,"\t\ta1_y+=a1_step_y;\n"); - fprintf(fp,"\t\ta2_x+=a2_step_x;\n"); - fprintf(fp,"\t\ta2_y+=a2_step_y;\n"); - fprintf(fp,"\t}\n"); - - // write values back to registers - fprintf(fp,"\tWREG(A1_PIXEL, (a1_y & 0xffff0000) | ((a1_x >> 16) & 0xffff));\n"); - fprintf(fp,"\tWREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xffff));\n"); - fprintf(fp,"\tWREG(A2_PIXEL, (a2_y & 0xffff0000) | ((a2_x >> 16) & 0xffff));\n"); - fprintf(fp,"}\n"); - fprintf(fp,"#endif\n"); -} +// In the spirit of "get it right first, *then* optimize" I've taken the liberty +// of removing all the unnecessary code caching. If it turns out to be a good way +// to optimize the blitter, then we may revisit it in the future... -////////////////////////////////////////////////////////////////////////////// -// Generate a start of function in x86 assembly -////////////////////////////////////////////////////////////////////////////// -// -// -// -////////////////////////////////////////////////////////////////////////////// -void blitter_gen_start_of_function(void) -{ - *blitter_ptr++ = 0x55; // push ebp - *blitter_ptr++ = 0x8B; // mov ebp,esp - *blitter_ptr++ = 0xEC; -} -////////////////////////////////////////////////////////////////////////////// -// Generate a end of function in x86 assembly -////////////////////////////////////////////////////////////////////////////// -// // +// Generic blit handler // -////////////////////////////////////////////////////////////////////////////// -void blitter_gen_end_of_function(void) +void blitter_generic(uint32 cmd) { - *blitter_ptr++ = 0x8B; // mov esp,ebp - *blitter_ptr++ = 0xE5; - *blitter_ptr++ = 0x5D; // pop ebp - *blitter_ptr++ = 0xC3; // ret -} - -#define HASHCODE_BIT(C,B) if (C) hashcode|=(1< 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)); -uint32 blitter_calc_hashcode(uint32 cmd) -{ - uint32 hashcode=0x00000000; - - // source and destination bit depth - hashcode|=((REG(A1_FLAGS)>>3)&0x07)<<0; - hashcode|=((REG(A2_FLAGS)>>3)&0x07)<<3; - - HASHCODE_BIT(DSTA2, 6); - HASHCODE_BIT(SRCEN, 7); - HASHCODE_BIT(SRCENZ, 8); - HASHCODE_BIT(DSTEN, 9); - HASHCODE_BIT(DSTENZ, 10); - HASHCODE_BIT(Z_OP_INF, 11); - HASHCODE_BIT(Z_OP_EQU, 12); - HASHCODE_BIT(Z_OP_SUP, 13); - HASHCODE_BIT(DCOMPEN, 14); - HASHCODE_BIT(CMPDST, 15); - HASHCODE_BIT(PATDSEL, 16); - HASHCODE_BIT(INTADD, 17); - HASHCODE_BIT(TOPBEN, 18); - HASHCODE_BIT(TOPNEN, 19); - HASHCODE_BIT(LFU_NAN, 20); - HASHCODE_BIT(LFU_NA, 21); - HASHCODE_BIT(LFU_AN, 22); - HASHCODE_BIT(LFU_A, 23); - HASHCODE_BIT(BKGWREN, 24); - HASHCODE_BIT(DSTWRZ, 25); - HASHCODE_BIT((cmd & 0x001c020), 26); // extra data read/write - HASHCODE_BIT((cmd & 0x00000040), 27); // source clipping - HASHCODE_BIT(a1_phrase_mode, 28); - HASHCODE_BIT(a2_phrase_mode, 29); - - return(hashcode); -} -////////////////////////////////////////////////////////////////////////////// -// Build the blitter code for the current blitter operation in the cache -////////////////////////////////////////////////////////////////////////////// -// -// -// -////////////////////////////////////////////////////////////////////////////// -void blitter_build_cached_code(uint32 cmd, uint32 cache_index) +if (specialLog) { + 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); } -////////////////////////////////////////////////////////////////////////////// -// Check if the blitter code for the current blitter operation is cached -////////////////////////////////////////////////////////////////////////////// -// -// -// -////////////////////////////////////////////////////////////////////////////// -struct s_blitter_cache * blitter_in_cache(uint32 cmd) -{ - uint32 i; - uint32 hashcode=blitter_calc_hashcode(cmd); -#ifdef LOG_BLITS - WriteLog("blitter: hashcode= 0x%.8x\n",hashcode); -#endif - struct s_blitter_cache *blitter_list=blitter_cache[hashcode>>24]; - - i=0; - while (blitter_list->next) +/* if (BCOMPEN) { - blitter_list=blitter_list->next; - - if (blitter_list->hashcode==hashcode) - return(blitter_list); - } -#ifdef GEN_CODE - blitter_list->next=(struct s_blitter_cache *)malloc(sizeof(struct s_blitter_cache)); - blitter_list->next->prev=blitter_list; - blitter_list->next->next=null; - blitter_list=blitter_list->next; - - blitter_list->code=(uint8*)malloc(4096); - blitter_list->hashcode=hashcode; - blitter_list->ready=0; - blitter_gen_c_code(blitters_code_fp,cmd,hashcode); - fprintf(blitters_code_init_fp,"\tblitter_add(0x%.8x,(uint8*)&blitter_0x%.8x);\n",hashcode,hashcode); -#else - //WriteLog("warning: using generic blitter for blitter 0x%.8x\n",hashcode); -#endif - return(null); -} -#ifndef USE_GENERIC_BLITTER -#include "include/blit_c.h" -#endif -////////////////////////////////////////////////////////////////////////////// -// Execute the cached blitter code for the current blitter operation -////////////////////////////////////////////////////////////////////////////// -// -// -// -////////////////////////////////////////////////////////////////////////////// -uint32 blitter_execute_cached_code(struct s_blitter_cache * blitter) -{ - if ((blitter == null) || (blitter->ready == 0)) - return 0; - - blitter_fn * fn = (blitter_fn *)blitter->code; - blitter->used = 1; - (*fn)(); - - return 1; -} - -void blitter_add(uint32 hashcode, uint8 *code) -{ - struct s_blitter_cache *blitter_list=blitter_cache[(hashcode>>24)]; - -// WriteLog("adding blitter for hashcode 0x%.8x\n",hashcode); + if (DSTA2) + a1_xadd = 0; + else + a2_xadd = 0; + }//*/ - while (blitter_list->next) + while (outer_loop--) { - blitter_list=blitter_list->next; - - if (blitter_list->hashcode==hashcode) - return; - } - blitter_list->next=(struct s_blitter_cache *)malloc(sizeof(struct s_blitter_cache)); - blitter_list->next->prev=blitter_list; - blitter_list->next->next=null; - blitter_list=blitter_list->next; - - blitter_list->code=code; - blitter_list->hashcode=hashcode; - blitter_list->ready=1; - blitter_list->used=0; -} - -void blitter_list(void) +if (specialLog) { -/* - WriteLog("Used blitters list:\n"); - - for (int i=0;i<256;i++) - { - struct s_blitter_cache *blitter_list=blitter_cache[i]; + 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, bitPos = 0; - while (blitter_list->next) + //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) { - blitter_list=blitter_list->next; - if (blitter_list->used) - WriteLog("\t0%.8x\n",blitter_list->hashcode); + if (n_pixels < bppSrc) + bitPos = bppSrc - n_pixels; } - } -*/ -} - -// -// Generic blit handler -// - -void blitter_generic(uint32 cmd) -{ -//Testing only! -//uint32 logGo = ((cmd == 0x01800E01 && REG(A1_BASE) == 0x898000) ? 1 : 0); -/* uint32 srcdata = 0; - uint32 srczdata = 0; - uint32 dstdata = 0; - uint32 dstzdata = 0; - uint32 writedata = 0; - uint32 inhibit = 0;*/ - uint32 srcdata, srczdata, dstdata, dstzdata, writedata, inhibit; - - while (outer_loop--) - { inner_loop = n_pixels; while (inner_loop--) { +if (specialLog) +{ + WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y); +} 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); } @@ -805,8 +441,81 @@ void blitter_generic(uint32 cmd) // 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); @@ -835,9 +544,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: -// ***CHECK*** Hmm. Seems to cause Rayman to freeze. Investigate. -// This doesn't seem to be it. Hmm. -// It was a bug in the TOM read word code (reading VC) + if (srcdata == 0) inhibit = 1;//*/ } @@ -848,9 +555,10 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: // if (dstdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode)) inhibit = 1; } + // This is DEFINITELY WRONG - if (a1_phrase_mode || a2_phrase_mode) - inhibit = !inhibit; +// if (a1_phrase_mode || a2_phrase_mode) +// inhibit = !inhibit; } if (CLIPA1) @@ -862,20 +570,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 @@ -886,6 +648,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); @@ -909,9 +675,10 @@ 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) { -// This is the sole source of the bogus YPOS values being written to the object list... !!! FIX !!! /*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5) { uint32 offset = a1_addr+(PIXEL_OFFSET_32(a1)<<2); @@ -925,7 +692,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) @@ -933,13 +700,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); } @@ -990,9 +757,6 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: else WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A1bpp);//*/ // What it boils down to is this: -// ***CHECK*** Hmm. Seems to cause Rayman to freeze. Investigate. -// This doesn't seem to be it. Hmm. -// It was a bug in the TOM read word code (reading VC) if (srcdata == 0) inhibit = 1;//*/ } @@ -1003,8 +767,10 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: // if (dstdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode)) inhibit = 1; } - if (a1_phrase_mode || a2_phrase_mode) - inhibit =! inhibit; + +// This is DEFINITELY WRONG +// if (a1_phrase_mode || a2_phrase_mode) +// inhibit = !inhibit; } if (CLIPA1) @@ -1021,7 +787,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); @@ -1077,16 +843,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; @@ -1094,39 +880,165 @@ 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. + +*/ +//NOTE: The way to fix the CD BIOS is to uncomment below and comment the stuff after +// the phrase mode mucking around. But it fucks up everything else... a1_x += a1_step_x; a1_y += a1_step_y; a2_x += a2_step_x; - a2_y += a2_step_y; + a2_y += a2_step_y;//*/ -/* if (a2_phrase_mode) + //New: Phrase mode taken into account! :-p +/* if (a1_phrase_mode) // v1 { - a1_x+=(64/a1_psize)*a1_xadd; - } - if (a2_phrase_mode) + // 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 newx = (a1_x >> 16) / size; + uint32 newxrem = (a1_x >> 16) % size; + a1_x &= 0x0000FFFF; + a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16; + }//*/ + if (a1_phrase_mode) // v2 { - for (int nb=0;nb<(64/a2_psize)+1;nb++) - a2_x = (a2_x + a2_xadd) & a2_mask_x; + // 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) // 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 newx = (a2_x >> 16) / size; + uint32 newxrem = (a2_x >> 16) % size; + a2_x &= 0x0000FFFF; + 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 !!! + //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;//*/ + } // write values back to registers WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF)); WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF)); WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF)); +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; dst = (cmd >> 3) & 0x07; @@ -1138,29 +1050,50 @@ void blitter_blit(uint32 cmd) op = (cmd >> 21) & 0x0F; ctrl = (cmd >> 25) & 0x3F; - a1_addr = REG(A1_BASE); - a2_addr = REG(A2_BASE); + // Addresses in A1/2_BASE are *phrase* aligned, i.e., bottom three bits are ignored! + // NOTE: This fixes Rayman's bad collision detection AND keeps T2K working! + a1_addr = REG(A1_BASE) & 0xFFFFFFF8; + a2_addr = REG(A2_BASE) & 0xFFFFFFF8; a1_zoffs = (REG(A1_FLAGS) >> 6) & 7; a2_zoffs = (REG(A2_FLAGS) >> 6) & 7; xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03; xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03; - a1_pitch = (REG(A1_FLAGS) & 3) ^ ((REG(A1_FLAGS) & 2) >> 1); - a2_pitch = (REG(A2_FLAGS) & 3) ^ ((REG(A2_FLAGS) & 2) >> 1); +// a1_pitch = (REG(A1_FLAGS) & 3) ^ ((REG(A1_FLAGS) & 2) >> 1); +// a2_pitch = (REG(A2_FLAGS) & 3) ^ ((REG(A2_FLAGS) & 2) >> 1); + a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)]; + a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)]; n_pixels = REG(PIXLINECOUNTER) & 0xFFFF; n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF; a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF); a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16); +//According to the JTRM, X is restricted to 15 bits and Y is restricted to 12. +//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 +// pixel size (this means the lookup above is WRONG)... !!! FIX !!! UINT32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F; a1_width = ((0x04 | m) << e) >> 2;//*/ a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16; a2_y = (REG(A2_PIXEL) & 0xFFFF0000); +//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 +// pixel size (this means the lookup above is WRONG)... !!! FIX !!! m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F; a2_width = ((0x04 | m) << e) >> 2;//*/ a2_mask_x = ((REG(A2_MASK) & 0x0000FFFF) << 16) | 0xFFFF; @@ -1200,10 +1133,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; @@ -1230,11 +1177,14 @@ void blitter_blit(uint32 cmd) break; //This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no? case XADDINC: +WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n"); // add the contents of the increment register // since there is no register for a2 we just add 1 - a2_xadd = 1 << 16; +//Let's do nothing, since it's not listed as a valid bit combo... +// a2_xadd = 1 << 16; break; } + if (XSIGNSUB_A2) a2_xadd = -a2_xadd; @@ -1265,129 +1215,64 @@ void blitter_blit(uint32 cmd) 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 = jaguar_long_read(0xF02274); + zadd = REG(ZINC); - for(int v=0; v<4; v++) - z_i[v] = (int32)jaguar_long_read(0xF0228C + (v << 2)); + for(int v=0; v<4; v++) + z_i[v] = REG(PHRASEZ0 + v*4); } + + // Gouraud shading if (GOURD || GOURZ || SRCSHADE) { - // gouraud shading - gouraud_add = jaguar_long_read(0xF02270); + 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] = jaguar_byte_read(0xF02268); - gd_i[0] = jaguar_byte_read(0xF02269); - gd_i[0] <<= 16; - gd_i[0] |= jaguar_word_read(0xF02240); - - gd_c[1] = jaguar_byte_read(0xF0226A); - gd_i[1] = jaguar_byte_read(0xF0226B); - gd_i[1] <<= 16; - gd_i[1] |= jaguar_word_read(0xF02242); - - gd_c[2] = jaguar_byte_read(0xF0226C); - gd_i[2] = jaguar_byte_read(0xF0226D); - gd_i[2] <<= 16; - gd_i[2] |= jaguar_word_read(0xF02244); - - gd_c[3] = jaguar_byte_read(0xF0226E); - gd_i[3] = jaguar_byte_read(0xF0226F); - gd_i[3] <<= 16; - gd_i[3] |= jaguar_word_read(0xF02246); - - 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 @@ -1437,17 +1322,115 @@ void blitter_blit(uint32 cmd) } #endif -extern int blit_start_log; -extern int op_start_log; +//NOTE: Pitch is ignored! + +//This *might* be the altimeter blits (they are)... +//On captured screen, x-pos for black (inner) is 259, for pink is 257 +//Black is short by 3, pink is short by 1... +/* +Blit! (00110000 <- 000BF010) count: 9 x 31, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200] + CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: + 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: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 262/124, A2 x/y: 128/0 +Blit! (00110000 <- 000BF010) count: 5 x 38, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200] + CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: + 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: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 264/117, A2 x/y: 407/0 + +Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200] + CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: + A1 step values: -10 (X), 1 (Y) + A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 262/132, A2 x/y: 129/0 +Blit! (00110000 <- 000BF010) count: 5 x 27, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200] + CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: + A1 step values: -8 (X), 1 (Y) + A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 264/128, A2 x/y: 336/0 + + 264v vCursor ends up here... + xxxxx...` + 111122223333 + +262v vCursor ends up here... + xxxxxxxxx.' + 1111222233334444 + +Fixed! Now for more: + +; This looks like the ship icon in the upper left corner... + +Blit! (00110000 <- 0010B2A8) count: 11 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: -12 (X), 1 (Y) + A2 step values: 0 (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: 20/24, A2 x/y: 5780/0 + +Also fixed! + +More (not sure this is a blitter problem as much as it's a GPU problem): +All but the "M" are trashed... +This does *NOT* look like a blitter problem, as it's rendering properly... +Actually, if you look at the A1 step values, there IS a discrepancy! + +; D + +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: -14 (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: 134/144, A2 x/y: 2516/0 +;129,146: +5,-2 + +; E + +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: -13 (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: 147/144, A2 x/y: 2660/0 + +; M + +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: -12 (X), 1 (Y) + A2 step values: 0 (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: 160/144, A2 x/y: 3764/0 + +; 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 + +*/ +//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, @@ -1463,29 +1446,30 @@ 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" : "")); + if (UPDA1) + WriteLog(" A1 step values: %d (X), %d (Y)\n", a1_step_x >> 16, a1_step_y >> 16); + if (UPDA2) - { WriteLog(" A2 step values: %d (X), %d (Y) [mask (%sused): %08X - %08X/%08X]\n", a2_step_x >> 16, a2_step_y >> 16, (a2f & 0x8000 ? "" : "un"), REG(A2_MASK), a2_mask_x, a2_mask_y); - } 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(" x/y: %d/%d\n", 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; } blitter_working = 1; -#ifndef USE_GENERIC_BLITTER - if (!blitter_execute_cached_code(blitter_in_cache(cmd))) -#endif - blitter_generic(cmd); +//#ifndef USE_GENERIC_BLITTER +// if (!blitter_execute_cached_code(blitter_in_cache(cmd))) +//#endif + blitter_generic(cmd); /*if (blit_start_log) { @@ -1493,10 +1477,10 @@ if (blit_start_log) { WriteLog("\nBytes at 004D58:\n"); for(int i=0x004D58; i<0x004D58+(10*127*4); i++) - WriteLog("%02X ", jaguar_byte_read(i)); + WriteLog("%02X ", JaguarReadByte(i)); WriteLog("\nBytes at F03000:\n"); for(int i=0xF03000; i<0xF03000+(6*127*4); i++) - WriteLog("%02X ", jaguar_byte_read(i)); + WriteLog("%02X ", JaguarReadByte(i)); WriteLog("\n\n"); } }//*/ @@ -1504,123 +1488,206 @@ if (blit_start_log) blitter_working = 0; } -uint32 blitter_long_read(uint32 offset) +void blitter_init(void) { - return (blitter_word_read(offset) << 16) | blitter_word_read(offset+2); + blitter_reset(); } -void blitter_long_write(uint32 offset, uint32 data) +void blitter_reset(void) { - blitter_word_write(offset, data >> 16); - blitter_word_write(offset+2, data & 0xFFFF); + memset(blitter_ram, 0x00, 0xA0); } -void blitter_init(void) +void blitter_done(void) { - if (!blitter_cache_init) - { - for (int i=0;i<256;i++) - { - blitter_cache[i] = (struct s_blitter_cache *)malloc(sizeof(struct s_blitter_cache)); - blitter_cache[i]->next=null; - blitter_cache[i]->prev=null; - } - blitter_cache_init = 1; - } -#ifndef USE_GENERIC_BLITTER - #include "include/blit_i.h" -#endif + WriteLog("BLIT: Done.\n"); +} - blitter_reset(); -#ifdef GEN_CODE - blitters_code_fp = fopen("include/blit_c.h", "awrt"); - blitters_code_init_fp = fopen("include/blit_i.h", "awrt"); -#endif +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]; } -void blitter_reset(void) +//Crappy! +uint16 BlitterReadWord(uint32 offset, uint32 who/*=UNKNOWN*/) { - memset(blitter_ram, 0x00, 0xA0); + return ((uint16)BlitterReadByte(offset, who) << 8) | (uint16)BlitterReadByte(offset+1, who); } -void blitter_done(void) +//Crappy! +uint32 BlitterReadLong(uint32 offset, uint32 who/*=UNKNOWN*/) { -// blitter_list(); -#ifdef GEN_CODE - fclose(blitters_code_fp); - fclose(blitters_code_init_fp); -#endif - WriteLog("BLIT: Done.\n"); + return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who); } -void blitter_byte_write(uint32 offset, uint8 data) +void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/) { /*if (offset & 0xFF == 0x7B) -{ - WriteLog("--> Wrote to B_STOP: value -> %02X\n", data); -}*/ + WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/ 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; } } blitter_ram[offset] = data; } -void blitter_word_write(uint32 offset, uint16 data) +void BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/) { - blitter_byte_write(offset+0, (data>>8) & 0xFF); - blitter_byte_write(offset+1, data & 0xFF); +//#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 -uint8 blitter_byte_read(uint32 offset) +void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/) { - offset &= 0xFF; - - // status register - if (offset == (0x38 + 3)) - return 0x01; // always idle +//#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 - return blitter_ram[offset]; + BlitterWriteWord(offset, data >> 16, who); + BlitterWriteWord(offset+2, data & 0xFFFF, who); } -uint16 blitter_word_read(uint32 offset) +void LogBlit(void) { - return ((uint16)blitter_byte_read(offset) << 8) | (uint16)blitter_byte_read(offset+1); + 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")); }