Files
2014-03-22 22:16:57 +01:00

2881 lines
63 KiB
C++

/*
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 <math.h>
#include <memory.h>
#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)<<CCB_POVER_SHIFT) /* Normal */
#define PMODE_ZERO ((0x00000002)<<CCB_POVER_SHIFT)
#define PMODE_ONE ((0x00000003)<<CCB_POVER_SHIFT)
// === CCBCTL0 flags ===
#define B15POS_MASK 0xC0000000
#define B0POS_MASK 0x30000000
#define SWAPHV 0x08000000
#define ASCALL 0x04000000
#define _CCBCTL0_u25 0x02000000
#define CFBDSUB 0x01000000
#define CFBDLSB_MASK 0x00C00000
#define PDCLSB_MASK 0x00300000
#define B15POS_SHIFT 30
#define B0POS_SHIFT 28
#define CFBD_SHIFT 22
#define PDCLSB_SHIFT 20
// B15POS_MASK definitions
#define B15POS_0 0x00000000
#define B15POS_1 0x40000000
#define B15POS_PDC 0xC0000000
// B0POS_MASK definitions
#define B0POS_0 0x00000000
#define B0POS_1 0x10000000
#define B0POS_PPMP 0x20000000
#define B0POS_PDC 0x30000000
/*
// CFBDLSB_MASK definitions
#define CFBDLSB_0 0x00000000
#define CFBDLSB_CFBD0 0x00400000
#define CFBDLSB_CFBD4 0x00800000
#define CFBDLSB_CFBD5 0x00C00000
// PDCLSB_MASK definitions
#define PDCLSB_0 0x00000000
#define PDCLSB_PDC0 0x00100000
#define PDCLSB_PDC4 0x00200000
#define PDCLSB_PDC5 0x00300000
*/
/* === Cel first preamble word flags === */
#define PRE0_LITERAL 0x80000000
#define PRE0_BGND 0x40000000
#define PREO_reservedA 0x30000000
#define PRE0_SKIPX_MASK 0x0F000000
#define PREO_reservedB 0x00FF0000
#define PRE0_VCNT_MASK 0x0000FFC0
#define PREO_reservedC 0x00000020
#define PRE0_LINEAR 0x00000010
#define PRE0_REP8 0x00000008
#define PRE0_BPP_MASK 0x00000007
#define PRE0_SKIPX_SHIFT 24
#define PRE0_VCNT_SHIFT 6
#define PRE0_BPP_SHIFT 0
/* PRE0_BPP_MASK definitions */
#define PRE0_BPP_1 0x00000001
#define PRE0_BPP_2 0x00000002
#define PRE0_BPP_4 0x00000003
#define PRE0_BPP_6 0x00000004
#define PRE0_BPP_8 0x00000005
#define PRE0_BPP_16 0x00000006
/* Subtract this value from the actual vertical source line count */
#define PRE0_VCNT_PREFETCH 1
/* === Cel second preamble word flags === */
#define PRE1_WOFFSET8_MASK 0xFF000000
#define PRE1_WOFFSET10_MASK 0x03FF0000
#define PRE1_NOSWAP 0x00004000
#define PRE1_TLLSB_MASK 0x00003000
#define PRE1_LRFORM 0x00000800
#define PRE1_TLHPCNT_MASK 0x000007FF
#define PRE1_WOFFSET8_SHIFT 24
#define PRE1_WOFFSET10_SHIFT 16
#define PRE1_TLLSB_SHIFT 12
#define PRE1_TLHPCNT_SHIFT 0
#define PRE1_TLLSB_0 0x00000000
#define PRE1_TLLSB_PDC0 0x00001000 /* Normal */
#define PRE1_TLLSB_PDC4 0x00002000
#define PRE1_TLLSB_PDC5 0x00003000
/* Subtract this value from the actual word offset */
#define PRE1_WOFFSET_PREFETCH 2
/* Subtract this value from the actual pixel count */
#define PRE1_TLHPCNT_PREFETCH 1
#define PPMP_0_SHIFT 0
#define PPMP_1_SHIFT 16
#define PPMPC_1S_MASK 0x00008000
#define PPMPC_MS_MASK 0x00006000
#define PPMPC_MF_MASK 0x00001C00
#define PPMPC_SF_MASK 0x00000300
#define PPMPC_2S_MASK 0x000000C0
#define PPMPC_AV_MASK 0x0000003E
#define PPMPC_2D_MASK 0x00000001
#define PPMPC_MS_SHIFT 13
#define PPMPC_MF_SHIFT 10
#define PPMPC_SF_SHIFT 8
#define PPMPC_2S_SHIFT 6
#define PPMPC_AV_SHIFT 1
/* PPMPC_1S_MASK definitions */
#define PPMPC_1S_PDC 0x00000000
#define PPMPC_1S_CFBD 0x00008000
/* PPMPC_MS_MASK definitions */
#define PPMPC_MS_CCB 0x00000000
#define PPMPC_MS_PIN 0x00002000
#define PPMPC_MS_PDC_MFONLY 0x00004000
#define PPMPC_MS_PDC 0x00004000
/* PPMPC_MF_MASK definitions */
#define PPMPC_MF_1 0x00000000
#define PPMPC_MF_2 0x00000400
#define PPMPC_MF_3 0x00000800
#define PPMPC_MF_4 0x00000C00
#define PPMPC_MF_5 0x00001000
#define PPMPC_MF_6 0x00001400
#define PPMPC_MF_7 0x00001800
#define PPMPC_MF_8 0x00001C00
/* PPMPC_SF_MASK definitions */
#define PPMPC_SF_2 0x00000100
#define PPMPC_SF_4 0x00000200
#define PPMPC_SF_8 0x00000300
#define PPMPC_SF_16 0x00000000
/* PPMPC_2S_MASK definitions */
#define PPMPC_2S_0 0x00000000
#define PPMPC_2S_CCB 0x00000040
#define PPMPC_2S_CFBD 0x00000080
#define PPMPC_2S_PDC 0x000000C0
/* PPMPC_2D_MASK definitions */
#define PPMPC_2D_1 0x00000000
#define PPMPC_2D_2 0x00000001
#pragma pack(push,1)
struct cp1btag{
unsigned short c:1;
unsigned short pad:15;
};
struct cp2btag{
unsigned short c:2;
unsigned short pad:14;
};
typedef struct cp4btag{
unsigned short c:4;
unsigned short pad:12;
} cp4b;
struct cp6btag{
unsigned short c:5;
unsigned short pw:1;
unsigned short pad:10;
};
struct cp8btag{
unsigned short c:5;
unsigned short mpw:1;
unsigned short m:2;
unsigned short pad:8;
};
struct cp16btag{
unsigned short c:5;
unsigned short mb:3;
unsigned short mg:3;
unsigned short mr:3;
unsigned short pad:1;
unsigned short pw:1;
};
struct up8btag{
unsigned short b:2;
unsigned short g:3;
unsigned short r:3;
unsigned short pad:8;
};
struct up16btag{
unsigned short bw:1;
unsigned short b:4;
unsigned short g:5;
unsigned short r:5;
unsigned short p:1;
};
struct res16btag{
unsigned short b:5;
unsigned short g:5;
unsigned short r:5;
unsigned short p:1;
};
union pdeco{
unsigned int raw;
cp1btag c1b;
cp2btag c2b;
cp4btag c4b;
cp6btag c6b;
cp8btag c8b;
cp16btag c16b;
up8btag u8b;
up16btag u16b;
res16btag r16b;
};
struct avtag
{
unsigned char NEG:1;
unsigned char XTEND:1;
unsigned char nCLIP:1;
unsigned char dv3:2;
unsigned char pad:3;
};
union AVS{
avtag avsignal;
unsigned int raw;
};
struct pixctag
{
unsigned char dv2:1;
unsigned char av:5; // why int don't work???
unsigned char s2:2;
unsigned char dv1:2;
unsigned char mxf:3;
unsigned char ms:2;
unsigned char s1:1;
};
union PXC
{
pixctag meaning;
unsigned int raw;
};
#pragma pack(pop)
//*******************************************
#pragma pack(push,1)
struct MADAMDatum
{
unsigned int mregs[2048+64];
unsigned short PLUT[32];
unsigned char PBUSQueue[20];
int RMOD;
int WMOD;
unsigned int _madam_FSM;
};
#pragma pack(pop)
static MADAMDatum madam;
unsigned int Get_madam_FSM(){return madam._madam_FSM;};
void Set_madam_FSM(unsigned int val){madam._madam_FSM=val;};
unsigned int _madam_SaveSize()
{
return sizeof(MADAMDatum);
}
void _madam_Save(void *buff)
{
memcpy(buff,&madam,sizeof(MADAMDatum));
}
void _madam_Load(void *buff)
{
memcpy(&madam,buff,sizeof(MADAMDatum));
}
#define mregs madam.mregs
#define PLUT madam.PLUT
#define PBUSQueue madam.PBUSQueue
#define RMOD madam.RMOD
#define WMOD madam.WMOD
#define _madam_FSM madam._madam_FSM
//*******************************************
unsigned int PXOR1, PXOR2;
#define PDV(x) ((((x)-1)&3)+1)
#define MIN(x,y) (x)+(((signed int)((y)-(x))>>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<n;i++)
{
PLUT[i]=_mem_read16((((pnt>>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<pixcount;pix++)
{
CURPIX=PDEC(bitoper.Read(bpp),&LAMV);
if(!pproj.Transparent)
{
//TexelDraw_Line(CURPIX, LAMV, xcur, ycur, 1);
framePixel = mreadh((PIXSOURCE+XY2OFF((xcur>>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<SPRHI;currentrow++)
{
bitoper.AttachBuffer(start);
offset=bitoper.Read(offsetl<<3);
BITCALC=((offset+2)<<2)<<5;
lastaddr=start+((offset+2)<<2);
eor=0;
xcur=xvert;
ycur=yvert;
xvert+=VDX1616;
yvert+=VDY1616;
while(!eor)//while not end of row
{
type=bitoper.Read(2);
if( (bitoper.GetBytePose()+start) >= (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<SPRHI;currentrow++)
{
bitoper.AttachBuffer(start);
offset=bitoper.Read(offsetl<<3);
BITCALC=((offset+2)<<2)<<5;
lastaddr=start+((offset+2)<<2);
eor=0;
xcur=xvert;
ycur=yvert;
hdx=HDX1616;
hdy=HDY1616;
xvert+=VDX1616;
yvert+=VDY1616;
HDX1616+=HDDX1616;
HDY1616+=HDDY1616;
xdown=xvert;
ydown=yvert;
while(!eor)//while not end of row
{
type=bitoper.Read(2);
if( (bitoper.GetBytePose()+start) >= (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<TEXTURE_HI_LIM;i++)
{
bitoper.AttachBuffer(PDATA);
BITCALC=((offset+2)<<2)<<5;
xcur=xvert+TEXTURE_WI_START*HDX1616;
ycur=yvert+TEXTURE_WI_START*HDY1616;
bitoper.Skip(bpp*(((PRE0>>24)&0xf)));
if(TEXTURE_WI_START)bitoper.Skip(bpp*(TEXTURE_WI_START));
xvert+=VDX1616;
yvert+=VDY1616;
for(j=TEXTURE_WI_START;j<SPRWI;j++)
{
CURPIX=PDEC(bitoper.Read(bpp),&LAMV);
if(!pproj.Transparent)
{
//TexelDraw_Line(CURPIX, LAMV, xcur, ycur, 1);
framePixel = mreadh((PIXSOURCE+XY2OFF((xcur>>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<SPRHI;i++)
{
bitoper.AttachBuffer(PDATA);
BITCALC=((offset+2)<<2)<<5;
xcur=xvert;
ycur=yvert;
xvert+=VDX1616;
yvert+=VDY1616;
bitoper.Skip(bpp*(((PRE0>>24)&0xf)));
for(j=0;j<SPRWI;j++)
{
CURPIX=PDEC(bitoper.Read(bpp),&LAMV);
if(!pproj.Transparent)
{
if(TexelDraw_Scale(CURPIX, LAMV, xcur>>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<SPRHI;i++)
{
bitoper.AttachBuffer(PDATA);
BITCALC=((offset+2)<<2)<<5;
xcur=xvert;
ycur=yvert;
hdx=HDX1616;
hdy=HDY1616;
xvert+=VDX1616;
yvert+=VDY1616;
HDX1616+=HDDX1616;
HDY1616+=HDDY1616;
bitoper.Skip(bpp*(((PRE0>>24)&0xf)));
xdown=xvert;
ydown=yvert;
for(j=0;j<SPRWI;j++)
{
CURPIX=PDEC(bitoper.Read(bpp),&LAMV);
if(!pproj.Transparent)
{
if(TexelDraw_Arbitrary(CURPIX, LAMV, xcur, ycur, xcur+hdx, ycur+hdy, xdown+HDX1616, ydown+HDY1616, xdown, ydown))
break;
if(speedfixes<1||(speedfixes>=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<TEXTURE_HI_LIM;i++)
{
xcur=xvert+TEXTURE_WI_START*HDX1616;
ycur=yvert+TEXTURE_WI_START*HDY1616;
xvert+=VDX1616;
yvert+=VDY1616;
for(j=TEXTURE_WI_START;j<SPRWI;j++)
{
CURPIX=PDEC(mreadh((PDATA+XY2OFF(j<<2,i,offset<<2))),&LAMV);
if(!pproj.Transparent)
{
//TexelDraw_Line(CURPIX, LAMV, xcur, ycur, 1);
framePixel = mreadh((PIXSOURCE+XY2OFF((xcur>>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<SPRHI;i++)
{
xcur=xvert;
ycur=yvert;
xvert+=VDX1616;
yvert+=VDY1616;
for(j=0;j<SPRWI;j++)
{
CURPIX=PDEC(mreadh((PDATA+XY2OFF(j<<2,i,offset<<2))),&LAMV);
if(!pproj.Transparent)
{
if(TexelDraw_Scale(CURPIX, LAMV, xcur>>16, ycur>>16, (xcur+HDX1616+VDX1616)>>16, (ycur+HDY1616+drawHeight)>>16))break;
}
xcur+=HDX1616;
ycur+=HDY1616;
}
}
}
else
{
//return;
for(i=0;i<SPRHI;i++)
{
xcur=xvert;
ycur=yvert;
xvert+=VDX1616;
yvert+=VDY1616;
xdown=xvert;
ydown=yvert;
hdx=HDX1616;
hdy=HDY1616;
HDX1616+=HDDX1616;
HDY1616+=HDDY1616;
for(j=0;j<SPRWI;j++)
{
CURPIX=PDEC(mreadh((PDATA+XY2OFF(j<<2,i,offset<<2))),&LAMV);
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;
}
}
}
if (fixmode&FIX_BIT_GRAPHICS_STEP_Y)
{
YPOS1616=ycur;
YPOS=YPOS1616/65536.0;
}
else
{
XPOS1616=xcur;
XPOS=XPOS1616/65536.0;
}
}
unsigned int _madam_GetCELCycles()
{
unsigned int val=CELCYCLES; // 1 word = 2 CELCYCLES, 1 hword= 1 CELCYCLE, 8 CELCYCLE=1 CPU SCYCLE
CELCYCLES=0;
return val;
}
void _madam_Reset()
{
int i;
for(i=0;i<2048;i++)
mregs[i]=0;
}
void _madam_SetMapping(unsigned int flag)
{
MAPPING=flag;
}
#define ROAN_SHIFT 16
#define ROAN_TYPE int
#include <math.h>
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<cnt;i++,xcur+=(HDX1616>>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)<<RESSCALE);
maxyt=((CLIPYVAL+1)<<RESSCALE);
if(HDX1616<0 && HDDX1616<0)
{
if((xA<0) && (xB<0) && (xC<0) && (xD<0))
return -1;
}
if(HDX1616>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<yB)maxy=yB;
if(maxy<yC)maxy=yC;
if(maxy<yD)maxy=yD;
i=(miny);
if(i<0)i=0;
if(maxy<maxyt)maxyt=maxy;
for(;i<maxyt;i++)
{
cnt_cross=0;
if(i<(yB) && i>=(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(;j<maxx;j++)
{
next=readPIX(PIXSOURCE, i, j);
if(next!=curr){curr=next;
pixel=PPROC(CURPIX,next,LAMV);
pixel = PPROJ_OUTPUT(CURPIX, pixel, next);
}
writePIX(FBTARGET, i, j, pixel);
}
}
}
if( ((CCBFLAGS&CCB_ACW)&&updowns[0]==0) ||
((CCBFLAGS&CCB_ACCW)&&updowns[0]==1))
{
j=xpoints[0];
if(j<0)j=0;
maxx=xpoints[1];
if(maxx>maxxt)maxx=maxxt;
for(;j<maxx;j++)
{
next=readPIX(PIXSOURCE, i, j);
if(next!=curr){curr=next;
pixel=PPROC(CURPIX,next,LAMV);
pixel=PPROJ_OUTPUT(CURPIX, pixel, next);
}
writePIX(FBTARGET, i, j, pixel);
}
}
}
}
return 0;
}