/* www.freedo.org The first and only working 3DO multiplayer emulator. The FreeDO licensed under modified GNU LGPL, with following notes: * The owners and original authors of the FreeDO have full right to develop closed source derivative work. * Any non-commercial uses of the FreeDO sources or any knowledge obtained by studying or reverse engineering of the sources, or any other material published by FreeDO have to be accompanied with full credits. * Any commercial uses of FreeDO sources or any knowledge obtained by studying or reverse engineering of the sources, or any other material published by FreeDO is strictly forbidden without owners approval. The above notes are taking precedence over GNU LGPL in conflicting situations. Project authors: Alexander Troosh Maxim Grishin Allen Wright John Sammons Felix Lazarev */ #include "stdafx.h" #include "freedoconfig.h" #include "Madam.h" #include "Clio.h" #include "vdlp.h" #include "arm.h" #include #include #include "bitop.h" BitReaderBig bitoper; #include "freedocore.h" extern _ext_Interface io_interface; /* === CCB control word flags === */ #define CCB_SKIP 0x80000000 #define CCB_LAST 0x40000000 #define CCB_NPABS 0x20000000 #define CCB_SPABS 0x10000000 #define CCB_PPABS 0x08000000 #define CCB_LDSIZE 0x04000000 #define CCB_LDPRS 0x02000000 #define CCB_LDPPMP 0x01000000 #define CCB_LDPLUT 0x00800000 #define CCB_CCBPRE 0x00400000 #define CCB_YOXY 0x00200000 #define CCB_ACSC 0x00100000 #define CCB_ALSC 0x00080000 #define CCB_ACW 0x00040000 #define CCB_ACCW 0x00020000 #define CCB_TWD 0x00010000 #define CCB_LCE 0x00008000 #define CCB_ACE 0x00004000 #define CCB_reserved13 0x00002000 #define CCB_MARIA 0x00001000 #define CCB_PXOR 0x00000800 #define CCB_USEAV 0x00000400 #define CCB_PACKED 0x00000200 #define CCB_POVER_MASK 0x00000180 #define CCB_PLUTPOS 0x00000040 #define CCB_BGND 0x00000020 #define CCB_NOBLK 0x00000010 #define CCB_PLUTA_MASK 0x0000000F #define CCB_POVER_SHIFT 7 #define CCB_PLUTA_SHIFT 0 #define PMODE_PDC ((0x00000000)<>31&((y)-(x)))) #define MAX(x,y) (y)-(((signed int)((y)-(x))>>31&((y)-(x)))) #define TESTCLIP(cx,cy) ( ((int)cx>=0)&&((int)cx<=((CLIPXVAL)<<16))&&((int)cy>=0)&&((int)cy<=((CLIPYVAL)<<16))) #define FLT(a) ((float)(int)(a)/65536.0) #define XY2OFF(a,b,c) ( (((int)b>>1)*c/*bitmap width*/) + (((int)(b)&1)<<1) + (a) ) #define PBMASK 0x80000000 #define KUP 0x08000000 #define KDN 0x10000000 #define KRI 0x04000000 #define KLE 0x02000000 #define KA 0x01000000 #define KB 0x00800000 #define KC 0x00400000 #define KP 0x00200000 #define KX 0x00100000 #define KRS 0x00080000 #define KLS 0x00040000 #define FIXP16_SHIFT 16 #define FIXP16_MAG 65536 #define FIXP16_DP_MASK 0x0000ffff #define FIXP16_WP_MASK 0xffff0000 #define FIXP16_ROUND_UP 0x0000ffff //0x8000 // TYPES /////////////////////////////////////////////////////////////////// // CLASSES ///////////////////////////////////////////////////////////////// unsigned int __fastcall mread(unsigned int addr); void __fastcall mwrite(unsigned int addr, unsigned int val); int TestInitVisual(int packed); int Init_Line_Map(); void Init_Scale_Map(); void Init_Arbitrary_Map(); int __fastcall TexelDraw_Line(unsigned short CURPIX, unsigned short LAMV, int xcur, int ycur, int cnt); int __fastcall TexelDraw_Scale(unsigned short CURPIX, unsigned short LAMV, int xcur, int ycur, int deltax, int deltay); int __fastcall TexelDraw_Arbitrary(unsigned short CURPIX, unsigned short LAMV, int xA, int yA, int xB, int yB, int xC, int yC, int xD, int yD); void __fastcall DrawPackedCel_New(); void __fastcall DrawLiteralCel_New(); void __fastcall DrawLRCel_New(); void HandleDMA8(); void DMAPBus(); unsigned int MAPPING; // general 3D vertex class #define INT1220(a) ((signed int)(a)>>20) #define INT1220up(a) ((signed int)((a)+(1<<19))>>20) static struct { unsigned int plutaCCBbits; unsigned int pixelBitsMask; bool tmask; } pdec; static struct { unsigned int pmode; unsigned int pmodeORmask; unsigned int pmodeANDmask; bool Transparent; } pproj; unsigned int pbus=0; unsigned char * Mem; unsigned int retuval; unsigned int BITADDR; //static unsigned int * BITPTR; //static unsigned int * BITEND; unsigned int BITBUFLEN; unsigned int BITBUF; unsigned int CCBFLAGS,/*PLUTDATA*/PIXC,PRE0,PRE1,TARGETPROJ,SRCDATA,debug; int SPRWI,SPRHI; unsigned int PLUTF,PDATF,NCCBF; int CELCYCLES,__smallcicles; bool ADD; //static SDL_Event cpuevent; int BITCALC; unsigned short bitbuf; //bit buffer unsigned char subbitbuf;// bit sub buffer int bitcount; // bit counter long compsize; // size of commpressed!!! in bytes!!! actually pixcount*bpp/8!!! unsigned int gFINISH; unsigned short RRR; int USECEL; unsigned int const BPP[8]={1,1,2,4,6,8,16,1}; unsigned char PSCALAR[8][4][32]; unsigned short MAPu8b[256+64], MAPc8bAMV[256+64], MAPc16bAMV[8*8*8+64]; int currentrow; unsigned int bpp; int pixcount; unsigned int type; unsigned int offsetl; unsigned int offset; //static unsigned int begining; unsigned int eor; int calcx; int nrows; unsigned int pix; unsigned short ttt; unsigned int OFF; unsigned int pSource; //AString str; //CelEngine STATBits #define STATBITS mregs[0x28] #define SPRON 0x10 #define SPRPAU 0x20 //CelEngine Registers #define SPRSTRT 0x100 #define SPRSTOP 0x104 #define SPRCNTU 0x108 #define SPRPAUS 0x10c #define CCBCTL0 mregs[0x110] #define REGCTL0 mregs[0x130] #define REGCTL1 mregs[0x134] #define REGCTL2 mregs[0x138] #define REGCTL3 mregs[0x13c] #define CLIPXVAL ((int)mregs[0x134]&0x3ff) #define CLIPYVAL ((int)(mregs[0x134]>>16)&0x3ff) #define PIXSOURCE (mregs[0x138]) #define FBTARGET (mregs[0x13c]) #define CURRENTCCB mregs[0x5a0] //next ccb == 0 stop the engine #define NEXTCCB mregs[0x5a4] #define PLUTDATA mregs[0x5a8] #define PDATA mregs[0x5ac] #define ENGAFETCH mregs[0x5b0] #define ENGALEN mregs[0x5b4] #define ENGBFETCH mregs[0x5b8] #define ENGBLEN mregs[0x5bc] #define PAL_EXP (&mregs[0x5d0]) #define CHAR_BIT (8) int FLOAT1612(int a) { return a<<4; } ////////////////////////////////////////////////////////////////////// // Quick divide helper ////////////////////////////////////////////////////////////////////// const int QUICK_DIVIDE_CACHE_SIZE = 512; static int QUICK_DIVIDE_UBOUND = 0; static int QUICK_DIVIDE_LBOUND = 0; static short quickDivide_lookups[QUICK_DIVIDE_CACHE_SIZE][QUICK_DIVIDE_CACHE_SIZE]; void quickDivide_init() { QUICK_DIVIDE_UBOUND = (QUICK_DIVIDE_CACHE_SIZE / 2) - 1; QUICK_DIVIDE_LBOUND = -(QUICK_DIVIDE_CACHE_SIZE / 2); for (int a = QUICK_DIVIDE_LBOUND; a <= QUICK_DIVIDE_UBOUND; a++) { for (int b = QUICK_DIVIDE_LBOUND; b <= QUICK_DIVIDE_UBOUND; b++) { if (b == 0) quickDivide_lookups[a - QUICK_DIVIDE_LBOUND][b - QUICK_DIVIDE_LBOUND] = 0; else quickDivide_lookups[a - QUICK_DIVIDE_LBOUND][b - QUICK_DIVIDE_LBOUND] = a / b; } } } int __inline quickDivide(int a, int b) { if (a >= QUICK_DIVIDE_LBOUND && a <= QUICK_DIVIDE_UBOUND && b >= QUICK_DIVIDE_LBOUND && b <= QUICK_DIVIDE_UBOUND) { return quickDivide_lookups[a - QUICK_DIVIDE_LBOUND][b - QUICK_DIVIDE_LBOUND]; } else return a / b; } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// //void MapCoord(poly *pol); //void RenderPoly(); unsigned int __fastcall _madam_Peek(unsigned int addr) { // if((addr>=0x400)&&(addr<=0x53f)) // printf("#Madam Peek [%X]=%X\n",addr,mregs[addr]); if((addr>=0x400)&&(addr<=0x53f)) { //we need to return actual fifo status!!!! return _clio_FIFOStruct(addr); } if(addr==0x28) // STATUS OF CEL { switch(_madam_FSM) { case FSM_IDLE:return 0x0; case FSM_SUSPENDED:return 0x30; case FSM_INPROCESS:return 0x10; } } if(addr>=0x580 && addr<0x5A0) { //sprintf(str,"CLUT - MADAM Read madam[0x%X]\n",addr); //CDebug::DPrint(str); } return mregs[addr]; } void __fastcall _madam_Poke(unsigned int addr, unsigned int val) { if(addr>0x2ff && addr<0x400) { // io_interface(EXT_DEBUG_PRINT,(void*)str.print("MADAM Write madam[0x%X] = 0x%8.8X\n",addr,val).CStr()); } /* if(addr==0x13c) { sprintf(str,"Switch screen SWI 0x%8X addr 0x%8X\n",last_SWI,val); CDebug::DPrint(str); }*/ if((addr>=0x400)&&(addr<=0x53f)) { _clio_SetFIFO(addr,val); return; } else switch(addr) { case 0x4: val=0x29; mregs[addr]=val; break; case 0x8: mregs[addr]=val; HandleDMA8(); break; case 0x580: _vdl_ProcessVDL(val); return; case 0x584: case 0x588: case 0x58C: case 0x590: case 0x594: case 0x598: case 0x59C: //_3do_DPrint(str.print("CLUT - MADAM Write madam[0x%X] = 0x%8.8X\n",addr,val)); mregs[addr]=val; return; case 0x0: // io_interface(EXT_KPRINT,(void*)val); return; case SPRSTRT: if(_madam_FSM==FSM_IDLE) _madam_FSM=FSM_INPROCESS; return; case SPRSTOP: _madam_FSM=FSM_IDLE; NEXTCCB=0; return; case SPRCNTU: if(_madam_FSM==FSM_SUSPENDED) _madam_FSM=FSM_INPROCESS; return; case SPRPAUS: if(_madam_FSM==FSM_INPROCESS) _madam_FSM=FSM_SUSPENDED; return; //Matrix engine macros #define M00 ((double)(signed int)mregs[0x600]) #define M01 ((double)(signed int)mregs[0x604]) #define M02 ((double)(signed int)mregs[0x608]) #define M03 ((double)(signed int)mregs[0x60C]) #define M10 ((double)(signed int)mregs[0x610]) #define M11 ((double)(signed int)mregs[0x614]) #define M12 ((double)(signed int)mregs[0x618]) #define M13 ((double)(signed int)mregs[0x61C]) #define M20 ((double)(signed int)mregs[0x620]) #define M21 ((double)(signed int)mregs[0x624]) #define M22 ((double)(signed int)mregs[0x628]) #define M23 ((double)(signed int)mregs[0x62C]) #define M30 ((double)(signed int)mregs[0x630]) #define M31 ((double)(signed int)mregs[0x634]) #define M32 ((double)(signed int)mregs[0x638]) #define M33 ((double)(signed int)mregs[0x63C]) #define V0 ((double)(signed int)mregs[0x640]) #define V1 ((double)(signed int)mregs[0x644]) #define V2 ((double)(signed int)mregs[0x648]) #define V3 ((double)(signed int)mregs[0x64C]) #define Rez0 mregs[0x660] #define Rez1 mregs[0x664] #define Rez2 mregs[0x668] #define Rez3 mregs[0x66C] //#define Nfrac16 ((__int64)mregs[0x680]<<32|(unsigned int)mregs[0x684]) #define Nfrac16 (((__int64)mregs[0x680]<<32)|(unsigned int)mregs[0x684]) // Matix engine case 0x7fc: mregs[0x7fc]=0; // Ours matrix engine already ready static double Rez0T,Rez1T,Rez2T,Rez3T; // io_interface(EXT_DEBUG_PRINT,(void*)str.print("MADAM Write madam[0x%X] = 0x%8.8X\n",addr,val).CStr()); switch(val) // Cmd { case 0: //printf("#Matrix = NOP\n"); Rez0=Rez0T; Rez1=Rez1T; Rez2=Rez2T; Rez3=Rez3T; return; // NOP case 1: //multiply a 4x4 matrix of 16.16 values by a vector of 16.16 values Rez0=Rez0T; Rez1=Rez1T; Rez2=Rez2T; Rez3=Rez3T; Rez0T=(int)((M00*V0+M01*V1+M02*V2+M03*V3)/65536.0); Rez1T=(int)((M10*V0+M11*V1+M12*V2+M13*V3)/65536.0); Rez2T=(int)((M20*V0+M21*V1+M22*V2+M23*V3)/65536.0); Rez3T=(int)((M30*V0+M31*V1+M32*V2+M33*V3)/65536.0); return; case 2: //multiply a 3x3 matrix of 16.16 values by a vector of 16.16 values Rez0=Rez0T; Rez1=Rez1T; Rez2=Rez2T; Rez3=Rez3T; Rez0T=(int)((M00*V0+M01*V1+M02*V2)/65536.0); Rez1T=(int)((M10*V0+M11*V1+M12*V2)/65536.0); Rez2T=(int)((M20*V0+M21*V1+M22*V2)/65536.0); //printf("#Matrix CMD2, R0=0x%8.8X, R1=0x%8.8X, R2=0x%8.8X\n",Rez0,Rez1,Rez2); return; case 3: // Multiply a 3x3 matrix of 16.16 values by multiple vectors, then multiply x and y by n/z { // Return the result vectors {x*n/z, y*n/z, z} Rez0=Rez0T; Rez1=Rez1T; Rez2=Rez2T; Rez3=Rez3T; double M; Rez2T=(signed int)((M20*V0+M21*V1+M22*V2)/65536.0); // z if(Rez2T!=0) M=Nfrac16/(double)Rez2T; // n/z else { M=Nfrac16; // io_interface(EXT_DEBUG_PRINT,(void*)"!!!Division by zero!!!\n"); } Rez0T=(signed int)((M00*V0+M01*V1+M02*V2)/65536.0); Rez1T=(signed int)((M10*V0+M11*V1+M12*V2)/65536.0); Rez0T=(double)((Rez0T*M)/65536.0/65536.0); // x * n/z Rez1T=(double)((Rez1T*M)/65536.0/65536.0); // y * n/z } return; default: //io_interface(EXT_DEBUG_PRINT,(void*)str.print("??? Unknown cmd MADAM[0x7FC]==0x%x\n", val).CStr()); return; } break; case 0x130: mregs[addr]=val; //modulo variables :) RMOD=((val&1)<<7)+((val&12)<<8)+((val&0x70)<<4); val>>=8; WMOD=((val&1)<<7)+((val&12)<<8)+((val&0x70)<<4); break; default: mregs[addr]=val; break; } } unsigned int OFFSET; unsigned int temp1; unsigned int Flag; double HDDX,HDDY,HDX,HDY,VDX,VDY,XPOS,YPOS,HDX_2,HDY_2; int HDDX1616,HDDY1616,HDX1616,HDY1616,VDX1616,VDY1616,XPOS1616,YPOS1616,HDX1616_2,HDY1616_2; unsigned int CEL_ORIGIN_VH_VALUE; char TEXEL_FUN_NUMBER; int TEXTURE_WI_START,TEXTURE_HI_START,TEXEL_INCX,TEXEL_INCY; int TEXTURE_WI_LIM, TEXTURE_HI_LIM; void LoadPLUT(unsigned int pnt,int n) { int i; for(i=0;i>1)+i)^1)<<1); } } int CCBCOUNTER; int _madam_HandleCEL() { __smallcicles=CELCYCLES=0; if(NEXTCCB!=0)CCBCOUNTER=0; STATBITS|=SPRON; Flag=0; while((NEXTCCB!=0)&&(!Flag)) //if(_madam_FSM==FSM_INPROCESS) { CCBCOUNTER++; if((NEXTCCB==0)||(Flag)) { _madam_FSM=FSM_IDLE; return CELCYCLES; } //1st step -- parce CCB and load it into registers CURRENTCCB=NEXTCCB&0xfffffc; if((CURRENTCCB>>20)>2) { _madam_FSM=FSM_IDLE; return CELCYCLES; } OFFSET=CURRENTCCB; CCBFLAGS=mread(CURRENTCCB); CURRENTCCB+=4; if(CCBFLAGS&CCB_PXOR) { PXOR1=0; PXOR2=0x1f1f1f1f; } else { PXOR1=0xFFffFFff; PXOR2=0; } Flag=0; PLUTF=PDATF=NCCBF=0; NEXTCCB=mread(CURRENTCCB)&(~3); if(!(CCBFLAGS&CCB_NPABS)) { NEXTCCB+=CURRENTCCB+4; NEXTCCB&=0xffffff; } if((NEXTCCB==0)) NCCBF=1; if((NEXTCCB>>20)>2) NCCBF=1; CURRENTCCB+=4; PDATA=mread(CURRENTCCB)&(~3); //if((PDATA==0)) // PDATF=1; if(!(CCBFLAGS&CCB_SPABS)) { PDATA+=CURRENTCCB+4; PDATA&=0xffffff; } if((PDATA>>20)>2) PDATF=1; CURRENTCCB+=4; if((CCBFLAGS&CCB_LDPLUT)) { PLUTDATA=mread(CURRENTCCB)&(~3); //if((PLUTDATA==0)) // PLUTF=1; if(!(CCBFLAGS&CCB_PPABS)) { PLUTDATA+=CURRENTCCB+4; PLUTDATA&=0xffffff; } if((PLUTDATA>>20)>2) PLUTF=1; } CURRENTCCB+=4; if(NCCBF) CCBFLAGS|=CCB_LAST; if(CCBFLAGS&CCB_LAST) Flag=1; if(CCBFLAGS&CCB_YOXY) { XPOS1616=mread(CURRENTCCB); XPOS=XPOS1616/65536.0; CURRENTCCB+=4; YPOS1616=mread(CURRENTCCB); YPOS=YPOS1616/65536.0; CURRENTCCB+=4; } else CURRENTCCB+=8; // Get the VH value for this cel. This is done in case the // cel later decides to use the position as the source of // its VH values in the projector. CEL_ORIGIN_VH_VALUE = (XPOS1616 & 0x1) | ((YPOS1616 & 0x1) << 15); //if((CCBFLAGS&CCB_SKIP)&& debug) // printf("###Cel skipped!!! PDATF=%d PLUTF=%d NCCBF=%d\n",PDATF,PLUTF,NCCBF); if(CCBFLAGS&CCB_LAST) NEXTCCB=0; if(CCBFLAGS&CCB_LDSIZE) { HDX1616=((int)mread(CURRENTCCB))>>4; HDX=HDX1616/65536.0; CURRENTCCB+=4; HDY1616=((int)mread(CURRENTCCB))>>4; HDY=HDY1616/65536.0; CURRENTCCB+=4; VDX1616=mread(CURRENTCCB); VDX=VDX1616/65536.0; CURRENTCCB+=4; VDY1616=mread(CURRENTCCB); VDY=VDY1616/65536.0; CURRENTCCB+=4; } if(CCBFLAGS&CCB_LDPRS) { HDDX1616=((int)mread(CURRENTCCB))>>4; HDDX=HDDX1616/65536.0; CURRENTCCB+=4; HDDY1616=((int)mread(CURRENTCCB))>>4; HDDY=HDDY1616/65536.0; CURRENTCCB+=4; } if(CCBFLAGS&CCB_LDPPMP) { PIXC=mread(CURRENTCCB); CURRENTCCB+=4; } if(CCBFLAGS&CCB_CCBPRE) { PRE0=mread(CURRENTCCB); CURRENTCCB+=4; if(!(CCBFLAGS&CCB_PACKED)) { PRE1=mread(CURRENTCCB); CURRENTCCB+=4; } } else if(!PDATF) { PRE0=mread(PDATA); PDATA+=4; if(!(CCBFLAGS&CCB_PACKED)) { PRE1=mread(PDATA); PDATA+=4; } } {// PDEC data compute //pdec.mode=PRE0&PRE0_BPP_MASK; switch(PRE0&PRE0_BPP_MASK) { case 0: case 7: continue; case 1: pdec.plutaCCBbits=(CCBFLAGS&0xf)*4; pdec.pixelBitsMask=1; // 1 bit break; case 2: pdec.plutaCCBbits=(CCBFLAGS&0xe)*4; pdec.pixelBitsMask=3; // 2 bit break; default://case 3: pdec.plutaCCBbits=(CCBFLAGS&0x8)*4; pdec.pixelBitsMask=15; // 4 bit break; } pdec.tmask=!(CCBFLAGS&CCB_BGND); pproj.pmode = (CCBFLAGS&CCB_POVER_MASK); pproj.pmodeORmask= (pproj.pmode==PMODE_ONE )? 0x8000:0x0000; pproj.pmodeANDmask=(pproj.pmode!=PMODE_ZERO)? 0xFFFF:0x7FFF; } if((CCBFLAGS&CCB_LDPLUT) && !PLUTF) //load PLUT { switch(PRE0&PRE0_BPP_MASK) { case 1: LoadPLUT(PLUTDATA,2); break; case 2: LoadPLUT(PLUTDATA,4); break; case 3: LoadPLUT(PLUTDATA,16); break; default: LoadPLUT(PLUTDATA,32); }; } //ok -- CCB decoded -- let's print out our current status //step#2 -- getting CEL data //* if(!(CCBFLAGS&CCB_SKIP) && !PDATF) { if(CCBFLAGS&CCB_PACKED) { DrawPackedCel_New(); } else { if((PRE1&PRE1_LRFORM)&&(BPP[PRE0&PRE0_BPP_MASK]==16)) DrawLRCel_New(); else DrawLiteralCel_New(); } }//if(!(CCBFLAGS& CCB_SKIP)) }//while //STATBITS&=~SPRON; if((NEXTCCB==0)||(Flag)) { _madam_FSM=FSM_IDLE; } return CELCYCLES; }//HandleCEL void HandleDMA8() { if(mregs[0x8]&0x8000)// pbus transfer { DMAPBus(); mregs[0x8]&=~0x8000; // dma done _clio_GenerateFiq(0,1); } } void DMAPBus() { unsigned int i=0; if((int)mregs[0x574]<0) return; mregs[0x574]-=4; mregs[0x570]+=4; mregs[0x578]+=4; while((int)mregs[0x574]>0) { if(i<5) WriteIO(mregs[0x570],((unsigned int*)PBUSQueue)[i]); else WriteIO(mregs[0x570],0xffffffff); mregs[0x574]-=4; mregs[0x570]+=4; mregs[0x578]+=4; i++; } mregs[0x574]=0xfffffffc; } void _madam_KeyPressed(unsigned char* data, unsigned int num) { if(num>16)num=16; if(num)memcpy(PBUSQueue,data,num); memset(&PBUSQueue[num],-1,20-num); } void _madam_Init(unsigned char *memory) { int i,j,n; ADD=0; debug=0; USECEL=1; CELCYCLES=0; Mem=memory; quickDivide_init(); MAPPING=1; _madam_FSM=FSM_IDLE; for(i=0;i<2048;i++) mregs[i]=0; mregs[004]=0x29; // DRAM dux init mregs[574]=0xfffffffc; #if 1 mregs[000]=0x01020000; // for Green matrix engine autodetect //mregs[000]=0x02022000; // for Green matrix engine autodetect #else mregs[000]=0x01020001; // for ARM soft emu of matrix engine #endif for(i=0;i<32;i++) for(j=0;j<8;j++) for(n=0;n<4;n++) { PSCALAR[j][n][i]=((i*(j+1))>>PDV(n)); } for(i=0;i<256;i++) { pdeco pix1,pix2; unsigned short pres, resamv; pix1.raw=i; pix2.r16b.b=(pix1.u8b.b<<3)+(pix1.u8b.b<<1)+(pix1.u8b.b>>1); pix2.r16b.g=(pix1.u8b.g<<2)+(pix1.u8b.g>>1); pix2.r16b.r=(pix1.u8b.r<<2)+(pix1.u8b.r>>1); pres=pix2.raw; pres&=0x7fff; //pmode=0; MAPu8b[i]=pres; resamv=(pix1.c8b.m<<1)+pix1.c8b.mpw; resamv=(resamv<<6)+(resamv<<3)+resamv; MAPc8bAMV[i]=resamv; } for(i=0;i<(8*8*8);i++) { pdeco pix1; pix1.raw=i<<5; MAPc16bAMV[i]=(pix1.c16b.mr<<6)+(pix1.c16b.mg<<3)+pix1.c16b.mb; } } extern void _3do_InternalFrame(int cicles); void exteraclocker() { if((CELCYCLES-__smallcicles)>>7) { __smallcicles=CELCYCLES; //_3do_InternalFrame(64); } } unsigned int __fastcall mread(unsigned int addr) { unsigned int val; #ifdef SAFEMEMACCESS // addr&=0x3FFFFF; #endif val=_mem_read32(addr); CELCYCLES+=1; //exteraclocker(); return val; } void __fastcall mwrite(unsigned int addr, unsigned int val) { #ifdef SAFEMEMACCESS addr&=0x3FFFFF; #endif _mem_write32(addr,val); CELCYCLES+=2; //exteraclocker(); } void __fastcall mwriteh(unsigned int addr, unsigned short val) { #ifdef SAFEMEMACCESS addr&=0x3fffff; #endif CELCYCLES+=2; _mem_write16((addr^2),val); //exteraclocker(); } unsigned short __fastcall mreadh(unsigned int addr) { #ifdef SAFEMEMACCESS // addr&=0x3FFFFF; #endif CELCYCLES+=1; //exteraclocker(); return _mem_read16((addr^2)); } unsigned int __fastcall readPLUTDATA(unsigned int offset) { CELCYCLES+=4; if(PLUTDATA==0) return 0; return *(unsigned short*)(PLUTDATA+(offset^2)); //return ((unsigned short*)PAL_EXP)[((offset^2)>>1)]; } unsigned int __fastcall PDEC(unsigned int pixel, unsigned short * amv) { pdeco pix1,pix2; unsigned short resamv,pres; pix1.raw=pixel; switch(PRE0&PRE0_BPP_MASK) { default: //case 1: // 1 bit //case 2: // 2 bits //case 3: // 4 bits pres=PLUT[(pdec.plutaCCBbits+((pix1.raw&pdec.pixelBitsMask)*2))>>1]; resamv=0x49; break; case 4: // 6 bits pres=PLUT[pix1.c6b.c]; pres=(pres&0x7FFF)+(pix1.c6b.pw<<15); //pmode=pix1.c6b.pw; ??? resamv=0x49; break; case 5: // 8 bits if(PRE0&PRE0_LINEAR) { // (Uncoded 8 bit CEL) pres=MAPu8b[pix1.raw&0xFF]; resamv=0x49; } else { // (Coded 8 bit CEL) pres=PLUT[pix1.c8b.c]; resamv=MAPc8bAMV[pix1.raw&0xFF]; } break; case 6: // 16 bits case 7: //*amv=0; //pres=0; //Transparent=0; if((PRE0&PRE0_LINEAR)) { // (Uncoded 16 bit CEL) pres=pix1.raw; //pres&=0x7ffe; //pres=0x11; // pres=(pres&0x7fff)+(pix1.u16b.p<<15);//pmode=pix1.u16b.p; ??? resamv=0x49; } else { // (Uncoded 16 bit CEL) pres=PLUT[pix1.c16b.c]; pres=(pres&0x7fff)|(pixel&0x8000); resamv=MAPc16bAMV[(pix1.raw>>5)&0x1FF]; //nop: pres=(pres&0x7fff)+(pix1.c16b.pw<<15);//pmode=pix1.c16b.pw; ??? } break; } *amv=resamv; // (Conceptual end of DECODER) ////////////////////// // TODO: Do PROJECTOR functions now? // They'll be done before using the PROCESSOR. //if(!(PRE1&PRE1_NOSWAP) && (CCBCTL0&(1<<27))) // pres=(pres&0x7ffe)|((pres&0x8000)>>15)|((pres&1)<<15); //if(!(CCBCTL0&0x80000000))pres=(pres&0x7fff)|((CCBCTL0>>15)&0x8000); //pres=(pres|pdec.pmodeORmask)&pdec.pmodeANDmask; pproj.Transparent=( ((pres&0x7fff)==0x0) & pdec.tmask ); return pres; } unsigned int __fastcall PPROJ_OUTPUT(unsigned int pdec_output, unsigned int pproc_output, unsigned int pframe_input) { unsigned int VHOutput; /////////////////////////// // CCB_PLUTPOS flag // Determine projector's originating source of VH values. if (CCBFLAGS & CCB_PLUTPOS) { // Use pixel decoder output. VHOutput = (pdec_output & 0x8001); } else { // Use VH values determined from the CEL's origin. VHOutput = CEL_ORIGIN_VH_VALUE; } ////////////////////////// // SWAPHV flag // Swap the H and V values now if requested. if (CCBCTL0 & SWAPHV) { // TODO: I have read that PRE1 is only set for unpacked CELs. // So... should this be ignored if using packed CELs? I don't know. if (!(PRE1&PRE1_NOSWAP)) { VHOutput=(VHOutput>>15)|((VHOutput&1)<<15); } } ////////////////////////// // CFBDSUB flag // Substitute the VH values from the frame buffer if requested. if (CCBCTL0 & CFBDSUB) { // TODO: This should be re-enabled sometime. However, it currently // causes the wing commander 3 movies to screw up again! There // must be some missing mbehavior elsewhere. //VHOutput = (pframe_input & 0x8001); } ////////////////////////// // B15POS_MASK settings // Substitute the V value explicitly if requested. int b15mode = (CCBCTL0 & B15POS_MASK); if (b15mode == B15POS_PDC) { // Don't touch it. } else if (b15mode == B15POS_0) { VHOutput = (VHOutput & ~0x8000); } else if (b15mode == B15POS_1) { VHOutput |= 0x8000; } ////////////////////////// // B15POS_MASK settings // Substitute the H value explicitly if requested. int b0mode = (CCBCTL0 & B0POS_MASK); if (b0mode == B0POS_PDC) { // Don't touch it. } else if (b0mode == B0POS_PPMP) { // Use LSB from pixel processor output. VHOutput = (VHOutput & ~0x1) | (pproc_output & 0x1); } else if (b0mode == B0POS_0) { VHOutput = (VHOutput & ~0x1); } else if (b0mode == B0POS_1) { VHOutput |= 0x01; } return (pproc_output & 0x7FFE) | VHOutput; } unsigned int __fastcall PPROC(unsigned int pixel, unsigned int fpix, unsigned int amv) { AVS AV; PXC pixc; pdeco input1,out,pix1; // Set PMODE according to the values set up in the CCBFLAGS word. // (This merely uses masks here because it's faster). // This is a duty of the PROJECTOR, but we'll do it here because its easier. pixel = (pixel|pproj.pmodeORmask)&pproj.pmodeANDmask; pixc.raw=PIXC&0xffff; if((pixel&0x8000)) { pixc.raw=PIXC>>16; } //pres,fpix //now let's select the sources //1. av //2. input1 //3. input2 //pixc.raw=0; if(CCBFLAGS&CCB_USEAV) { AV.raw=pixc.meaning.av; } else { AV.avsignal.dv3=0; AV.avsignal.nCLIP=0; AV.avsignal.XTEND=0; AV.avsignal.NEG=0; } if(!pixc.meaning.s1) input1.raw=pixel; else input1.raw=fpix; #pragma pack(push,1) union { unsigned int raw; struct { char R; char B; char G; char a; }; } color1, color2, AOP, BOP; #pragma pack(pop) switch(pixc.meaning.s2) { case 0: color2.raw=0; break; case 1: color2.R=color2.G=color2.B=(pixc.meaning.av>>AV.avsignal.dv3); break; case 2: pix1.raw=fpix; color2.R=(pix1.r16b.r)>>AV.avsignal.dv3; color2.G=(pix1.r16b.g)>>AV.avsignal.dv3; color2.B=(pix1.r16b.b)>>AV.avsignal.dv3; break; case 3: pix1.raw=pixel; color2.R=(pix1.r16b.r)>>AV.avsignal.dv3; color2.G=(pix1.r16b.g)>>AV.avsignal.dv3; color2.B=(pix1.r16b.b)>>AV.avsignal.dv3; break; } switch(pixc.meaning.ms) { case 0: color1.R=PSCALAR[pixc.meaning.mxf][pixc.meaning.dv1][input1.r16b.r]; color1.G=PSCALAR[pixc.meaning.mxf][pixc.meaning.dv1][input1.r16b.g]; color1.B=PSCALAR[pixc.meaning.mxf][pixc.meaning.dv1][input1.r16b.b]; break; case 1: color1.R=PSCALAR[(amv>>6)&7][pixc.meaning.dv1][input1.r16b.r]; color1.G=PSCALAR[(amv>>3)&7][pixc.meaning.dv1][input1.r16b.g]; color1.B=PSCALAR[amv&7][pixc.meaning.dv1][input1.r16b.b]; break; case 2: pix1.raw=pixel; color1.R=PSCALAR[pix1.r16b.r>>2][pix1.r16b.r&3][input1.r16b.r]; color1.G=PSCALAR[pix1.r16b.g>>2][pix1.r16b.g&3][input1.r16b.g]; color1.B=PSCALAR[pix1.r16b.b>>2][pix1.r16b.b&3][input1.r16b.b]; break; case 3: color1.R=PSCALAR[4][pixc.meaning.dv1][input1.r16b.r]; color1.G=PSCALAR[4][pixc.meaning.dv1][input1.r16b.g]; color1.B=PSCALAR[4][pixc.meaning.dv1][input1.r16b.b]; break; } /* // Use this to render magenta for testing. if (false) { pdeco fakeColor; fakeColor.r16b.r = 0x1b; fakeColor.r16b.g = 0x00; fakeColor.r16b.b = 0x1b; fakeColor.r16b.p = 1; return fakeColor.raw; } */ //ok -- we got the sources -- now RGB processing //AOP/BOP calculation AOP.raw=color1.raw&PXOR1; color1.raw&=PXOR2; if(AV.avsignal.NEG) BOP.raw=color2.raw^0x00ffffff; else { BOP.raw=color2.raw^color1.raw; } if(AV.avsignal.XTEND) { BOP.R=(BOP.R<<3)>>3; BOP.B=(BOP.B<<3)>>3; BOP.G=(BOP.G<<3)>>3; } color2.R=(AOP.R+BOP.R+AV.avsignal.NEG)>>pixc.meaning.dv2; color2.G=(AOP.G+BOP.G+AV.avsignal.NEG)>>pixc.meaning.dv2; color2.B=(AOP.B+BOP.B+AV.avsignal.NEG)>>pixc.meaning.dv2; //fprintf(flog,"%d %d %02x\t%02d %02d %02d\n", pixc.meaning.s2, pixc.meaning.ms, AV.raw, color2.R, color2.G, color2.B); if(!AV.avsignal.nCLIP) { if(color2.R<0) color2.R=0; else if(color2.R>31) color2.R=31; if(color2.G<0) color2.G=0; else if(color2.G>31) color2.G=31; if(color2.B<0) color2.B=0; else if(color2.B>31) color2.B=31; } out.raw=0; out.r16b.r=color2.R; out.r16b.g=color2.G; out.r16b.b=color2.B; // TODO: Is this something the PROJECTOR should do? if(!(CCBFLAGS&CCB_NOBLK) && out.raw==0) out.raw=1<<10; //if(!(PRE1&PRE1_NOSWAP) && (CCBCTL0&(1<<27))) //out.raw=(out.raw&0x7ffe)|((out.raw&0x8000)>>15)|((out.raw&1)<<15); //if(!(CCBCTL0&0x80000000))out.raw=(out.raw&0x7fff)|((CCBCTL0>>15)&0x8000); return out.raw; } unsigned int * _madam_GetRegs() { return mregs; } void __fastcall DrawPackedCel_New() { sf=100000; unsigned int pixel; unsigned int framePixel; unsigned int start; unsigned short CURPIX,LAMV; int i,j; int lastaddr; int xcur,ycur,xvert,yvert,xdown,ydown,hdx,hdy, scipw, wcnt; int accx, accy, scipstr; start = PDATA; nrows=(PRE0&PRE0_VCNT_MASK)>>PRE0_VCNT_SHIFT; bpp=BPP[PRE0&PRE0_BPP_MASK]; offsetl=2; if(bpp < 8) offsetl=1; pixcount=0; compsize=30; SPRHI=nrows+1; calcx=0; if(TestInitVisual(1))return; xvert=XPOS1616; yvert=YPOS1616; if(TEXEL_FUN_NUMBER==0) { //return; for(currentrow=0;currentrow<(TEXTURE_HI_LIM);currentrow++) { //Initbitoper.Read(start,300); bitoper.AttachBuffer(start); offset=bitoper.Read(offsetl<<3); //bitoper.Read(offsetl<<3); //BITCALC=((offset+2)<<2)<<5; lastaddr=start+((offset+2)<<2); // calcx=0; eor=0; xcur=xvert; ycur=yvert; xvert+=VDX1616; yvert+=VDY1616; //if((ycur>>16)>CLIPXVAL)ycur=CLIPXVAL<<16; //if(ycur<0)ycur=0; if(TEXTURE_HI_START){TEXTURE_HI_START--;start=lastaddr;continue;} scipw=TEXTURE_WI_START; wcnt=scipw; while(!eor)//while not end of row { type=bitoper.Read(2);//bitoper.Read(2); if( (int)(bitoper.GetBytePose()+start) >= (lastaddr))type=0; //pixcount=bitoper.Read(6)+1; pixcount=bitoper.Read(6)+1; if(scipw) { if(type==0) break; if(scipw>=(int)(pixcount)) { scipw-=(pixcount); if(HDX1616)xcur+=HDX1616*(pixcount); if(HDY1616)ycur+=HDY1616*(pixcount); if(type==1)bitoper.Skip(bpp*pixcount);//bitoper.Skip(bpp*(pixcount)); else if(type==3)bitoper.Skip(bpp);//bitoper.Skip(bpp); continue; } else { if(HDX1616)xcur+=HDX1616*(scipw); if(HDY1616)ycur+=HDY1616*(scipw); pixcount-=scipw; if(type==1)bitoper.Skip(bpp*scipw);//bitoper.Skip(bpp*scipw); scipw=0; } } //if(wcnt>=TEXTURE_WI_LIM)break; wcnt+=(pixcount); if(wcnt>TEXTURE_WI_LIM) { pixcount-=(wcnt-TEXTURE_WI_LIM); //if(pixcount>>31)break; } switch(type) { case 0: //end of row eor=1; break; case 1: //PACK_LITERAL for(pix=0;pix>16)<<2,ycur>>16,RMOD))); pixel = PPROC(CURPIX,framePixel,LAMV); pixel = PPROJ_OUTPUT(CURPIX, pixel, framePixel); mwriteh((FBTARGET+XY2OFF((xcur>>16)<<2,ycur>>16,WMOD)),pixel); } xcur+=HDX1616; ycur+=HDY1616; } break; case 2: //PACK_TRANSPARENT // calcx+=(pixcount+1); if(HDX1616)xcur+=HDX1616*(pixcount); if(HDY1616)ycur+=HDY1616*(pixcount); break; case 3: //PACK_REPEAT CURPIX=PDEC(bitoper.Read(bpp),&LAMV); if(CURPIX>32300&&CURPIX<33500&&(CURPIX>32760||CURPIX<32750)){ if(speedfixes>=0&&sdf==0&&speedfixes<=200001&&unknownflag11==0)speedfixes=200000;} if(unknownflag11>0&&sdf==0&&CURPIX<30000&&CURPIX>29000) speedfixes=-200000; if(!pproj.Transparent) { TexelDraw_Line(CURPIX, LAMV, xcur, ycur, (pixcount)); } if(HDX1616)xcur+=HDX1616*(pixcount); if(HDY1616)ycur+=HDY1616*(pixcount); break; }//type if(wcnt>=TEXTURE_WI_LIM)break; }//eor start=lastaddr; } } else if(TEXEL_FUN_NUMBER==1) { unknownflag11=100000; int drawHeight; drawHeight = VDY1616; if (CCBFLAGS&CCB_MARIA && drawHeight > (1 << 16)) drawHeight = (1 << 16); for(currentrow=0;currentrow= (lastaddr))type=0; int __pix=bitoper.Read(6)+1; switch(type) { case 0: //end of row eor=1; break; case 1: //PACK_LITERAL while(__pix) { __pix--; CURPIX=PDEC(bitoper.Read(bpp),&LAMV); if(!pproj.Transparent) { if (drawHeight != VDY1616 && YPOS < 0) { int sfdjlk = 0; } if(TexelDraw_Scale(CURPIX, LAMV, xcur>>16, ycur>>16, (xcur+(HDX1616+VDX1616))>>16, (ycur+(HDY1616+drawHeight))>>16)) break; } xcur+=HDX1616; ycur+=HDY1616; } break; case 2: //PACK_TRANSPARENT // calcx+=(pixcount+1); xcur+=HDX1616*(__pix); ycur+=HDY1616*(__pix); __pix=0; break; case 3: //PACK_REPEAT CURPIX=PDEC(bitoper.Read(bpp),&LAMV); if(!pproj.Transparent) { if(TexelDraw_Scale(CURPIX, LAMV, xcur>>16, ycur>>16, (xcur+(HDX1616*(__pix))+VDX1616)>>16, (ycur+(HDY1616*(__pix))+drawHeight)>>16))break; } xcur+=HDX1616*(__pix); ycur+=HDY1616*(__pix); __pix=0; break; }//type if(__pix)break; }//eor start=lastaddr; } } else { if(speedfixes>=0&&speedfixes<=100001) speedfixes=100000; for(currentrow=0;currentrow= (lastaddr))type=0; int __pix=bitoper.Read(6)+1; switch(type) { case 0: //end of row eor=1; break; case 1: //PACK_LITERAL while(__pix) { CURPIX=PDEC(bitoper.Read(bpp),&LAMV); __pix--; // if(speedfixes>=0&&speedfixes<=100001) speedfixes=300000; if(!pproj.Transparent) { if(TexelDraw_Arbitrary(CURPIX, LAMV, xcur, ycur, xcur+hdx, ycur+hdy, xdown+HDX1616, ydown+HDY1616, xdown, ydown)) break; } xcur+=hdx; ycur+=hdy; xdown+=HDX1616; ydown+=HDY1616; } //pixcount=0; break; case 2: //PACK_TRANSPARENT if(speedfixes>=0&&sdf>0/*&&speedfixes<=100001*/) speedfixes=300000; // calcx+=(pixcount+1); xcur+=hdx*(__pix); ycur+=hdy*(__pix); xdown+=HDX1616*(__pix); ydown+=HDY1616*(__pix); __pix=0; break; case 3: //PACK_REPEAT CURPIX=PDEC(bitoper.Read(bpp),&LAMV); if(speedfixes>=0&&speedfixes<200001&&((CURPIX>10000&&CURPIX<11000)&&sdf==0/*||(CURPIX>10500&&CURPIX<10650)*/))speedfixes=200000;//(CURPIX>10450&&CURPIX<10470) if(!pproj.Transparent) { while(__pix) { __pix--; if(TexelDraw_Arbitrary(CURPIX, LAMV, xcur, ycur, xcur+hdx, ycur+hdy, xdown+HDX1616, ydown+HDY1616, xdown, ydown)) break; xcur+=hdx; ycur+=hdy; xdown+=HDX1616; ydown+=HDY1616; } } else { xcur+=hdx*__pix; ycur+=hdy*__pix; xdown+=HDX1616*__pix; ydown+=HDY1616*__pix; __pix=0; } //pixcount=0; break; };//type if(__pix) break; }//eor start=lastaddr; } } SPRWI++; if (fixmode&FIX_BIT_GRAPHICS_STEP_Y) { YPOS1616=ycur; YPOS=YPOS1616/65536.0; } else { XPOS1616=xcur; XPOS=XPOS1616/65536.0; } } void __fastcall DrawLiteralCel_New() { sf=100000; unsigned int pixel; unsigned int framePixel; int i,j,xcur,ycur,xvert,yvert,xdown,ydown,hdx,hdy,pix_repit,scipstr; unsigned short CURPIX,LAMV; int get1,get2; // RMOD=RMODULO[REGCTL0]; // WMOD=WMODULO[REGCTL0]; bpp=BPP[PRE0&PRE0_BPP_MASK]; offsetl=2; if(bpp < 8) offsetl=1; pixcount=0; offset=(offsetl==1)?((PRE1&PRE1_WOFFSET8_MASK)>>PRE1_WOFFSET8_SHIFT):((PRE1&PRE1_WOFFSET10_MASK)>>PRE1_WOFFSET10_SHIFT); SPRWI=1+(PRE1&PRE1_TLHPCNT_MASK); SPRHI=((PRE0&PRE0_VCNT_MASK)>>PRE0_VCNT_SHIFT)+1; if(TestInitVisual(0))return; xvert=XPOS1616; yvert=YPOS1616; if(TEXEL_FUN_NUMBER==0) { // if(speedfixes>=0&&speedfixes<=100001) speedfixes=300000; sdf=100000; //øðèôòû NFS SPRWI-=((PRE0>>24)&0xf); xvert+=TEXTURE_HI_START*VDX1616; yvert+=TEXTURE_HI_START*VDY1616; PDATA+=((offset+2)<<2)*TEXTURE_HI_START; if(SPRWI>TEXTURE_WI_LIM)SPRWI=TEXTURE_WI_LIM; for(i=TEXTURE_HI_START;i>24)&0xf))); if(TEXTURE_WI_START)bitoper.Skip(bpp*(TEXTURE_WI_START)); xvert+=VDX1616; yvert+=VDY1616; for(j=TEXTURE_WI_START;j>16)<<2,ycur>>16,RMOD))); pixel = PPROC(CURPIX,framePixel,LAMV); pixel = PPROJ_OUTPUT(CURPIX, pixel, framePixel); mwriteh((FBTARGET+XY2OFF((xcur>>16)<<2,ycur>>16,WMOD)),pixel); } xcur+=HDX1616; ycur+=HDY1616; } PDATA+=(offset+2)<<2; } } else if(TEXEL_FUN_NUMBER==1) { SPRWI-=((PRE0>>24)&0xf); int drawHeight; drawHeight = VDY1616; if (CCBFLAGS&CCB_MARIA && drawHeight > (1 << 16)) drawHeight = (1 << 16); for(i=0;i>24)&0xf))); for(j=0;j>16, ycur>>16, (xcur+HDX1616+VDX1616)>>16, (ycur+HDY1616+drawHeight)>>16))break; } xcur+=HDX1616; ycur+=HDY1616; } PDATA+=(offset+2)<<2; } } else { SPRWI-=((PRE0>>24)&0xf); for(i=0;i>24)&0xf))); xdown=xvert; ydown=yvert; for(j=0;j=0&&speedfixes<200001)){ if (CURPIX>30000&&CURPIX<40000)speedfixes=0; else speedfixes=-100000;} } xcur+=hdx; ycur+=hdy; xdown+=HDX1616; ydown+=HDY1616; } PDATA+=(((offset+2)<<2)/*scipstr*/); } } if (fixmode&FIX_BIT_GRAPHICS_STEP_Y) { YPOS1616=ycur; YPOS=YPOS1616/65536.0; } else { XPOS1616=xcur; XPOS=XPOS1616/65536.0; } } void __fastcall DrawLRCel_New() { sf=100000; unsigned int pixel; unsigned int framePixel; int i,j,xcur,ycur,xvert,yvert,xdown,ydown,hdx,hdy; unsigned short CURPIX,LAMV; bpp=BPP[PRE0&PRE0_BPP_MASK]; offsetl=2; if(bpp < 8) offsetl=1; pixcount=0; offset=(offsetl==1)?((PRE1&PRE1_WOFFSET8_MASK)>>PRE1_WOFFSET8_SHIFT):((PRE1&PRE1_WOFFSET10_MASK)>>PRE1_WOFFSET10_SHIFT); offset+=2; SPRWI=1+(PRE1&PRE1_TLHPCNT_MASK); SPRHI=(((PRE0&PRE0_VCNT_MASK)>>PRE0_VCNT_SHIFT)<<1)+2; //doom fix if(TestInitVisual(0))return; xvert=XPOS1616; yvert=YPOS1616; if(TEXEL_FUN_NUMBER==0) { xvert+=TEXTURE_HI_START*VDX1616; yvert+=TEXTURE_HI_START*VDY1616; //if(SPRHI>TEXTURE_HI_LIM)SPRHI=TEXTURE_HI_LIM; if(SPRWI>TEXTURE_WI_LIM)SPRWI=TEXTURE_WI_LIM; for(i=TEXTURE_HI_START;i>16)<<2,ycur>>16,RMOD))); pixel = PPROC(CURPIX,framePixel,LAMV); pixel = PPROJ_OUTPUT(CURPIX, pixel, framePixel); mwriteh((FBTARGET+XY2OFF((xcur>>16)<<2,ycur>>16,WMOD)),pixel); } xcur+=HDX1616; ycur+=HDY1616; } } } else if(TEXEL_FUN_NUMBER==1) { int drawHeight; drawHeight = VDY1616; if (CCBFLAGS&CCB_MARIA && drawHeight > (1 << 16)) drawHeight = (1 << 16); for(i=0;i>16, ycur>>16, (xcur+HDX1616+VDX1616)>>16, (ycur+HDY1616+drawHeight)>>16))break; } xcur+=HDX1616; ycur+=HDY1616; } } } else { //return; for(i=0;i unsigned int TexelCCWTest(double hdx, double hdy, double vdx, double vdy) { if(((hdx+vdx)*(hdy-vdy)+vdx*vdy-hdx*hdy)<0.0)return CCB_ACCW; return CCB_ACW; } bool QuardCCWTest(int wdt) { unsigned int tmp; if(((CCBFLAGS&CCB_ACCW)) && ((CCBFLAGS&CCB_ACW)))return false; tmp=TexelCCWTest(HDX,HDY,VDX,VDY); if(tmp!=TexelCCWTest(HDX,HDY,VDX+(HDDX)*(float)wdt,VDY+(HDDY)*(float)wdt))return false; if(tmp!=TexelCCWTest(HDX+(HDDX)*SPRHI,HDY+(HDDY)*SPRHI,VDX,VDY))return false; if(tmp!=TexelCCWTest(HDX+(HDDX)*SPRHI,HDY+(HDDY)*SPRHI,VDX+(HDDX)*(float)SPRHI*(float)wdt,VDY+(HDDY)*(float)SPRHI*(float)wdt))return false; if(tmp==(CCBFLAGS&(CCB_ACCW|CCB_ACW))) return true; return false; } __inline int __abs(int val) { if(val>0)return val; return -val; } int TestInitVisual(int packed) { int xpoints[4],ypoints[4]; if((!(CCBFLAGS&CCB_ACCW)) && (!(CCBFLAGS&CCB_ACW)))return -1; if(!packed) { xpoints[0]=XPOS1616>>16; xpoints[1]=(XPOS1616+HDX1616*SPRWI)>>16; xpoints[2]=(XPOS1616+VDX1616*SPRHI)>>16; xpoints[3]=(XPOS1616+VDX1616*SPRHI+ (HDX1616+HDDX1616*SPRHI)*SPRWI)>>16; if(xpoints[0]<0 && xpoints[1]<0 && xpoints[2]<0 && xpoints[3]<0) return -1; if(xpoints[0]>CLIPXVAL && xpoints[1]>CLIPXVAL && xpoints[2]>CLIPXVAL && xpoints[3]>CLIPXVAL) return -1; ypoints[0]=YPOS1616>>16; ypoints[1]=(YPOS1616+HDY1616*SPRWI)>>16; ypoints[2]=(YPOS1616+VDY1616*SPRHI)>>16; ypoints[3]=(YPOS1616+VDY1616*SPRHI+ (HDY1616+HDDY1616*SPRHI)*SPRWI)>>16; if(ypoints[0]<0 && ypoints[1]<0 && ypoints[2]<0 && ypoints[3]<0) return -1; if(ypoints[0]>CLIPYVAL && ypoints[1]>CLIPYVAL && ypoints[2]>CLIPYVAL && ypoints[3]>CLIPYVAL) return -1; } else { xpoints[0]=XPOS1616>>16; xpoints[1]=(XPOS1616+VDX1616*SPRHI)>>16; if( xpoints[0]<0 && xpoints[1]<0 && HDX1616<=0 && HDDX1616<=0 ) return -1; if(xpoints[0]>CLIPXVAL && xpoints[1]>CLIPXVAL && HDX1616>=0 && HDDX1616>=0 ) return -1; ypoints[0]=YPOS1616>>16; ypoints[1]=(YPOS1616+VDY1616*SPRHI)>>16; if(ypoints[0]<0 && ypoints[1]<0 && HDY1616<=0 && HDDY1616<=0 ) return -1; if(ypoints[0]>CLIPYVAL && ypoints[1]>CLIPYVAL && HDY1616>=0 && HDDY1616>=0 ) return -1; } //* if(HDDX1616==0 && HDDY1616==0) { if(HDX1616==0 && VDY1616==0) { if((HDY1616<0 && VDX1616>0)||(HDY1616>0 && VDX1616<0)) { if((CCBFLAGS&CCB_ACW)) { if(__abs(HDY1616)==0x10000 && __abs(VDX1616)==0x10000 && !((YPOS1616|XPOS1616)&0xffff)) { return Init_Line_Map(); //return 0; } else { Init_Scale_Map(); return 0; } } } else { if((CCBFLAGS&CCB_ACCW)) { if(__abs(HDY1616)==0x10000 && __abs(VDX1616)==0x10000 && !((YPOS1616|XPOS1616)&0xffff)) { return Init_Line_Map(); //return 0; } else { Init_Scale_Map(); return 0; } } } return -1; } else if(HDY1616==0 && VDX1616==0) { if((HDX1616<0 && VDY1616>0)||(HDX1616>0 && VDY1616<0)) { if((CCBFLAGS&CCB_ACCW)) { if(__abs(HDX1616)==0x10000 && __abs(VDY1616)==0x10000 && !((YPOS1616|XPOS1616)&0xffff)) { return Init_Line_Map(); //return 0; } else { Init_Scale_Map(); return 0; } } } else { if((CCBFLAGS&CCB_ACW)) { if(__abs(HDX1616)==0x10000 && __abs(VDY1616)==0x10000 && !((YPOS1616|XPOS1616)&0xffff)) { return Init_Line_Map(); //return 0; } else { Init_Scale_Map(); return 0; } } } return -1; } } //*/ if(QuardCCWTest((!packed)?SPRWI:2048))return -1; Init_Arbitrary_Map(); return 0; } int Init_Line_Map() { TEXEL_FUN_NUMBER=0; TEXTURE_WI_START=0; TEXTURE_HI_START=0; TEXTURE_HI_LIM=SPRHI; if(HDX1616<0) XPOS1616-=0x8000; else if(VDX1616<0) XPOS1616-=0x8000; if(HDY1616<0) YPOS1616-=0x8000; else if(VDY1616<0) YPOS1616-=0x8000; if(VDX1616<0) { if(((XPOS1616)-((SPRHI-1)<<16)>>16)<0) TEXTURE_HI_LIM=(XPOS1616>>16)+1; if(TEXTURE_HI_LIM>SPRHI)TEXTURE_HI_LIM=SPRHI; } else if(VDX1616>0) { if(((XPOS1616+(SPRHI<<16))>>16)>CLIPXVAL) TEXTURE_HI_LIM=CLIPXVAL-(XPOS1616>>16)+1; } if(VDY1616<0) { if(((YPOS1616)-((SPRHI-1)<<16)>>16)<0) TEXTURE_HI_LIM=(YPOS1616>>16)+1; if(TEXTURE_HI_LIM>SPRHI)TEXTURE_HI_LIM=SPRHI; } else if(VDY1616>0) { if(((YPOS1616+(SPRHI<<16))>>16)>CLIPYVAL) TEXTURE_HI_LIM=CLIPYVAL-(YPOS1616>>16)+1; } if(HDX1616<0) TEXTURE_WI_LIM=(XPOS1616>>16)+1; else if(HDX1616>0) TEXTURE_WI_LIM=CLIPXVAL-(XPOS1616>>16)+1; if(HDY1616<0) TEXTURE_WI_LIM=(YPOS1616>>16)+1; else if(HDY1616>0) TEXTURE_WI_LIM=CLIPYVAL-(YPOS1616>>16)+1; if(XPOS1616<0) { if(HDX1616<0)return -1; else if(HDX1616>0) TEXTURE_WI_START=-(XPOS1616>>16); if(VDX1616<0)return -1; else if(VDX1616>0) TEXTURE_HI_START=-(XPOS1616>>16); } else if((XPOS1616>>16)>CLIPXVAL) { if(HDX1616>0)return -1; else if(HDX1616<0) TEXTURE_WI_START=(XPOS1616>>16)-CLIPXVAL; if(VDX1616>0)return -1; else if(VDX1616<0) TEXTURE_HI_START=(XPOS1616>>16)-CLIPXVAL; } if(YPOS1616<0) { if(HDY1616<0)return -1; else if(HDY1616>0) TEXTURE_WI_START=-(YPOS1616>>16); if(VDY1616<0)return -1; else if(VDY1616>0) TEXTURE_HI_START=-(YPOS1616>>16); } else if((YPOS1616>>16)>CLIPYVAL) { if(HDY1616>0)return -1; else if(HDY1616<0) TEXTURE_WI_START=(YPOS1616>>16)-CLIPYVAL; if(VDY1616>0)return -1; else if(VDY1616<0) TEXTURE_HI_START=(YPOS1616>>16)-CLIPYVAL; } //if(TEXTURE_WI_START<((PRE0>>24)&0xf)) // TEXTURE_WI_START=((PRE0>>24)&0xf); //TEXTURE_WI_START+=(PRE0>>24)&0xf; //if(TEXTURE_WI_START<0)TEXTURE_WI_START=0; //if(TEXTURE_HI_START<0)TEXTURE_HI_START=0; //if(TEXTURE_HI_LIM>SPRHI)TEXTURE_HI_LIM=SPRHI; if(TEXTURE_WI_LIM<=0)return -1; return 0; } void Init_Scale_Map() { int deltax,deltay; TEXEL_FUN_NUMBER=1; if(HDX1616<0) XPOS1616-=0x8000; else if(VDX1616<0) XPOS1616-=0x8000; if(HDY1616<0) YPOS1616-=0x8000; else if(VDY1616<0) YPOS1616-=0x8000; deltax=HDX1616+VDX1616; deltay=HDY1616+VDY1616; if(deltax<0)TEXEL_INCX=-1; else TEXEL_INCX=1; if(deltay<0)TEXEL_INCY=-1; else TEXEL_INCY=1; TEXEL_INCX<<=2; TEXTURE_WI_START=0; TEXTURE_HI_START=0; } void Init_Arbitrary_Map() { TEXEL_FUN_NUMBER=2; TEXTURE_WI_START=0; TEXTURE_HI_START=0; } int __fastcall TexelDraw_Line(unsigned short CURPIX, unsigned short LAMV, int xcur, int ycur, int cnt) { int i=0,j,incx,incy; unsigned int pixel; unsigned int curr=0xffffffff, next; xcur>>=16; ycur>>=16; for(i=0;i>16),ycur+=(HDY1616>>16)) { next=mreadh((PIXSOURCE+XY2OFF((xcur)<<2,ycur,RMOD))); if(next!=curr) { curr=next; pixel=PPROC(CURPIX,next,LAMV); } //pixel=PPROC(CURPIX,mreadh((PIXSOURCE+XY2OFF((xcur>>16)<<2,ycur>>16,RMOD))),LAMV); pixel = PPROJ_OUTPUT(CURPIX, pixel, next); mwriteh((FBTARGET+XY2OFF((xcur)<<2,ycur,WMOD)),pixel); } return 0; } __inline uint16 readPIX(uint32 src, int i, int j) { src+=XY2OFF((((j)>>(RESSCALE))<<2),(i>>RESSCALE),WMOD); if(RESSCALE) return *((uint16*)&Mem[(src^2)+(((i&1)<<1)+((j)&1))*1024*1024]); return *((uint16*)&Mem[src^2]); } __inline void writePIX(uint32 src, int i, int j, uint16 pix) { src+=XY2OFF((((j)>>(RESSCALE))<<2),(i>>RESSCALE),WMOD); if(RESSCALE) *((uint16*)&Mem[(src^2)+(((i&1)<<1)+((j)&1))*1024*1024])=pix; else *((uint16*)&Mem[src^2])=pix; } int __fastcall TexelDraw_Scale(unsigned short CURPIX, unsigned short LAMV, int xcur, int ycur, int deltax, int deltay) { int i,j; unsigned int pixel; unsigned int framePixel; unsigned int curr=-1, next; if((HDX1616<0) && (deltax)<0 && xcur<0) { return -1; } else if((HDY1616<0) && (deltay)<0 && ycur<0 ) { return -1; } else if((HDX1616>0) && (deltax)>(CLIPXVAL) && (xcur)>(CLIPXVAL)) { return -1; } else if((HDY1616>0) && ((deltay))>(CLIPYVAL) && (ycur)>(CLIPYVAL)) { return -1; } else { if((((int)xcur))==(((int)deltax)))return 0; for(i=((int)ycur);i!=(((int)deltay));i+=TEXEL_INCY) for(j=(((int)xcur))<<2;j!=((((int)deltax))<<2);j+=TEXEL_INCX) if((TESTCLIP((j<<14),(i<<16)))) { framePixel = mreadh((PIXSOURCE+XY2OFF(j,i,RMOD))); pixel=PPROC(CURPIX,framePixel,LAMV); pixel=PPROJ_OUTPUT(CURPIX, pixel, framePixel); //next=mreadh((PIXSOURCE+XY2OFF(j,i,RMOD))); //if(next!=curr){curr=next;pixel=PPROC(CURPIX,next,LAMV);} mwriteh((FBTARGET+XY2OFF(j,i,WMOD)),pixel); } } return 0; } __inline int TexelCCWTestSmp(int hdx, int hdy, int vdx, int vdy) { if(((hdx+vdx)*(hdy-vdy)+vdx*vdy-hdx*hdy)<0)return CCB_ACCW; return CCB_ACW; } int __fastcall TexelDraw_Arbitrary(unsigned short CURPIX, unsigned short LAMV, int xA, int yA, int xB, int yB, int xC, int yC, int xD, int yD) { int miny, maxy, i, itmp, xpoints[4], j, maxyt, maxxt, maxx, minx; int updowns[4],cnt_cross, jtmp; unsigned int pixel; unsigned int curr=-1, next; xA>>=(16-RESSCALE); xB>>=(16-RESSCALE); xC>>=(16-RESSCALE); xD>>=(16-RESSCALE); yA>>=(16-RESSCALE); yB>>=(16-RESSCALE); yC>>=(16-RESSCALE); yD>>=(16-RESSCALE); if((xA)==(xB) && (xB)==(xC) && (xC)==(xD)) return 0; maxxt=((CLIPXVAL+1)<0 && HDDX1616>0) { if(((xA)>=maxxt) && ((xB)>=maxxt) && ((xC)>=maxxt) && ((xD)>=maxxt)) return -1; } if(HDY1616<0 && HDDY1616<0) { if((yA<0) && (yB<0) && (yC<0) && (yD<0)) return -1; } if(HDY1616>0 && HDDY1616>0) { if(((yA)>=maxyt) && ((yB)>=maxyt) && ((yC)>=maxyt) && ((yD)>=maxyt)) return -1; } miny=maxy=yA; if(miny>yB)miny=yB; if(miny>yC)miny=yC; if(miny>yD)miny=yD; if(maxy=(yA)) { xpoints[cnt_cross]=(int)((quickDivide(((xB-xA)*(i-yA)),(yB-yA))+xA)); updowns[cnt_cross++]=1; } else if(i>=(yB) && i<(yA)) { xpoints[cnt_cross]=(int)((quickDivide(((xA-xB)*(i-yB)),(yA-yB))+xB)); updowns[cnt_cross++]=0; } if(i<(yC) && i>=(yB)) { xpoints[cnt_cross]=(int)((quickDivide(((xC-xB)*(i-yB)),(yC-yB))+xB)); updowns[cnt_cross++]=1; } else if(i>=(yC) && i<(yB)) { xpoints[cnt_cross]=(int)((quickDivide(((xB-xC)*(i-yC)),(yB-yC))+xC)); updowns[cnt_cross++]=0; } if(i<(yD) && i>=(yC)) { xpoints[cnt_cross]=(int)((quickDivide(((xD-xC)*(i-yC)),(yD-yC))+xC)); updowns[cnt_cross++]=1; } else if(i>=(yD) && i<(yC)) { xpoints[cnt_cross]=(int)((quickDivide(((xC-xD)*(i-yD)),(yC-yD))+xD)); updowns[cnt_cross++]=0; } if(cnt_cross&1) { if(i<(yA) && i>=(yD)) { xpoints[cnt_cross]=(int)((quickDivide(((xA-xD)*(i-yD)),(yA-yD))+xD)); updowns[cnt_cross]=1; } else if(i>=(yA) && i<(yD)) { xpoints[cnt_cross]=(int)((quickDivide(((xD-xA)*(i-yA)),(yD-yA))+xA)); updowns[cnt_cross]=0; } } if(cnt_cross!=0) { if(xpoints[0]>xpoints[1]) { xpoints[1]+=xpoints[0]; xpoints[0]=xpoints[1]-xpoints[0]; xpoints[1]=xpoints[1]-xpoints[0]; jtmp=updowns[0]; updowns[0]=updowns[1]; updowns[1]=jtmp; } if(cnt_cross>2) { if( ((CCBFLAGS&CCB_ACW)&&updowns[2]==0) || ((CCBFLAGS&CCB_ACCW)&&updowns[2]==1)) { j=xpoints[2]; if(j<0)j=0; maxx=xpoints[3]; if(maxx>maxxt)maxx=maxxt; for(;jmaxxt)maxx=maxxt; for(;j