diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-04-16 06:22:51 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-04-16 06:22:51 +0000 |
| commit | 8139fbf8204882663446bcb06f68789353597820 (patch) | |
| tree | 6ea1f39932b33faee84d603e956470e37f135804 /plugins | |
| download | pcsxr-8139fbf8204882663446bcb06f68789353597820.tar.gz | |
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@23061 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'plugins')
96 files changed, 40014 insertions, 0 deletions
diff --git a/plugins/dfOpenGL/AUTHORS b/plugins/dfOpenGL/AUTHORS new file mode 100644 index 00000000..84b50402 --- /dev/null +++ b/plugins/dfOpenGL/AUTHORS @@ -0,0 +1,5 @@ +This plugin is based on (built around) gpuZenOpenGL by CitiZen X (1998). +GPL'd by permission September 23, 2007. +Many hints taken from Pete Bernert's GPL soft gpu plugin. + +Stephen Chao <stephen@digitalnexus.org> diff --git a/plugins/dfOpenGL/GPU.c b/plugins/dfOpenGL/GPU.c new file mode 100644 index 00000000..4776f47b --- /dev/null +++ b/plugins/dfOpenGL/GPU.c @@ -0,0 +1,1014 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> + +#define GPU_INTERNALS_DEF +#include "gpu_i.h" +#include "primitive_drawing.h" +#include "cfg.h" +#include "PSEmu_PlugIn_Defs.h" + +#include <X11/extensions/xf86vmode.h> + +#define CALLBACK + +// PPDK developer must change libraryName field and can change revision and build + +const unsigned char version = PLUGIN_VERSION; // do not touch - library for PSEmu 1.x + +// it is up to developer but values must be in range 0-255 + +const unsigned char revision = 1; +const unsigned char build = 0; + +// to obtain library name for your plugin, mail: plugin@psemu.com +// this must be unique, and only we can provide this +static char *libraryName = "PCSX-df OpenGL Plugin"; + +float scalarDispWidth,scalarDispHeight; +float scalarDrawWidth,scalarDrawHeight; + + +// driver dependant variables +GpuConfS gpuConfig; + +static int initGPU = 0; +static int ScreenOpened = 0; + +#define RED(x) (x & 0xff) +#define BLUE(x) ((x>>16) & 0xff) +#define GREEN(x) ((x>>8) & 0xff) + +#define COLOR(x) (x & 0xffffff) + +// macros for easy access to packet information +#define GPUCOMMAND(x) ((x>>24) & 0xff) + +// memory image of the PSX vram +unsigned char psxVub[1024*520*2]; +signed char *psxVsb; +unsigned short *psxVuw; +signed short *psxVsw; +uint32_t *psxVul; +int32_t *psxVsl; + +int flip; + +// internal GPU + +static int32_t GPUdataRet; +int32_t GPUstatusRet; +int32_t GPUInfoVals[16]; + +static uint32_t gpuData[100]; +static unsigned char gpuCommand = 0; +static int32_t gpuDataC = 0; +static int32_t gpuDataP = 0; + +int drawingLines; + +VRAMLoad_t vramWrite; +struct PSXDisplay_t psxDisp, oldpsxDisp; +struct PSXDraw_t psxDraw; + +short dispWidths[8] = {256,320,512,640,368,384,512,640}; + +int dispLace = 0; +int dispLaceNew; +int imageTransfer; +int drawLace; + +#define FRAMES 16 +GLuint drawrec; +int drawreccount; + +short imTYc,imTXc,imTY,imTX; +int imSize; +short imageX0,imageX1; +short imageY0,imageY1; + +unsigned short textBuf[512*512]; +int newTextX0,newTextX1,newTextX2,newTextX3; +int newTextY0,newTextY1,newTextY2,newTextY3; + +GLuint xferTexture16 = 0; +GLuint xferTexture24 = 0; + +uint32_t gpuDataX; + + +typedef struct +{ + Display *dpy; + int screen; + Window win; + GLXContext ctx; + XSetWindowAttributes attr; + BOOL fs; + XF86VidModeModeInfo deskMode; + int x,y; + unsigned int width, height; + unsigned int bpp; +}GLWindow; + +static GLWindow GLWin; /* Set our OpenGL Window to static, we only want one */ + + + +char * CALLBACK PSEgetLibName(void) +{ + return libraryName; +} + +unsigned long CALLBACK PSEgetLibType(void) +{ + return PSE_LT_GPU; +} + +unsigned long CALLBACK PSEgetLibVersion(void) +{ + return version<<16|revision<<8|build; +} + + + + +long CALLBACK GPUinit() +{ + //if(capcom fighting game) dispWidths[4]=384; + //else dispWidths[4]=368; + + /* Set default configuration values */ + gpuConfig.bFullscreen=FALSE; + gpuConfig.bBilinear=FALSE; + gpuConfig.nMaxTextures=64; + gpuConfig.bWireFrame=FALSE; + gpuConfig.bAntialias=FALSE; + gpuConfig.bClearScreen=FALSE; + gpuConfig.FrameLimit=1; + + /* Read in values from the config file */ + readconfig(); + + // mapping the VRAM + psxVsb=(signed char *)psxVub; + psxVsw=(signed short *)psxVub; + psxVsl=(int32_t *)psxVub; + psxVuw=(unsigned short *)psxVub; + psxVul=(uint32_t *)psxVub; + + GPUstatusRet = 0x74000000; + memset(GPUInfoVals,0x00,16*sizeof(uint32_t)); + + return PSE_ERR_SUCCESS; +} + + +long CALLBACK GPUshutdown() +{ + if(initGPU==1) + { + initGPU=0; + } + return 0; +} + + +void DoGLInit(){ + int i; + + glViewport(0,0,gpuConfig.windowX,gpuConfig.windowY); + /* + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glScalef(1.0f,-1.0f,1.0f); + glOrtho(0.0,1024,0.0,512,1.0,-1.0); + */ + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(1.0f/256.0f,1.0f/256.0f,1.0f); + //glTranslatef(0.5f, 0.5f, 0); + + glEnable(GL_CLIP_PLANE0); + glEnable(GL_CLIP_PLANE1); + glEnable(GL_CLIP_PLANE2); + glEnable(GL_CLIP_PLANE3); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); + if(gpuConfig.bAntialias){ + glEnable(GL_LINE_SMOOTH); + glEnable(GL_POLYGON_SMOOTH); + } + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + + glEnable(GL_TEXTURE_2D); + for(i=0;i<gpuConfig.nMaxTextures;i++){ + texture[i].textAddrX=0; + texture[i].textAddrY=0; + texture[i].textTP=0; + texture[i].clutP=nullclutP; + texture[i].Update=FALSE; + glGenTextures(1,&texture[i].id); + glBindTexture(GL_TEXTURE_2D,texture[i].id); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + if(gpuConfig.bBilinear){ + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + }else{ + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + } + glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + glTexImage2D(GL_TEXTURE_2D,0,4,256,256,0,GL_RGBA,GL_UNSIGNED_BYTE,image); + } + + glGenTextures(1,&xferTexture24); + glBindTexture(GL_TEXTURE_2D,xferTexture24); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexImage2D(GL_TEXTURE_2D,0,3,1024,512,0,GL_RGB,GL_UNSIGNED_BYTE,0); + + glGenTextures(1,&xferTexture16); + glBindTexture(GL_TEXTURE_2D,xferTexture16); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexImage2D(GL_TEXTURE_2D,0,4,1024,512,0,GL_RGBA,GL_UNSIGNED_BYTE,0); + + glGenTextures(1,&nullid); + glBindTexture(GL_TEXTURE_2D,nullid); + glTexImage2D(GL_TEXTURE_2D,0,4,0,0,0,GL_RGBA,GL_UNSIGNED_BYTE,0); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if(gpuConfig.bWireFrame) + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + + drawrec = glGenLists(FRAMES); + glNewList(drawrec, GL_COMPILE); + drawreccount=0; + + + //black is reversed: transparent when STP not set, opaque when set + torgba[0]=0x00000000; + for(i=1;i<65536;i++){ + torgba[i] =(i&0x001f)<<3; + torgba[i]|=(i&0x03e0)<<6; + torgba[i]|=(i&0x7c00)<<9; + torgba[i]|=0xfe000000; + if (!(i&0x8000)) + torgba[i]|=0xff000000; + //torgba[i]|=0xff000000; + } + torgba[0x8000] = 0xff000000; + + for(i=0; i<128; i++) + texshade[i]=i<<1; + for(i=128; i<256; i++) + texshade[i]=255; + + gllog(0,(char*)glGetString(GL_VENDOR)); + gllog(0,(char*)glGetString(GL_RENDERER)); + gllog(0,(char*)glGetString(GL_VERSION)); + gllog(0,(char*)glGetString(GL_EXTENSIONS)); +} + +long CALLBACK GPUopen(unsigned long * disp,char * CapText,char * CfgFile) +{ + int attrListDbl[] = {GLX_RGBA, GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + None}; + + XVisualInfo *vi; + Colormap cmap; + int dpyWidth, dpyHeight; + int i; + int vidModeMajorVersion, vidModeMinorVersion; + XF86VidModeModeInfo **modes; + int modeNum; + int bestMode; + Atom wmDelete; + Window winDummy; + unsigned int borderDummy; + + GLWin.fs = gpuConfig.bFullscreen; + bestMode = 0; + + GLWin.dpy = XOpenDisplay(0); + GLWin.screen = DefaultScreen(GLWin.dpy); + XF86VidModeQueryVersion(GLWin.dpy, &vidModeMajorVersion, + &vidModeMinorVersion); + + XF86VidModeGetAllModeLines(GLWin.dpy, GLWin.screen, &modeNum, &modes); + + GLWin.deskMode = *modes[0]; + + for (i = 0; i < modeNum; i++) + { + if ((modes[i]->hdisplay == gpuConfig.windowX) && (modes[i]->vdisplay == gpuConfig.windowY)) + { + bestMode = i; + } + } + + vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl); + if (vi == NULL) + { + printf("Visual not found\n"); + exit(0); + } + + GLWin.ctx = glXCreateContext(GLWin.dpy, vi, 0, GL_TRUE); + + cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen),vi->visual, AllocNone); + GLWin.attr.colormap = cmap; + GLWin.attr.border_pixel = 0; + + GLWin.attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | StructureNotifyMask; + + + if(GLWin.fs) + { + XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, modes[bestMode]); + XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0); + dpyWidth = modes[bestMode]->hdisplay; + dpyHeight = modes[bestMode]->vdisplay; + XFree(modes); + GLWin.attr.override_redirect = True; + GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), + 0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, + &GLWin.attr); + XWarpPointer(GLWin.dpy, None, GLWin.win, 0, 0, 0, 0, 0, 0); + XMapRaised(GLWin.dpy, GLWin.win); + XGrabKeyboard(GLWin.dpy, GLWin.win, True, GrabModeAsync,GrabModeAsync, CurrentTime); + XGrabPointer(GLWin.dpy, GLWin.win, True, ButtonPressMask, + GrabModeAsync, GrabModeAsync, GLWin.win, None, CurrentTime); + } + else + { + GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), + 0, 0, gpuConfig.windowX, gpuConfig.windowY, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr); + wmDelete = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True); + XSetWMProtocols(GLWin.dpy, GLWin.win, &wmDelete, 1); + XSetStandardProperties(GLWin.dpy, GLWin.win, CapText, + CapText, None, NULL, 0, NULL); + XMapRaised(GLWin.dpy, GLWin.win); + } + + glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx); + XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, + &GLWin.width, &GLWin.height, &borderDummy, &GLWin.bpp); + + printf("Direct Rendering: %s\n",glXIsDirect(GLWin.dpy, GLWin.ctx) ? "true" : "false"); + printf("Running in %s mode\n",GLWin.fs ? "fullscreen" : "window"); + + if(disp) + *disp=(long)GLWin.dpy; // wanna x pointer? ok + + ScreenOpened=1; + + DoGLInit(); + + return 0; +} + +long CALLBACK GPUclose() +{ + if(GLWin.ctx) + { + if(!glXMakeCurrent(GLWin.dpy, None, NULL)) + { + printf("Error releasing drawing context : killGLWindow\n"); + } + glXDestroyContext(GLWin.dpy, GLWin.ctx); + GLWin.ctx = NULL; + } + + if(GLWin.fs) + { + XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, &GLWin.deskMode); + XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0); + } + XCloseDisplay(GLWin.dpy); + + return 0; +} + +bool db=FALSE; + + +void waitforrealtime(); + +/* +Here's how playstation double buffering works: +1) Vsync +2) Set buffer selection (via status 0x05) (psxDisp.startX & Y) +3) (Possibly) swap draw area, and draw. +1) Vsync +... + +The problem arises in step 3 when drawing is done in the back buffer while step 2 and the subsequent vsync shows the front. +Current solution is to record the draw commands (3), wait till (2), then playback the draw into the now-known buffer. +During vsync we output the most recent frame (3) to catch any offscreen drawing. This means we draw everything twice...but at least most of it will be clipped. + +*/ + +void updateScreenMode() +{ + int i=0; + + glEndList(); + + if(psxDisp.modeX>0 && psxDisp.modeY>0) + { + int height = (psxDisp.rangeY2-psxDisp.rangeY1) * ((int)psxDisp.interlaced+1); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glScalef(1.0f,-1.0f,1.0f); + glOrtho(psxDisp.startX, psxDisp.startX + psxDisp.modeX, + psxDisp.startY, psxDisp.startY + height, 1.0,-1.0); + //glOrtho(0,(double)1024,0,(double)768,1.0,-1.0); + //glOrtho(0,psxDisp.modeX,0,psxDisp.modeY,1.0,-1.0); + + //glMatrixMode(GL_MODELVIEW); + //glLoadIdentity(); + //glPushMatrix(); + //glTranslatef(-oldpsxDisp.startX, -oldpsxDisp.startY, 0); + for(i=0;i<=drawreccount;i++) + { + glCallList(drawrec+i); + //glXSwapBuffers(GLWin.dpy, GLWin.win); + } + drawreccount=0; + //glPopMatrix(); + } + + glNewList(drawrec,GL_COMPILE); +} + +void updateDisplay(void) +{ + glEndList(); + + glCallList(drawrec+drawreccount); + glFlush(); + if (gpuConfig.FrameLimit) + waitforrealtime(); + + glXSwapBuffers(GLWin.dpy, GLWin.win); + + drawreccount++; + drawreccount%=FRAMES; + + glNewList(drawrec+drawreccount,GL_COMPILE); +} + +// update lace is called every VSync +void CALLBACK GPUupdateLace(void) +{ + //if(dispLace) + //{ + drawingLines^=1; + //if(psxDisp.modeX>0 && psxDisp.modeY>0) + //{ + //gllog(0,"UPDATING LACE"); + updateDisplay(); + //} + //} +} + + +// process read request from GPU status register +unsigned long CALLBACK GPUreadStatus(void) +{ + // return the status of the GPU + /* + - gp1 - GPU Status + Mask + 04000000 - 1:Idle 0:Busy + 10000000 - 1:Ready 0:Not ready , to receive commands. + 80000000 - GPU is drawing 1:Odd 0:Even lines, in interlaced mode. + */ + //just'0x74000000' for now ! (idle, ready, even lines) + if (drawingLines==1) + return GPUstatusRet; + else + return GPUstatusRet|0x80000000; + //return 0x74000000; +} + + +// processes data send to GPU status register +// these are always single packet commands. +void CALLBACK GPUwriteStatus(uint32_t gdata) +{ + switch((gdata>>24)&0xff) + { + case 0x00: + memset(GPUInfoVals,0x00,16*sizeof(uint32_t)); + GPUstatusRet=0x14802000; + psxDisp.disabled = 1; + psxDraw.offsetX = psxDraw.offsetY = psxDraw.clipX1 = psxDraw.clipX2 = psxDraw.clipY1 = psxDraw.clipY2 = 0; + texinfo.mirror=0; + texinfo.x = texinfo.y = 0; + texinfo.colormode = texinfo.abr = 0; + psxDisp.colordepth24 = FALSE; + psxDisp.interlaced = FALSE; + psxDisp.changed = 1; + return; + case 0x03: + psxDisp.disabled = (gdata & 1); + if(psxDisp.disabled) + GPUstatusRet|=GPUSTATUS_DISPLAYDISABLED; + else GPUstatusRet&=~GPUSTATUS_DISPLAYDISABLED; + return; + case 0x04: + //gllog(77," GPU_S: TR_MODE: %x\n",gdata&0xffffff); + if((gdata&0xffffff)==0) imageTransfer=0; + if((gdata&0xffffff)==2) imageTransfer=3; + GPUstatusRet&=~GPUSTATUS_DMABITS; // Clear the current settings of the DMA bits + GPUstatusRet|=(gdata << 29); // Set the DMA bits according to the received data + return; + + case 0x05: + + oldpsxDisp.startY = psxDisp.startY; + oldpsxDisp.startX = psxDisp.startX; + + psxDisp.startY = (gdata>>10)&0x3ff; + psxDisp.startX = gdata & 0x3ff; + //gllog(77," GPU_S: DISPLAY SET: X=%d Y=%d\n",dispPosX,dispPosY); + + if (oldpsxDisp.startY != psxDisp.startY || oldpsxDisp.startX != psxDisp.startX) + psxDisp.changed = 1; + + updateScreenMode(); + + //if (dispLace==0) updateDisplay(); + return; + case 0x06: + psxDisp.rangeX1 = ( short ) ( gdata & 0x7ff ); + psxDisp.rangeX2 = ( short ) ( ( gdata>>12 ) & 0xfff ); + return; + case 0x07: + psxDisp.rangeY1 = ( short ) ( gdata & 0x3ff ); + psxDisp.rangeY2 = ( short ) ( ( gdata>>10 ) & 0x3ff ); + return; + case 0x08: + psxDisp.modeX = dispWidths[ (gdata&0x3)|((gdata&0x40)>>4) ]; + + if (gdata&0x04) psxDisp.modeY = 480; + else psxDisp.modeY = 240; + + psxDisp.colordepth24 = (gdata>>4)&0x1; // if 1 - TrueColor + if (psxDisp.colordepth24) + GPUstatusRet|=GPUSTATUS_RGB24; + else GPUstatusRet&=~GPUSTATUS_RGB24; + + psxDisp.pal = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC + if (psxDisp.pal) + GPUstatusRet|=GPUSTATUS_PAL; + else GPUstatusRet&=~GPUSTATUS_PAL; + + psxDisp.interlaced = (gdata>>5)&0x01; // if 1 - Interlace + //gllog(77,"!GPU! DISPLAY SET: W=%d Wo=%d H=%d TRUE=%d LACE=%d\n",dispHorNew,dispWidths[gdata&0x3],dispVerNew,dispColorNew,dispLaceNew); + if(psxDisp.modeY==480 && psxDisp.interlaced==1) drawLace = 1; + else drawLace = 0; + + psxDisp.changed = 1; + + return; + case 0x10: // ask about GPU version + gdata&=0xff; + + switch(gdata) + { + case 0x02: + GPUdataRet=GPUInfoVals[INFO_TW]; // tw infos + return; + case 0x03: + GPUdataRet=GPUInfoVals[INFO_DRAWSTART]; // draw start + return; + case 0x04: + GPUdataRet=GPUInfoVals[INFO_DRAWEND]; // draw end + return; + case 0x05: + case 0x06: + GPUdataRet=GPUInfoVals[INFO_DRAWOFF]; // draw offset + return; + case 0x07: + if(0) + GPUdataRet=0x01; + else GPUdataRet=0x02; // gpu type + return; + case 0x08: + case 0x0F: // some bios addr? + GPUdataRet=0xBFC03720; + return; + default: + gllog(77,"STATUS=%08x\n",gdata); + return; + } + return; + } + return; +} + +unsigned long CALLBACK GPUreadData(void) +{ + if(imageTransfer==2) + { + // **** + //imageTransfer = 0; + + // image transfer from VRAM + if ((imTY>=0) && (imTY<512) && (imTX>=0) && (imTX<1024)) + { + GPUdataRet=psxVul[imTY*512+imTX/2]; + //gllog(11,"RD: %08x",GPUdataRet); + } + imTX+=2; + imTXc-=2; + if(imTXc<=0) + { + imTX=imageX0; + imTXc=imageX1; + imTYc--; + imTY++; + } + imSize--; + if(imSize <= 0) + { + GPUstatusRet&=0xf7ffffff; + imageTransfer=0; + } + } + return GPUdataRet; +} + +void psx24torgba(char* s, int len) +{ + int i; + char *out = s; + char r1,g1,b1,r2,g2,b2; + + for (i=0; i<len; i+=2) + { + g1 = *s++; + r1 = *s++; + r2 = *s++; + b1 = *s++; + b2 = *s++; + g2 = *s++; + + *out++ = r1; + *out++ = g1; + *out++ = b1; + *out++ = r2; + *out++ = g2; + *out++ = b2; + } +} + +int PullFromPsxRam(uint32_t *pMem, int size) +{ + int count = 0; + unsigned short *input = (unsigned short*)pMem; + uint32_t *t = vramWrite.extratarget; + uint16_t *st = (uint16_t*)t; + + short x2 = vramWrite.x + vramWrite.w; + short y2 = vramWrite.y + vramWrite.h; + + unsigned short posx, posy; + + if (vramWrite.enabled == 0) { + imageTransfer = 0; + return 0; + } + + size <<=1; //multiply by 2 for int to short; + + while(vramWrite.cury < y2) + { + posy = (unsigned short) vramWrite.cury; + if (posy >= 512) + posy = 0; + while(vramWrite.curx < x2) + { + posx = (unsigned short) vramWrite.curx; + if (posx >= 1024) + posx = 0; + + if (!psxDisp.colordepth24) + *t++ = torgba[*input]; + else + *st++ = *input; + + psxVuw[(posy<<10)+posx] = *input; + + vramWrite.curx++; + count++; + input++; + + if (count == size) + { + if (vramWrite.curx == x2) + { + vramWrite.cury++; + vramWrite.curx=vramWrite.x; + } + goto NOMOREIMAGEDATA; + } + } + vramWrite.cury++; + vramWrite.curx=vramWrite.x; + } + +NOMOREIMAGEDATA: + if (vramWrite.cury >= y2) + { + float x,w; + + vramWrite.enabled = 0; + + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + glLoadIdentity(); + glScalef(1.0f/1024.0f,1.0f/512.0f,1.0f); + + if (psxDisp.colordepth24) + { + x=vramWrite.x*2/3; + w=vramWrite.w*2/3; + //psx24torgba((char*)vramWrite.extratarget, vramWrite.w*vramWrite.h*2/3); + glBindTexture(GL_TEXTURE_2D,xferTexture24); + glTexSubImage2D(GL_TEXTURE_2D,0,0,0,w,vramWrite.h,GL_RGB,GL_UNSIGNED_BYTE,vramWrite.extratarget); + } + else + { + x=vramWrite.x; + w=vramWrite.w; + glBindTexture(GL_TEXTURE_2D,xferTexture16); + glTexSubImage2D(GL_TEXTURE_2D,0,0,0,w,vramWrite.h,GL_RGBA,GL_UNSIGNED_BYTE,vramWrite.extratarget); + } + + glDisable(GL_BLEND); + glDisable(GL_CLIP_PLANE0); + glDisable(GL_CLIP_PLANE1); + glDisable(GL_CLIP_PLANE2); + glDisable(GL_CLIP_PLANE3); + + glColor3ub(255,255,255); + + glBegin(GL_POLYGON); + glTexCoord2s(0, 0); + glVertex2s(x,vramWrite.y); + + glTexCoord2s(w, 0); + glVertex2s(x+w,vramWrite.y); + + glTexCoord2s(w, vramWrite.h); + glVertex2s(x+w,vramWrite.y+vramWrite.h); + + glTexCoord2s(0, vramWrite.h); + glVertex2s(x,vramWrite.y+vramWrite.h); + glEnd(); + glEnable(GL_BLEND); + + glPopMatrix(); + + glEnable(GL_CLIP_PLANE0); + glEnable(GL_CLIP_PLANE1); + glEnable(GL_CLIP_PLANE2); + glEnable(GL_CLIP_PLANE3); + + + free(vramWrite.extratarget); + imageTransfer = 0; + if (count%2 == 1) + count++; + } + + return count>>1; //back from short to int +} + +void CALLBACK GPUwriteDataMem(uint32_t * pMem, int iSize) +{ + unsigned char command; + int i = 0; + uint32_t gdata; + + GPUIsBusy; + GPUIsNotReadyForCommands; + + for(;i<iSize;) + { + if((imageTransfer & 1) == 1) + { + i += PullFromPsxRam(pMem, iSize-i); + if (i >= iSize) + continue; + pMem += i; + } + + gdata=*pMem; + GPUdataRet=gdata; + pMem++; + i++; + + if(gpuDataC == 0) + { + command = (unsigned char) (gdata>>24) & 0xff; + if (primTableC[command]) + { + gpuDataC = primTableC[command]; + gpuCommand = command; + gpuData[0] = gdata; + gpuDataP = 1; + } + else + continue; + } + else + { + gpuData[gpuDataP] = gdata; + if ( gpuDataC>128 ) + { + if ( ( gpuDataC==254 && gpuDataP>=3 ) || + ( gpuDataC==255 && gpuDataP>=4 && ! ( gpuDataP&1 ) ) ) + { + if ( ( gpuData[gpuDataP] & 0xF000F000 ) == 0x50005000 ) + gpuDataP=gpuDataC-1; + } + } + gpuDataP++; + } + if(gpuDataP == gpuDataC) + { + gpuDataC=gpuDataP=0; + primTableJ[gpuCommand]((unsigned char *)gpuData); + } + } + + GPUdataRet=gdata; + + GPUIsReadyForCommands; + GPUIsIdle; +} + +void CALLBACK GPUwriteData(uint32_t gdata) +{ + GPUwriteDataMem(&gdata,1); +} + + +// this function will be removed soon +void CALLBACK GPUsetMode(uint32_t gdata) +{ + imageTransfer = gdata; + return; +} + +// this function will be removed soon +long CALLBACK GPUgetMode(void) +{ + return imageTransfer; +} + + +long CALLBACK GPUconfigure(void) +{ + ExecCfg ("CFG"); + return 0; +} + +uint32_t lUsedAddr[3]; + +__inline bool CheckForEndlessLoop(uint32_t laddr) +{ + if(laddr==lUsedAddr[1]) return TRUE; + if(laddr==lUsedAddr[2]) return TRUE; + + if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr; + else lUsedAddr[2]=laddr; + lUsedAddr[0]=laddr; + return FALSE; +} + +long CALLBACK GPUdmaChain(uint32_t * baseAddrL, uint32_t addr) +{ + uint32_t dmaMem; + unsigned char * baseAddrB; + short count;unsigned int DMACommandCounter = 0; + + lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff; + + baseAddrB = (unsigned char*) baseAddrL; + + do + { + addr&=0x1FFFFC; + if(DMACommandCounter++ > 2000000) break; + if(CheckForEndlessLoop(addr)) break; + + count = baseAddrB[addr+3]; + + dmaMem=addr+4; + + if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); + + addr = baseAddrL[addr>>2] & 0xffffff; + } + while (addr != 0xffffff); + + return 0; +} + +void CALLBACK GPUkeypressed(int keycode) +{ + switch ( keycode ) + { + case 0xFFC9: //X11 key: F12 + case ( ( 1<<29 ) | 0xFF0D ) : //special keycode from pcsx-df: alt-enter + //bChangeWinMode=TRUE; + break; + case 0xffc2: //F5 + //GPUmakeSnapshot(); + break; + case 0x60: //backtick ` + gpuConfig.FrameLimit = !gpuConfig.FrameLimit; + break; + } +} + + +void CALLBACK GPUabout(void) +{ + ExecCfg ("ABOUT"); +} + +long CALLBACK GPUtest(void) +{ + // if test fails this function should return negative value for error (unable to continue) + // and positive value for warning (can continue but output might be crappy) + return 0; +} + + +struct TGA_HEADER +{ + u8 identsize; // size of ID field that follows 18 u8 header (0 usually) + u8 colourmaptype; // type of colour map 0=none, 1=has palette + u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed + + s16 colourmapstart; // first colour map entry in palette + s16 colourmaplength; // number of colours in palette + u8 colourmapbits; // number of bits per palette entry 15,16,24,32 + + s16 xstart; // image x origin + s16 ystart; // image y origin + s16 width; // image width in pixels + s16 height; // image height in pixels + u8 bits; // image bits per pixel 8,16,24,32 + u8 descriptor; // image descriptor bits (vh flip bits) + + // pixel data follows header + +} __attribute__((packed)); + + +bool SaveTGA(const char* filename, int width, int height, void* pdata) +{ + struct TGA_HEADER hdr; + FILE* f = fopen(filename, "wb"); + if( f == NULL ) + return 0; + + assert( sizeof(struct TGA_HEADER) == 18 && sizeof(hdr) == 18 ); + + memset(&hdr, 0, sizeof(hdr)); + hdr.imagetype = 2; + hdr.bits = 32; + hdr.width = width; + hdr.height = height; + hdr.descriptor |= 8|(1<<5); // 8bit alpha, flip vertical + + fwrite(&hdr, sizeof(hdr), 1, f); + fwrite(pdata, width*height*4, 1, f); + fclose(f); + return 1; +} diff --git a/plugins/dfOpenGL/GPU.h b/plugins/dfOpenGL/GPU.h new file mode 100644 index 00000000..ba3a05fa --- /dev/null +++ b/plugins/dfOpenGL/GPU.h @@ -0,0 +1 @@ +bool SaveTGA(const char* filename, int width, int height, void* pdata);
\ No newline at end of file diff --git a/plugins/dfOpenGL/Makefile.am b/plugins/dfOpenGL/Makefile.am new file mode 100644 index 00000000..7bf6b441 --- /dev/null +++ b/plugins/dfOpenGL/Makefile.am @@ -0,0 +1,22 @@ +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) $(GLADE2_CFLAGS) -I/usr/X11R6/include \ + -g -O0 -Wall -fPIC + +bindir = @libdir@/games/psemu/ +libdir = @libdir@/games/psemu/ + +lib_LTLIBRARIES = libdfOpenGL.la + +libdfOpenGL_la_SOURCES = GPU.c primitive_drawing.c fps.c gllog.c cfg.c +libdfOpenGL_la_LDFLAGS = -module -avoid-version -L/usr/lib \ + -L/usr/X11R6/lib64 -L/usr/X11R6/lib -lX11 -lXxf86vm -lGL -lm + +bin_PROGRAMS = cfgDFOpenGL +cfgDFOpenGL_SOURCES = gpucfg-0.1df/main.c +cfgDFOpenGL_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) + +glade_DATA = gpucfg-0.1df/dfopengl.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) diff --git a/plugins/dfOpenGL/Makefile.in b/plugins/dfOpenGL/Makefile.in new file mode 100644 index 00000000..a3c04976 --- /dev/null +++ b/plugins/dfOpenGL/Makefile.in @@ -0,0 +1,602 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = cfgDFOpenGL$(EXEEXT) +subdir = plugins/dfOpenGL +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in AUTHORS TODO +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(gladedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libdfOpenGL_la_LIBADD = +am_libdfOpenGL_la_OBJECTS = GPU.lo primitive_drawing.lo fps.lo \ + gllog.lo cfg.lo +libdfOpenGL_la_OBJECTS = $(am_libdfOpenGL_la_OBJECTS) +libdfOpenGL_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libdfOpenGL_la_LDFLAGS) $(LDFLAGS) -o $@ +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_cfgDFOpenGL_OBJECTS = main.$(OBJEXT) +cfgDFOpenGL_OBJECTS = $(am_cfgDFOpenGL_OBJECTS) +am__DEPENDENCIES_1 = +cfgDFOpenGL_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libdfOpenGL_la_SOURCES) $(cfgDFOpenGL_SOURCES) +DIST_SOURCES = $(libdfOpenGL_la_SOURCES) $(cfgDFOpenGL_SOURCES) +gladeDATA_INSTALL = $(INSTALL_DATA) +DATA = $(glade_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFOPENGL = @DFOPENGL@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADE2_CFLAGS = @GLADE2_CFLAGS@ +GLADE2_LIBS = @GLADE2_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTK2_CFLAGS = @GTK2_CFLAGS@ +GTK2_LIBS = @GTK2_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NASM = @NASM@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @libdir@/games/psemu/ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@/games/psemu/ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) $(GLADE2_CFLAGS) -I/usr/X11R6/include \ + -g -O0 -Wall -fPIC + +lib_LTLIBRARIES = libdfOpenGL.la +libdfOpenGL_la_SOURCES = GPU.c primitive_drawing.c fps.c gllog.c cfg.c +libdfOpenGL_la_LDFLAGS = -module -avoid-version -L/usr/lib \ + -L/usr/X11R6/lib64 -L/usr/X11R6/lib -lX11 -lXxf86vm -lGL -lm + +cfgDFOpenGL_SOURCES = gpucfg-0.1df/main.c +cfgDFOpenGL_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) +glade_DATA = gpucfg-0.1df/dfopengl.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/dfOpenGL/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/dfOpenGL/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libdfOpenGL.la: $(libdfOpenGL_la_OBJECTS) $(libdfOpenGL_la_DEPENDENCIES) + $(libdfOpenGL_la_LINK) -rpath $(libdir) $(libdfOpenGL_la_OBJECTS) $(libdfOpenGL_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +cfgDFOpenGL$(EXEEXT): $(cfgDFOpenGL_OBJECTS) $(cfgDFOpenGL_DEPENDENCIES) + @rm -f cfgDFOpenGL$(EXEEXT) + $(LINK) $(cfgDFOpenGL_OBJECTS) $(cfgDFOpenGL_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GPU.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fps.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gllog.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/primitive_drawing.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +main.o: gpucfg-0.1df/main.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.o -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.o `test -f 'gpucfg-0.1df/main.c' || echo '$(srcdir)/'`gpucfg-0.1df/main.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gpucfg-0.1df/main.c' object='main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.o `test -f 'gpucfg-0.1df/main.c' || echo '$(srcdir)/'`gpucfg-0.1df/main.c + +main.obj: gpucfg-0.1df/main.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.obj -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.obj `if test -f 'gpucfg-0.1df/main.c'; then $(CYGPATH_W) 'gpucfg-0.1df/main.c'; else $(CYGPATH_W) '$(srcdir)/gpucfg-0.1df/main.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gpucfg-0.1df/main.c' object='main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.obj `if test -f 'gpucfg-0.1df/main.c'; then $(CYGPATH_W) 'gpucfg-0.1df/main.c'; else $(CYGPATH_W) '$(srcdir)/gpucfg-0.1df/main.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-gladeDATA: $(glade_DATA) + @$(NORMAL_INSTALL) + test -z "$(gladedir)" || $(MKDIR_P) "$(DESTDIR)$(gladedir)" + @list='$(glade_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(gladeDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(gladedir)/$$f'"; \ + $(gladeDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(gladedir)/$$f"; \ + done + +uninstall-gladeDATA: + @$(NORMAL_UNINSTALL) + @list='$(glade_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(gladedir)/$$f'"; \ + rm -f "$(DESTDIR)$(gladedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(gladedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-gladeDATA + +install-dvi: install-dvi-am + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-gladeDATA \ + uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-gladeDATA install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-gladeDATA uninstall-libLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/dfOpenGL/PSEmu_PlugIn_Defs.h b/plugins/dfOpenGL/PSEmu_PlugIn_Defs.h new file mode 100644 index 00000000..18b269cf --- /dev/null +++ b/plugins/dfOpenGL/PSEmu_PlugIn_Defs.h @@ -0,0 +1,121 @@ +/* + PSEmu Plugin Developer Kit Header definition + + (C)1998 Vision Thing + + This file can be used only to develop PSEmu Plugins + Other usage is highly prohibited. +*/ + + +// IMPORTANT!!! +// This file will be used by PSEmu version >= 1.0.3 +// so, please, develop Plugins w/o using this header file now +// if you want to add return codes (any) just drop mail to +// duddie@psemu.com + +#ifndef _PSEMU_PLUGIN_DEFS_H +#define _PSEMU_PLUGIN_DEFS_H + + +// header version +#define _PPDK_HEADER_VERSION 1 + +#define PLUGIN_VERSION 1 + +// plugin type returned by PSEgetLibType (types can be merged if plugin is multi type!) +#define PSE_LT_CDR 1 +#define PSE_LT_GPU 2 +#define PSE_LT_SPU 4 +#define PSE_LT_PAD 8 + + +// every function in DLL if completed sucessfully should return this value +#define PSE_ERR_SUCCESS 0 +// undefined error but fatal one, that kills all functionality +#define PSE_ERR_FATAL -1 + + +// XXX_Init return values +// Those return values apply to all libraries + +// initialization went OK +#define PSE_INIT_ERR_SUCCESS 0 + +// this driver is not configured +#define PSE_INIT_ERR_NOTCONFIGURED -2 + +// this driver can not operate properly on this hardware or hardware is not detected +#define PSE_INIT_ERR_NOHARDWARE -3 + + +/* GPU PlugIn */ + + +// GPU_Test return values + +// sucess, everything configured, and went OK. +#define PSE_GPU_ERR_SUCCESS 0 + +// this driver is not configured +#define PSE_GPU_ERR_NOTCONFIGURED 1 + + + +// GPU_Query - will be implemented in v2 +/* +typedef struct +{ + unsigned long flags; + unsigned long status; + HWND window; + unsigned char reserved[100]; +} gpuQueryS; +*/ +// gpuQueryS.flags +// this driver requests windowed mode, +#define PSE_GPU_FLAGS_WINDOWED 1 + +// gpuQueryS.status +// this driver cannot operate in this windowed mode +#define PSE_GPU_STATUS_WINDOWWRONG 1 + +// GPU_Query End - will be implemented in v2 + + +/* CDR PlugIn */ + +// CDR_Test return values + +// sucess, everything configured, and went OK. +#define PSE_CDR_ERR_SUCCESS 0 + +// ERRORS +#define PSE_CDR_ERR -40 +// this driver is not configured +#define PSE_CDR_ERR_NOTCONFIGURED PSE_CDR_ERR - 0 +// if this driver is unable to read data from medium +#define PSE_CDR_ERR_NOREAD PSE_CDR_ERR - 1 + +// WARNINGS +#define PSE_CDR_WARN 40 +// if this driver emulates lame mode ie. can read only 2048 tracks and sector header is emulated +// this might happen to CDROMS that do not support RAW mode reading - surelly it will kill many games +#define PSE_CDR_WARN_LAMECD PSE_CDR_WARN + 0 + + + + +/* SPU PlugIn */ + +// retricted info (now!) + + + + +/* PAD PlugIn */ + +// not yet finished + + +#endif // _PSEMU_PLUGIN_DEFS_H diff --git a/plugins/dfOpenGL/TODO b/plugins/dfOpenGL/TODO new file mode 100644 index 00000000..918620ab --- /dev/null +++ b/plugins/dfOpenGL/TODO @@ -0,0 +1,31 @@ +emulation: +-opaque texture pixels + -something better than my 0xfe alpha hack + -finish implementing, not just sprite +-masked drawing (silent hill) +-subtractive blending? +-VRAM read +-texture mirroring +-use software polygon clip test, not opengl clipping +-Texture window: repeating instead of scaling - difficult! +-lines, dots as 1 unit width rectangle +-check for clut changes + +optimization/features: +-change 11bit gpu integers to union bitfields - probably won't help much, but hey, it'll be elegant :) +-fix psx texture pixel co-ords so we can turn on bilinear filtering and antialiasing. +-rewrite texturing + -check vram uploads for updates to subtexture +-rewrite (and fix) blending +-render to texture for psx front/back buffer +-implement black & STP pixels as stencil + -needed for masked drawing anyway... + -(would this also fix FF7 outlines when bilinear filtered textures are enabled?) +-upscale textures +-pixel shaders + +Pcsx: +-save states +-fullscreen toggle +-gui config +-fps display
\ No newline at end of file diff --git a/plugins/dfOpenGL/cfg.c b/plugins/dfOpenGL/cfg.c new file mode 100644 index 00000000..c048da68 --- /dev/null +++ b/plugins/dfOpenGL/cfg.c @@ -0,0 +1,106 @@ +#include "cfg.h" +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/stat.h> + + +extern GpuConfS gpuConfig; +char * pConfigFile=NULL; + +#define GetValue(name, var) \ + p = strstr(pB, name); \ + if (p != NULL) { \ + p+=strlen(name); \ + while ((*p == ' ') || (*p == '=')) p++; \ + if (*p != '\n') var = atoi(p); \ + } + +void readconfig() +{ + struct stat buf; + FILE *in;char t[256];int len, size; + char * pB, * p; + + if(pConfigFile) + strcpy(t,pConfigFile); + else + { + strcpy(t,"dfopengl.cfg"); + in = fopen(t,"rb"); + if (!in) + { + strcpy(t,"cfg/dfopengl.cfg"); + in = fopen(t,"rb"); + if(!in) sprintf(t,"%s/.pcsx/plugins/dfopengl.cfg",getenv("HOME")); + else fclose(in); + } + else fclose(in); + } + + if (stat(t, &buf) == -1) return; + size = buf.st_size; + + in = fopen(t,"rb"); + if (!in) return; + + pB=(char *)malloc(size); + memset(pB,0,size); + + len = fread(pB, 1, size, in); + fclose(in); + + gpuConfig.bFullscreen=FALSE; + gpuConfig.bBilinear=FALSE; + gpuConfig.nMaxTextures=64; + gpuConfig.bWireFrame=FALSE; + gpuConfig.bAntialias=FALSE; + gpuConfig.bClearScreen=FALSE; + gpuConfig.FrameLimit=TRUE; + gpuConfig.windowX=1024; + gpuConfig.windowY=768; + + GetValue("Fullscreen", gpuConfig.bFullscreen); + GetValue("Bilinear", gpuConfig.bBilinear); + GetValue("MaxTextures", gpuConfig.nMaxTextures); + GetValue("Wireframe", gpuConfig.bWireFrame); + GetValue("Antialias", gpuConfig.bAntialias); + GetValue("Clearscreen", gpuConfig.bClearScreen); + GetValue("FrameLimit", gpuConfig.FrameLimit); + GetValue("windowX", gpuConfig.windowX); + GetValue("windowY", gpuConfig.windowY); + + + free(pB); + +} + +void writeconfig() +{ +} + +void ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgDFOpenGL"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + system(cfg); return; + } + + strcpy(cfg, "./cfg/cfgDFOpenGL"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + system(cfg); return; + } + + sprintf(cfg, "%s/.pcsx/plugins/cfg/cfgDFOpenGL", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + system(cfg); return; + } + + printf("ERROR: cfgDFOpenGL file not found!\n"); +} diff --git a/plugins/dfOpenGL/cfg.h b/plugins/dfOpenGL/cfg.h new file mode 100644 index 00000000..9f3c0830 --- /dev/null +++ b/plugins/dfOpenGL/cfg.h @@ -0,0 +1,10 @@ +#ifndef _GPU_CFG_H_ +#define _GPU_CFG_H_ + +#include "gpu_i.h" + +void readconfig(void); +void writeconfig(void); + + +#endif // _GPU_CFG_H_ diff --git a/plugins/dfOpenGL/fps.c b/plugins/dfOpenGL/fps.c new file mode 100644 index 00000000..21f95c7f --- /dev/null +++ b/plugins/dfOpenGL/fps.c @@ -0,0 +1,41 @@ +#include <sys/time.h> +#include <unistd.h> +#include "gpu_i.h" + +static const double NTSC = 100000000/5994; +static const double PAL = 100000000/5000; + +static double lastvsync = 0; +#define FRAMESAMPLES 10 + +double GetTime() //in microseconds +{ + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return (double)tv.tv_sec * 1000000 + tv.tv_usec; // to do that, but at least it works +} + +void waitforrealtime() +{ + double currenttime,tickstogo; + double target; + + currenttime = GetTime(); + + if (currenttime < lastvsync + 1000000) + target = lastvsync + (psxDisp.pal ? PAL : NTSC); + else + target = currenttime; + + lastvsync = target; + + while (currenttime < target) + { + tickstogo = target - currenttime; + if (tickstogo >= 500.0f) + { + usleep((useconds_t)tickstogo-200); //usleep in microseconds + } + currenttime = GetTime(); + } +} diff --git a/plugins/dfOpenGL/gllog.c b/plugins/dfOpenGL/gllog.c new file mode 100644 index 00000000..447b05a5 --- /dev/null +++ b/plugins/dfOpenGL/gllog.c @@ -0,0 +1,43 @@ +// comment next line and all gllog(xx,....) will go to gpulog.txt (enable logging) +#define _COMMENTLOG + +void gllog(int level, char *fmt,...) +{ +#ifndef _COMMENTLOG + static FILE *out=NULL; + static char tmpbuf[200], tmpbufold[200]; + + static int repeatcount=0; + + if(out==NULL) + { + // open output file ! + if((out=fopen("gpulog.txt","wb"))==NULL)exit(1); + } + // file already opened + + va_list marker; + va_start(marker,fmt); + vsprintf(tmpbuf, fmt, marker ); + va_end(marker); + + // we dont log the same line multiple times + if(strcmp(tmpbufold,tmpbuf)==0) + { + repeatcount++; + return; + } + else + { + // copy the new line to the old buffer + strcpy(tmpbufold,tmpbuf); + if(repeatcount>0) + { + fprintf(out,"Last message repeated %d times\n",repeatcount); + repeatcount=0; + } + fprintf(out,"Level: %d msg: %s\n",level,tmpbuf); + fflush(out); + } +#endif +} diff --git a/plugins/dfOpenGL/gpu_i.h b/plugins/dfOpenGL/gpu_i.h new file mode 100644 index 00000000..a45c0e94 --- /dev/null +++ b/plugins/dfOpenGL/gpu_i.h @@ -0,0 +1,208 @@ +#ifndef _GPU_INTERNALS_H +#define _GPU_INTERNALS_H + +#define GL_GLEXT_PROTOTYPES +#include <GL/glx.h> +#include <GL/gl.h> +#include <GL/glext.h> +#include <stdint.h> + +#ifdef GPU_INTERNALS_DEF +#define GPUVAR_DEF +#else +#define GPUVAR_DEF extern +#endif + +typedef int bool; +#define FALSE 0 +#define TRUE 1 + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +void gllog(int level, char *fmt,...); + +extern unsigned short lutBGR2RGB[65536]; + +extern unsigned short textBuf[]; + +extern int32_t GPUstatusRet; +extern int32_t GPUInfoVals[16]; + +#define INFO_TW 0 +#define INFO_DRAWSTART 1 +#define INFO_DRAWEND 2 +#define INFO_DRAWOFF 3 + +#define GPUSTATUS_ODDLINES 0x80000000 +#define GPUSTATUS_DMABITS 0x60000000 // Two bits +#define GPUSTATUS_READYFORCOMMANDS 0x10000000 +#define GPUSTATUS_READYFORVRAM 0x08000000 +#define GPUSTATUS_IDLE 0x04000000 +#define GPUSTATUS_DISPLAYDISABLED 0x00800000 +#define GPUSTATUS_INTERLACED 0x00400000 +#define GPUSTATUS_RGB24 0x00200000 +#define GPUSTATUS_PAL 0x00100000 +#define GPUSTATUS_DOUBLEHEIGHT 0x00080000 +#define GPUSTATUS_WIDTHBITS 0x00070000 // Three bits +#define GPUSTATUS_MASKENABLED 0x00001000 +#define GPUSTATUS_MASKDRAWN 0x00000800 +#define GPUSTATUS_DRAWINGALLOWED 0x00000400 +#define GPUSTATUS_DITHER 0x00000200 + +#define GPUIsBusy (GPUstatusRet &= ~GPUSTATUS_IDLE) +#define GPUIsIdle (GPUstatusRet |= GPUSTATUS_IDLE) + +#define GPUIsNotReadyForCommands (GPUstatusRet &= ~GPUSTATUS_READYFORCOMMANDS) +#define GPUIsReadyForCommands (GPUstatusRet |= GPUSTATUS_READYFORCOMMANDS) + +extern unsigned char psxVub[]; +extern signed char *psxVsb; +extern unsigned short *psxVuw; +extern signed short *psxVsw; +extern uint32_t *psxVul; +extern int32_t *psxVsl; + + +typedef struct { + uint32_t x, y; + uint32_t colormode; + uint32_t abr; //alpha blending + uint32_t mirror; +} TextureState_t; + +extern TextureState_t texinfo; + +typedef struct VRAMLOADTTAG +{ + short x; + short y; + short w; + short h; + short curx; + short cury; + uint32_t* extratarget; + bool enabled; +} VRAMLoad_t; + +extern VRAMLoad_t vramWrite; + +struct PSXDisplay_t { + short modeX; + short modeY; + short startX; + short startY; + bool disabled; + bool colordepth24; + bool interlaced; + bool pal; + + //Has to do with television hsync & vsync? + //1 Y line = 1 vtrace? (typical 16 to 256 (32 to 512)) + //X (typical 608 to 3168) + short rangeX1; + short rangeY1; + short rangeX2; + short rangeY2; + + bool changed; +}; +extern struct PSXDisplay_t psxDisp, oldpsxDisp; + +struct PSXDraw_t { + short offsetX; + short offsetY; + short clipX1; + short clipX2; + short clipY1; + short clipY2; + short texwinX1; + short texwinY1; + short texwinX2; + short texwinY2; + bool texwinenabled; + bool enabled; + bool setmask; + bool testmask; +}; +extern struct PSXDraw_t psxDraw; + +extern short dispWidths[8]; + +extern int32_t dispLace; +extern int32_t dispLaceNew; +extern int32_t imageTransfer; +extern int32_t drawLace; +extern int32_t drawingLines; + +extern short imTYc,imTXc,imTY,imTX; +extern int32_t imSize; +extern short imageX0,imageX1; +extern short imageY0,imageY1; + + +extern int32_t newTextX0,newTextX1,newTextX2,newTextX3; +extern int32_t newTextY0,newTextY1,newTextY2,newTextY3; +extern unsigned short textBuf[]; + +union uPointers{ + void *v; + unsigned char *b; + unsigned short *w; + uint32_t *d; + char *c; + short *s; + int32_t *l; +}; +extern unsigned char psxVub[]; +extern signed char *psxVsb; +extern unsigned short *psxVuw; +extern signed short *psxVsw; +extern uint32_t *psxVul; +extern int32_t *psxVsl; + +typedef struct +{ + bool bFullscreen; + bool bBilinear; + int nMaxTextures; + bool bWireFrame; + bool bAntialias; + bool bClearScreen; + bool FrameLimit; + short windowX; + short windowY; +} GpuConfS; +extern GpuConfS gpuConfig; + +extern short windowX, windowY; + +extern unsigned char texshade[256]; +extern uint32_t image[65536]; +extern uint32_t torgba[65536]; + + +struct texturecache{ + int32_t textAddrX; + int32_t textAddrY; + int32_t textTP; + int32_t clutP; + GLuint id; + bool Update; +}; +//#define maxtextures 32 +extern struct texturecache texture[64]; +extern GLuint xferTexture16; +extern GLuint xferTexture24; +extern GLuint nullid; +#define nullclutP (1024*512+1) + + +#endif // _GPU_INTERNALS_H diff --git a/plugins/dfOpenGL/gpucfg-0.1df/dfopengl.glade2 b/plugins/dfOpenGL/gpucfg-0.1df/dfopengl.glade2 new file mode 100644 index 00000000..a7d24cdc --- /dev/null +++ b/plugins/dfOpenGL/gpucfg-0.1df/dfopengl.glade2 @@ -0,0 +1,272 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--Generated with glade3 3.1.5 on Sun Mar 16 17:26:02 2008 by hoshy@mobilbox--> +<glade-interface> + <widget class="GtkWindow" id="CfgWnd"> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="spacing">6</property> + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>OpenGL Configuration Options</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <widget class="GtkCheckButton" id="chk_fullscreen"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Display Fullscreen</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chk_bilinear"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Bilinear</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Maximum Textures</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="te_maxtextures"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chk_wireframe"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Wireframe</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chk_antialias"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Antialias</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">4</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chk_clearscreen"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Clearscreen</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">5</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chk_framelimit"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Framelimit</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">6</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">WindowX</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="te_windowX"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">7</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox4"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <widget class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">WindowY</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="te_windowY"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">8</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkHButtonBox" id="hbuttonbox1"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <widget class="GtkButton" id="btn_close"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">gtk-close</property> + <property name="use_stock">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">6</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">6</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/plugins/dfOpenGL/gpucfg-0.1df/main.c b/plugins/dfOpenGL/gpucfg-0.1df/main.c new file mode 100644 index 00000000..ba9c2220 --- /dev/null +++ b/plugins/dfOpenGL/gpucfg-0.1df/main.c @@ -0,0 +1,261 @@ +#include <gtk/gtk.h> +#include <glade/glade.h> + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/stat.h> + +#define CONFIG_FILENAME "dfopengl.cfg" +#define READBINARY "rb" +#define WRITEBINARY "wb" + +void on_config_clicked (GtkWidget *widget, gpointer user_data) +{ + gtk_widget_destroy (widget); + exit (0); +} + +void on_about_clicked (GtkWidget *widget, gpointer user_data) +{ + gtk_widget_destroy (widget); + exit (0); +} + +void SetCfgVal(char * pB,char * pE,int val) +{ + char * p, *ps, *pC;char t[32]; + + sprintf(t,"%d",val); + + p=strstr(pB,pE); + if(p) + { + p=strstr(p,"="); + if(!p) return; + p++; + while(*p && *p!='\n' && (*p<'0' || *p>'9')) p++; + if(*p==0 || *p=='\n') return; + ps=p; + while(*p>='0' && *p<='9') p++; + pC=(char *)malloc(32767); + strcpy(pC,p); + strcpy(ps,t); + strcat(pB,pC); + free(pC); + } + else + { + strcat(pB,pE); + strcat(pB," = "); + strcat(pB,t); + strcat(pB,"\n"); + } +} + +void save_config (GtkWidget *widget, gpointer user_data) +{ + GladeXML *xml; + char cfg[255]; + FILE *in; + int len, val; + char *pB; + + pB=(char *)malloc(32767); + memset(pB,0,32767); + + strcpy(cfg, CONFIG_FILENAME); + + /* ADB TODO Why do we read this in just to replace it again? */ + in = fopen(cfg,READBINARY); + if(in) + { + len = fread(pB, 1, 32767, in); + fclose(in); + } + + xml = (GladeXML*) user_data; + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "chk_fullscreen"))); + SetCfgVal(pB,"\nFullscreen",val); + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "chk_bilinear"))); + SetCfgVal(pB,"\nBilinear",val); + val = atoi (gtk_entry_get_text (GTK_ENTRY (glade_xml_get_widget (xml, "te_maxtextures")))); + SetCfgVal(pB,"\nMaxTextures",val); + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "chk_wireframe"))); + SetCfgVal(pB,"\nWireframe",val); + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "chk_antialias"))); + SetCfgVal(pB,"\nAntialias",val); + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "chk_clearscreen"))); + SetCfgVal(pB,"\nClearscreen",val); + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "chk_framelimit"))); + SetCfgVal(pB,"\nFrameLimit",val); + val = atoi (gtk_entry_get_text (GTK_ENTRY (glade_xml_get_widget (xml, "te_windowX")))); + SetCfgVal(pB,"\nwindowX",val); + val = atoi (gtk_entry_get_text (GTK_ENTRY (glade_xml_get_widget (xml, "te_windowY")))); + SetCfgVal(pB,"\nwindowY",val); + + /* Write to the config file */ + if((in=fopen(cfg, WRITEBINARY))!=NULL) { + fwrite(pB,strlen(pB),1,in); + fclose(in); + } + free(pB); + + gtk_widget_destroy (glade_xml_get_widget (xml, "CfgWnd")); + + /* Close the window and exit control from the plugin */ + exit (0); +} + +/* This function checks for the value being outside the accepted range, + and returns the appropriate boundary value */ +int set_limit (char *p, int len, int lower, int upper) +{ + int val = 0; + + if (p) + val = atoi(p + len); + /* printf("Checking for val %d greater than %d and lower than %d, ", val, lower, upper);*/ + if (val < lower) + val = lower; + if (val > upper) + val = upper; + /* printf ("val is now %d\n", val);*/ + return val; +} + +int +main (int argc, char *argv[]) +{ + GtkWidget *widget; + GladeXML *xml; + FILE *in; + char t[256]; + int len; + char * pB, * p; + char cfg[255]; + char tempstr[128]; + + if (argc!=2) { + printf("Usage: cfgOpenGL {ABOUT | CFG}\n"); + return 0; + } + if(strcmp(argv[1],"CFG")!=0 && strcmp(argv[1],"ABOUT")!=0) { + printf("Usage: cfgOpenGL {ABOUT | CFG}\n"); + return 0; + } + + gtk_set_locale (); + gtk_init (&argc, &argv); + + if (strcmp(argv[1], "ABOUT") == 0) { + widget = gtk_about_dialog_new (); + gtk_about_dialog_set_name (GTK_ABOUT_DIALOG (widget), "PCSX OpenGL Video Plugin"); + gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (widget), "1.0"); + + g_signal_connect_data(GTK_OBJECT(widget), "response", + GTK_SIGNAL_FUNC(on_about_clicked), NULL, NULL, G_CONNECT_AFTER); + + gtk_widget_show (widget); + gtk_main(); + + return 0; + } + + xml = glade_xml_new(DATADIR "dfopengl.glade2", "CfgWnd", NULL); + if (!xml) { + g_warning("We could not load the interface!"); + return -1; + } + + strcpy(cfg, CONFIG_FILENAME); + + in = fopen(cfg, READBINARY); + if(in) { + pB = (char *)malloc(32767); + memset(pB, 0, 32767); + len = fread(pB, 1, 32767, in); + fclose(in); + } else { + pB = 0; + printf("Couldn't find config file %s - creating new file\n", cfg); + } + + /* Set default values */ + int bFullscreen = FALSE; + int bBilinear = FALSE; + int nMaxTextures = 64; + int bWireFrame = FALSE; + int bAntialias = FALSE; + int bClearScreen = FALSE; + int bFrameLimit = TRUE; + short nwindowX = 1024; + short nwindowY = 768; + + if (pB) { + strcpy(t,"\nFullscreen");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + bFullscreen = set_limit (p, len, 0, 1); + + strcpy(t,"\nBilinear");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + bBilinear = set_limit (p, len, 0, 1); + + strcpy(t,"\nMaxTextures");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + nMaxTextures = set_limit (p, len, 0, 128); /* TODO - What should the limit be? */ +printf("Max Textures is %d\n", nMaxTextures); + + strcpy(t,"\nWireframe");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + bWireFrame = set_limit (p, len, 0, 1); + + strcpy(t,"\nAntialias");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + bAntialias = set_limit (p, len, 0, 1); + + strcpy(t,"\nClearscreen");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + bClearScreen = set_limit (p, len, 0, 1); + + strcpy(t,"\nFrameLimit");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + bFrameLimit = set_limit (p, len, 0, 1); + + strcpy(t,"\nwindowX");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + nwindowX = set_limit (p, len, 0, 1600); /* TODO - limit ? */ + + strcpy(t,"\nwindowY");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + nwindowY = set_limit (p, len, 0, 1200); /* TODO - limit ? */ + + free(pB); + } + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chk_fullscreen")), bFullscreen); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chk_bilinear")), bBilinear); + + snprintf (tempstr, 10, "%d", nMaxTextures); + gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget(xml, "te_maxtextures")), tempstr); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chk_wireframe")), bWireFrame); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chk_antialias")), bAntialias); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chk_clearscreen")), bClearScreen); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chk_framelimit")), bFrameLimit); + + snprintf (tempstr, 10, "%d", nwindowX); + gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget(xml, "te_windowX")), tempstr); + + snprintf (tempstr, 10, "%d", nwindowY); + gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget(xml, "te_windowY")), tempstr); + + widget = glade_xml_get_widget(xml, "CfgWnd"); + g_signal_connect_data(GTK_OBJECT(widget), "delete_event", + GTK_SIGNAL_FUNC(on_config_clicked), NULL, NULL, G_CONNECT_AFTER); + gtk_widget_show_all (widget); + + widget = glade_xml_get_widget(xml, "btn_close"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(save_config), xml, NULL, G_CONNECT_AFTER); + + gtk_main (); + return 0; +} diff --git a/plugins/dfOpenGL/oldMakefile b/plugins/dfOpenGL/oldMakefile new file mode 100644 index 00000000..6fb3557b --- /dev/null +++ b/plugins/dfOpenGL/oldMakefile @@ -0,0 +1,32 @@ +CC = gcc +LD = gcc + +PLUGIN = libdfOpenGL.so +OBJECTS = GPU.o primitive_drawing.o fps.o gllog.o +#CFLAGS += `gtk-config --cflags` +CFLAGS = -g -O0 -Wall -fPIC +#CFGLIBS += `gtk-config --libs` +LIBS += -L/usr/lib -lXxf86vm -lGL -lm + +%.o : %.c + $(CC) $(CFLAGS) -c $< + +all: $(OBJECTS) + $(LD) -fPIC $(OBJECTS) -g -shared -o $(PLUGIN) $(LIBS) + +#cfg: ${CFGOBJS} +# $(LD) $(CFGOBJS) -g -o $(CFG) $(CFGLIBS) + +release: all + strip $(PLUGIN) +# strip $(CFG) +# cp $(PLUGIN).$(NUMBER) ../$(PLUGIN).$(NUMBER) +# cp $(CFG) ../$(CFG) + +clean: + rm -f *.o *.a *.so $(CFG) + + +# Dependencies + + diff --git a/plugins/dfOpenGL/primitive_drawing.c b/plugins/dfOpenGL/primitive_drawing.c new file mode 100644 index 00000000..8d2104bd --- /dev/null +++ b/plugins/dfOpenGL/primitive_drawing.c @@ -0,0 +1,1710 @@ +#include <stdlib.h> +#include <string.h> +#include "gpu_i.h" + +typedef unsigned char byte; + +byte texshade[256]; +uint32_t torgba[65536]; +uint32_t image[65536]; +char curText=0; +TextureState_t texinfo; +struct texturecache texture[64]; +GLuint nullid; + +struct TransparencySettings{ + int mode; + int src; + int dst; + byte alpha; + bool change; +}; + +struct TransparencySettings TransRate[4]={ + {GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,128,TRUE}, + {GL_FUNC_ADD, GL_ONE, GL_ONE_MINUS_SRC_ALPHA,0,TRUE}, + {GL_FUNC_ADD, GL_ZERO, GL_ONE_MINUS_SRC_COLOR, 0,TRUE}, + {GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE,64,TRUE} +}; +bool transparent=FALSE; +byte gAlpha; + +void cmdSTP(unsigned char * baseAddr) +{ + uint32_t gdata = ((uint32_t*)baseAddr)[0]; + + GPUstatusRet&=~0x1800; // Clear the necessary bits + GPUstatusRet|=((gdata & 0x03) << 11); // Set the necessary bits + + psxDraw.setmask = gdata & 1; + psxDraw.testmask = (gdata & 2) >> 1; + + gllog(77," CMD: STP: %x",gdata&0xffffff); +} + + +inline void UpdateTextureInfo ( uint32_t gdata ) +{ + texinfo.x = ( gdata << 6 ) & 0x3c0; // texture addr + texinfo.y = ( gdata << 4 ) & 0x100; + + //if ( gdata&200 ) iDither=iUseDither; else iDither=0; + + texinfo.colormode = ( gdata >> 7 ) & 0x3; // tex mode (4bit,8bit,15direct) + if ( texinfo.colormode==3 ) + texinfo.colormode=2; // seen in Wild9 :( + + texinfo.abr = ( gdata >> 5 ) & 0x3; // blend mode + + texinfo.mirror = gdata&0x3000 >> 12; //??? + + GPUstatusRet&=~0x07ff; // Clear the necessary bits + GPUstatusRet|= ( gdata & 0x07ff ); // set the necessary bits +} + +void cmdTexturePage(unsigned char * baseAddr) +{ + uint32_t gdata = ((uint32_t*)baseAddr)[0]; + + int32_t tempABR = (gdata >> 5) & 0x3; + if(texinfo.abr != tempABR){ + texinfo.abr = tempABR; + //glBlendEquation(TransRate[texinfo.abr].mode); + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + gAlpha=TransRate[texinfo.abr].alpha; + transparent=TRUE; + } + UpdateTextureInfo(gdata); + + + /*switch(texinfo.abr){ + case 0: + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + gAlpha=128; + break; + case 1: + glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); + gAlpha=0; + break; + case 2: + glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_COLOR); + gAlpha=0; + break; + case 3: + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + gAlpha=64; + break; + }*/ + //textREST = (gdata&0x00ffffff)>>9; + //gllog(77," CMD: TPage: %d,%d TP=%d ABR=%d REST=%x\n",textAddrX,textAddrY,textTP,texinfo.abr,(gdata&0x00ffffff)>>9); + return; +} + +void cmdTextureWindow(unsigned char *baseAddr) +{ + //hopefully true psx texture window emulation, oddities & all + //taken from peops soft gpu + + uint32_t gdata = ((uint32_t*)baseAddr)[0]; + //gllog(77,"CDM: TWin: %x *NI*", gdata&0xffffff); + + GPUInfoVals[INFO_TW]=gdata&0xFFFFF; + + uint32_t YAlign,XAlign; + + if(gdata & 0x020) + psxDraw.texwinY2 = 8; // xxxx1 + else if (gdata & 0x040) + psxDraw.texwinY2 = 16; // xxx10 + else if (gdata & 0x080) + psxDraw.texwinY2 = 32; // xx100 + else if (gdata & 0x100) + psxDraw.texwinY2 = 64; // x1000 + else if (gdata & 0x200) + psxDraw.texwinY2 = 128; // 10000 + else + psxDraw.texwinY2 = 256; // 00000 + + // Texture window size is determined by the least bit set of the relevant 5 bits + + if (gdata & 0x001) + psxDraw.texwinX2 = 8; // xxxx1 + else if (gdata & 0x002) + psxDraw.texwinX2 = 16; // xxx10 + else if (gdata & 0x004) + psxDraw.texwinX2 = 32; // xx100 + else if (gdata & 0x008) + psxDraw.texwinX2 = 64; // x1000 + else if (gdata & 0x010) + psxDraw.texwinX2 = 128; // 10000 + else + psxDraw.texwinX2 = 256; // 00000 + + // Re-calculate the bit field, because we can't trust what is passed in the data + + + YAlign = (uint32_t)(32 - (psxDraw.texwinY2 >> 3)); + XAlign = (uint32_t)(32 - (psxDraw.texwinX2 >> 3)); + + // Absolute position of the start of the texture window + + psxDraw.texwinY1 = (short)(((gdata >> 15) & YAlign) << 3); + psxDraw.texwinX1 = (short)(((gdata >> 10) & XAlign) << 3); + + if((psxDraw.texwinX1 == 0 && // tw turned off + psxDraw.texwinY1 == 0 && + psxDraw.texwinX2 == 0 && + psxDraw.texwinY2 == 0) || + (psxDraw.texwinX2 == 256 && + psxDraw.texwinY2 == 256)) + { + psxDraw.texwinenabled = 0; // -> just do it + } + else // otherwise + { + psxDraw.texwinenabled = 1; // -> tw turned on + } +} + +void cmdDrawAreaStart(unsigned char * baseAddr) +{ + uint32_t gdata = ((uint32_t*)baseAddr)[0]; + GPUInfoVals[INFO_DRAWSTART]=gdata&0x3FFFFF; + + psxDraw.clipX1 = gdata & 0x3ff; + psxDraw.clipY1 = (gdata>>10)&0x1ff; + + GLdouble equation[4]={0.0,0.0,0.0,0.0}; + equation[0]=1.0; + equation[3]=(GLdouble)-(psxDraw.clipX1); + glClipPlane(GL_CLIP_PLANE0,equation); + + equation[0]=0.0; + equation[1]=1.0; + equation[3]=(GLdouble)-(psxDraw.clipY1); + glClipPlane(GL_CLIP_PLANE1,equation); + + //gllog(77," CMD: DrawArea Start %d,%d %x",drawX,drawY,gdata); +} + +void cmdDrawAreaEnd(unsigned char * baseAddr) +{ + uint32_t gdata = ((uint32_t*)baseAddr)[0]; + GPUInfoVals[INFO_DRAWEND]=gdata&0x3FFFFF; + + psxDraw.clipX2 = gdata & 0x3ff; + psxDraw.clipY2 = (gdata>>10)&0x1ff; + + GLdouble equation[4]={0.0,0.0,0.0,0.0}; + equation[0]=-1.0; + equation[3]=(GLdouble)(psxDraw.clipX2); + glClipPlane(GL_CLIP_PLANE2,equation); + + equation[0]=0.0; + equation[1]=-1.0; + equation[3]=(GLdouble)(psxDraw.clipY2); + glClipPlane(GL_CLIP_PLANE3,equation); + + + //gllog(77," CMD: DrawArea End %d,%d",drawW,drawH); +} + +void cmdDrawOffset(unsigned char * baseAddr) +{ + uint32_t gdata = ((uint32_t*)baseAddr)[0]; + GPUInfoVals[INFO_DRAWOFF]=gdata&0x7FFFFF; + + psxDraw.offsetX = (short)(gdata & 0x7ff); + psxDraw.offsetY = (short)((gdata>>11)&0x7ff); + + psxDraw.offsetX=(short)(((int)psxDraw.offsetX<<21)>>21); + psxDraw.offsetY=(short)(((int)psxDraw.offsetY<<21)>>21); + + //gllog(77," CMD: Draw Offset %d,%d",ofsX,ofsY,gdata); +} + +void primLoadImage(unsigned char * baseAddr) +{ + short *sgpuData = ((short *) baseAddr); + //uint32_t *gpuData = ((uint32_t *) baseAddr); + + short x = (sgpuData[2]<<21)>>21; + short y = (sgpuData[3]<<21)>>21; + short w = (sgpuData[4]<<21)>>21; + short h = (sgpuData[5]<<21)>>21; + + if (w == -1024) w = 1024; + if (h == -512) h = 512; + + if (x < 0 || y < 0 || w<0 || h<0 || x+w > 1024 || y+h > 512) + { + return; + } + + vramWrite.curx = vramWrite.x = x; + vramWrite.cury = vramWrite.y = y; + vramWrite.w = w; + vramWrite.h = h; + vramWrite.extratarget = (uint32_t*)malloc(vramWrite.w*vramWrite.h*4); + vramWrite.enabled = 1; + + imageTransfer = 1; + + int i; + + for(i=0;i<gpuConfig.nMaxTextures;i++){ + if(((texture[i].textAddrX+255)>=x) + &&((texture[i].textAddrY+255)>=y) + &&(texture[i].textAddrX<=(x+w)) + &&(texture[i].textAddrY<=(y+h))){ + texture[i].Update=TRUE; + } + } + + //gllog(1," CMD: MEM->VRAM %d,%d %d,%d\n",imageX0,imageY0,imageX1,imageY1); +} + +void primStoreImage(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + + imageX0 = (short)(gpuData[1] & 0x3ff); + imageY0 = (short)(gpuData[1]>>16) & 0x1ff; + imageX1 = (short)(gpuData[2] & 0xffff); + imageY1 = (short)((gpuData[2]>>16) & 0xffff); + + //gllog(1," CMD: VRAM->MEM %d,%d %d,%d\n",imageX0,imageY0,imageX1,imageY1); + imTX=imageX0; imTY=imageY0; + imTXc=imageX1; imTYc=imageY1; + imSize=imageY1*imageX1/2; + + imageTransfer = 2; + GPUstatusRet|=0x08000000; +} + +void primMoveImage(unsigned char * baseAddr) +{ + // 0x80 image move (VRAM->VRAM) + uint32_t *gpuData = ((uint32_t *) baseAddr); + + unsigned short imageX0,imageY0,imageX1,imageY1,imageSX,imageSY,i,j; + + imageX0 = (short)(gpuData[1] & 0x3ff); + imageY0 = (short)(gpuData[1]>>16) & 0x1ff; + + imageX1 = (short)(gpuData[2] & 0x3ff); + imageY1 = (short)((gpuData[2]>>16) & 0x1ff); + + imageSY = (short)((gpuData[3]>>16) & 0xffff); + imageSX = (short)(gpuData[3] & 0xffff); + + for(i=0;i<gpuConfig.nMaxTextures;i++){ + if(((texture[i].textAddrX+255)>=imageX1) + &&((texture[i].textAddrY+255)>=imageY1) + &&(texture[i].textAddrX<=(imageX1+imageSX)) + &&(texture[i].textAddrY<=(imageY1+imageSY))){ + texture[i].Update=TRUE; + } + } + + //gllog(1," CMD: VRAM->VRAM %d,%d -> %d,%d (%d,%d)\n",imageX0,imageY0,imageX1,imageY1,imageSX,imageSY); + + if((imageY0+imageSY)>512) imageSY=512-imageY0; + if((imageY1+imageSY)>512) imageSY=512-imageY1; + if((imageX0+imageSX)>1024) imageSX=1024-imageX0; + if((imageX1+imageSX)>1024) imageSX=1024-imageX1; + for(j=0;j<imageSY;j++) + for(i=0;i<imageSX;i++) + psxVuw[((imageY1+j)<<10)+imageX1+i]=psxVuw[((imageY0+j)<<10)+imageX0+i]; +} + + + + +void primTileS(unsigned char * baseAddr) +{ + //gllog(2,"Tile S *NI*");// : %04x,%04x - %04x,%04x",baseAddrW[addr+2],baseAddrW[addr+3],baseAddrW[addr+4],baseAddrW[addr+5]); + //gllog(2,"Tile S *NI* : %04x,%04x - %04x,%04x",baseAddrW[addr+2],baseAddrW[addr+3],baseAddrW[addr+4],baseAddrW[addr+5]); + + //uint32_t *gpuData = (uint32_t *)baseAddr; + unsigned short *gpuPoint = (unsigned short*) baseAddr; + + short x = (gpuPoint[2]<<21)>>21; + short y = (gpuPoint[3]<<21)>>21; + short w = (gpuPoint[4]<<21)>>21; + short h = (gpuPoint[5]<<21)>>21; + + x += psxDraw.offsetX; + y += psxDraw.offsetY; + + if(baseAddr[3]&2){ //if blending on + //if(TransRate[texinfo.abr].change && !transparent){ + //glBlendEquation(TransRate[texinfo.abr].mode); + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + gAlpha=TransRate[texinfo.abr].alpha; + transparent=TRUE; + //} + //if(baseAddr[3]&1){ + // glColor4ub(255,255,255,gAlpha); + //}else{ + glColor4ub(baseAddr[0],baseAddr[1],baseAddr[2],gAlpha); + //} + }else{ + //if(TransRate[texinfo.abr].change && transparent){ + //glBlendEquation(TransRate[0].mode); + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + //} + //if(baseAddr[3]&1){ + // glColor3ub(255,255,255); + //}else{ + glColor3ub(baseAddr[0],baseAddr[1],baseAddr[2]); + //} + } + + glBegin(GL_POLYGON); + glVertex2s(x,y); + glVertex2s(x+w,y); + glVertex2s(x+w,y+h); + glVertex2s(x,y+h); + glEnd(); + + + return; +} + +void primBlkFill(unsigned char * baseAddr) +{ + short * gpuPoint = (short*) baseAddr; + //uint32_t *gpuData = ((uint32_t *) baseAddr); + + //gllog(2,"BlkFill : %04x,%04x - %04x,%04x",gpuPoint[2],gpuPoint[3],gpuPoint[4],gpuPoint[5]); + + short x = (gpuPoint[2]<<21)>>21; + short y = (gpuPoint[3]<<21)>>21; + short w = (gpuPoint[4]<<21)>>21; + short h = (gpuPoint[5]<<21)>>21; + +/* + this function is something like clear_with_given_color + and according to baseAddr + struct packet + { + unsigned char R,G,B,code; + unsigned short X,Y,W,H; + } + this function is not clipped bby drawing area, accesses whole VRAM +*/ + + glDisable(GL_CLIP_PLANE0); + glDisable(GL_CLIP_PLANE1); + glDisable(GL_CLIP_PLANE2); + glDisable(GL_CLIP_PLANE3); + + glColor3ub(baseAddr[0],baseAddr[1],baseAddr[2]); + glBegin(GL_POLYGON); + glVertex2s(x,y); + glVertex2s(x+w,y); + glVertex2s(x+w,y+h); + glVertex2s(x,y+h); + glEnd(); + + glEnable(GL_CLIP_PLANE0); + glEnable(GL_CLIP_PLANE1); + glEnable(GL_CLIP_PLANE2); + glEnable(GL_CLIP_PLANE3); +} + + + +void setupTexture(int32_t clutP){ + int i; + int32_t sprCY,sprCX,tbw; + short color,tC; + int ctext; + union uPointers psxVOffset,psxVOffset2; + + if( (texinfo.colormode&2) == 2 ) + clutP=nullclutP; + + ctext=curText; + for(i=0;i<gpuConfig.nMaxTextures;i++){ + if(texture[i].textAddrX==texinfo.x && texture[i].textAddrY==texinfo.y && clutP==texture[i].clutP) + { + if(texture[i].Update==TRUE || texinfo.colormode!=texture[i].textTP) + { + ctext=i; + break; + } + glBindTexture(GL_TEXTURE_2D,texture[i].id); + return; + } + } + + texture[ctext].textAddrX=texinfo.x; + texture[ctext].textAddrY=texinfo.y; + texture[ctext].textTP=texinfo.colormode; + texture[ctext].clutP=clutP; + texture[ctext].Update=FALSE; + glBindTexture(GL_TEXTURE_2D,texture[ctext].id); + if(ctext==curText){ + curText++; + if(curText>=gpuConfig.nMaxTextures)curText=0; + } + + + tbw=256; + psxVOffset.w=psxVuw+(texinfo.y<<10)+texinfo.x; + + uint32_t *pimage = image; + + switch(texinfo.colormode) + { + //4bit clut + case 0: + for (sprCY=0;sprCY<256;sprCY++){ + psxVOffset2.b=psxVOffset.b; + for (sprCX=0;sprCX<256;sprCX+=2){ + tC = (*psxVOffset2.b)&0x0f; + *pimage = torgba[psxVuw[clutP+tC]]; + pimage++; + + tC = (*psxVOffset2.b>>4)&0x0f; + *pimage = torgba[psxVuw[clutP+tC]]; + pimage++; + + psxVOffset2.b++; + } + psxVOffset.w+=1024; + } + break; + + //8bit clut + case 1: + if(texinfo.x==960)tbw=128; + for (sprCY=0;sprCY<256;sprCY++){ + psxVOffset2.b=psxVOffset.b; + for (sprCX=0;sprCX<tbw;sprCX++){ + tC = *psxVOffset2.b; + image[(sprCY<<8)+sprCX] = torgba[psxVuw[clutP+tC]]; + psxVOffset2.b++; + } + psxVOffset.w+=1024; + } + break; + + //15bit direct + case 2: + if(texinfo.x==960)tbw=64; + else if(texinfo.x==896)tbw=128; + else if(texinfo.x==832)tbw=192; + + for (sprCY=0;sprCY<256;sprCY++){ + psxVOffset2.w=psxVOffset.w; + for (sprCX=0;sprCX<tbw;sprCX++){ + color = *psxVOffset2.w; + image[(sprCY<<8)+sprCX] = torgba[color]; + psxVOffset2.w++; + } + psxVOffset.w+=1024; + } + break; + } + glTexSubImage2D(GL_TEXTURE_2D,0,0,0,256,256,GL_RGBA,GL_UNSIGNED_BYTE,image); +} + + +void setSpriteBlendMode(int32_t command){ + unsigned char *baseAddr = (unsigned char *)&command; + + //color info is 0-127, or bit 0x80 to indicate full color + //note: above applies to texture (and sprite) color shading info only? + unsigned char r,g,b; + r = texshade[baseAddr[0]]; + g = texshade[baseAddr[1]]; + b = texshade[baseAddr[2]]; + + if(baseAddr[3]&2){ //if blending on + //if(TransRate[texinfo.abr].change && !transparent){ + //glBlendEquation(TransRate[texinfo.abr].mode); + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + transparent=TRUE; + //} + if(baseAddr[3]&1){ //should always be 0 for sprite? Apparantly not... + glColor4ub(255,255,255,gAlpha); + }else{ + glColor4ub(r,g,b,gAlpha); + } + }else{ + //if(TransRate[texinfo.abr].change && transparent){ + //glBlendEquation(TransRate[0].mode); + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + //} + if(baseAddr[3]&1){ + glColor3ub(255,255,255); + }else{ + glColor3ub(r,g,b); + } + } +} + +void primSprt8(unsigned char * baseAddr) +{ +/* + fixed size (8x8) sprite +*/ + uint32_t *gpuData = (uint32_t *)baseAddr; + short *gpuPoint = (short*) baseAddr; + int32_t clutP; + short tx,ty; + short x,y; + + //gllog(2,"Sprt8x8 : %d,%d %02x",gpuPoint[2],gpuPoint[3],baseAddr[3]); + clutP = (gpuData[2]>>12) & 0x7fff0;//0xffff0; + tx = (short)(gpuData[2] & 0x000000ff); + ty = (short)((gpuData[2]>>8) & 0x000000ff); + + x = (gpuPoint[2]<<21)>>21; + y = (gpuPoint[3]<<21)>>21; + + x += psxDraw.offsetX; + y += psxDraw.offsetY; + + setupTexture(clutP); + setSpriteBlendMode(*gpuData); + + /*switch(baseAddr[3]&3){ + case 0: + glColor3ub(baseAddr[0],baseAddr[1],baseAddr[2]); + break; + case 1: + glColor3ub(255,255,255); + break; + case 2: + glColor4ub(baseAddr[0],baseAddr[1],baseAddr[2],gAlpha); + break; + case 3: + glColor4ub(255,255,255,gAlpha); + break; + }*/ + + glBegin(GL_POLYGON); + glTexCoord2s(tx,ty); + glVertex2s(x,y); + glTexCoord2s(tx+7,ty); + glVertex2s(x+8,y); + glTexCoord2s(tx+7,ty+7); + glVertex2s(x+8,y+8); + glTexCoord2s(tx,ty+7); + glVertex2s(x,y+8); + glEnd(); + + //draw opaque areas of texture + if(baseAddr[3]&2){ + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_EQUAL, 1); + glColor3ub(255,255,255); + glDisable(GL_BLEND); + glBegin(GL_POLYGON); + glTexCoord2s(tx,ty); + glVertex2s(x,y); + glTexCoord2s(tx+7,ty); + glVertex2s(x+8,y); + glTexCoord2s(tx+7,ty+7); + glVertex2s(x+8,y+8); + glTexCoord2s(tx,ty+7); + glVertex2s(x,y+8); + glEnd(); + glEnable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + } + + glBindTexture(GL_TEXTURE_2D,nullid); +} + +void primSprt16(unsigned char * baseAddr) +{ +/* + fixed size (16x16) sprite +*/ + uint32_t *gpuData = (uint32_t *)baseAddr; + short *gpuPoint = (short*) baseAddr; + int32_t clutP; + short tx,ty; + short x,y; + + //gllog(2,"Sprt16x16 : %d,%d %02x",gpuPoint[2],gpuPoint[3],baseAddr[3]); + clutP = (gpuData[2]>>12) & 0x7fff0;//0xffff0; + tx = (short)(gpuData[2] & 0x000000ff); + ty = (short)((gpuData[2]>>8) & 0x000000ff); + + x = (gpuPoint[2]<<21)>>21; + y = (gpuPoint[3]<<21)>>21; + + x += psxDraw.offsetX; + y += psxDraw.offsetY; + + setupTexture(clutP); + setSpriteBlendMode(*gpuData); + + glBegin(GL_POLYGON); + glTexCoord2s(tx,ty); + glVertex2s(x,y); + glTexCoord2s(tx+15,ty); + glVertex2s(x+16,y); + glTexCoord2s(tx+15,ty+15); + glVertex2s(x+16,y+16); + glTexCoord2s(tx,ty+15); + glVertex2s(x,y+16); + glEnd(); + + //draw opaque areas of texture + if(baseAddr[3]&2){ + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_EQUAL, 1); + glColor3ub(255,255,255); + glDisable(GL_BLEND); + glBegin(GL_POLYGON); + glTexCoord2s(tx,ty); + glVertex2s(x,y); + glTexCoord2s(tx+15,ty); + glVertex2s(x+16,y); + glTexCoord2s(tx+15,ty+15); + glVertex2s(x+16,y+16); + glTexCoord2s(tx,ty+15); + glVertex2s(x,y+16); + glEnd(); + glEnable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + } + + + glBindTexture(GL_TEXTURE_2D,nullid); +} + +void primSprtS(unsigned char * baseAddr) +{ +/* + free size (up to 256x256) sprite +*/ + uint32_t *gpuData = (uint32_t *)baseAddr; + short *gpuPoint = (short*) baseAddr; + int32_t clutP; + short tx,ty,sprtW,sprtH; + short tx1,tx2,ty1,ty2; + short x,y; + + clutP = (gpuData[2]>>12) & 0x7fff0;//0xffff0; + + tx = (short)(gpuData[2] & 0x000000ff); + ty = (short)((gpuData[2]>>8) & 0x000000ff); + sprtW = (short)(gpuData[3] & 0x3ff); + sprtH = (short)((gpuData[3]>>16) & 0x1ff); + + x = (gpuPoint[2]<<21)>>21; + y = (gpuPoint[3]<<21)>>21; + + x += psxDraw.offsetX; + y += psxDraw.offsetY; + + //gllog(2,"Sprt : %04x,%04x - %04x,%04x code=%02x pal=%05x",gpuPoint[2],gpuPoint[3],gpuPoint[6],gpuPoint[7],baseAddr[3],clutP); + /*if(textAddrX==320&&textAddrY==0){ + gllog(2,"Sprt : %d,%d - %d,%d pal=%05x",gpuPoint[2],gpuPoint[3],gpuPoint[6],gpuPoint[7],gpuData[2]>>12); + }*/ + + //scaled instead of repeated for now... + #define min(a,b) ((a) < (b) ? (a) : (b)) + + short minw = min(psxDraw.texwinX2, sprtW); + short minh = min(psxDraw.texwinY2, sprtH); + + tx1 = tx + psxDraw.texwinX1; + tx2 = tx1 + minw - 1; + ty1 = ty + psxDraw.texwinY1; + ty2 = ty1 + minh - 1; +/* + short tswap; + + #define swap(a,b) tswap = (a); (a)=(b); (b) = tswap + + switch (texinfo.mirror) + { + case 1: + swap(tx1, tx2); + break; + case 2: + swap(ty1, ty2); + break; + case 3: + swap(tx1,tx2); + swap(ty1,ty2); + break; + } +*/ + + setupTexture(clutP); + setSpriteBlendMode(*gpuData); + + glBegin(GL_POLYGON); + glTexCoord2s(tx1, ty1); + glVertex2s(x,y); + glTexCoord2s(tx2, ty1); + glVertex2s(x+sprtW,y); + glTexCoord2s(tx2, ty2); + glVertex2s(x+sprtW,y+sprtH); + glTexCoord2s(tx1, ty2); + glVertex2s(x,y+sprtH); + glEnd(); + + //draw opaque areas of texture + if(baseAddr[3]&2){ + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_EQUAL, 1); + glDisable(GL_BLEND); + glColor3ub(255,255,255); + glBegin(GL_POLYGON); + glTexCoord2s(tx1, ty1); + glVertex2s(x,y); + glTexCoord2s(tx2, ty1); + glVertex2s(x+sprtW,y); + glTexCoord2s(tx2, ty2); + glVertex2s(x+sprtW,y+sprtH); + glTexCoord2s(tx1, ty2); + glVertex2s(x,y+sprtH); + glEnd(); + glEnable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + } + + glBindTexture(GL_TEXTURE_2D,nullid); +} + + +void primLineF2(unsigned char *baseAddr) +{ +/* + Flat Line 2 vertices +*/ + short *gpuPoint=((short *) baseAddr); + short x1,y1,x2,y2; + + x1 = (gpuPoint[2]<<21)>>21; + y1 = (gpuPoint[3]<<21)>>21; + x2 = (gpuPoint[4]<<21)>>21; + y2 = (gpuPoint[5]<<21)>>21; + + x1 += psxDraw.offsetX; + y1 += psxDraw.offsetY; + x2 += psxDraw.offsetX; + y2 += psxDraw.offsetY; + + + if(baseAddr[3]&2){ + if(TransRate[texinfo.abr].change&&!transparent){ + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + transparent=TRUE; + } + glColor4ub(baseAddr[0],baseAddr[1],baseAddr[2],gAlpha); + }else{ + if(TransRate[texinfo.abr].change&&transparent){ + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + } + glColor3ub(baseAddr[0],baseAddr[1],baseAddr[2]); + } + /*if(baseAddr[3]&2){ + glColor4ub(baseAddr[0],baseAddr[1],baseAddr[2],gAlpha); + }else{ + glColor3ub(baseAddr[0],baseAddr[1],baseAddr[2]); + }*/ + glBegin(GL_LINES); + glVertex2s(x1,y1); + glVertex2s(x2,y2); + glEnd(); +} + +void primLineG2(unsigned char *baseAddr) +{ +/* + Goraud Line 2 vertices +*/ + short *gpuPoint=((short *) baseAddr); + short x1,y1,x2,y2; + unsigned char alpha; + + x1 = (gpuPoint[2]<<21)>>21; + y1 = (gpuPoint[3]<<21)>>21; + x2 = (gpuPoint[6]<<21)>>21; + y2 = (gpuPoint[7]<<21)>>21; + + x1 += psxDraw.offsetX; + y1 += psxDraw.offsetY; + x2 += psxDraw.offsetX; + y2 += psxDraw.offsetY; + + + if(baseAddr[3]&2){ + if(TransRate[texinfo.abr].change&&!transparent){ + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + transparent=TRUE; + } + alpha=gAlpha; + }else{ + if(TransRate[texinfo.abr].change&&transparent){ + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + } + alpha=255; + } + /*if(baseAddr[3]&2){ + alpha=gAlpha; + }else{ + alpha=255; + }*/ + glBegin(GL_LINES); + glColor4ub(baseAddr[0],baseAddr[1],baseAddr[2],alpha); + glVertex2s(x1,y1); + glColor4ub(baseAddr[8],baseAddr[9],baseAddr[10],alpha); + glVertex2s(x2,y2); + glEnd(); +} + +void primPolyF3(unsigned char *baseAddr) +{ +/* + Flat Shaded Polygon 3 vertices +*/ + short *gpuPoint=((short *) baseAddr); + short x1,x2,x3,y1,y2,y3; + + x1 = (gpuPoint[2]<<21)>>21; + y1 = (gpuPoint[3]<<21)>>21; + x2 = (gpuPoint[4]<<21)>>21; + y2 = (gpuPoint[5]<<21)>>21; + x3 = (gpuPoint[6]<<21)>>21; + y3 = (gpuPoint[7]<<21)>>21; + + x1 += psxDraw.offsetX; + y1 += psxDraw.offsetY; + x2 += psxDraw.offsetX; + y2 += psxDraw.offsetY; + x3 += psxDraw.offsetX; + y3 += psxDraw.offsetY; + + //gllog(77,"!GPU! P3 F %d,%d %d,%d %d,%d\n",lx0,ly0,lx1,ly1,lx2,ly2); + + if(baseAddr[3]&2){ + if(TransRate[texinfo.abr].change&&!transparent){ + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + transparent=TRUE; + } + gAlpha = TransRate[texinfo.abr].alpha; + glColor4ub(baseAddr[0],baseAddr[1],baseAddr[2],gAlpha); + }else{ + if(TransRate[texinfo.abr].change&&transparent){ + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + } + glColor3ub(baseAddr[0],baseAddr[1],baseAddr[2]); + } + glBegin(GL_POLYGON); + glVertex2s(x1,y1); + glVertex2s(x2,y2); + glVertex2s(x3,y3); + glEnd(); +} + +void primPolyF4(unsigned char *baseAddr) +{ +/* + Flat Shaded Polygon 4 vertices +*/ + short *gpuPoint=((short *) baseAddr); + short x1,x2,x3,x4,y1,y2,y3,y4; + + x1 = (gpuPoint[2]<<21)>>21; + y1 = (gpuPoint[3]<<21)>>21; + x2 = (gpuPoint[4]<<21)>>21; + y2 = (gpuPoint[5]<<21)>>21; + x3 = (gpuPoint[6]<<21)>>21; + y3 = (gpuPoint[7]<<21)>>21; + x4 = (gpuPoint[8]<<21)>>21; + y4 = (gpuPoint[9]<<21)>>21; + + x1 += psxDraw.offsetX; + y1 += psxDraw.offsetY; + x2 += psxDraw.offsetX; + y2 += psxDraw.offsetY; + x3 += psxDraw.offsetX; + y3 += psxDraw.offsetY; + x4 += psxDraw.offsetX; + y4 += psxDraw.offsetY; + + //gllog(77,"!GPU! P4 F %d,%d %d,%d %d,%d %d,%d %6x\n",lx0,ly0,lx1,ly1,lx2,ly2,lx3,ly3,gpuData[0]); + + if(baseAddr[3]&2){ + if(TransRate[texinfo.abr].change&&!transparent){ + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + transparent=TRUE; + } + gAlpha = TransRate[texinfo.abr].alpha; + glColor4ub(baseAddr[0],baseAddr[1],baseAddr[2],gAlpha); + }else{ + if(TransRate[texinfo.abr].change&&transparent){ + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + } + glColor3ub(baseAddr[0],baseAddr[1],baseAddr[2]); + } + glBegin(GL_POLYGON); + glVertex2s(x1,y1); + glVertex2s(x2,y2); + glVertex2s(x4,y4); + glVertex2s(x3,y3); + glEnd(); +} + +void primPolyG3(unsigned char *baseAddr) +{ +/* + Goraud Shaded Polygon 3 vertices +*/ + short *gpuPoint=((short *) baseAddr); + unsigned char alpha; + short x1,x2,x3,y1,y2,y3; + + x1 = (gpuPoint[2]<<21)>>21; + y1 = (gpuPoint[3]<<21)>>21; + x2 = (gpuPoint[6]<<21)>>21; + y2 = (gpuPoint[7]<<21)>>21; + x3 = (gpuPoint[10]<<21)>>21; + y3 = (gpuPoint[11]<<21)>>21; + + x1 += psxDraw.offsetX; + y1 += psxDraw.offsetY; + x2 += psxDraw.offsetX; + y2 += psxDraw.offsetY; + x3 += psxDraw.offsetX; + y3 += psxDraw.offsetY; + + //gllog(77,"!GPU! P3 G %d,%d %d,%d %d,%d\n",lx0,ly0,lx1,ly1,lx2,ly2); + + if(baseAddr[3]&2){ + if(TransRate[texinfo.abr].change&&!transparent){ + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + transparent=TRUE; + } + alpha = TransRate[texinfo.abr].alpha; + }else{ + if(TransRate[texinfo.abr].change&&transparent){ + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + } + alpha=255; + } + glBegin(GL_POLYGON); + glColor4ub(baseAddr[0],baseAddr[1],baseAddr[2],alpha); + glVertex2s(x1,y1); + glColor4ub(baseAddr[8],baseAddr[9],baseAddr[10],alpha); + glVertex2s(x2,y2); + glColor4ub(baseAddr[16],baseAddr[17],baseAddr[18],alpha); + glVertex2s(x3,y3); + glEnd(); +} + +void primPolyG4(unsigned char * baseAddr) +{ +/* + Goraud Shaded Polygon 4 vertices +*/ + short *gpuPoint=((short *) baseAddr); + short x1,x2,x3,x4,y1,y2,y3,y4; + unsigned char alpha; + + x1 = (gpuPoint[2]<<21)>>21; + y1 = (gpuPoint[3]<<21)>>21; + x2 = (gpuPoint[6]<<21)>>21; + y2 = (gpuPoint[7]<<21)>>21; + x3 = (gpuPoint[10]<<21)>>21; + y3 = (gpuPoint[11]<<21)>>21; + x4 = (gpuPoint[14]<<21)>>21; + y4 = (gpuPoint[15]<<21)>>21; + + x1 += psxDraw.offsetX; + y1 += psxDraw.offsetY; + x2 += psxDraw.offsetX; + y2 += psxDraw.offsetY; + x3 += psxDraw.offsetX; + y3 += psxDraw.offsetY; + x4 += psxDraw.offsetX; + y4 += psxDraw.offsetY; + + if(baseAddr[3]&2){ + if(TransRate[texinfo.abr].change&&!transparent){ + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + transparent=TRUE; + } + alpha = TransRate[texinfo.abr].alpha; + }else{ + if(TransRate[texinfo.abr].change&&transparent){ + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + } + alpha=255; + } + glBegin(GL_POLYGON); + glColor4ub(baseAddr[0],baseAddr[1],baseAddr[2],alpha); + glVertex2s(x1,y1); + glColor4ub(baseAddr[8],baseAddr[9],baseAddr[10],alpha); + glVertex2s(x2,y2); + glColor4ub(baseAddr[24],baseAddr[25],baseAddr[26],alpha); + glVertex2s(x4,y4); + glColor4ub(baseAddr[16],baseAddr[17],baseAddr[18],alpha); + glVertex2s(x3,y3); + glEnd(); +} + +void primPolyFT3(unsigned char * baseAddr) +{ +/* + Flat Shaded Textured Polygon 3 vertices +*/ + uint32_t *gpuData = (uint32_t *)baseAddr; + short *gpuPoint=((short *) baseAddr); + int32_t clutP; + short x1,x2,x3,y1,y2,y3; + short tx0,ty0,tx1,ty1,tx2,ty2; + unsigned short gpuDataX; + + + x1 = (gpuPoint[2]<<21)>>21; + y1 = (gpuPoint[3]<<21)>>21; + x2 = (gpuPoint[6]<<21)>>21; + y2 = (gpuPoint[7]<<21)>>21; + x3 = (gpuPoint[10]<<21)>>21; + y3 = (gpuPoint[11]<<21)>>21; + + x1 += psxDraw.offsetX; + y1 += psxDraw.offsetY; + x2 += psxDraw.offsetX; + y2 += psxDraw.offsetY; + x3 += psxDraw.offsetX; + y3 += psxDraw.offsetY; + + tx0 = (short)(gpuData[2] & 0xff); + ty0 = (short)((gpuData[2]>>8) & 0xff); + tx1 = (short)(gpuData[4] & 0xff); + ty1 = (short)((gpuData[4]>>8) & 0xff); + tx2 = (short)(gpuData[6] & 0xff); + ty2 = (short)((gpuData[6]>>8) & 0xff); + //gllog(77,"!GPU! P3 F %d,%d %d,%d %d,%d\n",lx0,ly0,lx1,ly1,lx2,ly2); + gpuDataX=(unsigned short)(gpuData[4]>>16); + + int32_t tempABR = (gpuDataX >>5) & 0x3; + if(texinfo.abr!=tempABR){ + texinfo.abr = tempABR; + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + gAlpha=TransRate[texinfo.abr].alpha; + transparent=TRUE; + } + UpdateTextureInfo(gpuDataX); + + /*switch(texinfo.abr){ + case 0: + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + gAlpha=128; + break; + case 1: + glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); + gAlpha=0; + break; + case 2: + glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_COLOR); + gAlpha=0; + break; + case 3: + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + gAlpha=64; + break; + }*/ + //gllog(77," CMD: P3TF: %d,%d TP=%d",textAddrX,textAddrY,textTP); + //gllog(77," CMD: P3TF: %d,%d %02x",lx0,ly0,baseAddr[3]); + + clutP = (gpuData[2]>>12) & 0x7fff0;//0xffff0; + setupTexture(clutP); + //setPolyTexBlendMode(*gpuData); + + baseAddr[0] = texshade[baseAddr[0]]; + baseAddr[1] = texshade[baseAddr[1]]; + baseAddr[2] = texshade[baseAddr[2]]; + + if(baseAddr[3]&2){ + if(TransRate[texinfo.abr].change&&!transparent){ + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + transparent=TRUE; + } + if(baseAddr[3]&1){ + glColor4ub(255,255,255,gAlpha); + //glColor4ub(255,255,255,255); + }else{ + glColor4ub(baseAddr[0],baseAddr[1],baseAddr[2],gAlpha); + } + }else{ + //if(TransRate[texinfo.abr].change&&transparent){ + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + //} + if(baseAddr[3]&1){ + glColor3ub(255,255,255); + }else{ + glColor3ub(baseAddr[0],baseAddr[1],baseAddr[2]); + } + } + + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + + short xtest = (x1-x2)*(tx0-tx1); + if (xtest == 0) + xtest = (x1-x3)*(tx0-tx2); + if (xtest < 0) + glTranslatef(1.0f, 0, 0); + + short ytest = (y1-y2)*(ty0-ty1); + if (ytest == 0) + ytest = (y1-y3)*(ty0-ty2); + if (ytest < 0) + glTranslatef(0, 1.0f, 0); + + glBegin(GL_POLYGON); + glTexCoord2s(tx0,ty0); + glVertex2s(x1,y1); + glTexCoord2s(tx1,ty1); + glVertex2s(x2,y2); + glTexCoord2s(tx2,ty2); + glVertex2s(x3,y3); + glEnd(); + + glPopMatrix(); + + glBindTexture(GL_TEXTURE_2D,nullid); +} + + +void primPolyFT4(unsigned char * baseAddr) +{ +/* + Flat Shaded Textured Polygon 4 vertices +*/ + + uint32_t *gpuData = (uint32_t *)baseAddr; + short *gpuPoint=((short *) baseAddr); + int32_t clutP; + short x1,x2,x3,x4,y1,y2,y3,y4; + short tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3; + unsigned short gpuDataX; + + x1 = (gpuPoint[2]<<21)>>21; + y1 = (gpuPoint[3]<<21)>>21; + x2 = (gpuPoint[6]<<21)>>21; + y2 = (gpuPoint[7]<<21)>>21; + x3 = (gpuPoint[10]<<21)>>21; + y3 = (gpuPoint[11]<<21)>>21; + x4 = (gpuPoint[14]<<21)>>21; + y4 = (gpuPoint[15]<<21)>>21; + + x1 += psxDraw.offsetX; + y1 += psxDraw.offsetY; + x2 += psxDraw.offsetX; + y2 += psxDraw.offsetY; + x3 += psxDraw.offsetX; + y3 += psxDraw.offsetY; + x4 += psxDraw.offsetX; + y4 += psxDraw.offsetY; + + tx0 = (short)(gpuData[2] & 0xff); + ty0 = (short)((gpuData[2]>>8) & 0xff); + tx1 = (short)(gpuData[4] & 0xff); + ty1 = (short)((gpuData[4]>>8) & 0xff); + tx2 = (short)(gpuData[6] & 0xff); + ty2 = (short)((gpuData[6]>>8) & 0xff); + tx3 = (short)(gpuData[8] & 0xff); + ty3 = (short)((gpuData[8]>>8) & 0xff); + //gllog(77,"!GPU! P4 F %d,%d %d,%d %d,%d %d,%d %6x\n",tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3,gpuData[0]); + + gpuDataX=(unsigned short)(gpuData[4]>>16); + + int32_t tempABR = (gpuDataX >> 5) & 0x3; + if(texinfo.abr!=tempABR){ + texinfo.abr = tempABR; + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + gAlpha=TransRate[texinfo.abr].alpha; + transparent=TRUE; + } + UpdateTextureInfo(gpuDataX); + + /*switch(texinfo.abr){ + case 0: + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + gAlpha=128; + break; + case 1: + glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); + gAlpha=0; + break; + case 2: + glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_COLOR); + gAlpha=0; + break; + case 3: + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + gAlpha=64; + break; + }*/ + //gllog(77," CMD: P4TF: %d,%d TP=%d",textAddrX,textAddrY,textTP); + //gllog(77," CMD: P4TG: %d,%d,%d,%d",baseAddr[3],baseAddr[15],baseAddr[39],baseAddr[27]); + //gllog(77," CMD: P4TF: %d,%d %02x",lx0,ly0,baseAddr[3]); + + clutP = (gpuData[2]>>12) & 0x7fff0;//0xffff0; + setupTexture(clutP); + + if(baseAddr[3]&2){ + if(TransRate[texinfo.abr].change&&!transparent){ + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + transparent=TRUE; + } + if(baseAddr[3]&1){ + glColor4ub(255,255,255,gAlpha); + //glColor4ub(255,255,255,255); + }else{ + glColor4ub(texshade[baseAddr[0]],texshade[baseAddr[1]],texshade[baseAddr[2]],gAlpha); + } + }else{ + //if(TransRate[texinfo.abr].change&&transparent){ + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + //} + if(baseAddr[3]&1){ + glColor3ub(255,255,255); + }else{ + glColor3ub(texshade[baseAddr[0]],texshade[baseAddr[1]],texshade[baseAddr[2]]); + } + } + + //verify order, otherwise it will pick wrong texture pixel if backwards + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + + short xtest = (x1-x2)^(tx0-tx1); + if (xtest == 0) + xtest = (x1-x3)^(tx0-tx2); + if (xtest < 0) + glTranslatef(1.0f, 0, 0); + + short ytest = (y1-y2)^(ty0-ty1); + if (ytest == 0) + ytest = (y1-y3)^(ty0-ty2); + if (ytest < 0) + glTranslatef(0, 1.0f, 0); + + glBegin(GL_POLYGON); + glTexCoord2s(tx0,ty0); + glVertex2s(x1,y1); + glTexCoord2s(tx1,ty1); + glVertex2s(x2,y2); + glTexCoord2s(tx3,ty3); + glVertex2s(x4,y4); + glTexCoord2s(tx2,ty2); + glVertex2s(x3,y3); + glEnd(); + + glPopMatrix(); + + glBindTexture(GL_TEXTURE_2D,nullid); +} + +void primPolyGT3(unsigned char *baseAddr) +{ +/* + Goraud Shaded Textured Polygon 3 vertices +*/ + uint32_t *gpuData = (uint32_t *)baseAddr; + short *gpuPoint=((short *) baseAddr); + int32_t clutP; + short x1,x2,x3,y1,y2,y3; + short tx0,ty0,tx1,ty1,tx2,ty2; + unsigned short gpuDataX; + unsigned char alpha; + + x1 = (gpuPoint[2]<<21)>>21; + y1 = (gpuPoint[3]<<21)>>21; + x2 = (gpuPoint[8]<<21)>>21; + y2 = (gpuPoint[9]<<21)>>21; + x3 = (gpuPoint[14]<<21)>>21; + y3 = (gpuPoint[15]<<21)>>21; + + x1 += psxDraw.offsetX; + y1 += psxDraw.offsetY; + x2 += psxDraw.offsetX; + y2 += psxDraw.offsetY; + x3 += psxDraw.offsetX; + y3 += psxDraw.offsetY; + + + tx0 = (short)(gpuData[2] & 0xff); + ty0 = (short)((gpuData[2]>>8) & 0xff); + tx1 = (short)(gpuData[5] & 0xff); + ty1 = (short)((gpuData[5]>>8) & 0xff); + tx2 = (short)(gpuData[8] & 0xff); + ty2 = (short)((gpuData[8]>>8) & 0xff); + //gllog(77,"!GPU! P3TG %d,%d %d,%d %d,%d\n",lx0,ly0,lx1,ly1,lx2,ly2); + + gpuDataX=(unsigned short)(gpuData[5]>>16); + int32_t tempABR = (gpuDataX >> 5) & 0x3; + if(texinfo.abr!=tempABR){ + texinfo.abr = tempABR; + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + gAlpha=TransRate[texinfo.abr].alpha; + transparent=TRUE; + } + UpdateTextureInfo(gpuDataX); + + /*switch(texinfo.abr){ + case 0: + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + gAlpha=128; + break; + case 1: + glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); + gAlpha=0; + break; + case 2: + glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_COLOR); + gAlpha=0; + break; + case 3: + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + gAlpha=64; + break; + }*/ + + //gllog(77," CMD: P3TG: %d,%d TP=%d",textAddrX,textAddrY,textTP); + //gllog(77," CMD: P3TG: %d,%d %02x",lx0,ly0,baseAddr[3]); + + clutP = (gpuData[2]>>12) & 0x7fff0;//0xffff0; + setupTexture(clutP); + if(baseAddr[3]&2){ + //if(TransRate[texinfo.abr].change&&!transparent){ + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + transparent=TRUE; + //} + alpha=gAlpha; + }else{ + //if(TransRate[texinfo.abr].change&&transparent){ + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + //} + alpha=255; + } + + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + + short xtest = (x1-x2)*(tx0-tx1); + if (xtest == 0) + xtest = (x1-x3)*(tx0-tx2); + if (xtest < 0) + glTranslatef(1.0f, 0, 0); + + short ytest = (y1-y2)*(ty0-ty1); + if (ytest == 0) + ytest = (y1-y3)*(ty0-ty2); + if (ytest < 0) + glTranslatef(0, 1.0f, 0); + + glBegin(GL_POLYGON); + glColor4ub(texshade[baseAddr[0]],texshade[baseAddr[1]],texshade[baseAddr[2]],alpha); + glTexCoord2s(tx0,ty0); + glVertex2s(x1,y1); + glColor4ub(texshade[baseAddr[12]],texshade[baseAddr[13]],texshade[baseAddr[14]],alpha); + glTexCoord2s(tx1,ty1); + glVertex2s(x2,y2); + glColor4ub(texshade[baseAddr[24]],texshade[baseAddr[25]],texshade[baseAddr[26]],alpha); + glTexCoord2s(tx2,ty2); + glVertex2s(x3,y3); + glEnd(); + + glPopMatrix(); + + glBindTexture(GL_TEXTURE_2D,nullid); +} + +void primPolyGT4(unsigned char *baseAddr) +{ +/* + Goraud Shaded Textured Polygon 4 vertices +*/ + uint32_t *gpuData = (uint32_t *)baseAddr; + short *gpuPoint=((short *) baseAddr); + int32_t clutP; + short x1,y1,x2,y2,x3,y3,x4,y4; + short tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3; + unsigned short gpuDataX; + unsigned char alpha; + + x1 = (gpuPoint[2]<<21)>>21; + y1 = (gpuPoint[3]<<21)>>21; + x2 = (gpuPoint[8]<<21)>>21; + y2 = (gpuPoint[9]<<21)>>21; + x3 = (gpuPoint[14]<<21)>>21; + y3 = (gpuPoint[15]<<21)>>21; + x4 = (gpuPoint[20]<<21)>>21; + y4 = (gpuPoint[21]<<21)>>21; + + x1 += psxDraw.offsetX; + y1 += psxDraw.offsetY; + x2 += psxDraw.offsetX; + y2 += psxDraw.offsetY; + x3 += psxDraw.offsetX; + y3 += psxDraw.offsetY; + x4 += psxDraw.offsetX; + y4 += psxDraw.offsetY; + + tx0 = (short)(gpuData[2] & 0xff); + ty0 = (short)((gpuData[2]>>8) & 0xff); + tx1 = (short)(gpuData[5] & 0xff); + ty1 = (short)((gpuData[5]>>8) & 0xff); + tx2 = (short)(gpuData[8] & 0xff); + ty2 = (short)((gpuData[8]>>8) & 0xff); + tx3 = (short)(gpuData[11] & 0xff); + ty3 = (short)((gpuData[11]>>8) & 0xff); + + gpuDataX=(unsigned short)(gpuData[5]>>16); + int32_t tempABR = (gpuDataX >> 5) & 0x3; + if(texinfo.abr!=tempABR){ + texinfo.abr = tempABR; + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + gAlpha=TransRate[texinfo.abr].alpha; + transparent=TRUE; + } + UpdateTextureInfo(gpuDataX); + + /*switch(texinfo.abr){ + case 0: + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + gAlpha=128; + break; + case 1: + glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); + gAlpha=0; + break; + case 2: + glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_COLOR); + gAlpha=0; + break; + case 3: + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + gAlpha=64; + break; + }*/ + + //gllog(77," CMD: P4TG: %d,%d TP=%d",textAddrX,textAddrY,textTP); + //gllog(77," CMD: P4TG: %d,%d %02x",lx0,ly0,baseAddr[3]); + + clutP = (gpuData[2]>>12) & 0x7fff0;//0xffff0; + setupTexture(clutP); + if(baseAddr[3]&2){ + //if(TransRate[texinfo.abr].change&&!transparent){ + glBlendFunc(TransRate[texinfo.abr].src,TransRate[texinfo.abr].dst); + transparent=TRUE; + //} + alpha=gAlpha; + }else{ + //if(TransRate[texinfo.abr].change&&transparent){ + glBlendFunc(TransRate[0].src,TransRate[0].dst); + transparent=FALSE; + //} + alpha=255; + } + + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + + short xtest = (x1-x2)*(tx0-tx1); + if (xtest == 0) + xtest = (x1-x3)*(tx0-tx2); + if (xtest < 0) + glTranslatef(1.0f, 0, 0); + + short ytest = (y1-y2)*(ty0-ty1); + if (ytest == 0) + ytest = (y1-y3)*(ty0-ty2); + if (ytest < 0) + glTranslatef(0, 1.0f, 0); + + glBegin(GL_POLYGON); + glColor4ub(texshade[baseAddr[0]],texshade[baseAddr[1]],texshade[baseAddr[2]],alpha); + glTexCoord2s(tx0,ty0); + glVertex2s(x1,y1); + glColor4ub(texshade[baseAddr[12]],texshade[baseAddr[13]],texshade[baseAddr[14]],alpha); + glTexCoord2s(tx1,ty1); + glVertex2s(x2,y2); + glColor4ub(texshade[baseAddr[36]],texshade[baseAddr[37]],texshade[baseAddr[38]],alpha); + glTexCoord2s(tx3,ty3); + glVertex2s(x4,y4); + glColor4ub(texshade[baseAddr[24]],texshade[baseAddr[25]],texshade[baseAddr[26]],alpha); + glTexCoord2s(tx2,ty2); + glVertex2s(x3,y3); + glEnd(); + + glPopMatrix(); + + glBindTexture(GL_TEXTURE_2D,nullid); +} + + +void primNI(unsigned char *bA) +{ + // primitive not implemented + if (bA[3]) gllog(255,"PRIM: *NI* %02x",bA[3]); +} + + +unsigned char primTableC[256] = +{ + // 00 + 0,0,3,0,0,0,0,0, + // 08 + 0,0,0,0,0,0,0,0, + // 10 + 0,0,0,0,0,0,0,0, + // 18 + 0,0,0,0,0,0,0,0, + // 20 + 4,4,4,4,7,7,7,7, + // 28 + 5,5,5,5,9,9,9,9, + // 30 + 6,6,6,6,9,9,9,9, + // 38 + 8,8,8,8,12,12,12,12, + // 40 + 3,3,3,3,0,0,0,0, // LineF2 + // 48 + 5,5,5,5,6,6,6,6, // LineF3 LineF4 + // 50 + 4,4,4,4,0,0,0,0, // LineG2 + // 58 + 7,7,7,7,9,9,9,9, // LineG3 LineG4 + // 60 + 3,3,3,3,4,4,4,4, // Tile Sprt + // 68 + 2,2,2,2,0,0,0,0, // Tile1 + // 70 + 2,2,2,2,3,3,3,3, // Tile8 Sprt8 + // 78 + 2,2,2,2,3,3,3,3, // Tile16 Sprt16 + // 80 + 4,0,0,0,0,0,0,0, + // 88 + 0,0,0,0,0,0,0,0, + // 90 + 0,0,0,0,0,0,0,0, + // 98 + 0,0,0,0,0,0,0,0, + // a0 + 3,0,0,0,0,0,0,0, + // a8 + 0,0,0,0,0,0,0,0, + // b0 + 0,0,0,0,0,0,0,0, + // b8 + 0,0,0,0,0,0,0,0, + // c0 + 3,0,0,0,0,0,0,0, + // c8 + 0,0,0,0,0,0,0,0, + // d0 + 0,0,0,0,0,0,0,0, + // d8 + 0,0,0,0,0,0,0,0, + // e0 + 0,1,1,1,1,1,1,0, + // e8 + 0,0,0,0,0,0,0,0, + // f0 + 0,0,0,0,0,0,0,0, + // f8 + 0,0,0,0,0,0,0,0 + +}; + +void (*primTableJ[256])(unsigned char *) = +{ + // 00 + primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI, + // 08 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 10 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 18 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 20 + primPolyF3,primPolyF3,primPolyF3,primPolyF3,primPolyFT3,primPolyFT3,primPolyFT3,primPolyFT3, + // 28 + primPolyF4,primPolyF4,primPolyF4,primPolyF4,primPolyFT4,primPolyFT4,primPolyFT4,primPolyFT4, + // 30 + primPolyG3,primPolyG3,primPolyG3,primPolyG3,primPolyGT3,primPolyGT3,primPolyGT3,primPolyGT3, + // 38 + primPolyG4,primPolyG4,primPolyG4,primPolyG4,primPolyGT4,primPolyGT4,primPolyGT4,primPolyGT4, + // 40 + primLineF2,primLineF2,primLineF2,primLineF2,primNI,primNI,primNI,primNI, + // 48 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 50 + primLineG2,primLineG2,primLineG2,primLineG2,primNI,primNI,primNI,primNI, + // 58 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 60 + primTileS,primTileS,primTileS,primTileS,primSprtS,primSprtS,primSprtS,primSprtS, + // 68 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 70 + primNI,primNI,primNI,primNI,primSprt8,primSprt8,primSprt8,primSprt8, + // 78 + primNI,primNI,primNI,primNI,primSprt16,primSprt16,primSprt16,primSprt16, + // 80 + primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 88 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 90 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 98 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a0 + primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c0 + primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // e0 + primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI, + // e8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI +}; + diff --git a/plugins/dfOpenGL/primitive_drawing.h b/plugins/dfOpenGL/primitive_drawing.h new file mode 100644 index 00000000..5e97c7b6 --- /dev/null +++ b/plugins/dfOpenGL/primitive_drawing.h @@ -0,0 +1,3 @@ + +extern unsigned char primTableC[256]; +extern void (*primTableJ[256])(unsigned char *); diff --git a/plugins/dfcdrom/Makefile.am b/plugins/dfcdrom/Makefile.am new file mode 100644 index 00000000..41949526 --- /dev/null +++ b/plugins/dfcdrom/Makefile.am @@ -0,0 +1,18 @@ +bindir = @libdir@/games/psemu/ +libdir = @libdir@/games/psemu/ + +lib_LTLIBRARIES = libDFCdrom.la + +libDFCdrom_la_SOURCES = cdr.c cfg.c +libDFCdrom_la_LDFLAGS = -module -avoid-version -lpthread + +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) \ + -DREVISION=1 -DBUILD=0 \ + -I../../libpcsxcore + +bin_PROGRAMS = cfgDFCdrom +cfgDFCdrom_SOURCES = cfg-gtk2.c main.c support.c interface.c callbacks.c +cfgDFCdrom_LDADD = $(GTK2_LIBS) diff --git a/plugins/dfcdrom/Makefile.in b/plugins/dfcdrom/Makefile.in new file mode 100644 index 00000000..be7449a5 --- /dev/null +++ b/plugins/dfcdrom/Makefile.in @@ -0,0 +1,562 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = cfgDFCdrom$(EXEEXT) +subdir = plugins/dfcdrom +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libDFCdrom_la_LIBADD = +am_libDFCdrom_la_OBJECTS = cdr.lo cfg.lo +libDFCdrom_la_OBJECTS = $(am_libDFCdrom_la_OBJECTS) +libDFCdrom_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libDFCdrom_la_LDFLAGS) $(LDFLAGS) -o $@ +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_cfgDFCdrom_OBJECTS = cfg-gtk2.$(OBJEXT) main.$(OBJEXT) \ + support.$(OBJEXT) interface.$(OBJEXT) callbacks.$(OBJEXT) +cfgDFCdrom_OBJECTS = $(am_cfgDFCdrom_OBJECTS) +am__DEPENDENCIES_1 = +cfgDFCdrom_DEPENDENCIES = $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libDFCdrom_la_SOURCES) $(cfgDFCdrom_SOURCES) +DIST_SOURCES = $(libDFCdrom_la_SOURCES) $(cfgDFCdrom_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFOPENGL = @DFOPENGL@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADE2_CFLAGS = @GLADE2_CFLAGS@ +GLADE2_LIBS = @GLADE2_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTK2_CFLAGS = @GTK2_CFLAGS@ +GTK2_LIBS = @GTK2_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NASM = @NASM@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @libdir@/games/psemu/ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@/games/psemu/ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +lib_LTLIBRARIES = libDFCdrom.la +libDFCdrom_la_SOURCES = cdr.c cfg.c +libDFCdrom_la_LDFLAGS = -module -avoid-version -lpthread +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) \ + -DREVISION=1 -DBUILD=0 \ + -I../../libpcsxcore + +cfgDFCdrom_SOURCES = cfg-gtk2.c main.c support.c interface.c callbacks.c +cfgDFCdrom_LDADD = $(GTK2_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/dfcdrom/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/dfcdrom/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libDFCdrom.la: $(libDFCdrom_la_OBJECTS) $(libDFCdrom_la_DEPENDENCIES) + $(libDFCdrom_la_LINK) -rpath $(libdir) $(libDFCdrom_la_OBJECTS) $(libDFCdrom_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +cfgDFCdrom$(EXEEXT): $(cfgDFCdrom_OBJECTS) $(cfgDFCdrom_DEPENDENCIES) + @rm -f cfgDFCdrom$(EXEEXT) + $(LINK) $(cfgDFCdrom_OBJECTS) $(cfgDFCdrom_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callbacks.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg-gtk2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interface.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/support.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-binPROGRAMS uninstall-libLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/dfcdrom/callbacks.c b/plugins/dfcdrom/callbacks.c new file mode 100644 index 00000000..09f72f63 --- /dev/null +++ b/plugins/dfcdrom/callbacks.c @@ -0,0 +1,210 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef __linux__ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <linux/cdrom.h> + +#include <gtk/gtk.h> + +#include "cdr.h" +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +/* list of drives */ +GList * driveslist = NULL; + +/* private functions prototypes */ +void fill_drives_list(void); +int is_cdrom(char *device); + + +/*************************************************************************** + * Config Dialog. + ***************************************************************************/ + +void on_cfg_dialog_show (GtkWidget *widget, gpointer user_data) +{ + GtkWidget *devcombo; + GtkWidget *rmmenu; + GtkWidget *subQbtn; + GtkWidget *spinC; + GtkWidget *spinS; + + LoadConf(); + fill_drives_list(); + + devcombo = lookup_widget (GTK_WIDGET (widget), "cddev_combo"); + rmmenu = lookup_widget (GTK_WIDGET (widget), "readmode_optionmenu"); + subQbtn = lookup_widget (GTK_WIDGET (widget), "subQ_button"); + spinC = lookup_widget (GTK_WIDGET (widget), "spinCacheSize"); + spinS = lookup_widget (GTK_WIDGET (widget), "spinCdrSpeed"); + + /* show values */ + gtk_combo_set_popdown_strings (GTK_COMBO (devcombo), driveslist); + gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (devcombo)->entry), CdromDev); + gtk_option_menu_set_history (GTK_OPTION_MENU (rmmenu), ReadMode); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (subQbtn), UseSubQ); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(spinC), (float)CacheSize); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(spinS), (float)CdrSpeed); + + /* ??? is correct to free? it's a global... */ + g_list_free(driveslist); +} + + +void on_cfg_cancelbutton_clicked (GtkButton *button, gpointer user_data) +{ + gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (button))); + gtk_main_quit(); +} + + +void on_cfg_okbutton_clicked (GtkButton *button, gpointer user_data) +{ + GtkWidget *deventry; + GtkWidget *rmmenu; + GtkWidget *subQbtn; + GtkWidget *spinC; + GtkWidget *spinS; + char *tmp; + + deventry = lookup_widget (GTK_WIDGET (button), "cddev_entry"); + rmmenu = lookup_widget (GTK_WIDGET (button), "readmode_optionmenu"); + subQbtn = lookup_widget (GTK_WIDGET (button), "subQ_button"); + spinC = lookup_widget (GTK_WIDGET (button), "spinCacheSize"); + spinS = lookup_widget (GTK_WIDGET (button), "spinCdrSpeed"); + + tmp = gtk_entry_get_text (GTK_ENTRY (deventry)); + strcpy(CdromDev, tmp); + ReadMode = gtk_option_menu_get_history (GTK_OPTION_MENU(rmmenu)); + UseSubQ = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(subQbtn)); + CacheSize= gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinC)); + CdrSpeed = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinS)); + + SaveConf(); + + gtk_widget_destroy(gtk_widget_get_toplevel (GTK_WIDGET (button))); + gtk_main_quit(); +} + + +/*************************************************************************** + * About Dialog. + ***************************************************************************/ + +void on_abt_okbutton_clicked (GtkButton *button, gpointer user_data) +{ + gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (button))); + gtk_main_quit(); +} + + +/*************************************************************************** + * Private functions. + ***************************************************************************/ + +/* + * get_drives_list: retrieves available cd drives. At the moment it use a quite + * ugly "brute force" method: we check for the most common location for cdrom + * in /dev and chech if they are cdrom devices. + * If your cdrom path is not listed here you'll have to type it in the dialog + * entry yourself (or add it here and recompile). + * Are there any other common entry to add to the list? (especially scsi, I + * deliberately ignored old non standard cdroms... ) + * If you come up with a better method let me know!! + */ + +void fill_drives_list(void) +{ + int i = 0; + static char *cdrom_devices[]={ + "/dev/cdrom", + "/dev/cdroms/cdrom0", + "/dev/cdroms/cdrom1", + "/dev/cdroms/cdrom2", + "/dev/cdroms/cdrom3", + "/dev/hda", + "/dev/hdb", + "/dev/hdc", + "/dev/hdd", + "/dev/scd0", + "/dev/scd1", + "/dev/scd2", + "/dev/scd3", + "/dev/optcd", + NULL}; + + /* fisrt we put our current drive */ + driveslist = g_list_append(driveslist, CdromDev); + + /* scan cdrom_devices for real cdrom and add them to driveslist */ + while(cdrom_devices[i] != NULL){ + + /* check that is not our current dev (already in list) */ + if (strcmp(cdrom_devices[i], CdromDev) != 0){ + + /* check that is a cdrom device */ + if (is_cdrom(cdrom_devices[i])){ + driveslist = g_list_append(driveslist, cdrom_devices[i]); + } + } + ++i; + } + + return; +} + + +/* function to check if the device is a cdrom */ +int is_cdrom(char *device){ + struct stat st; + int fd = -1; + + /* check if the file exist */ + if (stat(device, &st) <0) return 0; + + /* check if is a block or char device */ + if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) return 0; + + /* try to open the device file descriptor */ + if ((fd = open(device, O_RDONLY | O_NONBLOCK)) < 0) return 0; + + /* I need a method to check is a device is really a cdrom. + some problems/ideas are: + - different protocls (ide, scsi, old proprietary...) + - maybe we can use major number (see linux/major.h) to do some check. + major number can be retrieved with (st.st_rdev>>8) + scsi has SCSI_CDROM_MAJOR but does this cover all scsi drives? + beside IDE major is the same for hard disks and cdroms... + and DVDs? + - another idea is to parse /proc, but again IDE, scsi etc have + different files... I've not found a way to query "which cd drives + are available?" + + Now I use this ioctl which works also if the drive is empty, + I hope that is implemented for all the drives... here works + fine: at least doesn't let me to select my HD as cds ;) + */ + /* try a ioctl to see if it's a cdrom device */ + if (ioctl(fd, CDROM_GET_CAPABILITY, NULL) < 0){ + close(fd); + return 0; + } + + close(fd); + + /* yes, it seems a cd drive! */ + return 1; +} + +#endif diff --git a/plugins/dfcdrom/callbacks.h b/plugins/dfcdrom/callbacks.h new file mode 100644 index 00000000..622914d9 --- /dev/null +++ b/plugins/dfcdrom/callbacks.h @@ -0,0 +1,18 @@ +#include <gtk/gtk.h> + + +void +on_cfg_dialog_show (GtkWidget *widget, + gpointer user_data); + +void +on_cfg_cancelbutton_clicked (GtkButton *button, + gpointer user_data); + +void +on_cfg_okbutton_clicked (GtkButton *button, + gpointer user_data); + +void +on_abt_okbutton_clicked (GtkButton *button, + gpointer user_data); diff --git a/plugins/dfcdrom/cdr.c b/plugins/dfcdrom/cdr.c new file mode 100644 index 00000000..4649ff62 --- /dev/null +++ b/plugins/dfcdrom/cdr.c @@ -0,0 +1,636 @@ +/* + * Cdrom for Psemu Pro like Emulators + * + * By: linuzappz <linuzappz@hotmail.com> + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <unistd.h> +#include <pthread.h> +#include <time.h> +#include <string.h> + +#include "cdr.h" + +#ifdef __linux__ + +static inline int msf_to_lba(char m, char s, char f) { + return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET; +} + +pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + +long (*ReadTrackT[])() = { + ReadNormal, + ReadThreaded, +}; + +unsigned char* (*GetBufferT[])() = { + GetBNormal, + GetBThreaded, +}; + +long (*fReadTrack)(); +unsigned char* (*fGetBuffer)(); + +void *CdrThread(void *arg); + +char *LibName = "CD-ROM Drive Reader"; + +#else + +char *LibName = "CDR NULL Plugin"; + +#endif + +const unsigned char version = 1; // PSEmu 1.x library +const unsigned char revision = VERSION; +const unsigned char build = BUILD; + +char *PSEgetLibName(void) { + return LibName; +} + +unsigned long PSEgetLibType(void) { + return PSE_LT_CDR; +} + +unsigned long PSEgetLibVersion(void) { + return version << 16 | revision << 8 | build; +} + +#ifdef __linux__ + +long CDRinit(void) { + cdHandle = -1; + thread = -1; + + return 0; +} + +long CDRshutdown(void) { + return 0; +} + +long CDRopen(void) { + LoadConf(); + + if (cdHandle > 0) + return 0; /* it's already open */ + cdHandle = open(CdromDev, O_RDONLY); + if (cdHandle != -1) { // if we can't open the cdrom we'll works as a null plugin + ioctl(cdHandle, CDROM_LOCKDOOR, 0); +// ioctl(cdHandle, CDROMSTART, NULL); + + ioctl(cdHandle, CDROM_SELECT_SPEED, CdrSpeed); + } else { + fprintf(stderr, "CDR: Could not open %s\n", CdromDev); + } + + fReadTrack = ReadTrackT[ReadMode]; + fGetBuffer = GetBufferT[ReadMode]; + + if (ReadMode == THREADED) { + cdcache = (CacheData *)malloc(CacheSize * sizeof(CacheData)); + if (cdcache == NULL) return -1; + memset(cdcache, 0, CacheSize * sizeof(CacheData)); + } else { + cdbuffer = cr.buf + 12; /* skip sync data */ + } + + if (ReadMode == THREADED) { + pthread_attr_t attr; + + pthread_mutex_init(&mut, NULL); + pthread_cond_init(&cond, NULL); + locked = 0; + + pthread_attr_init(&attr); + pthread_create(&thread, &attr, CdrThread, NULL); + + cacheaddr = -1; + } else thread = -1; + + playing = 0; + stopth = 0; + + return 0; +} + +long CDRclose(void) { + if (cdHandle < 1) return 0; + + if (playing) CDRstop(); + close(cdHandle); + cdHandle = -1; + + if (thread != -1) { + if (locked == 0) { + stopth = 1; + while (locked == 0) usleep(5000); + } + + stopth = 2; + pthread_mutex_lock(&mut); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mut); + + pthread_join(thread, NULL); + pthread_mutex_destroy(&mut); + pthread_cond_destroy(&cond); + } + + if (ReadMode == THREADED) { + free(cdcache); + } + + return 0; +} + +// return Starting and Ending Track +// buffer: +// byte 0 - start track +// byte 1 - end track +long CDRgetTN(unsigned char *buffer) { + struct cdrom_tochdr toc; + + if (cdHandle < 1) { + buffer[0] = 1; + buffer[1] = 1; + return 0; + } + + if (ioctl(cdHandle, CDROMREADTOCHDR, &toc) == -1) + return -1; + + buffer[0] = toc.cdth_trk0; // start track + buffer[1] = toc.cdth_trk1; // end track + + return 0; +} + +// return Track Time +// buffer: +// byte 0 - frame +// byte 1 - second +// byte 2 - minute +long CDRgetTD(unsigned char track, unsigned char *buffer) { + struct cdrom_tocentry entry; + + if (cdHandle < 1) { + memset(buffer + 1, 0, 3); + return 0; + } + + if (track == 0) + track = 0xaa; // total time + entry.cdte_track = track; + entry.cdte_format = CDROM_MSF; + + if (ioctl(cdHandle, CDROMREADTOCENTRY, &entry) == -1) + return -1; + + buffer[0] = entry.cdte_addr.msf.frame; /* frame */ + buffer[1] = entry.cdte_addr.msf.second; /* second */ + buffer[2] = entry.cdte_addr.msf.minute; /* minute */ + + return 0; +} + +// normal reading +long ReadNormal() { + if (ioctl(cdHandle, CDROMREADRAW, &cr) == -1) + return -1; + + return 0; +} + +unsigned char* GetBNormal() { + return cdbuffer; +} + +// threaded reading (with cache) +long ReadThreaded() { + int addr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0); + int i; + + if (addr >= cacheaddr && addr < (cacheaddr + CacheSize) && + cacheaddr != -1) { + i = addr - cacheaddr; +// printf("found %d\n", (addr - cacheaddr)); + cdbuffer = cdcache[i].cr.buf + 12; + while (btoi(cdbuffer[0]) != cr.msf.cdmsf_min0 || + btoi(cdbuffer[1]) != cr.msf.cdmsf_sec0 || + btoi(cdbuffer[2]) != cr.msf.cdmsf_frame0) { + if (locked == 1) { + if (cdcache[i].ret == 0) break; + return -1; + } + usleep(5000); + } +// printf("%x:%x:%x, %p, %p\n", cdbuffer[0], cdbuffer[1], cdbuffer[2], cdbuffer, cdcache); + found = 1; + + return 0; + } else found = 0; + + if (locked == 0) { + stopth = 1; + while (locked == 0) { usleep(5000); } + stopth = 0; + } + + // not found in cache + locked = 0; + pthread_mutex_lock(&mut); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mut); + + return 0; +} + +unsigned char* GetBThreaded() { +// printf("threadc %d\n", found); + if (found == 1) { found = 0; return cdbuffer; } + cdbuffer = cdcache[0].cr.buf + 12; + while (btoi(cdbuffer[0]) != cr.msf.cdmsf_min0 || + btoi(cdbuffer[1]) != cr.msf.cdmsf_sec0 || + btoi(cdbuffer[2]) != cr.msf.cdmsf_frame0) { + if (locked == 1) return NULL; + usleep(5000); + } + if (cdcache[0].ret == -1) return NULL; + + return cdbuffer; +} + + +// read track +// time: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame +// uses bcd format +long CDRreadTrack(unsigned char *time) { + if (cdHandle < 1) { + memset(cr.buf, 0, DATA_SIZE); + return 0; + } + +// printf("CDRreadTrack %d:%d:%d\n", btoi(time[0]), btoi(time[1]), btoi(time[2])); + + if (UseSubQ) memcpy(lastTime, time, 3); + subqread = 0; + + cr.msf.cdmsf_min0 = btoi(time[0]); + cr.msf.cdmsf_sec0 = btoi(time[1]); + cr.msf.cdmsf_frame0 = btoi(time[2]); + + return fReadTrack(); +} + +void *CdrThread(void *arg) { + unsigned char curTime[3]; + int i; + + for (;;) { + locked = 1; + pthread_mutex_lock(&mut); + pthread_cond_wait(&cond, &mut); + + if (stopth == 2) pthread_exit(NULL); + // refill the buffer + cacheaddr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0); + + memcpy(curTime, &cr.msf, 3); + +// printf("start thc %d:%d:%d\n", curTime[0], curTime[1], curTime[2]); + + for (i=0; i<CacheSize; i++) { + memcpy(&cdcache[i].cr.msf, curTime, 3); +// printf("reading %d:%d:%d\n", crp.msf.cdmsf_min0, crp.msf.cdmsf_sec0, crp.msf.cdmsf_frame0); + cdcache[i].ret = ioctl(cdHandle, CDROMREADRAW, &cdcache[i].cr); + +// printf("readed %x:%x:%x\n", crd.buf[12], crd.buf[13], crd.buf[14]); + if (cdcache[i].ret == -1) break; + + curTime[2]++; + if (curTime[2] == 75) { + curTime[2] = 0; + curTime[1]++; + if (curTime[1] == 60) { + curTime[1] = 0; + curTime[0]++; + } + } + + if (stopth) break; + } + + pthread_mutex_unlock(&mut); + } + + return NULL; +} + +// return readed track +unsigned char *CDRgetBuffer(void) { + return fGetBuffer(); +} + +// plays cdda audio +// sector: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame +// does NOT uses bcd format +long CDRplay(unsigned char *sector) { + struct cdrom_msf addr; + unsigned char ptmp[4]; + + if (cdHandle < 1) + return 0; + + // 0 is the last track of every cdrom, so play up to there + if (CDRgetTD(0, ptmp) == -1) + return -1; + addr.cdmsf_min0 = sector[0]; + addr.cdmsf_sec0 = sector[1]; + addr.cdmsf_frame0 = sector[2]; + addr.cdmsf_min1 = ptmp[2]; + addr.cdmsf_sec1 = ptmp[1]; + addr.cdmsf_frame1 = ptmp[0]; + + if (ioctl(cdHandle, CDROMPLAYMSF, &addr) == -1) + return -1; + + playing = 1; + + return 0; +} + +// stops cdda audio +long CDRstop(void) { + struct cdrom_subchnl sc; + + if (cdHandle < 1) + return 0; + + sc.cdsc_format = CDROM_MSF; + if (ioctl(cdHandle, CDROMSUBCHNL, &sc) == -1) + return -1; + + switch (sc.cdsc_audiostatus) { + case CDROM_AUDIO_PAUSED: + case CDROM_AUDIO_PLAY: + ioctl(cdHandle, CDROMSTOP); + break; + } + + playing = 0; + + return 0; +} + +struct CdrStat { + unsigned long Type; + unsigned long Status; + unsigned char Time[3]; // current playing time +}; + +struct CdrStat ostat; + +// reads cdr status +// type: +// 0x00 - unknown +// 0x01 - data +// 0x02 - audio +// 0xff - no cdrom +// status: (only shell open supported) +// 0x00 - unknown +// 0x01 - error +// 0x04 - seek error +// 0x10 - shell open +// 0x20 - reading +// 0x40 - seeking +// 0x80 - playing +// time: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame + +long CDRgetStatus(struct CdrStat *stat) { + struct cdrom_subchnl sc; + int ret; + static time_t to; + + if (cdHandle < 1) + return -1; + + if (!playing) { // if not playing update stat only once in a second + if (to < time(NULL)) { + to = time(NULL); + } else { + memcpy(stat, &ostat, sizeof(struct CdrStat)); + return 0; + } + } + + memset(stat, 0, sizeof(struct CdrStat)); + + if (playing) { // return Time only if playing + sc.cdsc_format = CDROM_MSF; + if (ioctl(cdHandle, CDROMSUBCHNL, &sc) != -1) + memcpy(stat->Time, &sc.cdsc_absaddr.msf, 3); + } + + ret = ioctl(cdHandle, CDROM_DISC_STATUS); + switch (ret) { + case CDS_AUDIO: + stat->Type = 0x02; + break; + case CDS_DATA_1: + case CDS_DATA_2: + case CDS_XA_2_1: + case CDS_XA_2_2: + stat->Type = 0x01; + break; + } + ret = ioctl(cdHandle, CDROM_DRIVE_STATUS); + switch (ret) { + case CDS_NO_DISC: + case CDS_TRAY_OPEN: + stat->Type = 0xff; + stat->Status |= 0x10; + break; + default: + ioctl(cdHandle, CDROM_LOCKDOOR, 0); + break; + } + + switch (sc.cdsc_audiostatus) { + case CDROM_AUDIO_PLAY: + stat->Status |= 0x80; + break; + } + + memcpy(&ostat, stat, sizeof(struct CdrStat)); + + return 0; +} + +struct SubQ { + char res0[11]; + unsigned char ControlAndADR; + unsigned char TrackNumber; + unsigned char IndexNumber; + unsigned char TrackRelativeAddress[3]; + unsigned char Filler; + unsigned char AbsoluteAddress[3]; + char res1[72]; +}; + +struct SubQ subq; + +unsigned char *CDRgetBufferSub(void) { + struct cdrom_subchnl subchnl; + int ret; + + if (!UseSubQ) return NULL; + + if (subqread) return (unsigned char *)&subq; + + cr.msf.cdmsf_min0 = btoi(lastTime[0]); + cr.msf.cdmsf_sec0 = btoi(lastTime[1]); + cr.msf.cdmsf_frame0 = btoi(lastTime[2]); + if (ioctl(cdHandle, CDROMSEEK, &cr.msf) == -1) { + // will be slower, but there's no other way to make it accurate + if (ioctl(cdHandle, CDROMREADRAW, &cr) == -1) return NULL; + } + + subchnl.cdsc_format = CDROM_MSF; + ret = ioctl(cdHandle, CDROMSUBCHNL, &subchnl); + if (ret == -1) return NULL; + + subqread = 1; + + subq.TrackNumber = subchnl.cdsc_trk; + subq.IndexNumber = subchnl.cdsc_ind; + subq.TrackRelativeAddress[0] = itob(subchnl.cdsc_reladdr.msf.minute); + subq.TrackRelativeAddress[1] = itob(subchnl.cdsc_reladdr.msf.second); + subq.TrackRelativeAddress[2] = itob(subchnl.cdsc_reladdr.msf.frame); + subq.AbsoluteAddress[0] = itob(subchnl.cdsc_absaddr.msf.minute); + subq.AbsoluteAddress[1] = itob(subchnl.cdsc_absaddr.msf.second); + subq.AbsoluteAddress[2] = itob(subchnl.cdsc_absaddr.msf.frame); + +#if 0 + printf("subq : %x,%x : %x,%x,%x : %x,%x,%x\n", + subchnl.cdsc_trk, subchnl.cdsc_ind, + itob(subchnl.cdsc_reladdr.msf.minute), itob(subchnl.cdsc_reladdr.msf.second), itob(subchnl.cdsc_reladdr.msf.frame), + itob(subchnl.cdsc_absaddr.msf.minute), itob(subchnl.cdsc_absaddr.msf.second), itob(subchnl.cdsc_absaddr.msf.frame)); +#endif + + return (unsigned char *)&subq; +} + +void ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgDFCdrom"); + if (stat(cfg, &buf) != -1) { + strcat(cfg, " "); + strcat(cfg, arg); + system(cfg); + return; + } + + strcpy(cfg, "./cfg/DFCdrom"); + if (stat(cfg, &buf) != -1) { + strcat(cfg, " "); + strcat(cfg, arg); + system(cfg); + return; + } + + printf("cfgDFCdrom file not found!\n"); +} + +long CDRconfigure() { + ExecCfg("configure"); + + return 0; +} + +void CDRabout() { + ExecCfg("about"); +} + +long CDRtest(void) { + cdHandle = open(CdromDev, O_RDONLY); + if (cdHandle == -1) + return -1; + close(cdHandle); + cdHandle = -1; + return 0; +} + +#else + +long CDRinit(void) { + return 0; +} + +long CDRshutdown(void) { + return 0; +} + +long CDRopen(void) { + return 0; +} + +long CDRclose(void) { + return 0; +} + +long CDRgetTN(unsigned char *buffer) { + buffer[0] = 1; + buffer[1] = 1; + return 0; +} + +long CDRgetTD(unsigned char track, unsigned char *buffer) { + memset(buffer + 1, 0, 3); + return 0; +} + +long CDRreadTrack(unsigned char *time) { + return -1; +} + +unsigned char *CDRgetBuffer(void) { + return NULL; +} + +long CDRplay(unsigned char *sector) { + return 0; +} + +long CDRstop(void) { + return 0; +} + +long CDRconfigure() { + return 0; +} + +void CDRabout() { +} + +#endif diff --git a/plugins/dfcdrom/cdr.h b/plugins/dfcdrom/cdr.h new file mode 100644 index 00000000..1f9afbaa --- /dev/null +++ b/plugins/dfcdrom/cdr.h @@ -0,0 +1,68 @@ +#ifndef __CDR_H__ +#define __CDR_H__ + +#ifdef __linux__ +#include <linux/cdrom.h> +#endif + +typedef char HWND; + +#include <stdint.h> +#include "psemu_plugin_defs.h" + +char CdromDev[256]; +long ReadMode; +long UseSubQ; +long CacheSize; +long CdrSpeed; + +#define VERSION 1 + +#ifdef __linux__ + +#define DEV_DEF "/dev/cdrom" +#define NORMAL 0 +#define THREADED 1 +#define READ_MODES 2 + +#define DATA_SIZE (CD_FRAMESIZE_RAW-12) + +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ + +typedef union { + struct cdrom_msf msf; + unsigned char buf[CD_FRAMESIZE_RAW]; +} crdata; + +crdata cr; + +typedef struct { + crdata cr; + int ret; +} CacheData; + +CacheData *cdcache; +unsigned char *cdbuffer; +int cacheaddr; + +unsigned char lastTime[3]; +int cdHandle; +pthread_t thread; +int subqread, stopth; +int found, locked; +int playing; + +long ReadNormal(); +long ReadThreaded(); +unsigned char* GetBNormal(); +unsigned char* GetBThreaded(); + +long CDRstop(void); + +void LoadConf(); +void SaveConf(); + +#endif + +#endif /* __CDR_H__ */ diff --git a/plugins/dfcdrom/cfg-gtk2.c b/plugins/dfcdrom/cfg-gtk2.c new file mode 100644 index 00000000..ac3e829a --- /dev/null +++ b/plugins/dfcdrom/cfg-gtk2.c @@ -0,0 +1,62 @@ +/* + * Cdrom for Psemu Pro like Emulators + * + * By: linuzappz <linuzappz@hotmail.com> + * + */ + +#ifdef __linux__ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> +#include <time.h> +#include <string.h> + +#include "cdr.h" + +void LoadConf() { + FILE *f; + char cfg[255]; + + strcpy(CdromDev, DEV_DEF); + ReadMode = THREADED; + UseSubQ = 0; + CacheSize = 64; + CdrSpeed = 0; + + sprintf(cfg, "dfcdrom.cfg"); + f = fopen(cfg, "r"); + if (f == NULL) return; + + fscanf(f, "CdromDev = %s\n", CdromDev); + fscanf(f, "ReadMode = %ld\n", &ReadMode); + fscanf(f, "UseSubQ = %ld\n", &UseSubQ); + fscanf(f, "CacheSize = %ld\n", &CacheSize); + fscanf(f, "CdrSpeed = %ld\n", &CdrSpeed); + fclose(f); + + if (ReadMode >= READ_MODES) ReadMode = THREADED; + if (CacheSize <= 0) CacheSize = 32; + if (CacheSize > 2048) CacheSize = 2048; +} + +void SaveConf() { + FILE *f; + char cfg[255]; + + sprintf(cfg, "dfcdrom.cfg"); + f = fopen(cfg, "w"); + if (f == NULL) + return; + fprintf(f, "CdromDev = %s\n", CdromDev); + fprintf(f, "ReadMode = %ld\n", ReadMode); + fprintf(f, "UseSubQ = %ld\n", UseSubQ); + fprintf(f, "CacheSize = %ld\n", CacheSize); + fprintf(f, "CdrSpeed = %ld\n", CdrSpeed); + fclose(f); +} + +#endif diff --git a/plugins/dfcdrom/cfg.c b/plugins/dfcdrom/cfg.c new file mode 100644 index 00000000..ac3e829a --- /dev/null +++ b/plugins/dfcdrom/cfg.c @@ -0,0 +1,62 @@ +/* + * Cdrom for Psemu Pro like Emulators + * + * By: linuzappz <linuzappz@hotmail.com> + * + */ + +#ifdef __linux__ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> +#include <time.h> +#include <string.h> + +#include "cdr.h" + +void LoadConf() { + FILE *f; + char cfg[255]; + + strcpy(CdromDev, DEV_DEF); + ReadMode = THREADED; + UseSubQ = 0; + CacheSize = 64; + CdrSpeed = 0; + + sprintf(cfg, "dfcdrom.cfg"); + f = fopen(cfg, "r"); + if (f == NULL) return; + + fscanf(f, "CdromDev = %s\n", CdromDev); + fscanf(f, "ReadMode = %ld\n", &ReadMode); + fscanf(f, "UseSubQ = %ld\n", &UseSubQ); + fscanf(f, "CacheSize = %ld\n", &CacheSize); + fscanf(f, "CdrSpeed = %ld\n", &CdrSpeed); + fclose(f); + + if (ReadMode >= READ_MODES) ReadMode = THREADED; + if (CacheSize <= 0) CacheSize = 32; + if (CacheSize > 2048) CacheSize = 2048; +} + +void SaveConf() { + FILE *f; + char cfg[255]; + + sprintf(cfg, "dfcdrom.cfg"); + f = fopen(cfg, "w"); + if (f == NULL) + return; + fprintf(f, "CdromDev = %s\n", CdromDev); + fprintf(f, "ReadMode = %ld\n", ReadMode); + fprintf(f, "UseSubQ = %ld\n", UseSubQ); + fprintf(f, "CacheSize = %ld\n", CacheSize); + fprintf(f, "CdrSpeed = %ld\n", CdrSpeed); + fclose(f); +} + +#endif diff --git a/plugins/dfcdrom/cfgCdr.glade b/plugins/dfcdrom/cfgCdr.glade new file mode 100644 index 00000000..60fa04af --- /dev/null +++ b/plugins/dfcdrom/cfgCdr.glade @@ -0,0 +1,549 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkDialog" id="cfg_dialog"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="title" translatable="yes">CDR configuration</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_CENTER</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="has_separator">False</property> + <signal name="show" handler="on_cfg_dialog_show" last_modification_time="Mon, 18 Nov 2002 09:56:37 GMT"/> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="cfg_dialog-action_area"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="cfg_cancelbutton"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-6</property> + <signal name="clicked" handler="on_cfg_cancelbutton_clicked" last_modification_time="Sat, 16 Nov 2002 19:25:24 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="cfg_okbutton"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-5</property> + <signal name="clicked" handler="on_cfg_okbutton_clicked" last_modification_time="Sat, 16 Nov 2002 19:58:18 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkFrame" id="frame1"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkCombo" id="cddev_combo"> + <property name="border_width">10</property> + <property name="visible">True</property> + <property name="value_in_list">False</property> + <property name="allow_empty">True</property> + <property name="case_sensitive">False</property> + <property name="enable_arrow_keys">True</property> + <property name="enable_arrows_always">False</property> + + <child internal-child="entry"> + <widget class="GtkEntry" id="cddev_entry"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">chose yor cdrom device or type its path if it's not listed</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">True</property> + </widget> + </child> + + <child internal-child="list"> + <widget class="GtkList" id="combo-list1"> + <property name="visible">True</property> + <property name="selection_mode">GTK_SELECTION_BROWSE</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="cdr_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Select cdrom device</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame2"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="readmode_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Select read mode:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">5</property> + <property name="ypad">5</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkOptionMenu" id="readmode_optionmenu"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child> + <widget class="GtkMenu" id="menu1"> + + <child> + <widget class="GtkMenuItem" id="normal"> + <property name="visible">True</property> + <property name="label" translatable="yes">Normal (No Cache)</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="threaded"> + <property name="visible">True</property> + <property name="label" translatable="yes">Threaded - Faster (With Cache)</property> + <property name="use_underline">True</property> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">1</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHSeparator" id="hseparator1"> + <property name="visible">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">5</property> + + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">Cache Size (Def. 64): </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkSpinButton" id="spinCacheSize"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="climb_rate">1</property> + <property name="digits">0</property> + <property name="numeric">True</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">32 32 2048 1 16 16</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHSeparator" id="hseparator2"> + <property name="visible">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">5</property> + + <child> + <widget class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="label" translatable="yes">Cdrom Speed (Def. 0 = MAX): </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkSpinButton" id="spinCdrSpeed"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="climb_rate">1</property> + <property name="digits">0</property> + <property name="numeric">True</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">0 0 100 1 4 4</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHSeparator" id="cfg_hseparator"> + <property name="visible">True</property> + <accessibility> + <atkproperty name="AtkObject::accessible_name" translatable="yes">hseparator</atkproperty> + </accessibility> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="subQ_button"> + <property name="border_width">10</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Enable subQ read</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="options_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Options</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="abt_dialog"> + <property name="border_width">10</property> + <property name="width_request">300</property> + <property name="height_request">200</property> + <property name="visible">True</property> + <property name="title" translatable="yes">About CDR</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_CENTER</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">True</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="abt_dialog-vbox"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="abt_dialog-action_area"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="abt_okbutton"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-5</property> + <signal name="clicked" handler="on_abt_okbutton_clicked" last_modification_time="Sat, 16 Nov 2002 19:25:54 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox3"> + <property name="border_width">10</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span size="xx-large"><b>CDR plugin</b></span></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">5</property> + <property name="ypad">5</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">linux CDR plugin for Pcsx + +</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_FILL</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">5</property> + <property name="ypad">5</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes"><small>(c) linuzappz linuzappz@hotmail.com + xobro _xobro_@tin.it</small> +</property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">5</property> + <property name="ypad">5</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/plugins/dfcdrom/interface.c b/plugins/dfcdrom/interface.c new file mode 100644 index 00000000..bfb24cee --- /dev/null +++ b/plugins/dfcdrom/interface.c @@ -0,0 +1,339 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef __linux__ + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ + g_object_set_data (G_OBJECT (component), name, widget) + +GtkWidget* +create_cfg_dialog (void) +{ + GtkWidget *cfg_dialog; + GtkWidget *dialog_vbox1; + GtkWidget *vbox1; + GtkWidget *frame1; + GtkWidget *cddev_combo; + GtkWidget *cddev_entry; + GtkWidget *cdr_label; + GtkWidget *frame2; + GtkWidget *vbox2; + GtkWidget *hbox1; + GtkWidget *readmode_label; + GtkWidget *readmode_optionmenu; + GtkWidget *menu1; + GtkWidget *normal; + GtkWidget *threaded; + GtkWidget *hseparator1; + GtkWidget *hbox2; + GtkWidget *label4; + GtkObject *spinCacheSize_adj; + GtkWidget *spinCacheSize; + GtkWidget *hseparator2; + GtkWidget *hbox3; + GtkWidget *label5; + GtkObject *spinCdrSpeed_adj; + GtkWidget *spinCdrSpeed; + GtkWidget *cfg_hseparator; + AtkObject *atko; + GtkWidget *subQ_button; + GtkWidget *options_label; + GtkWidget *cfg_dialog_action_area; + GtkWidget *cfg_cancelbutton; + GtkWidget *cfg_okbutton; + GtkTooltips *tooltips; + + tooltips = gtk_tooltips_new (); + + cfg_dialog = gtk_dialog_new (); + gtk_container_set_border_width (GTK_CONTAINER (cfg_dialog), 5); + gtk_window_set_title (GTK_WINDOW (cfg_dialog), "CDR configuration"); + gtk_window_set_position (GTK_WINDOW (cfg_dialog), GTK_WIN_POS_CENTER); + gtk_window_set_modal (GTK_WINDOW (cfg_dialog), TRUE); + gtk_dialog_set_has_separator (GTK_DIALOG (cfg_dialog), FALSE); + + dialog_vbox1 = GTK_DIALOG (cfg_dialog)->vbox; + gtk_widget_show (dialog_vbox1); + + vbox1 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox1); + gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox1, TRUE, TRUE, 0); + + frame1 = gtk_frame_new (NULL); + gtk_widget_show (frame1); + gtk_box_pack_start (GTK_BOX (vbox1), frame1, TRUE, TRUE, 0); + + cddev_combo = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (cddev_combo)->popwin), + "GladeParentKey", cddev_combo); + gtk_widget_show (cddev_combo); + gtk_container_add (GTK_CONTAINER (frame1), cddev_combo); + gtk_container_set_border_width (GTK_CONTAINER (cddev_combo), 10); + + cddev_entry = GTK_COMBO (cddev_combo)->entry; + gtk_widget_show (cddev_entry); + gtk_tooltips_set_tip (tooltips, cddev_entry, "Choose yor CD-ROM device or type its path if it's not listed", NULL); + gtk_entry_set_activates_default (GTK_ENTRY (cddev_entry), TRUE); + + cdr_label = gtk_label_new ("Select CD-ROM device"); + gtk_widget_show (cdr_label); + gtk_frame_set_label_widget (GTK_FRAME (frame1), cdr_label); + gtk_label_set_justify (GTK_LABEL (cdr_label), GTK_JUSTIFY_LEFT); + + frame2 = gtk_frame_new (NULL); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox1), frame2, TRUE, TRUE, 0); + + vbox2 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (frame2), vbox2); + + hbox1 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox1), 5); + + readmode_label = gtk_label_new ("Select read mode:"); + gtk_widget_show (readmode_label); + gtk_box_pack_start (GTK_BOX (hbox1), readmode_label, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (readmode_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_padding (GTK_MISC (readmode_label), 5, 5); + + readmode_optionmenu = gtk_option_menu_new (); + gtk_widget_show (readmode_optionmenu); + gtk_box_pack_start (GTK_BOX (hbox1), readmode_optionmenu, TRUE, TRUE, 1); + gtk_container_set_border_width (GTK_CONTAINER (readmode_optionmenu), 5); + + menu1 = gtk_menu_new (); + + normal = gtk_menu_item_new_with_mnemonic ("Normal (No Cache)"); + gtk_widget_show (normal); + gtk_container_add (GTK_CONTAINER (menu1), normal); + + threaded = gtk_menu_item_new_with_mnemonic ("Threaded - Faster (With Cache)"); + gtk_widget_show (threaded); + gtk_container_add (GTK_CONTAINER (menu1), threaded); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (readmode_optionmenu), menu1); + + hseparator1 = gtk_hseparator_new (); + gtk_widget_show (hseparator1); + gtk_box_pack_start (GTK_BOX (vbox2), hseparator1, TRUE, TRUE, 0); + + hbox2 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox2); + gtk_box_pack_start (GTK_BOX (vbox2), hbox2, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox2), 5); + + label4 = gtk_label_new ("Cache Size (Def. 64): "); + gtk_widget_show (label4); + gtk_box_pack_start (GTK_BOX (hbox2), label4, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label4), GTK_JUSTIFY_LEFT); + +// spinCacheSize_adj = gtk_adjustment_new (32, 32, 2048, 1, 16, 16); + spinCacheSize_adj = gtk_adjustment_new (32, 32, 2048, 1, 16, 0); + spinCacheSize = gtk_spin_button_new (GTK_ADJUSTMENT (spinCacheSize_adj), 1, 0); + gtk_widget_show (spinCacheSize); + gtk_box_pack_start (GTK_BOX (hbox2), spinCacheSize, TRUE, TRUE, 0); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinCacheSize), TRUE); + + hseparator2 = gtk_hseparator_new (); + gtk_widget_show (hseparator2); + gtk_box_pack_start (GTK_BOX (vbox2), hseparator2, TRUE, TRUE, 0); + + hbox3 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox3); + gtk_box_pack_start (GTK_BOX (vbox2), hbox3, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox3), 5); + + label5 = gtk_label_new ("Cdrom Speed (Def. 0 = MAX): "); + gtk_widget_show (label5); + gtk_box_pack_start (GTK_BOX (hbox3), label5, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label5), GTK_JUSTIFY_LEFT); + +// spinCdrSpeed_adj = gtk_adjustment_new (0, 0, 100, 1, 4, 4); + spinCdrSpeed_adj = gtk_adjustment_new (0, 0, 100, 1, 4, 0); + spinCdrSpeed = gtk_spin_button_new (GTK_ADJUSTMENT (spinCdrSpeed_adj), 1, 0); + gtk_widget_show (spinCdrSpeed); + gtk_box_pack_start (GTK_BOX (hbox3), spinCdrSpeed, TRUE, TRUE, 0); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinCdrSpeed), TRUE); + + cfg_hseparator = gtk_hseparator_new (); + gtk_widget_show (cfg_hseparator); + gtk_box_pack_start (GTK_BOX (vbox2), cfg_hseparator, TRUE, TRUE, 0); + + subQ_button = gtk_check_button_new_with_mnemonic ("Enable Subchannel read"); + gtk_widget_show (subQ_button); + gtk_box_pack_start (GTK_BOX (vbox2), subQ_button, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (subQ_button), 10); + + options_label = gtk_label_new ("Options"); + gtk_widget_show (options_label); + gtk_frame_set_label_widget (GTK_FRAME (frame2), options_label); + gtk_label_set_justify (GTK_LABEL (options_label), GTK_JUSTIFY_LEFT); + + cfg_dialog_action_area = GTK_DIALOG (cfg_dialog)->action_area; + gtk_widget_show (cfg_dialog_action_area); + gtk_button_box_set_layout (GTK_BUTTON_BOX (cfg_dialog_action_area), GTK_BUTTONBOX_END); + + cfg_cancelbutton = gtk_button_new_from_stock ("gtk-cancel"); + gtk_widget_show (cfg_cancelbutton); + gtk_dialog_add_action_widget (GTK_DIALOG (cfg_dialog), cfg_cancelbutton, GTK_RESPONSE_CANCEL); + GTK_WIDGET_SET_FLAGS (cfg_cancelbutton, GTK_CAN_DEFAULT); + + cfg_okbutton = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (cfg_okbutton); + gtk_dialog_add_action_widget (GTK_DIALOG (cfg_dialog), cfg_okbutton, GTK_RESPONSE_OK); + GTK_WIDGET_SET_FLAGS (cfg_okbutton, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) cfg_dialog, "show", + G_CALLBACK (on_cfg_dialog_show), + NULL); + g_signal_connect ((gpointer) cfg_cancelbutton, "clicked", + G_CALLBACK (on_cfg_cancelbutton_clicked), + NULL); + g_signal_connect ((gpointer) cfg_dialog, "delete_event", + G_CALLBACK (on_cfg_cancelbutton_clicked), + NULL); + g_signal_connect ((gpointer) cfg_okbutton, "clicked", + G_CALLBACK (on_cfg_okbutton_clicked), + NULL); + + atko = gtk_widget_get_accessible (cfg_hseparator); + atk_object_set_name (atko, "hseparator"); + + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (cfg_dialog, cfg_dialog, "cfg_dialog"); + GLADE_HOOKUP_OBJECT_NO_REF (cfg_dialog, dialog_vbox1, "dialog_vbox1"); + GLADE_HOOKUP_OBJECT (cfg_dialog, vbox1, "vbox1"); + GLADE_HOOKUP_OBJECT (cfg_dialog, frame1, "frame1"); + GLADE_HOOKUP_OBJECT (cfg_dialog, cddev_combo, "cddev_combo"); + GLADE_HOOKUP_OBJECT (cfg_dialog, cddev_entry, "cddev_entry"); + GLADE_HOOKUP_OBJECT (cfg_dialog, cdr_label, "cdr_label"); + GLADE_HOOKUP_OBJECT (cfg_dialog, frame2, "frame2"); + GLADE_HOOKUP_OBJECT (cfg_dialog, vbox2, "vbox2"); + GLADE_HOOKUP_OBJECT (cfg_dialog, hbox1, "hbox1"); + GLADE_HOOKUP_OBJECT (cfg_dialog, readmode_label, "readmode_label"); + GLADE_HOOKUP_OBJECT (cfg_dialog, readmode_optionmenu, "readmode_optionmenu"); + GLADE_HOOKUP_OBJECT (cfg_dialog, menu1, "menu1"); + GLADE_HOOKUP_OBJECT (cfg_dialog, normal, "normal"); + GLADE_HOOKUP_OBJECT (cfg_dialog, threaded, "threaded"); + GLADE_HOOKUP_OBJECT (cfg_dialog, hseparator1, "hseparator1"); + GLADE_HOOKUP_OBJECT (cfg_dialog, hbox2, "hbox2"); + GLADE_HOOKUP_OBJECT (cfg_dialog, label4, "label4"); + GLADE_HOOKUP_OBJECT (cfg_dialog, spinCacheSize, "spinCacheSize"); + GLADE_HOOKUP_OBJECT (cfg_dialog, hseparator2, "hseparator2"); + GLADE_HOOKUP_OBJECT (cfg_dialog, hbox3, "hbox3"); + GLADE_HOOKUP_OBJECT (cfg_dialog, label5, "label5"); + GLADE_HOOKUP_OBJECT (cfg_dialog, spinCdrSpeed, "spinCdrSpeed"); + GLADE_HOOKUP_OBJECT (cfg_dialog, cfg_hseparator, "cfg_hseparator"); + GLADE_HOOKUP_OBJECT (cfg_dialog, subQ_button, "subQ_button"); + GLADE_HOOKUP_OBJECT (cfg_dialog, options_label, "options_label"); + GLADE_HOOKUP_OBJECT_NO_REF (cfg_dialog, cfg_dialog_action_area, "cfg_dialog_action_area"); + GLADE_HOOKUP_OBJECT (cfg_dialog, cfg_cancelbutton, "cfg_cancelbutton"); + GLADE_HOOKUP_OBJECT (cfg_dialog, cfg_okbutton, "cfg_okbutton"); + GLADE_HOOKUP_OBJECT_NO_REF (cfg_dialog, tooltips, "tooltips"); + + return cfg_dialog; +} + +GtkWidget* +create_abt_dialog (void) +{ + GtkWidget *abt_dialog; + GtkWidget *abt_dialog_vbox; + GtkWidget *vbox3; + GtkWidget *label3; + GtkWidget *label1; + GtkWidget *label2; + GtkWidget *abt_dialog_action_area; + GtkWidget *abt_okbutton; + + abt_dialog = gtk_dialog_new (); + gtk_widget_set_size_request (abt_dialog, 300, 200); + gtk_container_set_border_width (GTK_CONTAINER (abt_dialog), 10); + gtk_window_set_title (GTK_WINDOW (abt_dialog), "About CDR"); + gtk_window_set_position (GTK_WINDOW (abt_dialog), GTK_WIN_POS_CENTER); + gtk_window_set_destroy_with_parent (GTK_WINDOW (abt_dialog), TRUE); + + abt_dialog_vbox = GTK_DIALOG (abt_dialog)->vbox; + gtk_widget_show (abt_dialog_vbox); + + vbox3 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox3); + gtk_box_pack_start (GTK_BOX (abt_dialog_vbox), vbox3, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox3), 10); + + label3 = gtk_label_new ("<span size=\"xx-large\"><b>CDR plugin</b></span>"); + gtk_widget_show (label3); + gtk_box_pack_start (GTK_BOX (vbox3), label3, FALSE, FALSE, 0); + gtk_label_set_use_markup (GTK_LABEL (label3), TRUE); + gtk_label_set_justify (GTK_LABEL (label3), GTK_JUSTIFY_LEFT); + gtk_misc_set_padding (GTK_MISC (label3), 5, 5); + + label1 = gtk_label_new ("linux CDR plugin for Pcsx\n\n"); + gtk_widget_show (label1); + gtk_box_pack_start (GTK_BOX (vbox3), label1, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label1), GTK_JUSTIFY_FILL); + gtk_misc_set_padding (GTK_MISC (label1), 5, 5); + + label2 = gtk_label_new ("<small>(c) linuzappz linuzappz@hotmail.com\n xobro _xobro_@tin.it</small>\n"); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0); + gtk_label_set_use_markup (GTK_LABEL (label2), TRUE); + gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT); + gtk_misc_set_padding (GTK_MISC (label2), 5, 5); + + abt_dialog_action_area = GTK_DIALOG (abt_dialog)->action_area; + gtk_widget_show (abt_dialog_action_area); + gtk_button_box_set_layout (GTK_BUTTON_BOX (abt_dialog_action_area), GTK_BUTTONBOX_END); + + abt_okbutton = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (abt_okbutton); + gtk_dialog_add_action_widget (GTK_DIALOG (abt_dialog), abt_okbutton, GTK_RESPONSE_OK); + GTK_WIDGET_SET_FLAGS (abt_okbutton, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) abt_okbutton, "clicked", + G_CALLBACK (on_abt_okbutton_clicked), + NULL); + g_signal_connect ((gpointer) abt_dialog, "delete_event", + G_CALLBACK (on_abt_okbutton_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (abt_dialog, abt_dialog, "abt_dialog"); + GLADE_HOOKUP_OBJECT_NO_REF (abt_dialog, abt_dialog_vbox, "abt_dialog_vbox"); + GLADE_HOOKUP_OBJECT (abt_dialog, vbox3, "vbox3"); + GLADE_HOOKUP_OBJECT (abt_dialog, label3, "label3"); + GLADE_HOOKUP_OBJECT (abt_dialog, label1, "label1"); + GLADE_HOOKUP_OBJECT (abt_dialog, label2, "label2"); + GLADE_HOOKUP_OBJECT_NO_REF (abt_dialog, abt_dialog_action_area, "abt_dialog_action_area"); + GLADE_HOOKUP_OBJECT (abt_dialog, abt_okbutton, "abt_okbutton"); + + return abt_dialog; +} + +#endif diff --git a/plugins/dfcdrom/interface.h b/plugins/dfcdrom/interface.h new file mode 100644 index 00000000..e23e1adb --- /dev/null +++ b/plugins/dfcdrom/interface.h @@ -0,0 +1,6 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_cfg_dialog (void); +GtkWidget* create_abt_dialog (void); diff --git a/plugins/dfcdrom/main.c b/plugins/dfcdrom/main.c new file mode 100644 index 00000000..2b591045 --- /dev/null +++ b/plugins/dfcdrom/main.c @@ -0,0 +1,32 @@ + +#include <string.h> +#include <gtk/gtk.h> + +#include "interface.h" +#include "support.h" + +int main (int argc, char *argv[]) +{ +#ifdef __linux__ + GtkWidget *cfg_dialog; + GtkWidget *abt_dialog; + + gtk_set_locale (); + gtk_init (&argc, &argv); + + if (argc != 2) return 0; + + if (!strcmp(argv[1], "configure")) { + cfg_dialog = create_cfg_dialog (); + gtk_widget_show (cfg_dialog); + gtk_main (); + } else { + abt_dialog = create_abt_dialog (); + gtk_widget_show (abt_dialog); + gtk_main (); + } +#endif + return 0; +} + + diff --git a/plugins/dfcdrom/support.c b/plugins/dfcdrom/support.c new file mode 100644 index 00000000..9da69992 --- /dev/null +++ b/plugins/dfcdrom/support.c @@ -0,0 +1,147 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef __linux__ + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#include <gtk/gtk.h> + +#include "support.h" + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (!parent) + parent = g_object_get_data (G_OBJECT (widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to find pixmap files. */ +static gchar* +find_pixmap_file (const gchar *filename) +{ + GList *elem; + + /* We step through each of the pixmaps directory to find it. */ + elem = pixmaps_directories; + while (elem) + { + gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data, + G_DIR_SEPARATOR_S, filename); + if (g_file_test (pathname, G_FILE_TEST_EXISTS)) + return pathname; + g_free (pathname); + elem = elem->next; + } + return NULL; +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *pathname = NULL; + GtkWidget *pixmap; + + if (!filename || !filename[0]) + return gtk_image_new (); + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return gtk_image_new (); + } + + pixmap = gtk_image_new_from_file (pathname); + g_free (pathname); + return pixmap; +} + +/* This is an internally used function to create pixmaps. */ +GdkPixbuf* +create_pixbuf (const gchar *filename) +{ + gchar *pathname = NULL; + GdkPixbuf *pixbuf; + GError *error = NULL; + + if (!filename || !filename[0]) + return NULL; + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return NULL; + } + + pixbuf = gdk_pixbuf_new_from_file (pathname, &error); + if (!pixbuf) + { + fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", + pathname, error->message); + g_error_free (error); + } + g_free (pathname); + return pixbuf; +} + +/* This is used to set ATK action descriptions. */ +void +glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description) +{ + gint n_actions, i; + + n_actions = atk_action_get_n_actions (action); + for (i = 0; i < n_actions; i++) + { + if (!strcmp (atk_action_get_name (action, i), action_name)) + atk_action_set_description (action, i, description); + } +} + +#endif diff --git a/plugins/dfcdrom/support.h b/plugins/dfcdrom/support.h new file mode 100644 index 00000000..2dea079c --- /dev/null +++ b/plugins/dfcdrom/support.h @@ -0,0 +1,44 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtk/gtk.h> + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps used in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + +/* This is used to create the pixbufs used in the interface. */ +GdkPixbuf* create_pixbuf (const gchar *filename); + +/* This is used to set ATK action descriptions. */ +void glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description); + diff --git a/plugins/dfinput/Makefile.am b/plugins/dfinput/Makefile.am new file mode 100644 index 00000000..cb6d2648 --- /dev/null +++ b/plugins/dfinput/Makefile.am @@ -0,0 +1,22 @@ +bindir = @libdir@/games/psemu/ +libdir = @libdir@/games/psemu/ + +lib_LTLIBRARIES = libDFInput.la + +libDFInput_la_SOURCES = pad.c padjoy.h +libDFInput_la_LDFLAGS = -module -avoid-version -lpthread -lX11 \ + -L/usr/X11R6/lib64 -L/usr/X11R6/lib + +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) $(GLADE2_CFLAGS) -I/usr/X11R6/include \ + -DVERSION=0 -DREVISION=1 -DBUILD=0 + +bin_PROGRAMS = cfgDFInput +cfgDFInput_SOURCES = cfg.c padjoy.h +cfgDFInput_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) + +glade_DATA = dfinput.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) diff --git a/plugins/dfinput/Makefile.in b/plugins/dfinput/Makefile.in new file mode 100644 index 00000000..6210f4cb --- /dev/null +++ b/plugins/dfinput/Makefile.in @@ -0,0 +1,583 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = cfgDFInput$(EXEEXT) +subdir = plugins/dfinput +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(gladedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libDFInput_la_LIBADD = +am_libDFInput_la_OBJECTS = pad.lo +libDFInput_la_OBJECTS = $(am_libDFInput_la_OBJECTS) +libDFInput_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libDFInput_la_LDFLAGS) $(LDFLAGS) -o $@ +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_cfgDFInput_OBJECTS = cfg.$(OBJEXT) +cfgDFInput_OBJECTS = $(am_cfgDFInput_OBJECTS) +am__DEPENDENCIES_1 = +cfgDFInput_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libDFInput_la_SOURCES) $(cfgDFInput_SOURCES) +DIST_SOURCES = $(libDFInput_la_SOURCES) $(cfgDFInput_SOURCES) +gladeDATA_INSTALL = $(INSTALL_DATA) +DATA = $(glade_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFOPENGL = @DFOPENGL@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADE2_CFLAGS = @GLADE2_CFLAGS@ +GLADE2_LIBS = @GLADE2_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTK2_CFLAGS = @GTK2_CFLAGS@ +GTK2_LIBS = @GTK2_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NASM = @NASM@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @libdir@/games/psemu/ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@/games/psemu/ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +lib_LTLIBRARIES = libDFInput.la +libDFInput_la_SOURCES = pad.c padjoy.h +libDFInput_la_LDFLAGS = -module -avoid-version -lpthread -lX11 \ + -L/usr/X11R6/lib64 -L/usr/X11R6/lib + +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) $(GLADE2_CFLAGS) -I/usr/X11R6/include \ + -DVERSION=0 -DREVISION=1 -DBUILD=0 + +cfgDFInput_SOURCES = cfg.c padjoy.h +cfgDFInput_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) +glade_DATA = dfinput.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/dfinput/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/dfinput/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libDFInput.la: $(libDFInput_la_OBJECTS) $(libDFInput_la_DEPENDENCIES) + $(libDFInput_la_LINK) -rpath $(libdir) $(libDFInput_la_OBJECTS) $(libDFInput_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +cfgDFInput$(EXEEXT): $(cfgDFInput_OBJECTS) $(cfgDFInput_DEPENDENCIES) + @rm -f cfgDFInput$(EXEEXT) + $(LINK) $(cfgDFInput_OBJECTS) $(cfgDFInput_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pad.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-gladeDATA: $(glade_DATA) + @$(NORMAL_INSTALL) + test -z "$(gladedir)" || $(MKDIR_P) "$(DESTDIR)$(gladedir)" + @list='$(glade_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(gladeDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(gladedir)/$$f'"; \ + $(gladeDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(gladedir)/$$f"; \ + done + +uninstall-gladeDATA: + @$(NORMAL_UNINSTALL) + @list='$(glade_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(gladedir)/$$f'"; \ + rm -f "$(DESTDIR)$(gladedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(gladedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-gladeDATA + +install-dvi: install-dvi-am + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-gladeDATA \ + uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-gladeDATA install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-gladeDATA uninstall-libLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/dfinput/cfg.c b/plugins/dfinput/cfg.c new file mode 100644 index 00000000..3f6d0184 --- /dev/null +++ b/plugins/dfinput/cfg.c @@ -0,0 +1,1289 @@ +/* + * Pad for Psemu Pro like Emulators + * This is the config program, taken out from the pad + * It's also responsible for the about-dialog box + * + * Written by Erich Kitzmuller <ammoq@ammoq.com> + * Based on padXwin by linuzappz <linuzappz@hotmail.com> + * + * Copyright 2002,2003 by Erich Kitzmuller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#ifdef __linux__ +#include <linux/joystick.h> +#endif +#include <sys/stat.h> +#include <sys/time.h> +#include <unistd.h> +#include <gdk/gdk.h> +#include <gtk/gtk.h> +#include <glade/glade.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <errno.h> +#include "padjoy.h" + +#ifdef __linux__ +char *LibName = "Gamepad/Keyboard Input"; +#else +char *LibName = "Keyboard Input"; +#endif + +#define CONFIG_FILENAME "dfinput.cfg" + +const unsigned char version = VERSION; +const unsigned char revision = REVISION; +const unsigned char build = BUILD; + +// Prototypes +static void loadConfig(); +static void saveConfig(); +static char *eventDescription(EventCode); +static void initPadtime(); + +// Filenames for device files, e.g. "/dev/input/js0" +static char devicefilename[MAXDEVICES][FILENAME_MAX+1] = {"/dev/input/js0", "/dev/input/js1"}; + +// File desciptors for device files +static int devicefile[MAXDEVICES] = { -1, -1 }; + +// Use Threading for joy device input? +static int use_threads = 1; + +// Emulate Dualshock(TM) analog pad? +static int use_analog = 0; + +// calibration data +int minzero[MAXAXES]; +int maxzero[MAXAXES]; + +// axes status - so only changing status are reported +int axestatus[MAXDEVICES][MAXAXES]; + +// Assignment of PSX buttons to Events +static EventCode PadButtons[MAXDEVICES][MAXPSXBUTTONS] = +{ + { + KEY_EVENT(XK_e), // L2 + KEY_EVENT(XK_t), // R2 + KEY_EVENT(XK_w), // L1 + KEY_EVENT(XK_r), // R1 + KEY_EVENT(XK_d), // Triangle + KEY_EVENT(XK_x), // Circle + KEY_EVENT(XK_z), // Cross + KEY_EVENT(XK_s), // Square + KEY_EVENT(XK_c), // Select + NO_EVENT, // Left Analog + NO_EVENT, // Right Analog + KEY_EVENT(XK_v), // Start + KEY_EVENT(XK_Up), // Up + KEY_EVENT(XK_Right), // Right + KEY_EVENT(XK_Down), // Down + KEY_EVENT(XK_Left), // Left + NO_EVENT, // Left Anlaog X + NO_EVENT, // Left Analog Y + NO_EVENT, // Right Analog X + NO_EVENT // Right Analog Y + }, + { + NO_EVENT, // L2 + NO_EVENT, // R2 + NO_EVENT, // L1 + NO_EVENT, // R1 + NO_EVENT, // Triangle + NO_EVENT, // Circle + NO_EVENT, // Cross + NO_EVENT, // Square + NO_EVENT, // Select + NO_EVENT, // Left Analog + NO_EVENT, // Right Analog + NO_EVENT, // Start + NO_EVENT, // Up + NO_EVENT, // Right + NO_EVENT, // Down + NO_EVENT, // Left + NO_EVENT, // Left Anlaog X + NO_EVENT, // Left Analog Y + NO_EVENT, // Right Analog X + NO_EVENT // Right Analog Y + } +}; + +static Display *Dsp; + +static EventCode macroLaunch[MAXDEVICES][MAXMACROS]; +static EventCode macroEvents[MAXDEVICES][MAXMACROS][MAXMACROLENGTH]; +static long macroInterval[MAXDEVICES][MAXMACROS][MAXMACROLENGTH]; +static int macroActive[MAXDEVICES]; +static int macroIndex[MAXDEVICES]; +static long macroNext[MAXDEVICES]; + +void init_macros() { + int i,j; + + for (i=0; i<MAXDEVICES; i++) { + for (j=0; j<MAXMACROS; j++) { + macroLaunch[i][j]=NO_EVENT; + macroEvents[i][j][0]=NO_EVENT; + macroInterval[i][j][0]=0; + } + macroActive[i]=-1; + macroIndex[i]=0; + macroNext[i]=0; + } +} + +long PADinit(long flags) { + int i,j; + + init_macros(); + initPadtime(); + for (i=0; i<MAXDEVICES; i++) { + maxzero[i] = 250; + minzero[i] = -250; + + for (j=0; j<MAXAXES; j++) { + axestatus[i][j] = AXESTS_UNKNOWN; + } + } + loadConfig(); + + return 0; +} + +static long firstsecond = 0; + +static void initPadtime() { + struct timeval tv; + gettimeofday(&tv, NULL); + firstsecond = tv.tv_sec; +} + +// construct a time on our own +long getPadtime() { + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec-firstsecond)*10000+tv.tv_usec/100; +} + +unsigned short PadStat[2] = {0xffff, 0xffff}; + +// get pending events +static int getPendingEvents(int millisecondstowait, EventCode *events, int maxevents, int useGDK, int checkJoydevice, int checkXKeyboard, long *timing) { + fd_set rfds; + int retval; + int i; + int md; + int eventsread=0; + XEvent xe; + GdkEvent *ge; + int cntopen; + struct timeval tv; + int oldstatus; + +#ifdef __linux__ + struct js_event je; + + if (checkJoydevice) { + FD_ZERO(&rfds); + md = -1; + cntopen=0; + for (i=0; i<MAXDEVICES; i++) { + if (devicefile[i] > -1) { + FD_SET(devicefile[i], &rfds); + cntopen++; + } + if (devicefile[i] > md) md = devicefile[i]; + } + tv.tv_sec = millisecondstowait / 1000; + tv.tv_usec = 1000 * (millisecondstowait % 1000); + + retval = select(md+1, &rfds, NULL, NULL, &tv); + + while (retval && eventsread<maxevents-2*checkXKeyboard) { + for (i=0; i<MAXDEVICES; i++) { + if (devicefile[i]>-1 && FD_ISSET(devicefile[i], &rfds)) { + read (devicefile[i], &je, 8); + + if (je.type == JS_EVENT_AXIS && je.number<MAXAXES) { + if (axestatus[i][je.number] == AXESTS_ANALOG) { + /* this axe should be reported analog */ + events[eventsread++] = ANALOGAXIS_EVENT(i,je.number, (je.value+32768)>>8); + if (timing) { + (*timing)=getPadtime(); + timing++; + } + if (eventsread == maxevents) return eventsread; + } + else if (je.value > maxzero[i]) { + if (axestatus[i][je.number] != AXESTS_PLUS && + axestatus[i][je.number] != AXESTS_UNUSED) { + + oldstatus = axestatus[i][je.number]; + + axestatus[i][je.number] = AXESTS_PLUS; + + events[eventsread++] = AXISPLUS_EVENT(i,je.number); + if (timing) { + (*timing)=getPadtime(); + timing++; + } + if (eventsread==maxevents) return eventsread; + + if (oldstatus == AXESTS_MINUS) { + events[eventsread++] = RELEASE_EVENT+AXISMINUS_EVENT(i,je.number); + if (timing) { + (*timing)=getPadtime(); + timing++; + } + if (eventsread==maxevents) return eventsread; + } + + } + } + else if (je.value < minzero[i]) { + if (axestatus[i][je.number] != AXESTS_MINUS && + axestatus[i][je.number] != AXESTS_UNUSED) { + + oldstatus = axestatus[i][je.number]; + + axestatus[i][je.number] = AXESTS_MINUS; + + events[eventsread++] = AXISMINUS_EVENT(i,je.number); + if (timing) { + (*timing)=getPadtime(); + timing++; + } + if (eventsread==maxevents) return eventsread; + + if (oldstatus == AXESTS_PLUS) { + events[eventsread++] = RELEASE_EVENT+AXISPLUS_EVENT(i,je.number); + if (timing) { + (*timing)=getPadtime(); + timing++; + } + if (eventsread==maxevents) return eventsread; + } + } + } + else { + if (axestatus[i][je.number] != AXESTS_CENTER && + axestatus[i][je.number] != AXESTS_UNUSED) { + + oldstatus = axestatus[i][je.number]; + + axestatus[i][je.number] = AXESTS_CENTER; + + if (oldstatus == AXESTS_PLUS) { + events[eventsread++] = RELEASE_EVENT+AXISPLUS_EVENT(i,je.number); + if (timing) { + (*timing)=getPadtime(); + timing++; + } + if (eventsread==maxevents) return eventsread; + } + else if (oldstatus == AXESTS_MINUS) { + events[eventsread++] = RELEASE_EVENT+AXISMINUS_EVENT(i,je.number); + if (timing) { + (*timing)=getPadtime(); + timing++; + } + if (eventsread==maxevents) return eventsread; + } + } + } + } + else if (je.type == JS_EVENT_BUTTON && je.number<MAXBUTTONS) { + events[eventsread++] = (je.value?0:RELEASE_EVENT) + BUTTON_EVENT(i,je.number); + if (timing) { + (*timing)=getPadtime(); + timing++; + } + if (eventsread==maxevents) return eventsread; + } + } + } + tv.tv_sec = 0; + tv.tv_usec = 0; + + retval = select(md+1, &rfds, NULL, NULL, &tv); + } + + } +#endif + + if (checkXKeyboard) { + if (useGDK) { + while ((ge = gdk_event_get() ) != NULL ) { + if (ge->type == GDK_KEY_PRESS) { + events[eventsread++] = KEY_EVENT(ge->key.keyval); + if (timing) { + (*timing)=((GdkEventKey *)ge)->time*10; + timing++; + } + if (eventsread==maxevents) return eventsread; + } + else if (ge->type == GDK_KEY_RELEASE) { + events[eventsread++] = RELEASE_EVENT+KEY_EVENT(ge->key.keyval); + if (timing) { + (*timing)=((GdkEventKey *)ge)->time*10; + timing++; + } + if (eventsread==maxevents) return eventsread; + } + gdk_event_free(ge); + } + } + else { + while ((i=XPending(Dsp))) { + while (i--) { + XNextEvent(Dsp, &xe); + switch (xe.type) { + case KeyPress: + events[eventsread++] = KEY_EVENT(XLookupKeysym((XKeyEvent *)&xe, 0)); + if (timing) { + (*timing)=getPadtime(); + timing++; + } + if (eventsread==maxevents) return eventsread; + break; + case KeyRelease: + events[eventsread++] = RELEASE_EVENT+KEY_EVENT(XLookupKeysym((XKeyEvent *)&xe, 0)); + if (timing) { + (*timing)=getPadtime(); + timing++; + } + if (eventsread==maxevents) return eventsread; + break; +/* + case FocusIn: + XAutoRepeatOff(Dsp); + break; + case FocusOut: + XAutoRepeatOn(Dsp); + break; +*/ + } + } + } + } + } + + return eventsread; +} + + +/*---------------------------------------------------------------------*/ +/* Config Dialogue stuff */ +/*---------------------------------------------------------------------*/ + +// analyse Eventcode +static PadJoyEvent *EventCode2PadJoyEvent(EventCode p_e) { + static PadJoyEvent event; + EventCode e; + int i,p; + + event.event_type = EVENTTYPE_NONE; + event.pad = 0; + event.no = 0; + event.value = 0; + + if (!p_e) { + return &event; + } + + e = p_e; + + if (e>RELEASE_EVENT) { + event.value = 0; + e -= RELEASE_EVENT; + } + else { + event.value = 1; + } + + if (e && e<FIRST_JOY_EVENT) { + event.event_type = EVENTTYPE_KEY; + event.no = e; + return &event; + } + + if (e >= FIRST_ANALOG_EVENT) { + event.event_type = EVENTTYPE_ANALOG; + event.pad = (e-FIRST_ANALOG_EVENT)/(256*MAXAXES); + event.no = (e-ANALOGAXIS_EVENT(event.pad,0,0))/256; + event.value = e & 0xff; + return &event; + } + + + for (p=0; p<MAXDEVICES; p++) { + for (i=0; i<MAXAXES; i++) { + if (e == AXISPLUS_EVENT(p,i)) { + event.event_type = EVENTTYPE_AXISPLUS; + event.pad = p; + event.no = i; + return &event; + } + if (e == AXISMINUS_EVENT(p,i)) { + event.event_type = EVENTTYPE_AXISMINUS; + event.pad = p; + event.no = i; + return &event; + } + } + + for (i=0; i<MAXBUTTONS; i++) { + if (e == BUTTON_EVENT(p,i)) { + event.event_type = EVENTTYPE_BUTTON; + event.pad = p; + event.no = i; + return &event; + } + } + } + + return &event; +} + + + +// get the description of an Eventcode +// this implementation is not optimized, +// but I only need it for the configuration part so speed doesn't matter +// should be changed to use EventCode2PadJoyEvent +static char *eventDescription(EventCode e) { + static char buffer[256]; + int i,p; + + if (e && e<FIRST_JOY_EVENT) { + sprintf(buffer, "\"%s\"", XKeysymToString(e-FIRST_KEY_EVENT)); + return buffer; + } + + if (e >= FIRST_ANALOG_EVENT) { + p = (e-FIRST_ANALOG_EVENT)/(256*MAXAXES); + i = (e-ANALOGAXIS_EVENT(p,0,0))/256; + sprintf(buffer, "X%d", i); + return buffer; + } + + for (p=0; p<MAXDEVICES; p++) { + for (i=0; i<MAXAXES; i++) { + if (e == AXISPLUS_EVENT(p,i)) { + sprintf(buffer, "A%d+", i); + return buffer; + } + if (e == AXISMINUS_EVENT(p,i)) { + sprintf(buffer, "A%d-", i); + return buffer; + } + } + + for (i=0; i<MAXBUTTONS; i++) { + if (e == BUTTON_EVENT(p,i)) { + sprintf(buffer, "B%d", i); + return buffer; + } + } + } + + sprintf(buffer, "???"); + return buffer; +} + + +// get a String for each EventCode +// more accurate than eventDescription() +// should be changed to use EventCode2PadJoyEvent +static char *EventCode2String(EventCode p_e) { + static char buffer[256]; + int i,p,v; + char push_release; + EventCode e; + + if (!p_e) { + sprintf(buffer, "???"); + return buffer; + } + + e = p_e; + + if (e>RELEASE_EVENT) { + push_release = 'R'; + e -= RELEASE_EVENT; + } + else { + push_release = 'P'; + } + + if (e && e<FIRST_JOY_EVENT) { + sprintf(buffer, "K%c\"%s\"", push_release, XKeysymToString(e-FIRST_KEY_EVENT)); + return buffer; + } + + if (e >= FIRST_ANALOG_EVENT) { + p = (e-FIRST_ANALOG_EVENT)/(256*MAXAXES); + i = (e-ANALOGAXIS_EVENT(p,0,0))/256; + v = e & 0xff;; + sprintf(buffer, "X%dP%dv%d",p, i, v); + return buffer; + } + + + for (p=0; p<MAXDEVICES; p++) { + for (i=0; i<MAXAXES; i++) { + if (e == AXISPLUS_EVENT(p,i)) { + sprintf(buffer, "A%d%c%d+", p, push_release, i); + return buffer; + } + if (e == AXISMINUS_EVENT(p,i)) { + sprintf(buffer, "A%d%c%d-", p, push_release, i); + return buffer; + } + } + + for (i=0; i<MAXBUTTONS; i++) { + if (e == BUTTON_EVENT(p,i)) { + sprintf(buffer, "B%d%c%d", p, push_release, i); + return buffer; + } + } + } + + sprintf(buffer, "???"); + return buffer; +} + +// reversal of EventCode2String +static EventCode String2EventCode(char *s) { + static char buffer[256]; + int i,p; + char *q; + char push_release; + EventCode e; + + if (s[0]>='0' && s[0]<='9') return atoi(s); // allow numeric input + + e=0; + push_release = 'P'; + + switch(s[0]) { + case 'K': + push_release = s[1]; + strncpy(buffer, s+3, 255); + q=buffer; + i=1; + while (*q) { + if (*q=='"') i=!i; + if (*q==' ' && !i) + *q='\0'; + else + q++; + } + if (s[2]=='"' && buffer[0] && buffer[strlen(buffer)-1]=='"') { + buffer[strlen(buffer)-1] = '\0'; + e = KEY_EVENT(XStringToKeysym(buffer)); + } + break; + case 'A': + if (s[1]>='0' && s[1]<='1' && strlen(s)>=5) { + p = s[1]-'0'; + push_release = s[2]; + i = atoi(s+3); + q=s+3; + while (*q && *q!='+' && *q!='-') q++; + if (*q=='+') + e = AXISPLUS_EVENT(p,i); + else if (*q=='-') + e = AXISMINUS_EVENT(p,i); + } + break; + case 'B': + if (s[1]>='0' && s[1]<='1' && strlen(s)>=4) { + p = s[1]-'0'; + push_release = s[2]; + i = atoi(s+3); + e = BUTTON_EVENT(p,i); + } + break; + case 'X': + if (s[1]>='0' && s[1]<='1' && strlen(s)>=5) { + p = s[1]-'0'; + i = atoi(s+3); + q=s+3; + while (*q && *q!='v') q++; + if (*q=='v') + e = ANALOGAXIS_EVENT(p,i,atoi(q+1)); + } + break; + } + + if (push_release=='R') + return e+RELEASE_EVENT; + else + return e; +} + +static void saveConfig() { + FILE *f; + int i,j,k; + + f = fopen(CONFIG_FILENAME, "w"); + if (!f) { + fprintf(stderr, "DFInput error: couldn't write config file!\n"); + return; + } + + fprintf(f,"[general]\n"); + fprintf(f,"use_threads = %d\n", use_threads); + fprintf(f,"use_analog = %d\n", use_analog); + for (i=0;i<MAXDEVICES;i++) { + fprintf(f,"[pad %d]\n", i+1); + fprintf(f,"devicefilename = %s\n", devicefilename[i]); + fprintf(f,"minzero = %d\n", minzero[i]); + fprintf(f,"maxzero = %d\n", maxzero[i]); + fprintf(f,"event_l2 = %s\n", EventCode2String(PadButtons[i][0])); + fprintf(f,"event_r2 = %s\n", EventCode2String(PadButtons[i][1])); + fprintf(f,"event_l1 = %s\n", EventCode2String(PadButtons[i][2])); + fprintf(f,"event_r1 = %s\n", EventCode2String(PadButtons[i][3])); + fprintf(f,"event_triangle = %s\n", EventCode2String(PadButtons[i][4])); + fprintf(f,"event_circle = %s\n", EventCode2String(PadButtons[i][5])); + fprintf(f,"event_cross = %s\n", EventCode2String(PadButtons[i][6])); + fprintf(f,"event_square = %s\n", EventCode2String(PadButtons[i][7])); + fprintf(f,"event_select = %s\n", EventCode2String(PadButtons[i][8])); + fprintf(f,"event_lanalog = %s\n", EventCode2String(PadButtons[i][9])); + fprintf(f,"event_ranalog = %s\n", EventCode2String(PadButtons[i][10])); + fprintf(f,"event_start = %s\n", EventCode2String(PadButtons[i][11])); + fprintf(f,"event_up = %s\n", EventCode2String(PadButtons[i][12])); + fprintf(f,"event_right = %s\n", EventCode2String(PadButtons[i][13])); + fprintf(f,"event_down = %s\n", EventCode2String(PadButtons[i][14])); + fprintf(f,"event_left = %s\n", EventCode2String(PadButtons[i][15])); + fprintf(f,"event_lanax = %s\n", EventCode2String(PadButtons[i][16])); + fprintf(f,"event_lanay = %s\n", EventCode2String(PadButtons[i][17])); + fprintf(f,"event_ranax = %s\n", EventCode2String(PadButtons[i][18])); + fprintf(f,"event_ranay = %s\n", EventCode2String(PadButtons[i][19])); + for (j=0; j<MAXMACROS; j++) { + fprintf(f, "[macro %d]\n", j+1); + fprintf(f, "event_launch = %s\n", EventCode2String(macroLaunch[i][j])); + fprintf(f, "events ="); + for (k=0; k<MAXMACROLENGTH && macroEvents[i][j][k]; k++) { + fprintf(f, " %s", EventCode2String(macroEvents[i][j][k])); + } + fprintf(f,"\n"); + fprintf(f, "interval ="); + for (k=0; k<MAXMACROLENGTH && macroEvents[i][j][k]; k++) { + fprintf(f, " %ld", macroInterval[i][j][k]); + } + fprintf(f,"\n"); + } + } + + fclose(f); +} + +static void loadConfig() { + FILE *f; + int i; + char line[FILENAME_MAX+30]; + int pad=0; + int macronr=0; + char *val; + + f = fopen(CONFIG_FILENAME, "r"); + if (!f) { +// fprintf(stderr, "DFInput warning: config file not found."); + return; + } + + while(!feof(f)) { + fgets(line, FILENAME_MAX+29, f); + i=strlen(line)-1; + while (i>0 && line[i]<32) line[i--]='\0'; + + val=NULL; + while(i>0) { + if (line[i]=='=') val = line+(i+1); + i--; + } + if (val) { + while (*val==' ') val++; + } + + if (!strcmp(line, "[general]")) { + // nothing to do + } + else if (!strncmp(line, "use_threads", 11)) { + use_threads = atoi(val); + } + else if (!strncmp(line, "use_analog", 10)) { + use_analog = atoi(val); + } + else if (!strcmp(line, "[pad 1]")) { + pad = 0; + } + else if (!strcmp(line, "[pad 2]")) { + pad = 1; + } + else if (!strncmp(line, "[macro ", 7)) { + macronr = atoi(line+7)-1; + if (macronr<0 || macronr>=MAXMACROS) macronr=0; + } + else if (!strncmp(line, "devicefilename", 14)) { + strcpy(devicefilename[pad], val); + } + else if (!strncmp(line, "minzero", 7)) { + minzero[pad] = atoi(val); + } + else if (!strncmp(line, "maxzero", 7)) { + maxzero[pad] = atoi(val); + } + else if (!strncmp(line, "event_l2", 8)) PadButtons[pad][0] = String2EventCode(val); + else if (!strncmp(line, "event_r2", 8)) PadButtons[pad][1] = String2EventCode(val); + else if (!strncmp(line, "event_l1", 8)) PadButtons[pad][2] = String2EventCode(val); + else if (!strncmp(line, "event_r1", 8)) PadButtons[pad][3] = String2EventCode(val); + else if (!strncmp(line, "event_triangle", 14)) PadButtons[pad][4] = String2EventCode(val); + else if (!strncmp(line, "event_circle", 12)) PadButtons[pad][5] = String2EventCode(val); + else if (!strncmp(line, "event_cross", 11)) PadButtons[pad][6] = String2EventCode(val); + else if (!strncmp(line, "event_square", 12)) PadButtons[pad][7] = String2EventCode(val); + else if (!strncmp(line, "event_select", 12)) PadButtons[pad][8] = String2EventCode(val); + else if (!strncmp(line, "event_lanalog", 13)) PadButtons[pad][9] = String2EventCode(val); + else if (!strncmp(line, "event_ranalog", 13)) PadButtons[pad][10] = String2EventCode(val); + else if (!strncmp(line, "event_start", 11)) PadButtons[pad][11] = String2EventCode(val); + else if (!strncmp(line, "event_up", 8)) PadButtons[pad][12] = String2EventCode(val); + else if (!strncmp(line, "event_right", 11)) PadButtons[pad][13] = String2EventCode(val); + else if (!strncmp(line, "event_down", 10)) PadButtons[pad][14] = String2EventCode(val); + else if (!strncmp(line, "event_left", 10)) PadButtons[pad][15] = String2EventCode(val); + else if (!strncmp(line, "event_lanax", 11)) PadButtons[pad][16] = String2EventCode(val); + else if (!strncmp(line, "event_lanay", 11)) PadButtons[pad][17] = String2EventCode(val); + else if (!strncmp(line, "event_ranax", 11)) PadButtons[pad][18] = String2EventCode(val); + else if (!strncmp(line, "event_ranay", 11)) PadButtons[pad][19] = String2EventCode(val); + else if (!strncmp(line, "event_launch", 12)) macroLaunch[pad][macronr] = String2EventCode(val); + else if (!strncmp(line, "events", 6)) { + i=0; + while (*val) { + macroEvents[pad][macronr][i++]=String2EventCode(val); + while (*val && *val!=' ') val++; + if (*val==' ') val++; + } + macroEvents[pad][macronr][i]=NO_EVENT; + } + else if (!strncmp(line, "interval", 8)) { + i=0; + while (*val) { + macroInterval[pad][macronr][i++]=atol(val); + while (*val && *val!=' ') val++; + if (*val==' ') val++; + } + } +// else fprintf(stderr, "DFInput error: can't interpret %s\n", line); + } +} + +static int currentPad=0; + +static struct { + GtkWidget *config_window; + +/* ADB + GSList *padnogroup; + GtkWidget *padno_radio[2];*/ + GtkWidget *filename_entry; // TODO + GtkWidget *button[CONFIGBUTTONCOUNT]; + GtkWidget *label[CONFIGBUTTONCOUNT]; +/* ADB + GSList *pcsxgroup; + GtkWidget *epsxe_radio; + GtkWidget *pcsx_radio; + GtkWidget *thread_check; + GtkWidget *analog_check;*/ + GtkWidget *macro_button[MAXMACROS]; + GtkWidget *macro_label[MAXMACROS]; + GtkWidget *macro_def_button[MAXMACROS]; + + GtkWidget *ok_button; + GtkWidget *cancel_button; +} ConfWidgets; + +static struct { int nr; + char *label; + int x; + int y; } + buttonInfo[CONFIGBUTTONCOUNT] = +{ +{0, " L2 ", 20, 30}, +{2, " L1 ", 20, 70}, +{1, " R2 ", 350, 30}, +{3, " R1 ", 350, 70}, +{12, " ^ ", 70, 110}, +{15, " < ", 20, 140}, +{13, " > ", 120, 140}, +{14, " v ", 70, 170}, +{4, " /\\ ", 300, 110}, +{7, " [_] ", 250, 140}, +{5, " (_) ", 350, 140}, +{6, " >< ", 300, 170}, +{8, " Select ", 100, 200}, +{11, " Start ", 250, 200}, +{9, " + ", 90, 280}, +{10," + ", 320, 280}, +{16," -- ", 20, 280}, +{17," | ", 70, 250}, +{18," -- ",250, 280}, +{19," | ",300, 250} +}; + +static void showPadConfiguration() { + int i; + + // gtk_toggle_button_set_active(ConfWidgets.padno_radio[currentPad], TRUE); + // gtk_toggle_button_set_active(ConfWidgets.padno_radio[1-currentPad], FALSE); + + gtk_entry_set_text ( GTK_ENTRY(ConfWidgets.filename_entry), devicefilename[currentPad] ); + + for (i=0; i<CONFIGBUTTONCOUNT; i++) { + gtk_label_set(GTK_LABEL(ConfWidgets.label[i]), eventDescription(PadButtons[currentPad][buttonInfo[i].nr])); + } + + for (i=0; i<MAXMACROS; i++) { + gtk_label_set(GTK_LABEL(ConfWidgets.macro_label[i]), eventDescription(macroLaunch[currentPad][i])); + } +} + +static void OnConfCancel(GtkWidget *widget, gpointer user_data) { + loadConfig(); + gtk_widget_hide(ConfWidgets.config_window); + gtk_widget_destroy(ConfWidgets.config_window); + gtk_main_quit(); +} + +static void OnConfOk(GtkWidget *widget, gpointer user_data) { + saveConfig(); + gtk_widget_hide(ConfWidgets.config_window); + gtk_widget_destroy(ConfWidgets.config_window); + gtk_main_quit(); +} + +static void OnConfBtn(GtkWidget *But, gpointer data) { + EventCode events[MAXCNT]; + EventCode e=NO_EVENT; + int i,j,cnt; + KeySym ksym; + PadJoyEvent *pje; + int ok=0; + int labelnr = (int) gtk_object_get_user_data(GTK_OBJECT(But)); + int btnnr = buttonInfo[labelnr].nr; + int e_rem1 =NO_EVENT; + int e_rem2 =NO_EVENT; + + devicefile[currentPad] = open(devicefilename[currentPad], O_RDONLY); + + if (devicefilename[currentPad][0] && devicefile[currentPad] == -1) { + fprintf(stderr, "DFInput: could not open device %s, errno=%d\n", devicefilename[currentPad], errno); + } + + for (i=0; i<MAXDEVICES; i++) { + for (j=0; j<MAXAXES; j++) { + axestatus[i][j] = AXESTS_UNKNOWN; + } + } + + for (i=0; i<100 && !ok; i++) { + cnt = getPendingEvents(30, events, MAXCNT, 1, 1, 1, NULL); + + for (j=0; j<cnt && !ok; j++) { + e = events[j]; + if (e<RELEASE_EVENT) { + pje = EventCode2PadJoyEvent(e); + if (btnnr>15) { + if (pje->event_type == EVENTTYPE_AXISPLUS || pje->event_type == EVENTTYPE_AXISMINUS) { + e = ANALOGAXIS_EVENT(pje->pad, pje->no, 0); + PadButtons[currentPad][btnnr] = e; + ok = 1; + e_rem1 = AXISPLUS_EVENT(pje->pad, pje->no); + e_rem2 = AXISMINUS_EVENT(pje->pad, pje->no); + } + } + else if (e<FIRST_JOY_EVENT) { + ksym = e-FIRST_KEY_EVENT; + if (ksym != XK_Escape) { + PadButtons[currentPad][btnnr] = e; + ok=1; + } + } + else { + PadButtons[currentPad][btnnr] = e; + if (pje->event_type == EVENTTYPE_AXISPLUS || pje->event_type == EVENTTYPE_AXISMINUS) { + e_rem1 = ANALOGAXIS_EVENT(pje->pad, pje->no, 0); + } + ok=1; + } + } + + if (!ok) { + fprintf(stderr, "DFInput: event %ld (%s) is not usable.\n", (long) e, EventCode2String(e)); + } + } + } + + if (!ok) { + fprintf(stderr, "DFInput: no usable input received.\n"); + } + + while (getPendingEvents(0, events, MAXCNT, 1, 1, 1, NULL)){} // read pending events to clear buffers + + close(devicefile[currentPad]); + devicefile[currentPad] = -1; + + if (ok) { + // If this event is assigned to another button, remove this assignment + for (i=0; i<MAXDEVICES; i++) { + for (j=0; j<MAXPSXBUTTONS; j++) { + if ((PadButtons[i][j] == e || PadButtons[i][j] == e_rem1 || PadButtons[i][j] == e_rem2) && + (i!=currentPad || j!=btnnr)) { + PadButtons[i][j] = NO_EVENT; + } + } + for (j=0; j<MAXMACROS; j++) { + if (macroLaunch[i][j] == e || macroLaunch[i][j] == e_rem1 || macroLaunch[i][j] == e_rem2) { + macroLaunch[i][j] = NO_EVENT; + } + } + } + + showPadConfiguration(); + } +} + +static void OnMacroBtn(GtkWidget *But, gpointer data) { + EventCode events[MAXCNT]; + EventCode e=NO_EVENT; + PadJoyEvent *pje; + int i,j,cnt; + KeySym ksym; + int ok=0; + int e_rem1 =NO_EVENT; + + int macronr = (int) gtk_object_get_user_data(GTK_OBJECT(But)); + + devicefile[currentPad] = open(devicefilename[currentPad], O_RDONLY); + + for (i=0; i<MAXDEVICES; i++) { + for (j=0; j<MAXAXES; j++) { + axestatus[i][j] = AXESTS_UNKNOWN; + } + } + + for (i=0; i<100 && !ok; i++) { + cnt = getPendingEvents(30, events, MAXCNT, 1, 1, 1, NULL); + + for (j=0; j<cnt && !ok; j++) { + e = events[j]; + if (e<RELEASE_EVENT) { + pje = EventCode2PadJoyEvent(e); + if (e<FIRST_JOY_EVENT) { + ksym = e-FIRST_KEY_EVENT; + if (ksym != XK_Escape) { + macroLaunch[currentPad][macronr] = e; + ok=1; + } + } + else { + macroLaunch[currentPad][macronr] = e; + ok=1; + if (pje->event_type == EVENTTYPE_AXISPLUS || pje->event_type == EVENTTYPE_AXISMINUS) { + e_rem1 = ANALOGAXIS_EVENT(pje->pad, pje->no, 0); + } + } + } + } + } + while (getPendingEvents(0, events, MAXCNT, 1, 1, 1, NULL)){} // read pending events to clear buffers + + close(devicefile[currentPad]); + devicefile[currentPad] = -1; + + if (ok) { + // If this event is assigned to another button, remove this assignment + for (i=0; i<MAXDEVICES; i++) { + for (j=0; j<MAXPSXBUTTONS; j++) { + if (PadButtons[i][j] == e || PadButtons[i][j] == e_rem1) { + PadButtons[i][j] = NO_EVENT; + } + } + for (j=0; j<MAXMACROS; j++) { + if (macroLaunch[i][j] == e && (i!=currentPad || j!=macronr)) { + macroLaunch[i][j] = NO_EVENT; + } + } + } + + showPadConfiguration(); + } +} + +static void OnMacroDefineBtn(GtkWidget *But, gpointer data) { + EventCode events[MAXCNT]; + EventCode e=NO_EVENT; + PadJoyEvent *pje; + int i,j,cnt; + int ok=0; + long now; + long timing[MAXCNT]; + + int macronr = (int) gtk_object_get_user_data(GTK_OBJECT(But)); + + devicefile[currentPad] = open(devicefilename[currentPad], O_RDONLY); + + now = -1; + + for (i=0; i<MAXDEVICES; i++) { + for (j=0; j<MAXAXES; j++) { + axestatus[i][j] = AXESTS_UNUSED; + } + } + + for (i=0; i<MAXDEVICES; i++) { + for (j=0; j<MAXPSXBUTTONS; j++) { + pje = EventCode2PadJoyEvent(PadButtons[i][j]); + + if (pje->event_type == EVENTTYPE_AXISPLUS || pje->event_type == EVENTTYPE_AXISMINUS) { + axestatus[pje->pad][pje->no] = AXESTS_UNKNOWN; + } + else if (pje->event_type == EVENTTYPE_ANALOG && use_analog) { + axestatus[pje->pad][pje->no] = AXESTS_ANALOG; + } + } + } + + i=0; + + gtk_widget_add_events(ConfWidgets.config_window,GDK_KEY_RELEASE_MASK); + + /* Listen for input events until finished (Escape is pressed) or timeout */ + while (!ok && i<MAXMACROLENGTH-1) { + cnt = getPendingEvents(2000, events, MAXCNT, 1, 1, 1, timing); + + if (cnt && now<0) { + now=timing[0]; + } + else if (!cnt && i) { + // inactivity for 2 seconds, finish definition + ok=1; + } + + for (j=0; j<cnt && !ok && i<MAXMACROLENGTH-1; j++) { + e = events[j]; + if ((e-FIRST_KEY_EVENT) != XK_Escape && (e-FIRST_KEY_EVENT) != (XK_Escape+RELEASE_EVENT)) { + macroEvents[currentPad][macronr][i] = e; + macroInterval[currentPad][macronr][i] = timing[j]-now; + now = timing[j]; + i++; + } + else { + ok=1; + } + } + } + + if (i>0) { + macroEvents[currentPad][macronr][i] = NO_EVENT; + } + + close(devicefile[currentPad]); + devicefile[currentPad] = -1; + +} + +static void OnThreadCheck(GtkWidget *But, gpointer data) { + use_threads = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(But)); +} + +static void OnAnalogCheck(GtkWidget *But, gpointer data) { + use_analog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(But)); +} + +static void OnPadnoRadio(GtkWidget *But, gpointer data) { + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (But))) + currentPad = (int) data; + showPadConfiguration(); +} + +static void OnFilenameEntry(GtkWidget *Ent, gpointer data) { + strcpy(devicefilename[currentPad], gtk_entry_get_text(GTK_ENTRY(Ent))); +} + +/* Closed by clicking on the top-right hand corner */ +void on_config_win_clicked (GtkWidget *widget, gpointer user_data) { + gtk_widget_destroy (widget); + gtk_main_quit(); + exit (0); +} + +static void CreateConfigWindow(void) { + char buffer[100]; + int i; + GtkWidget *hbox; + + GladeXML *xml; + xml = glade_xml_new (DATADIR "dfinput.glade2", "CfgWin", NULL); + /* ADB TODO Error checking */ + + GtkWidget *widget = glade_xml_get_widget (xml, "CfgWin"); + ConfWidgets.config_window = widget; + GtkWidget *fixedbox = glade_xml_get_widget (xml, "fixed1"); + + g_signal_connect_data(GTK_OBJECT(widget), "delete_event", + GTK_SIGNAL_FUNC(on_config_win_clicked), NULL, NULL, G_CONNECT_AFTER); + +/* DELETE hbox = gtk_hbox_new(FALSE, 0); + gtk_fixed_put(GTK_FIXED(fixedbox), hbox, 10, 10); + gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("Pad number:"), FALSE, TRUE, 2);*/ + +// ConfWidgets.padnogroup = NULL; + + widget = glade_xml_get_widget (xml, "radiobutton1"); + g_signal_connect_data (GTK_OBJECT (widget), "toggled", + GTK_SIGNAL_FUNC (OnPadnoRadio), (gpointer) 0, NULL, G_CONNECT_AFTER); + widget = glade_xml_get_widget (xml, "radiobutton2"); + g_signal_connect_data (GTK_OBJECT (widget), "toggled", + GTK_SIGNAL_FUNC (OnPadnoRadio), (gpointer) 1, NULL, G_CONNECT_AFTER); + +// hbox = gtk_hbox_new(FALSE, 0); +// gtk_fixed_put (GTK_FIXED (fixedbox), hbox, 10, 40); + +// gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("Device file:"), FALSE, TRUE, 2); + /*ConfWidgets.filename_entry = gtk_entry_new();*/ + + widget = glade_xml_get_widget (xml, "filename_entry"); + gtk_entry_set_text ( GTK_ENTRY(widget), (gchar *) devicefilename[0] ); + gtk_entry_set_max_length ( GTK_ENTRY(widget), FILENAME_MAX); + //gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.filename_entry, FALSE, TRUE, 2); + gtk_signal_connect(GTK_OBJECT(widget), "changed", GTK_SIGNAL_FUNC(OnFilenameEntry), NULL); + ConfWidgets.filename_entry = widget; + +/* TODO + ConfWidgets.thread_check = gtk_check_button_new_with_label("multithreaded");*/ + widget = glade_xml_get_widget (xml, "chkMultithreaded"); + g_signal_connect_data (GTK_OBJECT (widget), "toggled", + GTK_SIGNAL_FUNC (OnThreadCheck), NULL, NULL, G_CONNECT_AFTER); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget), use_threads); + + /* TODO + ConfWidgets.analog_check = gtk_check_button_new_with_label("analog");*/ + widget = glade_xml_get_widget (xml, "chkAnalog"); + g_signal_connect_data (GTK_OBJECT (widget), "toggled", + GTK_SIGNAL_FUNC (OnAnalogCheck), NULL, NULL, G_CONNECT_AFTER); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget), use_analog); + + // Pad Buttons + for (i=0; i<CONFIGBUTTONCOUNT; i++) { + hbox = gtk_hbox_new(FALSE, 0); + ConfWidgets.button[i] = gtk_button_new_with_label(buttonInfo[i].label); + gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.button[i], FALSE, TRUE, 2); + gtk_fixed_put(GTK_FIXED(fixedbox), hbox, buttonInfo[i].x, buttonInfo[i].y); + gtk_object_set_user_data(GTK_OBJECT(ConfWidgets.button[i]), (char *)i); + gtk_signal_connect(GTK_OBJECT(ConfWidgets.button[i]), "clicked", GTK_SIGNAL_FUNC(OnConfBtn), NULL); + ConfWidgets.label[i] = gtk_label_new(eventDescription(PadButtons[0][buttonInfo[i].nr])); + gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.label[i], FALSE, TRUE, 2); + } + + hbox = gtk_hbox_new(FALSE, 0); + gtk_fixed_put(GTK_FIXED(fixedbox), hbox, 20, 390); + // Macro Buttons + for (i=0; i<MAXMACROS; i++) { + sprintf(buffer, "M%d", i+1); + ConfWidgets.macro_button[i] = gtk_button_new_with_label(buffer); + gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.macro_button[i], FALSE, TRUE, 2); + gtk_object_set_user_data(GTK_OBJECT(ConfWidgets.macro_button[i]), (char *)i); + gtk_signal_connect(GTK_OBJECT(ConfWidgets.macro_button[i]), "clicked", GTK_SIGNAL_FUNC(OnMacroBtn), NULL); + ConfWidgets.macro_label[i] = gtk_label_new(eventDescription(macroLaunch[0][i])); + gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.macro_label[i], FALSE, TRUE, 2); + ConfWidgets.macro_def_button[i] = gtk_button_new_with_label("Def"); + gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.macro_def_button[i], FALSE, TRUE, 2); + gtk_object_set_user_data(GTK_OBJECT(ConfWidgets.macro_def_button[i]), (char *)i); + gtk_signal_connect(GTK_OBJECT(ConfWidgets.macro_def_button[i]), "clicked", GTK_SIGNAL_FUNC(OnMacroDefineBtn), NULL); + if (i<MAXMACROS-1) { + gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(" "), FALSE, TRUE, 2); + } + } + + gtk_widget_show_all (GTK_WIDGET (fixedbox)); + + widget = glade_xml_get_widget (xml, "btnOK"); + g_signal_connect_data (GTK_OBJECT (widget), "clicked", GTK_SIGNAL_FUNC (OnConfOk), NULL, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget (xml, "btnCancel"); + g_signal_connect_data (GTK_OBJECT (widget), "clicked", GTK_SIGNAL_FUNC (OnConfCancel), NULL, NULL, G_CONNECT_AFTER); +} + +long PADconfigure(void) { + currentPad = 0; + initPadtime(); + PADinit(0); + CreateConfigWindow(); + gtk_widget_show_all(ConfWidgets.config_window); + + gtk_main(); + + return 0; +} + + +/*---------------------------------------------------------------------*/ +/* About dialogue stuff */ +/*---------------------------------------------------------------------*/ + +void PADabout(void) { + GladeXML *xml; + xml = glade_xml_new (DATADIR "dfinput.glade2", "AboutWin", NULL); + + GtkWidget *widget = glade_xml_get_widget (xml, "AboutWin"); + + /* TODO Authors, about, version */ + + gtk_dialog_run (GTK_DIALOG (widget)); + gtk_widget_destroy (widget); +// gtk_main_quit(); +} + +/*---------------------------------------------------------------------*/ +/* Main program */ +/*---------------------------------------------------------------------*/ + +int main(int argc, char **argv) { + gtk_set_locale(); + gtk_init (&argc, &argv); + + if (argc>1 && !strcmp(argv[1], "-about")) { + PADabout(); + } + else { + PADconfigure(); + } + + gtk_exit (0); + + return 0; +} diff --git a/plugins/dfinput/dfinput.glade2 b/plugins/dfinput/dfinput.glade2 new file mode 100644 index 00000000..b6905f2e --- /dev/null +++ b/plugins/dfinput/dfinput.glade2 @@ -0,0 +1,226 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--*- mode: xml -*--> +<glade-interface> + <widget class="GtkWindow" id="CfgWin"> + <property name="visible">True</property> + <property name="title" translatable="yes">Configure Gamepad/Keyboard</property> + <property name="modal">True</property> + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="border_width">6</property> + <property name="spacing">6</property> + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="border_width">6</property> + <property name="spacing">50</property> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Pad number:</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="radiobutton1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">1</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="radiobutton2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">2</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + <property name="group">radiobutton1</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="border_width">6</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes">Device file:</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="filename_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="visible">True</property> + <property name="border_width">6</property> + <property name="spacing">6</property> + <child> + <widget class="GtkCheckButton" id="chkMultithreaded"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Multi-threaded</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chkAnalog"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Analog</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkFrame" id="frame1"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">GTK_SHADOW_OUT</property> + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="bottom_padding">5</property> + <property name="left_padding">12</property> + <property name="right_padding">12</property> + <child> + <widget class="GtkFixed" id="fixed1"> + <property name="visible">True</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Button Configuration</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkHButtonBox" id="hbuttonbox1"> + <property name="visible">True</property> + <property name="spacing">6</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <widget class="GtkButton" id="btnCancel"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + </child> + <child> + <widget class="GtkButton" id="btnOK"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkAboutDialog" id="AboutWin"> + <property name="visible">True</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="comments" translatable="yes">Based on PadJoy by Erich Kitzmüller (ammoq@ammoq.com)</property> + <property name="authors">Erich Kitzmüller (ammoq@ammoq.com) +Andrew Burton (adb@iinet.net.au)</property> + <property name="translator_credits" translatable="yes" comments="TRANSLATORS: Replace this string with your names, one name per line.">translator-credits</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox1"> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area1"> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/plugins/dfinput/pad.c b/plugins/dfinput/pad.c new file mode 100644 index 00000000..dd564479 --- /dev/null +++ b/plugins/dfinput/pad.c @@ -0,0 +1,989 @@ +/* + * Pad for Psemu Pro like Emulators + * This is the plugin + * + * Modified for PCSX-df by Ryan Schultz + * + * Written by Erich Kitzmuller <ammoq@ammoq.com> + * Based on padXwin by linuzappz <linuzappz@hotmail.com> + * + * Copyright 2002,2003 by Erich Kitzmuller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#ifdef __linux__ +#include <linux/joystick.h> +#endif +#include <sys/stat.h> +#include <sys/time.h> +#include <unistd.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/XKBlib.h> +#include <pthread.h> +#include <errno.h> +#include "padjoy.h" + +#ifdef __linux__ +char *LibName = "Gamepad/Keyboard Input"; +#else +char *LibName = "Keyboard Input"; +#endif + +const unsigned char version = VERSION; +const unsigned char revision = REVISION; +const unsigned char build = BUILD; + +// Prototypes +static void loadConfig(); +static void *thread_check_joydevice(void *arg); +static void initPadtime(); +static PadJoyEvent *EventCode2PadJoyEvent(EventCode p_e); + +// Filenames for device files, e.g. "/dev/input/js0" +static char devicefilename[MAXDEVICES][FILENAME_MAX+1] = {"/dev/input/js0", "/dev/input/js1"}; + +// File desciptors for device files +static int devicefile[MAXDEVICES] = { -1, -1 }; + +// Use Threading for joy device input? +static int use_threads = 1; +static pthread_t joy_thread; +static int die_thread_die = 0; + +// Emulate Dualshock(TM) analog pad? +static int use_analog = 0; + +// any joydevice open? +static int joydevice_open = 0; + +// initialisation already done? +static int init_done = 0; + +// calibration data +int minzero[MAXAXES]; +int maxzero[MAXAXES]; + +// axes status - so only changing status are reported +int axestatus[MAXDEVICES][MAXAXES]; + +// Assignment of PSX buttons to Events +static EventCode PadButtons[MAXDEVICES][MAXPSXBUTTONS] = +{ + { + KEY_EVENT(XK_e), // L2 + KEY_EVENT(XK_t), // R2 + KEY_EVENT(XK_w), // L1 + KEY_EVENT(XK_r), // R1 + KEY_EVENT(XK_d), // Triangle + KEY_EVENT(XK_x), // Circle + KEY_EVENT(XK_z), // Cross + KEY_EVENT(XK_s), // Square + KEY_EVENT(XK_c), // Select + NO_EVENT, // Left Analog + NO_EVENT, // Right Analog + KEY_EVENT(XK_v), // Start + KEY_EVENT(XK_Up), // Up + KEY_EVENT(XK_Right), // Right + KEY_EVENT(XK_Down), // Down + KEY_EVENT(XK_Left), // Left + NO_EVENT, // Left Analog X + NO_EVENT, // Left Analog Y + NO_EVENT, // Right Analog X + NO_EVENT // Right Analog Y + }, + { + NO_EVENT, // L2 + NO_EVENT, // R2 + NO_EVENT, // L1 + NO_EVENT, // R1 + NO_EVENT, // Triangle + NO_EVENT, // Circle + NO_EVENT, // Cross + NO_EVENT, // Square + NO_EVENT, // Select + NO_EVENT, // Left Analog + NO_EVENT, // Right Analog + NO_EVENT, // Start + NO_EVENT, // Up + NO_EVENT, // Right + NO_EVENT, // Down + NO_EVENT, // Left + NO_EVENT, // Left Analog X + NO_EVENT, // Left Analog Y + NO_EVENT, // Right Analog X + NO_EVENT // Right Analog Y + } +}; + +static Display *Dsp; +static Atom wmprotocols, wmdelwindow; + +static EventCode macroLaunch[MAXDEVICES][MAXMACROS]; +static EventCode macroEvents[MAXDEVICES][MAXMACROS][MAXMACROLENGTH]; +static long macroInterval[MAXDEVICES][MAXMACROS][MAXMACROLENGTH]; +static int macroActive[MAXDEVICES]; +static int macroIndex[MAXDEVICES]; +static long macroNext[MAXDEVICES]; + +unsigned short PadStat[MAXDEVICES] = {0xffff, 0xffff}; + +int AnalogValue[MAXDEVICES][MAXPSXBUTTONS-4] = {{127,127,127,127}, {127,127,127,127}}; + +char *PSEgetLibName(void) { + return LibName; +} + +uint32_t PSEgetLibType(void) { + return 8; // PSE_LT_PAD +} + +uint32_t PSEgetLibVersion(void) { + return version<<16|revision<<8|build; +} + +void init_macros() { + int i,j; + + for (i=0; i<MAXDEVICES; i++) { + for (j=0; j<MAXMACROS; j++) { + macroLaunch[i][j] = NO_EVENT; + macroEvents[i][j][0] = NO_EVENT; + macroInterval[i][j][0] = 0; + } + macroActive[i] = -1; + macroIndex[i] = 0; + macroNext[i] = 0; + } +} + +long PADinit(long flags) { + int i,j; + + init_macros(); + initPadtime(); + for (i = 0; i < MAXDEVICES; i++) { + maxzero[i] = 250; + minzero[i] = -250; + + for (j = 0; j < MAXAXES; j++) { + axestatus[i][j] = AXESTS_UNKNOWN; + } + } + loadConfig(); + + return 0; +} + +long PADshutdown(void) { + return 0; +} + +long PADopen(unsigned long *Disp) { + int i,j; + int res; + PadJoyEvent *pje; + + if (init_done) { +// fprintf(stderr, "DFInput warning: device already initialized.\n"); + return 0; + } + + Dsp = (Display *)*Disp; + XkbSetDetectableAutoRepeat(Dsp, 1, NULL); + + // TODO: find a way to grab the window, and set protocol WM_DELETE_WINDOW if not already set by the video plugin + wmprotocols = XInternAtom(Dsp,"WM_PROTOCOLS",0); + wmdelwindow = XInternAtom(Dsp,"WM_DELETE_WINDOW",0); + //XSetWMProtocols(Dsp, window, &wmdelwindow, 1); //need window! + + joydevice_open = 0; + +#ifdef __linux__ + for (i = 0; i < MAXDEVICES; i++) { + if (devicefilename[i][0]) { + devicefile[i] = open(devicefilename[i], O_RDONLY); + if (devicefile[i] == -1) { + fprintf(stderr, "DFInput error: could not open device %s!\n", devicefilename[i]); + } + else { + joydevice_open = 1; + } + } + else { + devicefile [i] = -1; + } + } +#endif + + for (i = 0; i < MAXDEVICES; i++) { + for (j = 0; j < MAXAXES; j++) { + axestatus[i][j] = AXESTS_UNUSED; + } + } + + for (i=0; i<MAXDEVICES; i++) { + for (j = 0; j < MAXPSXBUTTONS; j++) { + pje = EventCode2PadJoyEvent(PadButtons[i][j]); + + if (pje->event_type == EVENTTYPE_AXISPLUS || pje->event_type == EVENTTYPE_AXISMINUS) { + axestatus[pje->pad][pje->no] = AXESTS_UNKNOWN; + } +#ifdef __linux__ + else if (pje->event_type == EVENTTYPE_ANALOG && use_analog) { + axestatus[pje->pad][pje->no] = AXESTS_ANALOG; + } +#endif + } + } + +#ifdef __linux__ + if (use_threads) { + die_thread_die = 0; + if (joydevice_open) { + fprintf(stderr, "DFInput: starting thread...\n"); + sleep(1); + res = pthread_create(&joy_thread, NULL, thread_check_joydevice, (void *) NULL); + + if (res!=0) { + fprintf(stderr, "DFInput warning: thread failure, switching to polling!\n"); + use_threads = 0; + } + } + } +#endif + + init_done = 1; + + return 0; +} + +long PADclose(void) { + int i; + +#ifdef __linux__ + for (i=0; i<2; i++) { + if (devicefile[i] > -1) { + close (devicefile[i]); + } + } + + if (use_threads) { + die_thread_die = 1; + if (joydevice_open) { + pthread_join(joy_thread, (void **) NULL); + } + } +#endif + + init_done=0; + + XAutoRepeatOn(Dsp); + + return 0; +} + +long PADquery(void) { + return 3; // both pads +} + +static long firstsecond = 0; + +static void initPadtime() { + struct timeval tv; + gettimeofday(&tv, NULL); + firstsecond = tv.tv_sec; +} + +// construct a time on our own +long getPadtime() { + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec-firstsecond)*10000+tv.tv_usec/100; +} + +// get pending events +static int getPendingEvents(int millisecondstowait, EventCode *events, int maxevents, int checkJoydevice, int checkXKeyboard, long *timing) { + fd_set rfds; + int retval; + int i; + int md; + int eventsread=0; + XEvent xe; + XClientMessageEvent *xce; + int cntopen; + struct timeval tv; + int oldstatus; + +#ifdef __linux__ + struct js_event je; + + if (checkJoydevice) { + FD_ZERO(&rfds); + md = -1; + cntopen=0; + for (i=0; i<MAXDEVICES; i++) { + if (devicefile[i] > -1) { + FD_SET(devicefile[i], &rfds); + cntopen++; + } + if (devicefile[i] > md) md = devicefile[i]; + } + tv.tv_sec = millisecondstowait / 1000; + tv.tv_usec = 1000 * (millisecondstowait % 1000); + + retval = select(md + 1, &rfds, NULL, NULL, &tv); + + while (retval && eventsread < maxevents - 2 * checkXKeyboard) { + for (i = 0; i < MAXDEVICES; i++) { + if (devicefile[i] > -1 && FD_ISSET(devicefile[i], &rfds)) { + read (devicefile[i], &je, 8); + + if (je.type == JS_EVENT_AXIS && je.number < MAXAXES) { + if (axestatus[i][je.number] == AXESTS_ANALOG) { + /* this axe should be reported analog */ + events[eventsread++] = ANALOGAXIS_EVENT(i,je.number, (je.value + 32768) >> 8); + if (timing) { + (*timing) = getPadtime(); + timing++; + } + if (eventsread == maxevents) return eventsread; + + } + else if (je.value > maxzero[i]) { + if (axestatus[i][je.number] != AXESTS_PLUS && + axestatus[i][je.number] != AXESTS_UNUSED) { + + oldstatus = axestatus[i][je.number]; + + axestatus[i][je.number] = AXESTS_PLUS; + + events[eventsread++] = AXISPLUS_EVENT(i, je.number); + if (timing) { + (*timing) = getPadtime(); + timing++; + } + if (eventsread==maxevents) return eventsread; + + if (oldstatus == AXESTS_MINUS) { + events[eventsread++] = RELEASE_EVENT + AXISMINUS_EVENT(i, je.number); + if (timing) { + (*timing) = getPadtime(); + timing++; + } + if (eventsread == maxevents) return eventsread; + } + + } + } + else if (je.value < minzero[i]) { + if (axestatus[i][je.number] != AXESTS_MINUS && + axestatus[i][je.number] != AXESTS_UNUSED) { + + oldstatus = axestatus[i][je.number]; + + axestatus[i][je.number] = AXESTS_MINUS; + + events[eventsread++] = AXISMINUS_EVENT(i, je.number); + if (timing) { + (*timing) = getPadtime(); + timing++; + } + if (eventsread == maxevents) return eventsread; + + if (oldstatus == AXESTS_PLUS) { + events[eventsread++] = RELEASE_EVENT+AXISPLUS_EVENT(i, je.number); + if (timing) { + (*timing) = getPadtime(); + timing++; + } + if (eventsread == maxevents) return eventsread; + } + } + } + else { + if (axestatus[i][je.number] != AXESTS_CENTER && + axestatus[i][je.number] != AXESTS_UNUSED) { + + oldstatus = axestatus[i][je.number]; + + axestatus[i][je.number] = AXESTS_CENTER; + + if (oldstatus == AXESTS_PLUS) { + events[eventsread++] = RELEASE_EVENT+AXISPLUS_EVENT(i,je.number); + if (timing) { + (*timing) = getPadtime(); + timing++; + } + if (eventsread == maxevents) return eventsread; + } + else if (oldstatus == AXESTS_MINUS) { + events[eventsread++] = RELEASE_EVENT+AXISMINUS_EVENT(i,je.number); + if (timing) { + (*timing) = getPadtime(); + timing++; + } + if (eventsread == maxevents) return eventsread; + } + } + } + } + else if (je.type == JS_EVENT_BUTTON && je.number<MAXBUTTONS) { + events[eventsread++] = (je.value ? 0 : RELEASE_EVENT) + BUTTON_EVENT(i, je.number); + if (timing) { + (*timing) = getPadtime(); + timing++; + } + if (eventsread == maxevents) return eventsread; + } + } + } + tv.tv_sec = 0; + tv.tv_usec = 0; + + retval = select(md + 1, &rfds, NULL, NULL, &tv); + } + + } +#endif + + if (checkXKeyboard) { + while ((i = XPending(Dsp))) { + while (i--) { + XNextEvent(Dsp, &xe); + switch (xe.type) { + case KeyPress: + events[eventsread++] = KEY_EVENT(XLookupKeysym((XKeyEvent *)&xe, 0)); + if (timing) { + (*timing) = getPadtime(); + timing++; + } + if (eventsread == maxevents) return eventsread; + break; + case KeyRelease: + events[eventsread++] = RELEASE_EVENT + KEY_EVENT(XLookupKeysym((XKeyEvent *)&xe, 0)); + if (timing) { + (*timing) = getPadtime(); + timing++; + } + if (eventsread == maxevents) return eventsread; + break; + case ClientMessage: + xce = (XClientMessageEvent *)&xe; + if (xce->message_type == wmprotocols && (Atom)xce->data.l[0] == wmdelwindow) { + events[eventsread++] = KEY_EVENT(XK_Escape); + if (eventsread == maxevents) return eventsread; + } + break; +/* + case FocusIn: + XAutoRepeatOff(Dsp); + break; + case FocusOut: + XAutoRepeatOn(Dsp); + break; +*/ + } + } + } + } + + return eventsread; +} + +// Key Event not used... +static EventCode keyLeftOver = NO_EVENT; + +static void CheckPads(int checkJoydevice, int checkXKeyboard, int blocking) { + EventCode events[MAXCNT]; + int cnt; + int release; + EventCode e; + int i,j,k,l; + int notfound; + long now; + int v; + + if (checkJoydevice || checkXKeyboard) { + cnt = getPendingEvents(blocking<<8, events, MAXCNT, checkJoydevice, checkXKeyboard, NULL); + } + else { + cnt = 0; + } + + // more events come from the macros + // only process makros when blocking is not set, since + // this cannot be done by the joy device thread + + if (!blocking) { + now= -1; + for (j = 0; j < MAXDEVICES; j++) { + if (macroActive[j] > -1) { + if (now < 0) { + now = getPadtime(); + } + + while (now >= macroNext[j] && cnt < MAXCNT && macroActive[j] > -1) { + events[cnt++]=macroEvents[j][macroActive[j]][macroIndex[j]]; + macroIndex[j]++; + if (macroIndex[j] == MAXMACROLENGTH || macroEvents[j][macroActive[j]][macroIndex[j]] == NO_EVENT) { + macroActive[j] = -1; + } + else { + macroNext[j] += macroInterval[j][macroActive[j]][macroIndex[j]]; + } + } + } + } + } + + for (i = 0; i < cnt; i++) { + e = events[i]; + if (e >= RELEASE_EVENT) { + release = 1; + e -= RELEASE_EVENT; + } + else { + release = 0; + } + + notfound = 1; + if (e >= FIRST_ANALOG_EVENT) { + v = e & 0xff; + e -= v; + for (j = 0; j < MAXDEVICES && notfound; j++) { + for (k = 16; k < MAXPSXBUTTONS && notfound; k++) { + if (PadButtons[j][k] == e) { + AnalogValue[j][k - 16] = v; + notfound = 0; + } + } + } + } + else + { + for (j=0; j<MAXDEVICES && notfound; j++) { + for (k=0; k<MAXPSXBUTTONS && notfound; k++) { + if (PadButtons[j][k] == e) { + notfound = 0; + if (release) { + PadStat[j]|=(1<<k); + } + else { + PadStat[j]&=~(1<<k); + } + } + } + for (k=0; k<MAXMACROS && notfound; k++) { + if (macroLaunch[j][k] == e) { + notfound=0; + if (release) { + // release all buttons pressed by the macro + for (l=macroIndex[j]; l<MAXMACROLENGTH && macroEvents[j][macroActive[j]][l] != NO_EVENT; l++) { + if (macroEvents[j][macroActive[j]][l] >= RELEASE_EVENT) { + if (cnt<MAXCNT) { + events[cnt++]=macroEvents[j][macroActive[j]][l]; + } + } + + } + + macroActive[j]= -1; // stop Makro from running + } + else { + macroActive[j]=k; + macroIndex[j]=0; + macroNext[j]=getPadtime(); + } + } + } + } + } + if (notfound && e < FIRST_JOY_EVENT) { + keyLeftOver = e + (release << 30); + } + } +} + + +long PADreadPort1(PadDataS *pad) { + if (!use_threads) { + CheckPads(joydevice_open, 1, 0); + } + else { + CheckPads(0, 1, 0); + } + + pad->buttonStatus = PadStat[0]; +#ifdef __linux__ + if (use_analog) { + pad->controllerType = 7; // analog Pad + pad->leftJoyX = AnalogValue[0][0]; + pad->leftJoyY = AnalogValue[0][1]; + pad->rightJoyX = AnalogValue[0][2]; + pad->rightJoyY = AnalogValue[0][3]; + } + else { +#endif + pad->controllerType = 4; // standard +#ifdef __linux__ + } +#endif + // ePSXe different from pcsx, swap bytes + pad->buttonStatus = (pad->buttonStatus>>8)|(pad->buttonStatus<<8); + + return 0; +} + +long PADreadPort2(PadDataS *pad) { + if (!use_threads) { + CheckPads(joydevice_open, 1, 0); + } + else { + CheckPads(0, 1, 0); + } + + pad->buttonStatus = PadStat[1]; +#ifdef __linux__ + if (use_analog) { + pad->controllerType = 7; // analog Pad + pad->leftJoyX = AnalogValue[1][0]; + pad->leftJoyY = AnalogValue[1][1]; + pad->rightJoyX = AnalogValue[1][2]; + pad->rightJoyY = AnalogValue[1][3]; + } + else { +#endif + pad->controllerType = 4; // standard +#ifdef __linux__ + } +#endif + + // ePSXe different from pcsx, swap bytes + pad->buttonStatus = (pad->buttonStatus>>8)|(pad->buttonStatus<<8); + + return 0; +} + +long PADkeypressed(void) { + int ksym; + + CheckPads(0, 1, 1); + + if (keyLeftOver == NO_EVENT) return 0; + + ksym = keyLeftOver-FIRST_KEY_EVENT; + keyLeftOver = NO_EVENT; + + return ksym; +} + +#ifdef __linux__ + +static void *thread_check_joydevice(void *arg) { + while (!die_thread_die) { + CheckPads(1, 0, 1); + } + return NULL; +} + +#endif + +// analyse Eventcode +static PadJoyEvent *EventCode2PadJoyEvent(EventCode p_e) { + static PadJoyEvent event; + EventCode e; + int i,p; + + event.event_type = EVENTTYPE_NONE; + event.pad = 0; + event.no = 0; + event.value = 0; + + if (!p_e) { + return &event; + } + + e = p_e; + + if (e > RELEASE_EVENT) { + event.value = 0; + e -= RELEASE_EVENT; + } + else { + event.value = 1; + } + + if (e && e<FIRST_JOY_EVENT) { + event.event_type = EVENTTYPE_KEY; + event.no = e; + return &event; + } + + if (e >= FIRST_ANALOG_EVENT) { + event.event_type = EVENTTYPE_ANALOG; + event.pad = (e-FIRST_ANALOG_EVENT)/(256*MAXAXES); + event.no = (e-ANALOGAXIS_EVENT(event.pad,0,0))/256; + event.value = e & 0xff; + return &event; + } + + + for (p=0; p<MAXDEVICES; p++) { + for (i=0; i<MAXAXES; i++) { + if (e == AXISPLUS_EVENT(p,i)) { + event.event_type = EVENTTYPE_AXISPLUS; + event.pad = p; + event.no = i; + return &event; + } + if (e == AXISMINUS_EVENT(p,i)) { + event.event_type = EVENTTYPE_AXISMINUS; + event.pad = p; + event.no = i; + return &event; + } + } + + for (i=0; i<MAXBUTTONS; i++) { + if (e == BUTTON_EVENT(p,i)) { + event.event_type = EVENTTYPE_BUTTON; + event.pad = p; + event.no = i; + return &event; + } + } + } + + return &event; +} + + +// reversal of EventCode2String +static EventCode String2EventCode(char *s) { + static char buffer[256]; + int i,p; + char *q; + char push_release; + EventCode e; + + if (s[0] >= '0' && s[0] <= '9') return atoi(s); // allow numeric input + + e=0; + push_release = 'P'; + + switch(s[0]) { + case 'K': + push_release = s[1]; + strncpy(buffer, s + 3, 255); + q=buffer; + i=1; + while (*q) { + if (*q=='"') i = !i; + if (*q==' ' && !i) + *q='\0'; + else + q++; + } + if (s[2]=='"' && buffer[0] && buffer[strlen(buffer)-1]=='"') { + buffer[strlen(buffer)-1] = '\0'; + e = KEY_EVENT(XStringToKeysym(buffer)); + } + break; + case 'A': + if (s[1] >= '0' && s[1] <= '1' && strlen(s) >= 5) { + p = s[1] - '0'; + push_release = s[2]; + i = atoi(s+3); + q=s+3; + while (*q && *q != '+' && *q != '-') q++; + if (*q == '+') + e = AXISPLUS_EVENT(p,i); + else if (*q == '-') + e = AXISMINUS_EVENT(p,i); + } + break; + case 'B': + if (s[1] >= '0' && s[1] <= '1' && strlen(s) >= 4) { + p = s[1] - '0'; + push_release = s[2]; + i = atoi(s + 3); + e = BUTTON_EVENT(p, i); + } + break; + case 'X': + if (s[1] >= '0' && s[1] <= '1' && strlen(s) >= 5) { + p = s[1] - '0'; + i = atoi(s + 3); + q = s + 3; + while (*q && *q != 'v') q++; + if (*q == 'v') + e = ANALOGAXIS_EVENT(p,i,atoi(q + 1)); + } + break; + } + + if (push_release == 'R') + return e + RELEASE_EVENT; + else + return e; +} + +static void loadConfig() { + FILE *f; + int i; + char line[FILENAME_MAX+30]; + int pad=0; + int macronr=0; + char *val; + + f = fopen("dfinput.cfg", "r"); + if (f == NULL) { +// fprintf(stderr, "DFInput warning: config file not found.\n"); + return; + } + + while(!feof(f)) { + fgets(line, FILENAME_MAX+29, f); + i=strlen(line)-1; + while (i>0 && line[i]<32) line[i--]='\0'; + + val=NULL; + while(i>0) { + if (line[i]=='=') val = line+(i+1); + i--; + } + if (val) { + while (*val==' ') val++; + } + + if (!strcmp(line, "[general]")) { + // nothing to do + } + else if (!strncmp(line, "use_threads", 11)) { + use_threads = atoi(val); + } + else if (!strncmp(line, "use_analog", 10)) { + use_analog = atoi(val); + } + + else if (!strcmp(line, "[pad 1]")) { + pad = 0; + } + else if (!strcmp(line, "[pad 2]")) { + pad = 1; + } + else if (!strncmp(line, "[macro ", 7)) { + macronr = atoi(line+7)-1; + if (macronr<0 || macronr>=MAXMACROS) macronr=0; + } + else if (!strncmp(line, "devicefilename", 14)) { + strcpy(devicefilename[pad], val); + } + else if (!strncmp(line, "minzero", 7)) { + minzero[pad] = atoi(val); + } + else if (!strncmp(line, "maxzero", 7)) { + maxzero[pad] = atoi(val); + } + else if (!strncmp(line, "event_l2", 8)) PadButtons[pad][0] = String2EventCode(val); + else if (!strncmp(line, "event_r2", 8)) PadButtons[pad][1] = String2EventCode(val); + else if (!strncmp(line, "event_l1", 8)) PadButtons[pad][2] = String2EventCode(val); + else if (!strncmp(line, "event_r1", 8)) PadButtons[pad][3] = String2EventCode(val); + else if (!strncmp(line, "event_triangle", 14)) PadButtons[pad][4] = String2EventCode(val); + else if (!strncmp(line, "event_circle", 12)) PadButtons[pad][5] = String2EventCode(val); + else if (!strncmp(line, "event_cross", 11)) PadButtons[pad][6] = String2EventCode(val); + else if (!strncmp(line, "event_square", 12)) PadButtons[pad][7] = String2EventCode(val); + else if (!strncmp(line, "event_select", 12)) PadButtons[pad][8] = String2EventCode(val); + else if (!strncmp(line, "event_lanalog", 13)) PadButtons[pad][9] = String2EventCode(val); + else if (!strncmp(line, "event_ranalog", 13)) PadButtons[pad][10] = String2EventCode(val); + else if (!strncmp(line, "event_start", 11)) PadButtons[pad][11] = String2EventCode(val); + else if (!strncmp(line, "event_up", 8)) PadButtons[pad][12] = String2EventCode(val); + else if (!strncmp(line, "event_right", 11)) PadButtons[pad][13] = String2EventCode(val); + else if (!strncmp(line, "event_down", 10)) PadButtons[pad][14] = String2EventCode(val); + else if (!strncmp(line, "event_left", 10)) PadButtons[pad][15] = String2EventCode(val); + else if (!strncmp(line, "event_lanax", 11)) PadButtons[pad][16] = String2EventCode(val); + else if (!strncmp(line, "event_lanay", 11)) PadButtons[pad][17] = String2EventCode(val); + else if (!strncmp(line, "event_ranax", 11)) PadButtons[pad][18] = String2EventCode(val); + else if (!strncmp(line, "event_ranay", 11)) PadButtons[pad][19] = String2EventCode(val); + else if (!strncmp(line, "event_launch", 12)) macroLaunch[pad][macronr] = String2EventCode(val); + else if (!strncmp(line, "events", 6)) { + i=0; + while (*val) { + macroEvents[pad][macronr][i++]=String2EventCode(val); + while (*val && *val!=' ') val++; + if (*val==' ') val++; + } + macroEvents[pad][macronr][i]=NO_EVENT; + } + else if (!strncmp(line, "interval", 8)) { + i=0; + while (*val) { + macroInterval[pad][macronr][i++]=atol(val); + while (*val && *val!=' ') val++; + if (*val==' ') val++; + } + } +// else fprintf(stderr, "DFInput error: can't interpret %s\n", line); + } +} + +long PADconfigure(void) { + system("cfg/cfgDFInput"); + return 0; +} + + +/*---------------------------------------------------------------------*/ +/* About dialogue stuff */ +/*---------------------------------------------------------------------*/ + + +void PADabout(void) { + system("cfg/cfgDFInput -about"); +} + +#ifdef __linux__ + +long PADtest(void) { + int i; + int f; + + int r=1; + + loadConfig(); + for (i=0; i<2; i++) { + if (devicefilename[i][0]) { + r = 0; + f = open(devicefilename[i], O_RDONLY); + if (f == -1) { + return -1; + } + close (f); + } + } + + return r; +} + +#endif diff --git a/plugins/dfinput/padjoy.h b/plugins/dfinput/padjoy.h new file mode 100644 index 00000000..e51f2db4 --- /dev/null +++ b/plugins/dfinput/padjoy.h @@ -0,0 +1,82 @@ +#ifndef _PADJOY_H_ + +#define _PADJOY_H_ + +#define DEBUG(x) fprintf(stderr, "DFInput: %s\n", x); + +// Maximum number of joy devices +#define MAXDEVICES 2 +// Maximum number of supported axis (per device, a normal joystick has 2) +#define MAXAXES 20 +// Maximum number of supported buttons (per device) +#define MAXBUTTONS 32 +// Number of PSX-Buttons (including analog axis) +#define MAXPSXBUTTONS 20 + +// Status of digital Axes (avoids repeated events of the same type on an analog pad) +#define AXESTS_UNUSED -1 +#define AXESTS_UNKNOWN 0 +#define AXESTS_CENTER 1 +#define AXESTS_PLUS 2 +#define AXESTS_MINUS 3 +#define AXESTS_ANALOG 4 + +// every kind of supported event is coded into a long int +typedef int32_t EventCode; + +// Position of directional buttons in PadButtons +#define PSXBTN_UP 12 +#define PSXBTN_RIGHT 13 +#define PSXBTN_DOWN 14 +#define PSXBTN_LEFT 15 + +// macros to define Eventcodes +// this may look like I make it too complicated, but it keeps things open for future improvements +#define NO_EVENT 0 +#define FIRST_KEY_EVENT 0 +#define FIRST_JOY_EVENT (1<<16) +#define RELEASE_EVENT (1<<30) +#define FIRST_ANALOG_EVENT (1<<20) + +#define KEY_EVENT(n) (FIRST_KEY_EVENT+(n)) +#define AXISPLUS_EVENT(p,n) (FIRST_JOY_EVENT+2*(n)+(p)*(2*MAXAXES+MAXBUTTONS)) +#define AXISMINUS_EVENT(p,n) (FIRST_JOY_EVENT+2*(n)+1+(p)*(2*MAXAXES+MAXBUTTONS)) +#define BUTTON_EVENT(p,n) (FIRST_JOY_EVENT+2*MAXAXES+(n)+(p)*(2*MAXAXES+MAXBUTTONS)) +#define ANALOGAXIS_EVENT(p,n,v) (FIRST_ANALOG_EVENT+256*(n)+(v)+(p)*(256*MAXAXES)) + +// Makro Definitions etc. +#define MAXMACROS 3 +#define MAXMACROLENGTH 100 + +typedef struct +{ + unsigned char controllerType; + unsigned short buttonStatus; + unsigned char rightJoyX, rightJoyY, leftJoyX, leftJoyY; + unsigned char moveX, moveY; + unsigned char reserved[91]; +} PadDataS; + +// Number of events to fetch at once... +#define MAXCNT 100 + +/* number of buttons required for configuration */ +#define CONFIGBUTTONCOUNT 20 + +#define EVENTTYPE_NONE -1 +#define EVENTTYPE_KEY 0 +#define EVENTTYPE_BUTTON 1 +#define EVENTTYPE_AXISPLUS 2 +#define EVENTTYPE_AXISMINUS 3 +#define EVENTTYPE_ANALOG 4 + +// The following struct is used in the config part only +typedef struct +{ + unsigned int event_type; // Button, Axe, AnalogAxe + unsigned int pad; + unsigned int no; // Keycode in case of key event + int value; // 0=release, 1=press, or analog value in case of EVENTTYPE_ANALOG +} PadJoyEvent; + +#endif diff --git a/plugins/dfsound/Makefile.am b/plugins/dfsound/Makefile.am new file mode 100644 index 00000000..5e4db842 --- /dev/null +++ b/plugins/dfsound/Makefile.am @@ -0,0 +1,33 @@ +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) $(GLADE2_CFLAGS) \ + -DVERSION=0 -DREVISION=1 -DBUILD=0 + +bindir = @libdir@/games/psemu/ +libdir = @libdir@/games/psemu/ + +lib_LTLIBRARIES = libDFSound.la + +libDFSound_la_SOURCES = spu.c cfg.c dma.c freeze.c psemu.c registers.c \ + alsa.c oss.c nullsnd.c + +libDFSound_la_CFLAGS = +libDFSound_la_LDFLAGS = -module -avoid-version -lpthread -lm + +if HAVE_ALSA +libDFSound_la_CFLAGS += -DUSEALSA=1 +libDFSound_la_LDFLAGS += $(ALSA_LIBS) +endif + +if HAVE_OSS +libDFSound_la_CFLAGS += -DUSEOSS=1 +endif + +bin_PROGRAMS = cfgDFSound +cfgDFSound_SOURCES = spucfg-0.1df/main.c +cfgDFSound_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) + +glade_DATA = spucfg-0.1df/dfsound.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) diff --git a/plugins/dfsound/Makefile.in b/plugins/dfsound/Makefile.in new file mode 100644 index 00000000..bf163c92 --- /dev/null +++ b/plugins/dfsound/Makefile.in @@ -0,0 +1,677 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_ALSA_TRUE@am__append_1 = -DUSEALSA=1 +@HAVE_ALSA_TRUE@am__append_2 = $(ALSA_LIBS) +@HAVE_OSS_TRUE@am__append_3 = -DUSEOSS=1 +bin_PROGRAMS = cfgDFSound$(EXEEXT) +subdir = plugins/dfsound +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(gladedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libDFSound_la_LIBADD = +am_libDFSound_la_OBJECTS = libDFSound_la-spu.lo libDFSound_la-cfg.lo \ + libDFSound_la-dma.lo libDFSound_la-freeze.lo \ + libDFSound_la-psemu.lo libDFSound_la-registers.lo \ + libDFSound_la-alsa.lo libDFSound_la-oss.lo \ + libDFSound_la-nullsnd.lo +libDFSound_la_OBJECTS = $(am_libDFSound_la_OBJECTS) +libDFSound_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libDFSound_la_CFLAGS) \ + $(CFLAGS) $(libDFSound_la_LDFLAGS) $(LDFLAGS) -o $@ +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_cfgDFSound_OBJECTS = main.$(OBJEXT) +cfgDFSound_OBJECTS = $(am_cfgDFSound_OBJECTS) +am__DEPENDENCIES_1 = +cfgDFSound_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libDFSound_la_SOURCES) $(cfgDFSound_SOURCES) +DIST_SOURCES = $(libDFSound_la_SOURCES) $(cfgDFSound_SOURCES) +gladeDATA_INSTALL = $(INSTALL_DATA) +DATA = $(glade_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFOPENGL = @DFOPENGL@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADE2_CFLAGS = @GLADE2_CFLAGS@ +GLADE2_LIBS = @GLADE2_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTK2_CFLAGS = @GTK2_CFLAGS@ +GTK2_LIBS = @GTK2_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NASM = @NASM@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @libdir@/games/psemu/ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@/games/psemu/ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) $(GLADE2_CFLAGS) \ + -DVERSION=0 -DREVISION=1 -DBUILD=0 + +lib_LTLIBRARIES = libDFSound.la +libDFSound_la_SOURCES = spu.c cfg.c dma.c freeze.c psemu.c registers.c \ + alsa.c oss.c nullsnd.c + +libDFSound_la_CFLAGS = $(am__append_1) $(am__append_3) +libDFSound_la_LDFLAGS = -module -avoid-version -lpthread -lm \ + $(am__append_2) +cfgDFSound_SOURCES = spucfg-0.1df/main.c +cfgDFSound_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) +glade_DATA = spucfg-0.1df/dfsound.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/dfsound/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/dfsound/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libDFSound.la: $(libDFSound_la_OBJECTS) $(libDFSound_la_DEPENDENCIES) + $(libDFSound_la_LINK) -rpath $(libdir) $(libDFSound_la_OBJECTS) $(libDFSound_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +cfgDFSound$(EXEEXT): $(cfgDFSound_OBJECTS) $(cfgDFSound_DEPENDENCIES) + @rm -f cfgDFSound$(EXEEXT) + $(LINK) $(cfgDFSound_OBJECTS) $(cfgDFSound_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-alsa.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-cfg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-dma.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-freeze.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-nullsnd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-oss.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-psemu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-registers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-spu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libDFSound_la-spu.lo: spu.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-spu.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-spu.Tpo -c -o libDFSound_la-spu.lo `test -f 'spu.c' || echo '$(srcdir)/'`spu.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-spu.Tpo $(DEPDIR)/libDFSound_la-spu.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='spu.c' object='libDFSound_la-spu.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-spu.lo `test -f 'spu.c' || echo '$(srcdir)/'`spu.c + +libDFSound_la-cfg.lo: cfg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-cfg.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-cfg.Tpo -c -o libDFSound_la-cfg.lo `test -f 'cfg.c' || echo '$(srcdir)/'`cfg.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-cfg.Tpo $(DEPDIR)/libDFSound_la-cfg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cfg.c' object='libDFSound_la-cfg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-cfg.lo `test -f 'cfg.c' || echo '$(srcdir)/'`cfg.c + +libDFSound_la-dma.lo: dma.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-dma.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-dma.Tpo -c -o libDFSound_la-dma.lo `test -f 'dma.c' || echo '$(srcdir)/'`dma.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-dma.Tpo $(DEPDIR)/libDFSound_la-dma.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dma.c' object='libDFSound_la-dma.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-dma.lo `test -f 'dma.c' || echo '$(srcdir)/'`dma.c + +libDFSound_la-freeze.lo: freeze.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-freeze.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-freeze.Tpo -c -o libDFSound_la-freeze.lo `test -f 'freeze.c' || echo '$(srcdir)/'`freeze.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-freeze.Tpo $(DEPDIR)/libDFSound_la-freeze.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='freeze.c' object='libDFSound_la-freeze.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-freeze.lo `test -f 'freeze.c' || echo '$(srcdir)/'`freeze.c + +libDFSound_la-psemu.lo: psemu.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-psemu.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-psemu.Tpo -c -o libDFSound_la-psemu.lo `test -f 'psemu.c' || echo '$(srcdir)/'`psemu.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-psemu.Tpo $(DEPDIR)/libDFSound_la-psemu.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='psemu.c' object='libDFSound_la-psemu.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-psemu.lo `test -f 'psemu.c' || echo '$(srcdir)/'`psemu.c + +libDFSound_la-registers.lo: registers.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-registers.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-registers.Tpo -c -o libDFSound_la-registers.lo `test -f 'registers.c' || echo '$(srcdir)/'`registers.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-registers.Tpo $(DEPDIR)/libDFSound_la-registers.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='registers.c' object='libDFSound_la-registers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-registers.lo `test -f 'registers.c' || echo '$(srcdir)/'`registers.c + +libDFSound_la-alsa.lo: alsa.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-alsa.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-alsa.Tpo -c -o libDFSound_la-alsa.lo `test -f 'alsa.c' || echo '$(srcdir)/'`alsa.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-alsa.Tpo $(DEPDIR)/libDFSound_la-alsa.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alsa.c' object='libDFSound_la-alsa.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-alsa.lo `test -f 'alsa.c' || echo '$(srcdir)/'`alsa.c + +libDFSound_la-oss.lo: oss.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-oss.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-oss.Tpo -c -o libDFSound_la-oss.lo `test -f 'oss.c' || echo '$(srcdir)/'`oss.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-oss.Tpo $(DEPDIR)/libDFSound_la-oss.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='oss.c' object='libDFSound_la-oss.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-oss.lo `test -f 'oss.c' || echo '$(srcdir)/'`oss.c + +libDFSound_la-nullsnd.lo: nullsnd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-nullsnd.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-nullsnd.Tpo -c -o libDFSound_la-nullsnd.lo `test -f 'nullsnd.c' || echo '$(srcdir)/'`nullsnd.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-nullsnd.Tpo $(DEPDIR)/libDFSound_la-nullsnd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nullsnd.c' object='libDFSound_la-nullsnd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-nullsnd.lo `test -f 'nullsnd.c' || echo '$(srcdir)/'`nullsnd.c + +main.o: spucfg-0.1df/main.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.o -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.o `test -f 'spucfg-0.1df/main.c' || echo '$(srcdir)/'`spucfg-0.1df/main.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='spucfg-0.1df/main.c' object='main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.o `test -f 'spucfg-0.1df/main.c' || echo '$(srcdir)/'`spucfg-0.1df/main.c + +main.obj: spucfg-0.1df/main.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.obj -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.obj `if test -f 'spucfg-0.1df/main.c'; then $(CYGPATH_W) 'spucfg-0.1df/main.c'; else $(CYGPATH_W) '$(srcdir)/spucfg-0.1df/main.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='spucfg-0.1df/main.c' object='main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.obj `if test -f 'spucfg-0.1df/main.c'; then $(CYGPATH_W) 'spucfg-0.1df/main.c'; else $(CYGPATH_W) '$(srcdir)/spucfg-0.1df/main.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-gladeDATA: $(glade_DATA) + @$(NORMAL_INSTALL) + test -z "$(gladedir)" || $(MKDIR_P) "$(DESTDIR)$(gladedir)" + @list='$(glade_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(gladeDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(gladedir)/$$f'"; \ + $(gladeDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(gladedir)/$$f"; \ + done + +uninstall-gladeDATA: + @$(NORMAL_UNINSTALL) + @list='$(glade_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(gladedir)/$$f'"; \ + rm -f "$(DESTDIR)$(gladedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(gladedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-gladeDATA + +install-dvi: install-dvi-am + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-gladeDATA \ + uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-gladeDATA install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-gladeDATA uninstall-libLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/dfsound/adsr.c b/plugins/dfsound/adsr.c new file mode 100644 index 00000000..2496e461 --- /dev/null +++ b/plugins/dfsound/adsr.c @@ -0,0 +1,641 @@ +/***************************************************************************
+ adsr.c - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#include "stdafx.h"
+
+#define _IN_ADSR
+
+// will be included from spu.c
+#ifdef _IN_SPU
+
+////////////////////////////////////////////////////////////////////////
+// ADSR func
+////////////////////////////////////////////////////////////////////////
+
+unsigned long RateTable[160];
+
+void InitADSR(void) // INIT ADSR
+{
+ unsigned long r,rs,rd;int i;
+
+ memset(RateTable,0,sizeof(unsigned long)*160); // build the rate table according to Neill's rules (see at bottom of file)
+
+ r=3;rs=1;rd=0;
+
+ for(i=32;i<160;i++) // we start at pos 32 with the real values... everything before is 0
+ {
+ if(r<0x3FFFFFFF)
+ {
+ r+=rs;
+ rd++;if(rd==5) {rd=1;rs*=2;}
+ }
+ if(r>0x3FFFFFFF) r=0x3FFFFFFF;
+
+ RateTable[i]=r;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE void StartADSR(int ch) // MIX ADSR
+{
+ s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars
+ s_chan[ch].ADSRX.State=0;
+ s_chan[ch].ADSRX.EnvelopeVol=0;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE int MixADSR(int ch) // MIX ADSR
+{
+ if(s_chan[ch].bStop) // should be stopped:
+ { // do release
+ if(s_chan[ch].ADSRX.ReleaseModeExp)
+ {
+ switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
+ {
+ case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +0 + 32]; break;
+ case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +4 + 32]; break;
+ case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +6 + 32]; break;
+ case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +8 + 32]; break;
+ case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +9 + 32]; break;
+ case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +10+ 32]; break;
+ case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +11+ 32]; break;
+ case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +12+ 32]; break;
+ }
+ }
+ else
+ {
+ s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32];
+ }
+
+ if(s_chan[ch].ADSRX.EnvelopeVol<0)
+ {
+ s_chan[ch].ADSRX.EnvelopeVol=0;
+ s_chan[ch].bOn=0;
+ //s_chan[ch].bReverb=0;
+ //s_chan[ch].bNoise=0;
+ }
+
+ s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+ return s_chan[ch].ADSRX.lVolume;
+ }
+ else // not stopped yet?
+ {
+ if(s_chan[ch].ADSRX.State==0) // -> attack
+ {
+ if(s_chan[ch].ADSRX.AttackModeExp)
+ {
+ if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
+ s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
+ else
+ s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32];
+ }
+ else
+ {
+ s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
+ }
+
+ if(s_chan[ch].ADSRX.EnvelopeVol<0)
+ {
+ s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
+ s_chan[ch].ADSRX.State=1;
+ }
+
+ s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+ return s_chan[ch].ADSRX.lVolume;
+ }
+ //--------------------------------------------------//
+ if(s_chan[ch].ADSRX.State==1) // -> decay
+ {
+ switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
+ {
+ case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+0 + 32]; break;
+ case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+4 + 32]; break;
+ case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+6 + 32]; break;
+ case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+8 + 32]; break;
+ case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+9 + 32]; break;
+ case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+10+ 32]; break;
+ case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+11+ 32]; break;
+ case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+12+ 32]; break;
+ }
+
+ if(s_chan[ch].ADSRX.EnvelopeVol<0) s_chan[ch].ADSRX.EnvelopeVol=0;
+ if(((s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= s_chan[ch].ADSRX.SustainLevel)
+ {
+ s_chan[ch].ADSRX.State=2;
+ }
+
+ s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+ return s_chan[ch].ADSRX.lVolume;
+ }
+ //--------------------------------------------------//
+ if(s_chan[ch].ADSRX.State==2) // -> sustain
+ {
+ if(s_chan[ch].ADSRX.SustainIncrease)
+ {
+ if(s_chan[ch].ADSRX.SustainModeExp)
+ {
+ if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
+ s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
+ else
+ s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32];
+ }
+ else
+ {
+ s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
+ }
+
+ if(s_chan[ch].ADSRX.EnvelopeVol<0)
+ {
+ s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
+ }
+ }
+ else
+ {
+ if(s_chan[ch].ADSRX.SustainModeExp)
+ {
+ switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
+ {
+ case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +0 + 32];break;
+ case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +4 + 32];break;
+ case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +6 + 32];break;
+ case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +8 + 32];break;
+ case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +9 + 32];break;
+ case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +10+ 32];break;
+ case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +11+ 32];break;
+ case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +12+ 32];break;
+ }
+ }
+ else
+ {
+ s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32];
+ }
+
+ if(s_chan[ch].ADSRX.EnvelopeVol<0)
+ {
+ s_chan[ch].ADSRX.EnvelopeVol=0;
+ }
+ }
+ s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+ return s_chan[ch].ADSRX.lVolume;
+ }
+ }
+ return 0;
+}
+
+#endif
+
+/*
+James Higgs ADSR investigations:
+
+PSX SPU Envelope Timings
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+First, here is an extract from doomed's SPU doc, which explains the basics
+of the SPU "volume envelope":
+
+*** doomed doc extract start ***
+
+--------------------------------------------------------------------------
+Voices.
+--------------------------------------------------------------------------
+The SPU has 24 hardware voices. These voices can be used to reproduce sample
+data, noise or can be used as frequency modulator on the next voice.
+Each voice has it's own programmable ADSR envelope filter. The main volume
+can be programmed independently for left and right output.
+
+The ADSR envelope filter works as follows:
+Ar = Attack rate, which specifies the speed at which the volume increases
+ from zero to it's maximum value, as soon as the note on is given. The
+ slope can be set to lineair or exponential.
+Dr = Decay rate specifies the speed at which the volume decreases to the
+ sustain level. Decay is always decreasing exponentially.
+Sl = Sustain level, base level from which sustain starts.
+Sr = Sustain rate is the rate at which the volume of the sustained note
+ increases or decreases. This can be either lineair or exponential.
+Rr = Release rate is the rate at which the volume of the note decreases
+ as soon as the note off is given.
+
+ lvl |
+ ^ | /\Dr __
+ Sl _| _ / _ \__--- \
+ | / ---__ \ Rr
+ | /Ar Sr \ \
+ | / \\
+ |/___________________\________
+ ->time
+
+The overal volume can also be set to sweep up or down lineairly or
+exponentially from it's current value. This can be done seperately
+for left and right.
+
+Relevant SPU registers:
+-------------------------------------------------------------
+$1f801xx8 Attack/Decay/Sustain level
+bit |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00|
+desc.|Am| Ar |Dr |Sl |
+
+Am 0 Attack mode Linear
+ 1 Exponential
+
+Ar 0-7f attack rate
+Dr 0-f decay rate
+Sl 0-f sustain level
+-------------------------------------------------------------
+$1f801xxa Sustain rate, Release Rate.
+bit |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00|
+desc.|Sm|Sd| 0| Sr |Rm|Rr |
+
+Sm 0 sustain rate mode linear
+ 1 exponential
+Sd 0 sustain rate mode increase
+ 1 decrease
+Sr 0-7f Sustain Rate
+Rm 0 Linear decrease
+ 1 Exponential decrease
+Rr 0-1f Release Rate
+
+Note: decay mode is always Expontial decrease, and thus cannot
+be set.
+-------------------------------------------------------------
+$1f801xxc Current ADSR volume
+bit |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
+desc.|ADSRvol |
+
+ADSRvol Returns the current envelope volume when
+ read.
+-- James' Note: return range: 0 -> 32767
+
+*** doomed doc extract end ***
+
+By using a small PSX proggie to visualise the envelope as it was played,
+the following results for envelope timing were obtained:
+
+1. Attack rate value (linear mode)
+
+ Attack value range: 0 -> 127
+
+ Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | | 80 |
+ -----------------------------------------------------------------
+ Frames | 11 | 21 | 42 | 84 | 169| 338| 676| |2890|
+
+ Note: frames is no. of PAL frames to reach full volume (100%
+ amplitude)
+
+ Hmm, noticing that the time taken to reach full volume doubles
+ every time we add 4 to our attack value, we know the equation is
+ of form:
+ frames = k * 2 ^ (value / 4)
+
+ (You may ponder about envelope generator hardware at this point,
+ or maybe not... :)
+
+ By substituting some stuff and running some checks, we get:
+
+ k = 0.00257 (close enuf)
+
+ therefore,
+ frames = 0.00257 * 2 ^ (value / 4)
+ If you just happen to be writing an emulator, then you can probably
+ use an equation like:
+
+ %volume_increase_per_tick = 1 / frames
+
+
+ ------------------------------------
+ Pete:
+ ms=((1<<(value>>2))*514)/10000
+ ------------------------------------
+
+2. Decay rate value (only has log mode)
+
+ Decay value range: 0 -> 15
+
+ Value | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
+ ------------------------------------------------
+ frames | | | | | 6 | 12 | 24 | 47 |
+
+ Note: frames here is no. of PAL frames to decay to 50% volume.
+
+ formula: frames = k * 2 ^ (value)
+
+ Substituting, we get: k = 0.00146
+
+ Further info on logarithmic nature:
+ frames to decay to sustain level 3 = 3 * frames to decay to
+ sustain level 9
+
+ Also no. of frames to 25% volume = roughly 1.85 * no. of frames to
+ 50% volume.
+
+ Frag it - just use linear approx.
+
+ ------------------------------------
+ Pete:
+ ms=((1<<value)*292)/10000
+ ------------------------------------
+
+
+3. Sustain rate value (linear mode)
+
+ Sustain rate range: 0 -> 127
+
+ Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 |
+ -------------------------------------------
+ frames | 9 | 19 | 37 | 74 | 147| 293| 587|
+
+ Here, frames = no. of PAL frames for volume amplitude to go from 100%
+ to 0% (or vice-versa).
+
+ Same formula as for attack value, just a different value for k:
+
+ k = 0.00225
+
+ ie: frames = 0.00225 * 2 ^ (value / 4)
+
+ For emulation purposes:
+
+ %volume_increase_or_decrease_per_tick = 1 / frames
+
+ ------------------------------------
+ Pete:
+ ms=((1<<(value>>2))*450)/10000
+ ------------------------------------
+
+
+4. Release rate (linear mode)
+
+ Release rate range: 0 -> 31
+
+ Value | 13 | 14 | 15 | 16 | 17 |
+ ---------------------------------------------------------------
+ frames | 18 | 36 | 73 | 146| 292|
+
+ Here, frames = no. of PAL frames to decay from 100% vol to 0% vol
+ after "note-off" is triggered.
+
+ Formula: frames = k * 2 ^ (value)
+
+ And so: k = 0.00223
+
+ ------------------------------------
+ Pete:
+ ms=((1<<value)*446)/10000
+ ------------------------------------
+
+
+Other notes:
+
+Log stuff not figured out. You may get some clues from the "Decay rate"
+stuff above. For emu purposes it may not be important - use linear
+approx.
+
+To get timings in millisecs, multiply frames by 20.
+
+
+
+- James Higgs 17/6/2000
+james7780@yahoo.com
+
+//---------------------------------------------------------------
+
+OLD adsr mixing according to james' rules... has to be called
+every one millisecond
+
+
+ long v,v2,lT,l1,l2,l3;
+
+ if(s_chan[ch].bStop) // psx wants to stop? -> release phase
+ {
+ if(s_chan[ch].ADSR.ReleaseVal!=0) // -> release not 0: do release (if 0: stop right now)
+ {
+ if(!s_chan[ch].ADSR.ReleaseVol) // --> release just started? set up the release stuff
+ {
+ s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime;
+ s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume;
+ s_chan[ch].ADSR.ReleaseTime = // --> calc how long does it take to reach the wanted sus level
+ (s_chan[ch].ADSR.ReleaseTime*
+ s_chan[ch].ADSR.ReleaseVol)/1024;
+ }
+ // -> NO release exp mode used (yet)
+ v=s_chan[ch].ADSR.ReleaseVol; // -> get last volume
+ lT=s_chan[ch].ADSR.lTime- // -> how much time is past?
+ s_chan[ch].ADSR.ReleaseStartTime;
+ l1=s_chan[ch].ADSR.ReleaseTime;
+
+ if(lT<l1) // -> we still have to release
+ {
+ v=v-((v*lT)/l1); // --> calc new volume
+ }
+ else // -> release is over: now really stop that sample
+ {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
+ }
+ else // -> release IS 0: release at once
+ {
+ v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;
+ }
+ }
+ else
+ {//--------------------------------------------------// not in release phase:
+ v=1024;
+ lT=s_chan[ch].ADSR.lTime;
+ l1=s_chan[ch].ADSR.AttackTime;
+
+ if(lT<l1) // attack
+ { // no exp mode used (yet)
+// if(s_chan[ch].ADSR.AttackModeExp)
+// {
+// v=(v*lT)/l1;
+// }
+// else
+ {
+ v=(v*lT)/l1;
+ }
+ if(v==0) v=1;
+ }
+ else // decay
+ { // should be exp, but who cares? ;)
+ l2=s_chan[ch].ADSR.DecayTime;
+ v2=s_chan[ch].ADSR.SustainLevel;
+
+ lT-=l1;
+ if(lT<l2)
+ {
+ v-=(((v-v2)*lT)/l2);
+ }
+ else // sustain
+ { // no exp mode used (yet)
+ l3=s_chan[ch].ADSR.SustainTime;
+ lT-=l2;
+ if(s_chan[ch].ADSR.SustainModeDec>0)
+ {
+ if(l3!=0) v2+=((v-v2)*lT)/l3;
+ else v2=v;
+ }
+ else
+ {
+ if(l3!=0) v2-=(v2*lT)/l3;
+ else v2=v;
+ }
+
+ if(v2>v) v2=v;
+ if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
+
+ v=v2;
+ }
+ }
+ }
+
+ //----------------------------------------------------//
+ // ok, done for this channel, so increase time
+
+ s_chan[ch].ADSR.lTime+=1; // 1 = 1.020408f ms;
+
+ if(v>1024) v=1024; // adjust volume
+ if(v<0) v=0;
+ s_chan[ch].ADSR.lVolume=v; // store act volume
+
+ return v; // return the volume factor
+*/
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+
+/*
+-----------------------------------------------------------------------------
+Neill Corlett
+Playstation SPU envelope timing notes
+-----------------------------------------------------------------------------
+
+This is preliminary. This may be wrong. But the model described herein fits
+all of my experimental data, and it's just simple enough to sound right.
+
+ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally.
+The value returned by channel reg 0xC is (envelope_level>>16).
+
+Each sample, an increment or decrement value will be added to or
+subtracted from this envelope level.
+
+Create the rate log table. The values double every 4 entries.
+ entry #0 = 4
+
+ 4, 5, 6, 7,
+ 8,10,12,14,
+ 16,20,24,28, ...
+
+ entry #40 = 4096...
+ entry #44 = 8192...
+ entry #48 = 16384...
+ entry #52 = 32768...
+ entry #56 = 65536...
+
+increments and decrements are in terms of ratelogtable[n]
+n may exceed the table bounds (plan on n being between -32 and 127).
+table values are all clipped between 0x00000000 and 0x3FFFFFFF
+
+when you "voice on", the envelope is always fully reset.
+(yes, it may click. the real thing does this too.)
+
+envelope level begins at zero.
+
+each state happens for at least 1 cycle
+(transitions are not instantaneous)
+this may result in some oddness: if the decay rate is uberfast, it will cut
+the envelope from full down to half in one sample, potentially skipping over
+the sustain level
+
+ATTACK
+------
+- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and
+ proceed to DECAY.
+
+Linear attack mode:
+- line extends upward to 0x7FFFFFFF
+- increment per sample is ratelogtable[(Ar^0x7F)-0x10]
+
+Logarithmic attack mode:
+if envelope_level < 0x60000000:
+ - line extends upward to 0x60000000
+ - increment per sample is ratelogtable[(Ar^0x7F)-0x10]
+else:
+ - line extends upward to 0x7FFFFFFF
+ - increment per sample is ratelogtable[(Ar^0x7F)-0x18]
+
+DECAY
+-----
+- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN.
+ Do not clip to the sustain level.
+- current line ends at (envelope_level & 0x07FFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+ 0: ratelogtable[(4*(Dr^0x1F))-0x18+0]
+ 1: ratelogtable[(4*(Dr^0x1F))-0x18+4]
+ 2: ratelogtable[(4*(Dr^0x1F))-0x18+6]
+ 3: ratelogtable[(4*(Dr^0x1F))-0x18+8]
+ 4: ratelogtable[(4*(Dr^0x1F))-0x18+9]
+ 5: ratelogtable[(4*(Dr^0x1F))-0x18+10]
+ 6: ratelogtable[(4*(Dr^0x1F))-0x18+11]
+ 7: ratelogtable[(4*(Dr^0x1F))-0x18+12]
+ (note that this is the same as the release rate formula, except that
+ decay rates 10-1F aren't possible... those would be slower in theory)
+
+SUSTAIN
+-------
+- no terminating condition except for voice off
+- Sd=0 (increase) behavior is identical to ATTACK for both log and linear.
+- Sd=1 (decrease) behavior:
+Linear sustain decrease:
+- line extends to 0x00000000
+- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F]
+Logarithmic sustain decrease:
+- current line ends at (envelope_level & 0x07FFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+ 0: ratelogtable[(Sr^0x7F)-0x1B+0]
+ 1: ratelogtable[(Sr^0x7F)-0x1B+4]
+ 2: ratelogtable[(Sr^0x7F)-0x1B+6]
+ 3: ratelogtable[(Sr^0x7F)-0x1B+8]
+ 4: ratelogtable[(Sr^0x7F)-0x1B+9]
+ 5: ratelogtable[(Sr^0x7F)-0x1B+10]
+ 6: ratelogtable[(Sr^0x7F)-0x1B+11]
+ 7: ratelogtable[(Sr^0x7F)-0x1B+12]
+
+RELEASE
+-------
+- if the envelope level has overflowed to negative, clip to 0 and QUIT.
+
+Linear release mode:
+- line extends to 0x00000000
+- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C]
+
+Logarithmic release mode:
+- line extends to (envelope_level & 0x0FFFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+ 0: ratelogtable[(4*(Rr^0x1F))-0x18+0]
+ 1: ratelogtable[(4*(Rr^0x1F))-0x18+4]
+ 2: ratelogtable[(4*(Rr^0x1F))-0x18+6]
+ 3: ratelogtable[(4*(Rr^0x1F))-0x18+8]
+ 4: ratelogtable[(4*(Rr^0x1F))-0x18+9]
+ 5: ratelogtable[(4*(Rr^0x1F))-0x18+10]
+ 6: ratelogtable[(4*(Rr^0x1F))-0x18+11]
+ 7: ratelogtable[(4*(Rr^0x1F))-0x18+12]
+
+-----------------------------------------------------------------------------
+*/
+
diff --git a/plugins/dfsound/adsr.h b/plugins/dfsound/adsr.h new file mode 100644 index 00000000..ff2af1ff --- /dev/null +++ b/plugins/dfsound/adsr.h @@ -0,0 +1,19 @@ +/***************************************************************************
+ adsr.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+INLINE void StartADSR(int ch);
+INLINE int MixADSR(int ch);
diff --git a/plugins/dfsound/alsa.c b/plugins/dfsound/alsa.c new file mode 100644 index 00000000..4806b4c7 --- /dev/null +++ b/plugins/dfsound/alsa.c @@ -0,0 +1,168 @@ +/*************************************************************************** + alsa.c - description + ------------------- + begin : Sat Mar 01 2003 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#ifdef USEALSA + +#define _IN_OSS + +#include "externals.h" + +#define ALSA_PCM_NEW_HW_PARAMS_API +#define ALSA_PCM_NEW_SW_PARAMS_API +#include <alsa/asoundlib.h> + +#define ALSA_MEM_DEF +#include "alsa.h" +static snd_pcm_t *handle = NULL; +static snd_pcm_uframes_t buffer_size; + +// SETUP SOUND +void SetupSound(void) +{ + snd_pcm_hw_params_t *hwparams; + snd_pcm_sw_params_t *swparams; + snd_pcm_status_t *status; + int pspeed; + int pchannels; + int format; + int buffer_time; + int period_time; + int err; + + if(iDisStereo) pchannels=1; + else pchannels=2; + + pspeed=44100; + format=SND_PCM_FORMAT_S16; + buffer_time=500000; + period_time=buffer_time/4; + + if((err=snd_pcm_open(&handle, "default", + SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))<0) + { + printf("Audio open error: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_nonblock(handle, 0))<0) + { + printf("Can't set blocking moded: %s\n", snd_strerror(err)); + return; + } + + snd_pcm_hw_params_alloca(&hwparams); + snd_pcm_sw_params_alloca(&swparams); + if((err=snd_pcm_hw_params_any(handle, hwparams))<0) + { + printf("Broken configuration for this PCM: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED))<0) + { + printf("Access type not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_format(handle, hwparams, format))<0) + { + printf("Sample format not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_channels(handle, hwparams, pchannels))<0) + { + printf("Channels count not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_rate_near(handle, hwparams, &pspeed, 0))<0) + { + printf("Rate not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0))<0) + { + printf("Buffer time error: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0))<0) + { + printf("Period time error: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params(handle, hwparams))<0) + { + printf("Unable to install hw params: %s\n", snd_strerror(err)); + return; + } + + snd_pcm_status_alloca(&status); + if((err=snd_pcm_status(handle, status))<0) + { + printf("Unable to get status: %s\n", snd_strerror(err)); + return; + } + + buffer_size=snd_pcm_status_get_avail(status); +} + +// REMOVE SOUND +void RemoveSound(void) +{ + if(handle != NULL) + { + snd_pcm_drop(handle); + snd_pcm_close(handle); + handle = NULL; + } +} + +// GET BYTES BUFFERED +unsigned long SoundGetBytesBuffered(void) +{ + unsigned long l; + + if(handle == NULL) // failed to open? + return SOUNDSIZE; + l = snd_pcm_avail_update(handle); + if(l<0) return 0; + if(l<buffer_size/2) // can we write in at least the half of fragments? + l=SOUNDSIZE; // -> no? wait + else l=0; // -> else go on + + return l; +} + +// FEED SOUND DATA +void SoundFeedStreamData(unsigned char* pSound,long lBytes) +{ + if(handle == NULL) return; + + if(snd_pcm_state(handle) == SND_PCM_STATE_XRUN) + snd_pcm_prepare(handle); + snd_pcm_writei(handle,pSound, + iDisStereo == 1 ? lBytes/2 : lBytes/4); +} + +#endif + diff --git a/plugins/dfsound/alsa.h b/plugins/dfsound/alsa.h new file mode 100644 index 00000000..b45eae95 --- /dev/null +++ b/plugins/dfsound/alsa.h @@ -0,0 +1,28 @@ +/***************************************************************************
+ alsa.h - description
+ -------------------
+ begin : Sat Mar 01 2003
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _ALSA_SOUND_H
+#define _ALSA_SOUND_H
+
+#ifdef ALSA_MEM_DEF
+#define ALSA_MEM_EXTERN
+#else
+#define ALSA_MEM_EXTERN extern
+#endif
+
+ALSA_MEM_EXTERN int sound_buffer_size;
+
+#endif // _ALSA_SOUND_H
diff --git a/plugins/dfsound/cfg.c b/plugins/dfsound/cfg.c new file mode 100644 index 00000000..f51d3568 --- /dev/null +++ b/plugins/dfsound/cfg.c @@ -0,0 +1,171 @@ +/***************************************************************************
+ cfg.c - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#include "stdafx.h"
+
+#define _IN_CFG
+
+#include "externals.h"
+
+////////////////////////////////////////////////////////////////////////
+// LINUX CONFIG/ABOUT HANDLING
+////////////////////////////////////////////////////////////////////////
+
+#include <unistd.h>
+
+////////////////////////////////////////////////////////////////////////
+// START EXTERNAL CFG TOOL
+////////////////////////////////////////////////////////////////////////
+
+void StartCfgTool(char * pCmdLine)
+{
+ FILE * cf;char filename[255],t[255];
+
+ strcpy(filename,"cfg/cfgDFSound");
+ cf=fopen(filename,"rb");
+ if(cf!=NULL)
+ {
+ fclose(cf);
+ getcwd(t,255);
+ chdir("cfg");
+ sprintf(filename,"./cfgDFSound %s",pCmdLine);
+ system(filename);
+ chdir(t);
+ }
+ else
+ {
+ strcpy(filename,"cfgDFSound");
+ cf=fopen(filename,"rb");
+ if(cf!=NULL)
+ {
+ fclose(cf);
+ sprintf(filename,"./cfgDFSound %s",pCmdLine);
+ system(filename);
+ }
+ else
+ {
+ sprintf(filename,"%s/cfgDFSound",getenv("HOME"));
+ cf=fopen(filename,"rb");
+ if(cf!=NULL)
+ {
+ fclose(cf);
+ getcwd(t,255);
+ chdir(getenv("HOME"));
+ sprintf(filename,"./cfgDFSound %s",pCmdLine);
+ system(filename);
+ chdir(t);
+ }
+ else printf("Sound error: cfgDFSound not found!\n");
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////
+// READ LINUX CONFIG FILE
+/////////////////////////////////////////////////////////
+
+void ReadConfigFile(void)
+{
+ FILE *in;char t[256];int len;
+ char * pB, * p;
+
+ strcpy(t,"dfsound.cfg");
+ in = fopen(t,"rb");
+ if(!in)
+ {
+ strcpy(t,"cfg/dfsound.cfg");
+ in = fopen(t,"rb");
+ if(!in)
+ {
+ sprintf(t,"%s/dfsound.cfg",getenv("HOME"));
+ in = fopen(t,"rb");
+ if(!in) return;
+ }
+ }
+
+ pB = (char *)malloc(32767);
+ memset(pB,0,32767);
+
+ len = fread(pB, 1, 32767, in);
+ fclose(in);
+
+ strcpy(t,"\nVolume");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;}
+ if(p) iVolume=4-atoi(p+len);
+ if(iVolume<1) iVolume=1;
+ if(iVolume>4) iVolume=4;
+
+ strcpy(t,"\nUseXA");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;}
+ if(p) iUseXA=atoi(p+len);
+ if(iUseXA<0) iUseXA=0;
+ if(iUseXA>1) iUseXA=1;
+
+ strcpy(t,"\nXAPitch");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;}
+ if(p) iXAPitch=atoi(p+len);
+ if(iXAPitch<0) iXAPitch=0;
+ if(iXAPitch>1) iXAPitch=1;
+
+ strcpy(t,"\nHighCompMode");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;}
+ if(p) iUseTimer=atoi(p+len);
+ if(iUseTimer<0) iUseTimer=0;
+ // note: timer mode 1 (win time events) is not supported
+ // in linux. But timer mode 2 (spuupdate) is safe to use.
+ if(iUseTimer) iUseTimer=2;
+
+#ifdef NOTHREADLIB
+ iUseTimer=2;
+#endif
+
+ strcpy(t,"\nSPUIRQWait");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;}
+ if(p) iSPUIRQWait=atoi(p+len);
+ if(iSPUIRQWait<0) iSPUIRQWait=0;
+ if(iSPUIRQWait>1) iSPUIRQWait=1;
+
+ strcpy(t,"\nUseReverb");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;}
+ if(p) iUseReverb=atoi(p+len);
+ if(iUseReverb<0) iUseReverb=0;
+ if(iUseReverb>2) iUseReverb=2;
+
+ strcpy(t,"\nUseInterpolation");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;}
+ if(p) iUseInterpolation=atoi(p+len);
+ if(iUseInterpolation<0) iUseInterpolation=0;
+ if(iUseInterpolation>3) iUseInterpolation=3;
+
+ strcpy(t,"\nDisStereo");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;}
+ if(p) iDisStereo=atoi(p+len);
+ if(iDisStereo<0) iDisStereo=0;
+ if(iDisStereo>1) iDisStereo=1;
+
+ free(pB);
+}
+
+/////////////////////////////////////////////////////////
+// READ CONFIG called by spu funcs
+/////////////////////////////////////////////////////////
+
+void ReadConfig(void)
+{
+ iVolume=3;
+ iUseXA=1;
+ iXAPitch=0;
+ iSPUIRQWait=1;
+ iUseTimer=2;
+ iUseReverb=2;
+ iUseInterpolation=2;
+ iDisStereo=0;
+
+ ReadConfigFile();
+}
diff --git a/plugins/dfsound/cfg.h b/plugins/dfsound/cfg.h new file mode 100644 index 00000000..f64d6d62 --- /dev/null +++ b/plugins/dfsound/cfg.h @@ -0,0 +1,19 @@ +/***************************************************************************
+ cfg.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+void ReadConfig(void);
+void StartCfgTool(char * pCmdLine);
diff --git a/plugins/dfsound/dma.c b/plugins/dfsound/dma.c new file mode 100644 index 00000000..7b81a1bf --- /dev/null +++ b/plugins/dfsound/dma.c @@ -0,0 +1,97 @@ +/***************************************************************************
+ dma.c - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#include "stdafx.h"
+
+#define _IN_DMA
+
+#include "externals.h"
+
+////////////////////////////////////////////////////////////////////////
+// READ DMA (one value)
+////////////////////////////////////////////////////////////////////////
+
+unsigned short CALLBACK SPUreadDMA(void)
+{
+ unsigned short s=spuMem[spuAddr>>1];
+ spuAddr+=2;
+ if(spuAddr>0x7ffff) spuAddr=0;
+
+ iWatchDog=0;
+
+ return s;
+}
+
+////////////////////////////////////////////////////////////////////////
+// READ DMA (many values)
+////////////////////////////////////////////////////////////////////////
+
+void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize)
+{
+ int i;
+
+ for(i=0;i<iSize;i++)
+ {
+ *pusPSXMem++=spuMem[spuAddr>>1]; // spu addr got by writeregister
+ spuAddr+=2; // inc spu addr
+ if(spuAddr>0x7ffff) spuAddr=0; // wrap
+ }
+
+ iWatchDog=0;
+}
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+// to investigate: do sound data updates by writedma affect spu
+// irqs? Will an irq be triggered, if new data is written to
+// the memory irq address?
+
+////////////////////////////////////////////////////////////////////////
+// WRITE DMA (one value)
+////////////////////////////////////////////////////////////////////////
+
+void CALLBACK SPUwriteDMA(unsigned short val)
+{
+ spuMem[spuAddr>>1] = val; // spu addr got by writeregister
+
+ spuAddr+=2; // inc spu addr
+ if(spuAddr>0x7ffff) spuAddr=0; // wrap
+
+ iWatchDog=0;
+}
+
+////////////////////////////////////////////////////////////////////////
+// WRITE DMA (many values)
+////////////////////////////////////////////////////////////////////////
+
+void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize)
+{
+ int i;
+
+ for(i=0;i<iSize;i++)
+ {
+ spuMem[spuAddr>>1] = *pusPSXMem++; // spu addr got by writeregister
+ spuAddr+=2; // inc spu addr
+ if(spuAddr>0x7ffff) spuAddr=0; // wrap
+ }
+
+ iWatchDog=0;
+}
+
+////////////////////////////////////////////////////////////////////////
diff --git a/plugins/dfsound/dma.h b/plugins/dfsound/dma.h new file mode 100644 index 00000000..440536fe --- /dev/null +++ b/plugins/dfsound/dma.h @@ -0,0 +1,31 @@ +/***************************************************************************
+ dma.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+
+unsigned short CALLBACK SPUreadDMA(void);
+void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize);
+void CALLBACK SPUwriteDMA(unsigned short val);
+void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize);
diff --git a/plugins/dfsound/dsoundoss.h b/plugins/dfsound/dsoundoss.h new file mode 100644 index 00000000..3702312f --- /dev/null +++ b/plugins/dfsound/dsoundoss.h @@ -0,0 +1,22 @@ +/*************************************************************************** + dsoundoss.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +void SetupSound(void); +void RemoveSound(void); +unsigned long SoundGetBytesBuffered(void); +void SoundFeedStreamData(unsigned char* pSound,long lBytes); +unsigned long timeGetTime_spu(); diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h new file mode 100644 index 00000000..a1f47253 --- /dev/null +++ b/plugins/dfsound/externals.h @@ -0,0 +1,283 @@ +/***************************************************************************
+ externals.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#include <stdint.h>
+/////////////////////////////////////////////////////////
+// generic defines
+/////////////////////////////////////////////////////////
+
+#define PSE_LT_SPU 4
+#define PSE_SPU_ERR_SUCCESS 0
+#define PSE_SPU_ERR -60
+#define PSE_SPU_ERR_NOTCONFIGURED PSE_SPU_ERR - 1
+#define PSE_SPU_ERR_INIT PSE_SPU_ERR - 2
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+////////////////////////////////////////////////////////////////////////
+// spu defines
+////////////////////////////////////////////////////////////////////////
+
+// sound buffer sizes
+// 400 ms complete sound buffer
+#define SOUNDSIZE 70560
+// 137 ms test buffer... if less than that is buffered, a new upload will happen
+#define TESTSIZE 24192
+
+// num of channels
+#define MAXCHAN 24
+
+// ~ 1 ms of data
+#define NSSIZE 45
+
+///////////////////////////////////////////////////////////
+// struct defines
+///////////////////////////////////////////////////////////
+
+// ADSR INFOS PER CHANNEL
+typedef struct
+{
+ int AttackModeExp;
+ long AttackTime;
+ long DecayTime;
+ long SustainLevel;
+ int SustainModeExp;
+ long SustainModeDec;
+ long SustainTime;
+ int ReleaseModeExp;
+ unsigned long ReleaseVal;
+ long ReleaseTime;
+ long ReleaseStartTime;
+ long ReleaseVol;
+ long lTime;
+ long lVolume;
+} ADSRInfo;
+
+typedef struct
+{
+ int State;
+ int AttackModeExp;
+ int AttackRate;
+ int DecayRate;
+ int SustainLevel;
+ int SustainModeExp;
+ int SustainIncrease;
+ int SustainRate;
+ int ReleaseModeExp;
+ int ReleaseRate;
+ int EnvelopeVol;
+ long lVolume;
+ long lDummy1;
+ long lDummy2;
+} ADSRInfoEx;
+
+///////////////////////////////////////////////////////////
+
+// Tmp Flags
+
+// used for debug channel muting
+#define FLAG_MUTE 1
+
+// used for simple interpolation
+#define FLAG_IPOL0 2
+#define FLAG_IPOL1 4
+
+///////////////////////////////////////////////////////////
+
+// MAIN CHANNEL STRUCT
+typedef struct
+{
+ // no mutexes used anymore... don't need them to sync access
+ //HANDLE hMutex;
+
+ int bNew; // start flag
+
+ int iSBPos; // mixing stuff
+ int spos;
+ int sinc;
+ int SB[32+32]; // Pete added another 32 dwords in 1.6 ... prevents overflow issues with gaussian/cubic interpolation (thanx xodnizel!), and can be used for even better interpolations, eh? :)
+ int sval;
+
+ unsigned char * pStart; // start ptr into sound mem
+ unsigned char * pCurr; // current pos in sound mem
+ unsigned char * pLoop; // loop ptr in sound mem
+
+ int bOn; // is channel active (sample playing?)
+ int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase)
+ int bReverb; // can we do reverb on this channel? must have ctrl register bit, to get active
+ int iActFreq; // current psx pitch
+ int iUsedFreq; // current pc pitch
+ int iLeftVolume; // left volume
+ int iLeftVolRaw; // left psx volume value
+ int bIgnoreLoop; // ignore loop bit, if an external loop address is used
+ int iMute; // mute mode
+ int iRightVolume; // right volume
+ int iRightVolRaw; // right psx volume value
+ int iRawPitch; // raw pitch (0...3fff)
+ int iIrqDone; // debug irq done flag
+ int s_1; // last decoding infos
+ int s_2;
+ int bRVBActive; // reverb active flag
+ int iRVBOffset; // reverb offset
+ int iRVBRepeat; // reverb repeat
+ int bNoise; // noise active flag
+ int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel)
+ int iRVBNum; // another reverb helper
+ int iOldNoise; // old noise val for this channel
+ ADSRInfo ADSR; // active ADSR settings
+ ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start)
+
+} SPUCHAN;
+
+///////////////////////////////////////////////////////////
+
+typedef struct
+{
+ int StartAddr; // reverb area start addr in samples
+ int CurrAddr; // reverb area curr addr in samples
+
+ int VolLeft;
+ int VolRight;
+ int iLastRVBLeft;
+ int iLastRVBRight;
+ int iRVBLeft;
+ int iRVBRight;
+
+
+ int FB_SRC_A; // (offset)
+ int FB_SRC_B; // (offset)
+ int IIR_ALPHA; // (coef.)
+ int ACC_COEF_A; // (coef.)
+ int ACC_COEF_B; // (coef.)
+ int ACC_COEF_C; // (coef.)
+ int ACC_COEF_D; // (coef.)
+ int IIR_COEF; // (coef.)
+ int FB_ALPHA; // (coef.)
+ int FB_X; // (coef.)
+ int IIR_DEST_A0; // (offset)
+ int IIR_DEST_A1; // (offset)
+ int ACC_SRC_A0; // (offset)
+ int ACC_SRC_A1; // (offset)
+ int ACC_SRC_B0; // (offset)
+ int ACC_SRC_B1; // (offset)
+ int IIR_SRC_A0; // (offset)
+ int IIR_SRC_A1; // (offset)
+ int IIR_DEST_B0; // (offset)
+ int IIR_DEST_B1; // (offset)
+ int ACC_SRC_C0; // (offset)
+ int ACC_SRC_C1; // (offset)
+ int ACC_SRC_D0; // (offset)
+ int ACC_SRC_D1; // (offset)
+ int IIR_SRC_B1; // (offset)
+ int IIR_SRC_B0; // (offset)
+ int MIX_DEST_A0; // (offset)
+ int MIX_DEST_A1; // (offset)
+ int MIX_DEST_B0; // (offset)
+ int MIX_DEST_B1; // (offset)
+ int IN_COEF_L; // (coef.)
+ int IN_COEF_R; // (coef.)
+} REVERBInfo;
+
+///////////////////////////////////////////////////////////
+// SPU.C globals
+///////////////////////////////////////////////////////////
+
+#ifndef _IN_SPU
+
+// psx buffers / addresses
+
+extern unsigned short regArea[];
+extern unsigned short spuMem[];
+extern unsigned char * spuMemC;
+extern unsigned char * pSpuIrq;
+extern unsigned char * pSpuBuffer;
+
+// user settings
+
+extern int iUseXA;
+extern int iVolume;
+extern int iXAPitch;
+extern int iUseTimer;
+extern int iSPUIRQWait;
+extern int iDebugMode;
+extern int iRecordMode;
+extern int iUseReverb;
+extern int iUseInterpolation;
+extern int iDisStereo;
+// MISC
+
+extern int iWatchDog;
+
+extern SPUCHAN s_chan[];
+extern REVERBInfo rvb;
+
+extern unsigned long dwNoiseVal;
+extern unsigned short spuCtrl;
+extern unsigned short spuStat;
+extern unsigned short spuIrq;
+extern unsigned long spuAddr;
+extern int bEndThread;
+extern int bThreadEnded;
+extern int bSpuInit;
+extern unsigned long dwNewChannel;
+
+extern int SSumR[];
+extern int SSumL[];
+extern int iCycle;
+extern short * pS;
+
+extern void (CALLBACK *cddavCallback)(unsigned short,unsigned short);
+
+#endif
+
+///////////////////////////////////////////////////////////
+// XA.C globals
+///////////////////////////////////////////////////////////
+
+#ifndef _IN_XA
+
+extern xa_decode_t * xapGlobal;
+
+extern uint32_t * XAFeed;
+extern uint32_t * XAPlay;
+extern uint32_t * XAStart;
+extern uint32_t * XAEnd;
+
+extern uint32_t XARepeat;
+extern uint32_t XALastVal;
+
+extern int iLeftXAVol;
+extern int iRightXAVol;
+
+#endif
+
+///////////////////////////////////////////////////////////
+// REVERB.C globals
+///////////////////////////////////////////////////////////
+
+#ifndef _IN_REVERB
+
+extern int * sRVBPlay;
+extern int * sRVBEnd;
+extern int * sRVBStart;
+extern int iReverbOff;
+extern int iReverbRepeat;
+extern int iReverbNum;
+
+#endif
diff --git a/plugins/dfsound/freeze.c b/plugins/dfsound/freeze.c new file mode 100644 index 00000000..37045b81 --- /dev/null +++ b/plugins/dfsound/freeze.c @@ -0,0 +1,202 @@ +/***************************************************************************
+ freeze.c - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#include "stdafx.h"
+
+#define _IN_FREEZE
+
+#include "externals.h"
+#include "registers.h"
+#include "spu.h"
+#include "regs.h"
+
+////////////////////////////////////////////////////////////////////////
+// freeze structs
+////////////////////////////////////////////////////////////////////////
+
+typedef struct
+{
+ char szSPUName[8];
+ uint32_t ulFreezeVersion;
+ uint32_t ulFreezeSize;
+ unsigned char cSPUPort[0x200];
+ unsigned char cSPURam[0x80000];
+ xa_decode_t xaS;
+} SPUFreeze_t;
+
+typedef struct
+{
+ unsigned short spuIrq;
+ uint32_t pSpuIrq;
+ uint32_t dummy0;
+ uint32_t dummy1;
+ uint32_t dummy2;
+ uint32_t dummy3;
+
+ SPUCHAN s_chan[MAXCHAN];
+
+} SPUOSSFreeze_t;
+
+////////////////////////////////////////////////////////////////////////
+
+void LoadStateV5(SPUFreeze_t * pF); // newest version
+void LoadStateUnknown(SPUFreeze_t * pF); // unknown format
+
+////////////////////////////////////////////////////////////////////////
+// SPUFREEZE: called by main emu on savestate load/save
+////////////////////////////////////////////////////////////////////////
+
+long CALLBACK SPUfreeze(uint32_t ulFreezeMode,SPUFreeze_t * pF)
+{
+ int i;SPUOSSFreeze_t * pFO;
+
+ if(!pF) return 0; // first check
+
+ if(ulFreezeMode) // info or save?
+ {//--------------------------------------------------//
+ if(ulFreezeMode==1)
+ memset(pF,0,sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t));
+
+ strcpy(pF->szSPUName,"PBOSS");
+ pF->ulFreezeVersion=5;
+ pF->ulFreezeSize=sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t);
+
+ if(ulFreezeMode==2) return 1; // info mode? ok, bye
+ // save mode:
+ RemoveTimer(); // stop timer
+
+ memcpy(pF->cSPURam,spuMem,0x80000); // copy common infos
+ memcpy(pF->cSPUPort,regArea,0x200);
+
+ if(xapGlobal && XAPlay!=XAFeed) // some xa
+ {
+ pF->xaS=*xapGlobal;
+ }
+ else
+ memset(&pF->xaS,0,sizeof(xa_decode_t)); // or clean xa
+
+ pFO=(SPUOSSFreeze_t *)(pF+1); // store special stuff
+
+ pFO->spuIrq=spuIrq;
+ if(pSpuIrq) pFO->pSpuIrq = (unsigned long)pSpuIrq-(unsigned long)spuMemC;
+
+ for(i=0;i<MAXCHAN;i++)
+ {
+ memcpy((void *)&pFO->s_chan[i],(void *)&s_chan[i],sizeof(SPUCHAN));
+ if(pFO->s_chan[i].pStart)
+ pFO->s_chan[i].pStart-=(unsigned long)spuMemC;
+ if(pFO->s_chan[i].pCurr)
+ pFO->s_chan[i].pCurr-=(unsigned long)spuMemC;
+ if(pFO->s_chan[i].pLoop)
+ pFO->s_chan[i].pLoop-=(unsigned long)spuMemC;
+ }
+
+ SetupTimer(); // sound processing on again
+
+ return 1;
+ //--------------------------------------------------//
+ }
+
+ if(ulFreezeMode!=0) return 0; // bad mode? bye
+
+ RemoveTimer(); // we stop processing while doing the save!
+
+ memcpy(spuMem,pF->cSPURam,0x80000); // get ram
+ memcpy(regArea,pF->cSPUPort,0x200);
+
+ if(pF->xaS.nsamples<=4032) // start xa again
+ SPUplayADPCMchannel(&pF->xaS);
+
+ xapGlobal=0;
+
+ if(!strcmp(pF->szSPUName,"PBOSS") &&
+ pF->ulFreezeVersion==5)
+ LoadStateV5(pF);
+ else LoadStateUnknown(pF);
+
+ // repair some globals
+ for(i=0;i<=62;i+=2)
+ SPUwriteRegister(H_Reverb+i,regArea[(H_Reverb+i-0xc00)>>1]);
+ SPUwriteRegister(H_SPUReverbAddr,regArea[(H_SPUReverbAddr-0xc00)>>1]);
+ SPUwriteRegister(H_SPUrvolL,regArea[(H_SPUrvolL-0xc00)>>1]);
+ SPUwriteRegister(H_SPUrvolR,regArea[(H_SPUrvolR-0xc00)>>1]);
+
+ SPUwriteRegister(H_SPUctrl,(unsigned short)(regArea[(H_SPUctrl-0xc00)>>1]|0x4000));
+ SPUwriteRegister(H_SPUstat,regArea[(H_SPUstat-0xc00)>>1]);
+ SPUwriteRegister(H_CDLeft,regArea[(H_CDLeft-0xc00)>>1]);
+ SPUwriteRegister(H_CDRight,regArea[(H_CDRight-0xc00)>>1]);
+
+ // fix to prevent new interpolations from crashing
+ for(i=0;i<MAXCHAN;i++) s_chan[i].SB[28]=0;
+
+ SetupTimer(); // start sound processing again
+
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+void LoadStateV5(SPUFreeze_t * pF)
+{
+ int i;SPUOSSFreeze_t * pFO;
+
+ pFO=(SPUOSSFreeze_t *)(pF+1);
+
+ spuIrq = pFO->spuIrq;
+ if(pFO->pSpuIrq) pSpuIrq = pFO->pSpuIrq+spuMemC; else pSpuIrq=0;
+
+ for(i=0;i<MAXCHAN;i++)
+ {
+ memcpy((void *)&s_chan[i],(void *)&pFO->s_chan[i],sizeof(SPUCHAN));
+
+ s_chan[i].pStart+=(unsigned long)spuMemC;
+ s_chan[i].pCurr+=(unsigned long)spuMemC;
+ s_chan[i].pLoop+=(unsigned long)spuMemC;
+ s_chan[i].iMute=0;
+ s_chan[i].iIrqDone=0;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+void LoadStateUnknown(SPUFreeze_t * pF)
+{
+ int i;
+
+ for(i=0;i<MAXCHAN;i++)
+ {
+ s_chan[i].bOn=0;
+ s_chan[i].bNew=0;
+ s_chan[i].bStop=0;
+ s_chan[i].ADSR.lVolume=0;
+ s_chan[i].pLoop=spuMemC;
+ s_chan[i].pStart=spuMemC;
+ s_chan[i].pLoop=spuMemC;
+ s_chan[i].iMute=0;
+ s_chan[i].iIrqDone=0;
+ }
+
+ dwNewChannel=0;
+ pSpuIrq=0;
+
+ for(i=0;i<0xc0;i++)
+ {
+ SPUwriteRegister(0x1f801c00+i*2,regArea[i]);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
diff --git a/plugins/dfsound/gauss_i.h b/plugins/dfsound/gauss_i.h new file mode 100644 index 00000000..5a3a676d --- /dev/null +++ b/plugins/dfsound/gauss_i.h @@ -0,0 +1,150 @@ +/***************************************************************************
+ gauss_i.h - description
+ -----------------------
+ begin : Sun Feb 08 2003
+ copyright : (C) 2003 by Chris Moeller, eh, whatever
+ email : chris@kode54.tk
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#ifndef GAUSS_H
+#define GAUSS_H
+
+const int gauss[]={
+ 0x172, 0x519, 0x176, 0x000, 0x16E, 0x519, 0x17A, 0x000,
+ 0x16A, 0x518, 0x17D, 0x000, 0x166, 0x518, 0x181, 0x000,
+ 0x162, 0x518, 0x185, 0x000, 0x15F, 0x518, 0x189, 0x000,
+ 0x15B, 0x518, 0x18D, 0x000, 0x157, 0x517, 0x191, 0x000,
+ 0x153, 0x517, 0x195, 0x000, 0x150, 0x517, 0x19A, 0x000,
+ 0x14C, 0x516, 0x19E, 0x000, 0x148, 0x516, 0x1A2, 0x000,
+ 0x145, 0x515, 0x1A6, 0x000, 0x141, 0x514, 0x1AA, 0x000,
+ 0x13E, 0x514, 0x1AE, 0x000, 0x13A, 0x513, 0x1B2, 0x000,
+ 0x137, 0x512, 0x1B7, 0x001, 0x133, 0x511, 0x1BB, 0x001,
+ 0x130, 0x511, 0x1BF, 0x001, 0x12C, 0x510, 0x1C3, 0x001,
+ 0x129, 0x50F, 0x1C8, 0x001, 0x125, 0x50E, 0x1CC, 0x001,
+ 0x122, 0x50D, 0x1D0, 0x001, 0x11E, 0x50C, 0x1D5, 0x001,
+ 0x11B, 0x50B, 0x1D9, 0x001, 0x118, 0x50A, 0x1DD, 0x001,
+ 0x114, 0x508, 0x1E2, 0x001, 0x111, 0x507, 0x1E6, 0x002,
+ 0x10E, 0x506, 0x1EB, 0x002, 0x10B, 0x504, 0x1EF, 0x002,
+ 0x107, 0x503, 0x1F3, 0x002, 0x104, 0x502, 0x1F8, 0x002,
+ 0x101, 0x500, 0x1FC, 0x002, 0x0FE, 0x4FF, 0x201, 0x002,
+ 0x0FB, 0x4FD, 0x205, 0x003, 0x0F8, 0x4FB, 0x20A, 0x003,
+ 0x0F5, 0x4FA, 0x20F, 0x003, 0x0F2, 0x4F8, 0x213, 0x003,
+ 0x0EF, 0x4F6, 0x218, 0x003, 0x0EC, 0x4F5, 0x21C, 0x004,
+ 0x0E9, 0x4F3, 0x221, 0x004, 0x0E6, 0x4F1, 0x226, 0x004,
+ 0x0E3, 0x4EF, 0x22A, 0x004, 0x0E0, 0x4ED, 0x22F, 0x004,
+ 0x0DD, 0x4EB, 0x233, 0x005, 0x0DA, 0x4E9, 0x238, 0x005,
+ 0x0D7, 0x4E7, 0x23D, 0x005, 0x0D4, 0x4E5, 0x241, 0x005,
+ 0x0D2, 0x4E3, 0x246, 0x006, 0x0CF, 0x4E0, 0x24B, 0x006,
+ 0x0CC, 0x4DE, 0x250, 0x006, 0x0C9, 0x4DC, 0x254, 0x006,
+ 0x0C7, 0x4D9, 0x259, 0x007, 0x0C4, 0x4D7, 0x25E, 0x007,
+ 0x0C1, 0x4D5, 0x263, 0x007, 0x0BF, 0x4D2, 0x267, 0x008,
+ 0x0BC, 0x4D0, 0x26C, 0x008, 0x0BA, 0x4CD, 0x271, 0x008,
+ 0x0B7, 0x4CB, 0x276, 0x009, 0x0B4, 0x4C8, 0x27B, 0x009,
+ 0x0B2, 0x4C5, 0x280, 0x009, 0x0AF, 0x4C3, 0x284, 0x00A,
+ 0x0AD, 0x4C0, 0x289, 0x00A, 0x0AB, 0x4BD, 0x28E, 0x00A,
+ 0x0A8, 0x4BA, 0x293, 0x00B, 0x0A6, 0x4B7, 0x298, 0x00B,
+ 0x0A3, 0x4B5, 0x29D, 0x00B, 0x0A1, 0x4B2, 0x2A2, 0x00C,
+ 0x09F, 0x4AF, 0x2A6, 0x00C, 0x09C, 0x4AC, 0x2AB, 0x00D,
+ 0x09A, 0x4A9, 0x2B0, 0x00D, 0x098, 0x4A6, 0x2B5, 0x00E,
+ 0x096, 0x4A2, 0x2BA, 0x00E, 0x093, 0x49F, 0x2BF, 0x00F,
+ 0x091, 0x49C, 0x2C4, 0x00F, 0x08F, 0x499, 0x2C9, 0x00F,
+ 0x08D, 0x496, 0x2CE, 0x010, 0x08B, 0x492, 0x2D3, 0x010,
+ 0x089, 0x48F, 0x2D8, 0x011, 0x086, 0x48C, 0x2DC, 0x011,
+ 0x084, 0x488, 0x2E1, 0x012, 0x082, 0x485, 0x2E6, 0x013,
+ 0x080, 0x481, 0x2EB, 0x013, 0x07E, 0x47E, 0x2F0, 0x014,
+ 0x07C, 0x47A, 0x2F5, 0x014, 0x07A, 0x477, 0x2FA, 0x015,
+ 0x078, 0x473, 0x2FF, 0x015, 0x076, 0x470, 0x304, 0x016,
+ 0x075, 0x46C, 0x309, 0x017, 0x073, 0x468, 0x30E, 0x017,
+ 0x071, 0x465, 0x313, 0x018, 0x06F, 0x461, 0x318, 0x018,
+ 0x06D, 0x45D, 0x31D, 0x019, 0x06B, 0x459, 0x322, 0x01A,
+ 0x06A, 0x455, 0x326, 0x01B, 0x068, 0x452, 0x32B, 0x01B,
+ 0x066, 0x44E, 0x330, 0x01C, 0x064, 0x44A, 0x335, 0x01D,
+ 0x063, 0x446, 0x33A, 0x01D, 0x061, 0x442, 0x33F, 0x01E,
+ 0x05F, 0x43E, 0x344, 0x01F, 0x05E, 0x43A, 0x349, 0x020,
+ 0x05C, 0x436, 0x34E, 0x020, 0x05A, 0x432, 0x353, 0x021,
+ 0x059, 0x42E, 0x357, 0x022, 0x057, 0x42A, 0x35C, 0x023,
+ 0x056, 0x425, 0x361, 0x024, 0x054, 0x421, 0x366, 0x024,
+ 0x053, 0x41D, 0x36B, 0x025, 0x051, 0x419, 0x370, 0x026,
+ 0x050, 0x415, 0x374, 0x027, 0x04E, 0x410, 0x379, 0x028,
+ 0x04D, 0x40C, 0x37E, 0x029, 0x04C, 0x408, 0x383, 0x02A,
+ 0x04A, 0x403, 0x388, 0x02B, 0x049, 0x3FF, 0x38C, 0x02C,
+ 0x047, 0x3FB, 0x391, 0x02D, 0x046, 0x3F6, 0x396, 0x02E,
+ 0x045, 0x3F2, 0x39B, 0x02F, 0x043, 0x3ED, 0x39F, 0x030,
+ 0x042, 0x3E9, 0x3A4, 0x031, 0x041, 0x3E5, 0x3A9, 0x032,
+ 0x040, 0x3E0, 0x3AD, 0x033, 0x03E, 0x3DC, 0x3B2, 0x034,
+ 0x03D, 0x3D7, 0x3B7, 0x035, 0x03C, 0x3D2, 0x3BB, 0x036,
+ 0x03B, 0x3CE, 0x3C0, 0x037, 0x03A, 0x3C9, 0x3C5, 0x038,
+ 0x038, 0x3C5, 0x3C9, 0x03A, 0x037, 0x3C0, 0x3CE, 0x03B,
+ 0x036, 0x3BB, 0x3D2, 0x03C, 0x035, 0x3B7, 0x3D7, 0x03D,
+ 0x034, 0x3B2, 0x3DC, 0x03E, 0x033, 0x3AD, 0x3E0, 0x040,
+ 0x032, 0x3A9, 0x3E5, 0x041, 0x031, 0x3A4, 0x3E9, 0x042,
+ 0x030, 0x39F, 0x3ED, 0x043, 0x02F, 0x39B, 0x3F2, 0x045,
+ 0x02E, 0x396, 0x3F6, 0x046, 0x02D, 0x391, 0x3FB, 0x047,
+ 0x02C, 0x38C, 0x3FF, 0x049, 0x02B, 0x388, 0x403, 0x04A,
+ 0x02A, 0x383, 0x408, 0x04C, 0x029, 0x37E, 0x40C, 0x04D,
+ 0x028, 0x379, 0x410, 0x04E, 0x027, 0x374, 0x415, 0x050,
+ 0x026, 0x370, 0x419, 0x051, 0x025, 0x36B, 0x41D, 0x053,
+ 0x024, 0x366, 0x421, 0x054, 0x024, 0x361, 0x425, 0x056,
+ 0x023, 0x35C, 0x42A, 0x057, 0x022, 0x357, 0x42E, 0x059,
+ 0x021, 0x353, 0x432, 0x05A, 0x020, 0x34E, 0x436, 0x05C,
+ 0x020, 0x349, 0x43A, 0x05E, 0x01F, 0x344, 0x43E, 0x05F,
+ 0x01E, 0x33F, 0x442, 0x061, 0x01D, 0x33A, 0x446, 0x063,
+ 0x01D, 0x335, 0x44A, 0x064, 0x01C, 0x330, 0x44E, 0x066,
+ 0x01B, 0x32B, 0x452, 0x068, 0x01B, 0x326, 0x455, 0x06A,
+ 0x01A, 0x322, 0x459, 0x06B, 0x019, 0x31D, 0x45D, 0x06D,
+ 0x018, 0x318, 0x461, 0x06F, 0x018, 0x313, 0x465, 0x071,
+ 0x017, 0x30E, 0x468, 0x073, 0x017, 0x309, 0x46C, 0x075,
+ 0x016, 0x304, 0x470, 0x076, 0x015, 0x2FF, 0x473, 0x078,
+ 0x015, 0x2FA, 0x477, 0x07A, 0x014, 0x2F5, 0x47A, 0x07C,
+ 0x014, 0x2F0, 0x47E, 0x07E, 0x013, 0x2EB, 0x481, 0x080,
+ 0x013, 0x2E6, 0x485, 0x082, 0x012, 0x2E1, 0x488, 0x084,
+ 0x011, 0x2DC, 0x48C, 0x086, 0x011, 0x2D8, 0x48F, 0x089,
+ 0x010, 0x2D3, 0x492, 0x08B, 0x010, 0x2CE, 0x496, 0x08D,
+ 0x00F, 0x2C9, 0x499, 0x08F, 0x00F, 0x2C4, 0x49C, 0x091,
+ 0x00F, 0x2BF, 0x49F, 0x093, 0x00E, 0x2BA, 0x4A2, 0x096,
+ 0x00E, 0x2B5, 0x4A6, 0x098, 0x00D, 0x2B0, 0x4A9, 0x09A,
+ 0x00D, 0x2AB, 0x4AC, 0x09C, 0x00C, 0x2A6, 0x4AF, 0x09F,
+ 0x00C, 0x2A2, 0x4B2, 0x0A1, 0x00B, 0x29D, 0x4B5, 0x0A3,
+ 0x00B, 0x298, 0x4B7, 0x0A6, 0x00B, 0x293, 0x4BA, 0x0A8,
+ 0x00A, 0x28E, 0x4BD, 0x0AB, 0x00A, 0x289, 0x4C0, 0x0AD,
+ 0x00A, 0x284, 0x4C3, 0x0AF, 0x009, 0x280, 0x4C5, 0x0B2,
+ 0x009, 0x27B, 0x4C8, 0x0B4, 0x009, 0x276, 0x4CB, 0x0B7,
+ 0x008, 0x271, 0x4CD, 0x0BA, 0x008, 0x26C, 0x4D0, 0x0BC,
+ 0x008, 0x267, 0x4D2, 0x0BF, 0x007, 0x263, 0x4D5, 0x0C1,
+ 0x007, 0x25E, 0x4D7, 0x0C4, 0x007, 0x259, 0x4D9, 0x0C7,
+ 0x006, 0x254, 0x4DC, 0x0C9, 0x006, 0x250, 0x4DE, 0x0CC,
+ 0x006, 0x24B, 0x4E0, 0x0CF, 0x006, 0x246, 0x4E3, 0x0D2,
+ 0x005, 0x241, 0x4E5, 0x0D4, 0x005, 0x23D, 0x4E7, 0x0D7,
+ 0x005, 0x238, 0x4E9, 0x0DA, 0x005, 0x233, 0x4EB, 0x0DD,
+ 0x004, 0x22F, 0x4ED, 0x0E0, 0x004, 0x22A, 0x4EF, 0x0E3,
+ 0x004, 0x226, 0x4F1, 0x0E6, 0x004, 0x221, 0x4F3, 0x0E9,
+ 0x004, 0x21C, 0x4F5, 0x0EC, 0x003, 0x218, 0x4F6, 0x0EF,
+ 0x003, 0x213, 0x4F8, 0x0F2, 0x003, 0x20F, 0x4FA, 0x0F5,
+ 0x003, 0x20A, 0x4FB, 0x0F8, 0x003, 0x205, 0x4FD, 0x0FB,
+ 0x002, 0x201, 0x4FF, 0x0FE, 0x002, 0x1FC, 0x500, 0x101,
+ 0x002, 0x1F8, 0x502, 0x104, 0x002, 0x1F3, 0x503, 0x107,
+ 0x002, 0x1EF, 0x504, 0x10B, 0x002, 0x1EB, 0x506, 0x10E,
+ 0x002, 0x1E6, 0x507, 0x111, 0x001, 0x1E2, 0x508, 0x114,
+ 0x001, 0x1DD, 0x50A, 0x118, 0x001, 0x1D9, 0x50B, 0x11B,
+ 0x001, 0x1D5, 0x50C, 0x11E, 0x001, 0x1D0, 0x50D, 0x122,
+ 0x001, 0x1CC, 0x50E, 0x125, 0x001, 0x1C8, 0x50F, 0x129,
+ 0x001, 0x1C3, 0x510, 0x12C, 0x001, 0x1BF, 0x511, 0x130,
+ 0x001, 0x1BB, 0x511, 0x133, 0x001, 0x1B7, 0x512, 0x137,
+ 0x000, 0x1B2, 0x513, 0x13A, 0x000, 0x1AE, 0x514, 0x13E,
+ 0x000, 0x1AA, 0x514, 0x141, 0x000, 0x1A6, 0x515, 0x145,
+ 0x000, 0x1A2, 0x516, 0x148, 0x000, 0x19E, 0x516, 0x14C,
+ 0x000, 0x19A, 0x517, 0x150, 0x000, 0x195, 0x517, 0x153,
+ 0x000, 0x191, 0x517, 0x157, 0x000, 0x18D, 0x518, 0x15B,
+ 0x000, 0x189, 0x518, 0x15F, 0x000, 0x185, 0x518, 0x162,
+ 0x000, 0x181, 0x518, 0x166, 0x000, 0x17D, 0x518, 0x16A,
+ 0x000, 0x17A, 0x519, 0x16E, 0x000, 0x176, 0x519, 0x172};
+#endif
diff --git a/plugins/dfsound/nullsnd.c b/plugins/dfsound/nullsnd.c new file mode 100644 index 00000000..fd7ce015 --- /dev/null +++ b/plugins/dfsound/nullsnd.c @@ -0,0 +1,30 @@ +#include "stdafx.h" +#define _IN_OSS +#include "externals.h" + +#if !defined (USEALSA) && !defined (USEOSS) + +#warning "Using NULL sound output..." + +// SETUP SOUND +void SetupSound(void) +{ +} + +// REMOVE SOUND +void RemoveSound(void) +{ +} + +// GET BYTES BUFFERED +unsigned long SoundGetBytesBuffered(void) +{ + return 0; +} + +// FEED SOUND DATA +void SoundFeedStreamData(unsigned char* pSound,long lBytes) +{ +} + +#endif diff --git a/plugins/dfsound/oss.c b/plugins/dfsound/oss.c new file mode 100644 index 00000000..59c34d74 --- /dev/null +++ b/plugins/dfsound/oss.c @@ -0,0 +1,160 @@ +/*************************************************************************** + oss.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#ifdef USEOSS + +#define _IN_OSS + +#include "externals.h" + +//////////////////////////////////////////////////////////////////////// +// oss globals +//////////////////////////////////////////////////////////////////////// + +#define OSS_MEM_DEF +#include "oss.h" +static int oss_audio_fd = -1; +extern int errno; + +//////////////////////////////////////////////////////////////////////// +// SETUP SOUND +//////////////////////////////////////////////////////////////////////// + +void SetupSound(void) +{ + int pspeed=44100; + int pstereo; + int format; + int fragsize = 0; + int myfrag; + int oss_speed, oss_stereo; + + if(iDisStereo) pstereo=OSS_MODE_MONO; + else pstereo=OSS_MODE_STEREO; + + oss_speed = pspeed; + oss_stereo = pstereo; + + if((oss_audio_fd=open("/dev/dsp",O_WRONLY,0))==-1) + { + printf("Sound device not available!\n"); + return; + } + + if(ioctl(oss_audio_fd,SNDCTL_DSP_RESET,0)==-1) + { + printf("Sound reset failed\n"); + return; + } + + // we use 64 fragments with 1024 bytes each + + fragsize=10; + myfrag=(63<<16)|fragsize; + + if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFRAGMENT,&myfrag)==-1) + { + printf("Sound set fragment failed!\n"); + return; + } + + format = AFMT_S16_NE; + + if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFMT,&format) == -1) + { + printf("Sound format not supported!\n"); + return; + } + + if(format!=AFMT_S16_NE) + { + printf("Sound format not supported!\n"); + return; + } + + if(ioctl(oss_audio_fd,SNDCTL_DSP_STEREO,&oss_stereo)==-1) + { + printf("Stereo mode not supported!\n"); + return; + } + + if(oss_stereo!=1) + { + iDisStereo=1; + } + + if(ioctl(oss_audio_fd,SNDCTL_DSP_SPEED,&oss_speed)==-1) + { + printf("Sound frequency not supported\n"); + return; + } + + if(oss_speed!=pspeed) + { + printf("Sound frequency not supported\n"); + return; + } +} + +//////////////////////////////////////////////////////////////////////// +// REMOVE SOUND +//////////////////////////////////////////////////////////////////////// + +void RemoveSound(void) +{ + if(oss_audio_fd != -1 ) + { + close(oss_audio_fd); + oss_audio_fd = -1; + } +} + +//////////////////////////////////////////////////////////////////////// +// GET BYTES BUFFERED +//////////////////////////////////////////////////////////////////////// + +unsigned long SoundGetBytesBuffered(void) +{ + audio_buf_info info; + unsigned long l; + + if(oss_audio_fd == -1) return SOUNDSIZE; + if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==-1) + l=0; + else + { + if(info.fragments<(info.fragstotal>>1)) // can we write in at least the half of fragments? + l=SOUNDSIZE; // -> no? wait + else l=0; // -> else go on + } + + return l; +} + +//////////////////////////////////////////////////////////////////////// +// FEED SOUND DATA +//////////////////////////////////////////////////////////////////////// + +void SoundFeedStreamData(unsigned char* pSound,long lBytes) +{ + if(oss_audio_fd == -1) return; + write(oss_audio_fd,pSound,lBytes); +} + +#endif diff --git a/plugins/dfsound/oss.h b/plugins/dfsound/oss.h new file mode 100644 index 00000000..b4664ab6 --- /dev/null +++ b/plugins/dfsound/oss.h @@ -0,0 +1,33 @@ +/*************************************************************************** + oss_sound.h - description + ------------------- + begin : Wed Dec 8 1999 + copyright : (C) 1999 by Marcin "Duddie" Dudar + email : duddie@psemu.com + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _OSS_SOUND_H +#define _OSS_SOUND_H + +#ifdef OSS_MEM_DEF +#define OSS_MEM_EXTERN +#else +#define OSS_MEM_EXTERN extern +#endif + +OSS_MEM_EXTERN int sound_buffer_size; + +#define OSS_MODE_STEREO 1 +#define OSS_MODE_MONO 0 + +#define OSS_SPEED_44100 44100 + +#endif // _OSS_SOUND_H diff --git a/plugins/dfsound/psemu.c b/plugins/dfsound/psemu.c new file mode 100644 index 00000000..2aeac7ed --- /dev/null +++ b/plugins/dfsound/psemu.c @@ -0,0 +1,99 @@ +/***************************************************************************
+ psemu.c - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#include "stdafx.h"
+
+#define _IN_PSEMU
+
+#include "externals.h"
+#include "regs.h"
+#include "dma.h"
+
+////////////////////////////////////////////////////////////////////////
+// OLD, SOMEWHAT (BUT NOT MUCH) SUPPORTED PSEMUPRO FUNCS
+////////////////////////////////////////////////////////////////////////
+
+unsigned short CALLBACK SPUgetOne(unsigned long val)
+{
+ if(spuAddr!=0xffffffff)
+ {
+ return SPUreadDMA();
+ }
+ if(val>=512*1024) val=512*1024-1;
+ return spuMem[val>>1];
+}
+
+void CALLBACK SPUputOne(unsigned long val,unsigned short data)
+{
+ if(spuAddr!=0xffffffff)
+ {
+ SPUwriteDMA(data);
+ return;
+ }
+ if(val>=512*1024) val=512*1024-1;
+ spuMem[val>>1] = data;
+}
+
+void CALLBACK SPUplaySample(unsigned char ch)
+{
+}
+
+void CALLBACK SPUsetAddr(unsigned char ch, unsigned short waddr)
+{
+ s_chan[ch].pStart=spuMemC+((unsigned long) waddr<<3);
+}
+
+void CALLBACK SPUsetPitch(unsigned char ch, unsigned short pitch)
+{
+ SetPitch(ch,pitch);
+}
+
+void CALLBACK SPUsetVolumeL(unsigned char ch, short vol)
+{
+ SetVolumeR(ch,vol);
+}
+
+void CALLBACK SPUsetVolumeR(unsigned char ch, short vol)
+{
+ SetVolumeL(ch,vol);
+}
+
+void CALLBACK SPUstartChannels1(unsigned short channels)
+{
+ SoundOn(0,16,channels);
+}
+
+void CALLBACK SPUstartChannels2(unsigned short channels)
+{
+ SoundOn(16,24,channels);
+}
+
+void CALLBACK SPUstopChannels1(unsigned short channels)
+{
+ SoundOff(0,16,channels);
+}
+
+void CALLBACK SPUstopChannels2(unsigned short channels)
+{
+ SoundOff(16,24,channels);
+}
+
+void CALLBACK SPUplaySector(unsigned long mode, unsigned char * p)
+{
+ if(!iUseXA) return; // no XA? bye
+}
+
diff --git a/plugins/dfsound/psemuxa.h b/plugins/dfsound/psemuxa.h new file mode 100644 index 00000000..84c62604 --- /dev/null +++ b/plugins/dfsound/psemuxa.h @@ -0,0 +1,28 @@ +//============================================
+//=== Audio XA decoding
+//=== Kazzuya
+//============================================
+
+#ifndef DECODEXA_H
+#define DECODEXA_H
+
+typedef struct
+{
+ long y0, y1;
+} ADPCM_Decode_t;
+
+typedef struct
+{
+ int freq;
+ int nbits;
+ int stereo;
+ int nsamples;
+ ADPCM_Decode_t left, right;
+ short pcm[16384];
+} xa_decode_t;
+
+long xa_decode_sector( xa_decode_t *xdp,
+ unsigned char *sectorp,
+ int is_first_sector );
+
+#endif
diff --git a/plugins/dfsound/registers.c b/plugins/dfsound/registers.c new file mode 100644 index 00000000..54f5f24e --- /dev/null +++ b/plugins/dfsound/registers.c @@ -0,0 +1,589 @@ +/***************************************************************************
+ registers.c - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#include "stdafx.h"
+
+#define _IN_REGISTERS
+
+#include "externals.h"
+#include "registers.h"
+#include "regs.h"
+#include "reverb.h"
+
+/*
+// adsr time values (in ms) by James Higgs ... see the end of
+// the adsr.c source for details
+
+#define ATTACK_MS 514L
+#define DECAYHALF_MS 292L
+#define DECAY_MS 584L
+#define SUSTAIN_MS 450L
+#define RELEASE_MS 446L
+*/
+
+// we have a timebase of 1.020408f ms, not 1 ms... so adjust adsr defines
+#define ATTACK_MS 494L
+#define DECAYHALF_MS 286L
+#define DECAY_MS 572L
+#define SUSTAIN_MS 441L
+#define RELEASE_MS 437L
+
+////////////////////////////////////////////////////////////////////////
+// WRITE REGISTERS: called by main emu
+////////////////////////////////////////////////////////////////////////
+
+void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val)
+{
+ const unsigned long r=reg&0xfff;
+ regArea[(r-0xc00)>>1] = val;
+
+ if(r>=0x0c00 && r<0x0d80) // some channel info?
+ {
+ int ch=(r>>4)-0xc0; // calc channel
+ switch(r&0x0f)
+ {
+ //------------------------------------------------// r volume
+ case 0:
+ SetVolumeL((unsigned char)ch,val);
+ break;
+ //------------------------------------------------// l volume
+ case 2:
+ SetVolumeR((unsigned char)ch,val);
+ break;
+ //------------------------------------------------// pitch
+ case 4:
+ SetPitch(ch,val);
+ break;
+ //------------------------------------------------// start
+ case 6:
+ s_chan[ch].pStart=spuMemC+((unsigned long) val<<3);
+ break;
+ //------------------------------------------------// level with pre-calcs
+ case 8:
+ {
+ const unsigned long lval=val;unsigned long lx;
+ //---------------------------------------------//
+ s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0;
+ s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;
+ s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;
+ s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;
+ //---------------------------------------------//
+ if(!iDebugMode) break;
+ //---------------------------------------------// stuff below is only for debug mode
+
+ s_chan[ch].ADSR.AttackModeExp=(lval&0x8000)?1:0; //0x007f
+
+ lx=(((lval>>8) & 0x007f)>>2); // attack time to run from 0 to 100% volume
+ lx=min(31,lx); // no overflow on shift!
+ if(lx)
+ {
+ lx = (1<<lx);
+ if(lx<2147483) lx=(lx*ATTACK_MS)/10000L; // another overflow check
+ else lx=(lx/10000L)*ATTACK_MS;
+ if(!lx) lx=1;
+ }
+ s_chan[ch].ADSR.AttackTime=lx;
+
+ s_chan[ch].ADSR.SustainLevel= // our adsr vol runs from 0 to 1024, so scale the sustain level
+ (1024*((lval) & 0x000f))/15;
+
+ lx=(lval>>4) & 0x000f; // decay:
+ if(lx) // our const decay value is time it takes from 100% to 0% of volume
+ {
+ lx = ((1<<(lx))*DECAY_MS)/10000L;
+ if(!lx) lx=1;
+ }
+ s_chan[ch].ADSR.DecayTime = // so calc how long does it take to run from 100% to the wanted sus level
+ (lx*(1024-s_chan[ch].ADSR.SustainLevel))/1024;
+ }
+ break;
+ //------------------------------------------------// adsr times with pre-calcs
+ case 10:
+ {
+ const unsigned long lval=val;unsigned long lx;
+
+ //----------------------------------------------//
+ s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;
+ s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1;
+ s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f;
+ s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;
+ s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;
+ //----------------------------------------------//
+ if(!iDebugMode) break;
+ //----------------------------------------------// stuff below is only for debug mode
+
+ s_chan[ch].ADSR.SustainModeExp = (lval&0x8000)?1:0;
+ s_chan[ch].ADSR.ReleaseModeExp = (lval&0x0020)?1:0;
+
+ lx=((((lval>>6) & 0x007f)>>2)); // sustain time... often very high
+ lx=min(31,lx); // values are used to hold the volume
+ if(lx) // until a sound stop occurs
+ { // the highest value we reach (due to
+ lx = (1<<lx); // overflow checking) is:
+ if(lx<2147483) lx=(lx*SUSTAIN_MS)/10000L; // 94704 seconds = 1578 minutes = 26 hours...
+ else lx=(lx/10000L)*SUSTAIN_MS; // should be enuff... if the stop doesn't
+ if(!lx) lx=1; // come in this time span, I don't care :)
+ }
+ s_chan[ch].ADSR.SustainTime = lx;
+
+ lx=(lval & 0x001f);
+ s_chan[ch].ADSR.ReleaseVal =lx;
+ if(lx) // release time from 100% to 0%
+ { // note: the release time will be
+ lx = (1<<lx); // adjusted when a stop is coming,
+ if(lx<2147483) lx=(lx*RELEASE_MS)/10000L; // so at this time the adsr vol will
+ else lx=(lx/10000L)*RELEASE_MS; // run from (current volume) to 0%
+ if(!lx) lx=1;
+ }
+ s_chan[ch].ADSR.ReleaseTime=lx;
+
+ if(lval & 0x4000) // add/dec flag
+ s_chan[ch].ADSR.SustainModeDec=-1;
+ else s_chan[ch].ADSR.SustainModeDec=1;
+ }
+ break;
+ //------------------------------------------------// adsr volume... mmm have to investigate this
+ case 12:
+ break;
+ //------------------------------------------------//
+ case 14: // loop?
+ //WaitForSingleObject(s_chan[ch].hMutex,2000); // -> no multithread fuckups
+ s_chan[ch].pLoop=spuMemC+((unsigned long) val<<3);
+ s_chan[ch].bIgnoreLoop=1;
+ //ReleaseMutex(s_chan[ch].hMutex); // -> oki, on with the thread
+ break;
+ //------------------------------------------------//
+ }
+ iWatchDog=0;
+ return;
+ }
+
+ switch(r)
+ {
+ //-------------------------------------------------//
+ case H_SPUaddr:
+ spuAddr = (unsigned long) val<<3;
+ break;
+ //-------------------------------------------------//
+ case H_SPUdata:
+ spuMem[spuAddr>>1] = val;
+ spuAddr+=2;
+ if(spuAddr>0x7ffff) spuAddr=0;
+ break;
+ //-------------------------------------------------//
+ case H_SPUctrl:
+ spuCtrl=val;
+ break;
+ //-------------------------------------------------//
+ case H_SPUstat:
+ spuStat=val & 0xf800;
+ break;
+ //-------------------------------------------------//
+ case H_SPUReverbAddr:
+ if(val==0xFFFF || val<=0x200)
+ {rvb.StartAddr=rvb.CurrAddr=0;}
+ else
+ {
+ const long iv=(unsigned long)val<<2;
+ if(rvb.StartAddr!=iv)
+ {
+ rvb.StartAddr=(unsigned long)val<<2;
+ rvb.CurrAddr=rvb.StartAddr;
+ }
+ }
+ break;
+ //-------------------------------------------------//
+ case H_SPUirqAddr:
+ spuIrq = val;
+ pSpuIrq=spuMemC+((unsigned long) val<<3);
+ break;
+ //-------------------------------------------------//
+ case H_SPUrvolL:
+ rvb.VolLeft=val;
+ break;
+ //-------------------------------------------------//
+ case H_SPUrvolR:
+ rvb.VolRight=val;
+ break;
+ //-------------------------------------------------//
+
+/*
+ case H_ExtLeft:
+ //auxprintf("EL %d\n",val);
+ break;
+ //-------------------------------------------------//
+ case H_ExtRight:
+ //auxprintf("ER %d\n",val);
+ break;
+ //-------------------------------------------------//
+ case H_SPUmvolL:
+ //auxprintf("ML %d\n",val);
+ break;
+ //-------------------------------------------------//
+ case H_SPUmvolR:
+ //auxprintf("MR %d\n",val);
+ break;
+ //-------------------------------------------------//
+ case H_SPUMute1:
+ //auxprintf("M0 %04x\n",val);
+ break;
+ //-------------------------------------------------//
+ case H_SPUMute2:
+ //auxprintf("M1 %04x\n",val);
+ break;
+*/
+ //-------------------------------------------------//
+ case H_SPUon1:
+ SoundOn(0,16,val);
+ break;
+ //-------------------------------------------------//
+ case H_SPUon2:
+ SoundOn(16,24,val);
+ break;
+ //-------------------------------------------------//
+ case H_SPUoff1:
+ SoundOff(0,16,val);
+ break;
+ //-------------------------------------------------//
+ case H_SPUoff2:
+ SoundOff(16,24,val);
+ break;
+ //-------------------------------------------------//
+ case H_CDLeft:
+ iLeftXAVol=val & 0x7fff;
+ if(cddavCallback) cddavCallback(0,val);
+ break;
+ case H_CDRight:
+ iRightXAVol=val & 0x7fff;
+ if(cddavCallback) cddavCallback(1,val);
+ break;
+ //-------------------------------------------------//
+ case H_FMod1:
+ FModOn(0,16,val);
+ break;
+ //-------------------------------------------------//
+ case H_FMod2:
+ FModOn(16,24,val);
+ break;
+ //-------------------------------------------------//
+ case H_Noise1:
+ NoiseOn(0,16,val);
+ break;
+ //-------------------------------------------------//
+ case H_Noise2:
+ NoiseOn(16,24,val);
+ break;
+ //-------------------------------------------------//
+ case H_RVBon1:
+ ReverbOn(0,16,val);
+ break;
+ //-------------------------------------------------//
+ case H_RVBon2:
+ ReverbOn(16,24,val);
+ break;
+ //-------------------------------------------------//
+ case H_Reverb+0:
+
+ rvb.FB_SRC_A=val;
+
+ // OK, here's the fake REVERB stuff...
+ // depending on effect we do more or less delay and repeats... bah
+ // still... better than nothing :)
+
+ SetREVERB(val);
+ break;
+
+
+ case H_Reverb+2 : rvb.FB_SRC_B=(short)val; break;
+ case H_Reverb+4 : rvb.IIR_ALPHA=(short)val; break;
+ case H_Reverb+6 : rvb.ACC_COEF_A=(short)val; break;
+ case H_Reverb+8 : rvb.ACC_COEF_B=(short)val; break;
+ case H_Reverb+10 : rvb.ACC_COEF_C=(short)val; break;
+ case H_Reverb+12 : rvb.ACC_COEF_D=(short)val; break;
+ case H_Reverb+14 : rvb.IIR_COEF=(short)val; break;
+ case H_Reverb+16 : rvb.FB_ALPHA=(short)val; break;
+ case H_Reverb+18 : rvb.FB_X=(short)val; break;
+ case H_Reverb+20 : rvb.IIR_DEST_A0=(short)val; break;
+ case H_Reverb+22 : rvb.IIR_DEST_A1=(short)val; break;
+ case H_Reverb+24 : rvb.ACC_SRC_A0=(short)val; break;
+ case H_Reverb+26 : rvb.ACC_SRC_A1=(short)val; break;
+ case H_Reverb+28 : rvb.ACC_SRC_B0=(short)val; break;
+ case H_Reverb+30 : rvb.ACC_SRC_B1=(short)val; break;
+ case H_Reverb+32 : rvb.IIR_SRC_A0=(short)val; break;
+ case H_Reverb+34 : rvb.IIR_SRC_A1=(short)val; break;
+ case H_Reverb+36 : rvb.IIR_DEST_B0=(short)val; break;
+ case H_Reverb+38 : rvb.IIR_DEST_B1=(short)val; break;
+ case H_Reverb+40 : rvb.ACC_SRC_C0=(short)val; break;
+ case H_Reverb+42 : rvb.ACC_SRC_C1=(short)val; break;
+ case H_Reverb+44 : rvb.ACC_SRC_D0=(short)val; break;
+ case H_Reverb+46 : rvb.ACC_SRC_D1=(short)val; break;
+ case H_Reverb+48 : rvb.IIR_SRC_B1=(short)val; break;
+ case H_Reverb+50 : rvb.IIR_SRC_B0=(short)val; break;
+ case H_Reverb+52 : rvb.MIX_DEST_A0=(short)val; break;
+ case H_Reverb+54 : rvb.MIX_DEST_A1=(short)val; break;
+ case H_Reverb+56 : rvb.MIX_DEST_B0=(short)val; break;
+ case H_Reverb+58 : rvb.MIX_DEST_B1=(short)val; break;
+ case H_Reverb+60 : rvb.IN_COEF_L=(short)val; break;
+ case H_Reverb+62 : rvb.IN_COEF_R=(short)val; break;
+ }
+
+ iWatchDog=0;
+}
+
+////////////////////////////////////////////////////////////////////////
+// READ REGISTER: called by main emu
+////////////////////////////////////////////////////////////////////////
+
+unsigned short CALLBACK SPUreadRegister(unsigned long reg)
+{
+ const unsigned long r=reg&0xfff;
+
+ iWatchDog=0;
+
+ if(r>=0x0c00 && r<0x0d80)
+ {
+ switch(r&0x0f)
+ {
+ case 12: // get adsr vol
+ {
+ const int ch=(r>>4)-0xc0;
+ if(s_chan[ch].bNew) return 1; // we are started, but not processed? return 1
+ if(s_chan[ch].ADSRX.lVolume && // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well
+ !s_chan[ch].ADSRX.EnvelopeVol)
+ return 1;
+ return (unsigned short)(s_chan[ch].ADSRX.EnvelopeVol>>16);
+ }
+
+ case 14: // get loop address
+ {
+ const int ch=(r>>4)-0xc0;
+ if(s_chan[ch].pLoop==NULL) return 0;
+ return (unsigned short)((s_chan[ch].pLoop-spuMemC)>>3);
+ }
+ }
+ }
+
+ switch(r)
+ {
+ case H_SPUctrl:
+ return spuCtrl;
+
+ case H_SPUstat:
+ return spuStat;
+
+ case H_SPUaddr:
+ return (unsigned short)(spuAddr>>3);
+
+ case H_SPUdata:
+ {
+ unsigned short s=spuMem[spuAddr>>1];
+ spuAddr+=2;
+ if(spuAddr>0x7ffff) spuAddr=0;
+ return s;
+ }
+
+ case H_SPUirqAddr:
+ return spuIrq;
+
+ //case H_SPUIsOn1:
+ // return IsSoundOn(0,16);
+
+ //case H_SPUIsOn2:
+ // return IsSoundOn(16,24);
+
+ }
+
+ return regArea[(r-0xc00)>>1];
+}
+
+////////////////////////////////////////////////////////////////////////
+// SOUND ON register write
+////////////////////////////////////////////////////////////////////////
+
+void SoundOn(int start,int end,unsigned short val) // SOUND ON PSX COMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1) // loop channels
+ {
+ if((val&1) && s_chan[ch].pStart) // mmm... start has to be set before key on !?!
+ {
+ s_chan[ch].bIgnoreLoop=0;
+ s_chan[ch].bNew=1;
+ dwNewChannel|=(1<<ch); // bitfield for faster testing
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+// SOUND OFF register write
+////////////////////////////////////////////////////////////////////////
+
+void SoundOff(int start,int end,unsigned short val) // SOUND OFF PSX COMMAND
+{
+ int ch;
+ for(ch=start;ch<end;ch++,val>>=1) // loop channels
+ {
+ if(val&1) // && s_chan[i].bOn) mmm...
+ {
+ s_chan[ch].bStop=1;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+// FMOD register write
+////////////////////////////////////////////////////////////////////////
+
+void FModOn(int start,int end,unsigned short val) // FMOD ON PSX COMMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1) // loop channels
+ {
+ if(val&1) // -> fmod on/off
+ {
+ if(ch>0)
+ {
+ s_chan[ch].bFMod=1; // --> sound channel
+ s_chan[ch-1].bFMod=2; // --> freq channel
+ }
+ }
+ else
+ {
+ s_chan[ch].bFMod=0; // --> turn off fmod
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+// NOISE register write
+////////////////////////////////////////////////////////////////////////
+
+void NoiseOn(int start,int end,unsigned short val) // NOISE ON PSX COMMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1) // loop channels
+ {
+ if(val&1) // -> noise on/off
+ {
+ s_chan[ch].bNoise=1;
+ }
+ else
+ {
+ s_chan[ch].bNoise=0;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+// LEFT VOLUME register write
+////////////////////////////////////////////////////////////////////////
+
+// please note: sweep and phase invert are wrong... but I've never seen
+// them used
+
+void SetVolumeL(unsigned char ch,short vol) // LEFT VOLUME
+{
+ s_chan[ch].iLeftVolRaw=vol;
+
+ if(vol&0x8000) // sweep?
+ {
+ short sInc=1; // -> sweep up?
+ if(vol&0x2000) sInc=-1; // -> or down?
+ if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this
+ vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64
+ vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half!
+ vol*=128;
+ }
+ else // no sweep:
+ {
+ if(vol&0x4000) // -> mmm... phase inverted? have to investigate this
+ //vol^=0xffff;
+ vol=0x3fff-(vol&0x3fff);
+ }
+
+ vol&=0x3fff;
+ s_chan[ch].iLeftVolume=vol; // store volume
+}
+
+////////////////////////////////////////////////////////////////////////
+// RIGHT VOLUME register write
+////////////////////////////////////////////////////////////////////////
+
+void SetVolumeR(unsigned char ch,short vol) // RIGHT VOLUME
+{
+ s_chan[ch].iRightVolRaw=vol;
+
+ if(vol&0x8000) // comments... see above :)
+ {
+ short sInc=1;
+ if(vol&0x2000) sInc=-1;
+ if(vol&0x1000) vol^=0xffff;
+ vol=((vol&0x7f)+1)/2;
+ vol+=vol/(2*sInc);
+ vol*=128;
+ }
+ else
+ {
+ if(vol&0x4000) //vol=vol^=0xffff;
+ vol=0x3fff-(vol&0x3fff);
+ }
+
+ vol&=0x3fff;
+
+ s_chan[ch].iRightVolume=vol;
+}
+
+////////////////////////////////////////////////////////////////////////
+// PITCH register write
+////////////////////////////////////////////////////////////////////////
+
+void SetPitch(int ch,unsigned short val) // SET PITCH
+{
+ int NP;
+ if(val>0x3fff) NP=0x3fff; // get pitch val
+ else NP=val;
+
+ s_chan[ch].iRawPitch=NP;
+
+ NP=(44100L*NP)/4096L; // calc frequency
+ if(NP<1) NP=1; // some security
+ s_chan[ch].iActFreq=NP; // store frequency
+}
+
+////////////////////////////////////////////////////////////////////////
+// REVERB register write
+////////////////////////////////////////////////////////////////////////
+
+void ReverbOn(int start,int end,unsigned short val) // REVERB ON PSX COMMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1) // loop channels
+ {
+ if(val&1) // -> reverb on/off
+ {
+ s_chan[ch].bReverb=1;
+ }
+ else
+ {
+ s_chan[ch].bReverb=0;
+ }
+ }
+}
diff --git a/plugins/dfsound/registers.h b/plugins/dfsound/registers.h new file mode 100644 index 00000000..f2a93970 --- /dev/null +++ b/plugins/dfsound/registers.h @@ -0,0 +1,144 @@ +/***************************************************************************
+ registers.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#define H_SPUReverbAddr 0x0da2
+#define H_SPUirqAddr 0x0da4
+#define H_SPUaddr 0x0da6
+#define H_SPUdata 0x0da8
+#define H_SPUctrl 0x0daa
+#define H_SPUstat 0x0dae
+#define H_SPUmvolL 0x0d80
+#define H_SPUmvolR 0x0d82
+#define H_SPUrvolL 0x0d84
+#define H_SPUrvolR 0x0d86
+#define H_SPUon1 0x0d88
+#define H_SPUon2 0x0d8a
+#define H_SPUoff1 0x0d8c
+#define H_SPUoff2 0x0d8e
+#define H_FMod1 0x0d90
+#define H_FMod2 0x0d92
+#define H_Noise1 0x0d94
+#define H_Noise2 0x0d96
+#define H_RVBon1 0x0d98
+#define H_RVBon2 0x0d9a
+#define H_SPUMute1 0x0d9c
+#define H_SPUMute2 0x0d9e
+#define H_CDLeft 0x0db0
+#define H_CDRight 0x0db2
+#define H_ExtLeft 0x0db4
+#define H_ExtRight 0x0db6
+#define H_Reverb 0x0dc0
+#define H_SPUPitch0 0x0c04
+#define H_SPUPitch1 0x0c14
+#define H_SPUPitch2 0x0c24
+#define H_SPUPitch3 0x0c34
+#define H_SPUPitch4 0x0c44
+#define H_SPUPitch5 0x0c54
+#define H_SPUPitch6 0x0c64
+#define H_SPUPitch7 0x0c74
+#define H_SPUPitch8 0x0c84
+#define H_SPUPitch9 0x0c94
+#define H_SPUPitch10 0x0ca4
+#define H_SPUPitch11 0x0cb4
+#define H_SPUPitch12 0x0cc4
+#define H_SPUPitch13 0x0cd4
+#define H_SPUPitch14 0x0ce4
+#define H_SPUPitch15 0x0cf4
+#define H_SPUPitch16 0x0d04
+#define H_SPUPitch17 0x0d14
+#define H_SPUPitch18 0x0d24
+#define H_SPUPitch19 0x0d34
+#define H_SPUPitch20 0x0d44
+#define H_SPUPitch21 0x0d54
+#define H_SPUPitch22 0x0d64
+#define H_SPUPitch23 0x0d74
+
+#define H_SPUStartAdr0 0x0c06
+#define H_SPUStartAdr1 0x0c16
+#define H_SPUStartAdr2 0x0c26
+#define H_SPUStartAdr3 0x0c36
+#define H_SPUStartAdr4 0x0c46
+#define H_SPUStartAdr5 0x0c56
+#define H_SPUStartAdr6 0x0c66
+#define H_SPUStartAdr7 0x0c76
+#define H_SPUStartAdr8 0x0c86
+#define H_SPUStartAdr9 0x0c96
+#define H_SPUStartAdr10 0x0ca6
+#define H_SPUStartAdr11 0x0cb6
+#define H_SPUStartAdr12 0x0cc6
+#define H_SPUStartAdr13 0x0cd6
+#define H_SPUStartAdr14 0x0ce6
+#define H_SPUStartAdr15 0x0cf6
+#define H_SPUStartAdr16 0x0d06
+#define H_SPUStartAdr17 0x0d16
+#define H_SPUStartAdr18 0x0d26
+#define H_SPUStartAdr19 0x0d36
+#define H_SPUStartAdr20 0x0d46
+#define H_SPUStartAdr21 0x0d56
+#define H_SPUStartAdr22 0x0d66
+#define H_SPUStartAdr23 0x0d76
+
+#define H_SPULoopAdr0 0x0c0e
+#define H_SPULoopAdr1 0x0c1e
+#define H_SPULoopAdr2 0x0c2e
+#define H_SPULoopAdr3 0x0c3e
+#define H_SPULoopAdr4 0x0c4e
+#define H_SPULoopAdr5 0x0c5e
+#define H_SPULoopAdr6 0x0c6e
+#define H_SPULoopAdr7 0x0c7e
+#define H_SPULoopAdr8 0x0c8e
+#define H_SPULoopAdr9 0x0c9e
+#define H_SPULoopAdr10 0x0cae
+#define H_SPULoopAdr11 0x0cbe
+#define H_SPULoopAdr12 0x0cce
+#define H_SPULoopAdr13 0x0cde
+#define H_SPULoopAdr14 0x0cee
+#define H_SPULoopAdr15 0x0cfe
+#define H_SPULoopAdr16 0x0d0e
+#define H_SPULoopAdr17 0x0d1e
+#define H_SPULoopAdr18 0x0d2e
+#define H_SPULoopAdr19 0x0d3e
+#define H_SPULoopAdr20 0x0d4e
+#define H_SPULoopAdr21 0x0d5e
+#define H_SPULoopAdr22 0x0d6e
+#define H_SPULoopAdr23 0x0d7e
+
+#define H_SPU_ADSRLevel0 0x0c08
+#define H_SPU_ADSRLevel1 0x0c18
+#define H_SPU_ADSRLevel2 0x0c28
+#define H_SPU_ADSRLevel3 0x0c38
+#define H_SPU_ADSRLevel4 0x0c48
+#define H_SPU_ADSRLevel5 0x0c58
+#define H_SPU_ADSRLevel6 0x0c68
+#define H_SPU_ADSRLevel7 0x0c78
+#define H_SPU_ADSRLevel8 0x0c88
+#define H_SPU_ADSRLevel9 0x0c98
+#define H_SPU_ADSRLevel10 0x0ca8
+#define H_SPU_ADSRLevel11 0x0cb8
+#define H_SPU_ADSRLevel12 0x0cc8
+#define H_SPU_ADSRLevel13 0x0cd8
+#define H_SPU_ADSRLevel14 0x0ce8
+#define H_SPU_ADSRLevel15 0x0cf8
+#define H_SPU_ADSRLevel16 0x0d08
+#define H_SPU_ADSRLevel17 0x0d18
+#define H_SPU_ADSRLevel18 0x0d28
+#define H_SPU_ADSRLevel19 0x0d38
+#define H_SPU_ADSRLevel20 0x0d48
+#define H_SPU_ADSRLevel21 0x0d58
+#define H_SPU_ADSRLevel22 0x0d68
+#define H_SPU_ADSRLevel23 0x0d78
+
diff --git a/plugins/dfsound/regs.h b/plugins/dfsound/regs.h new file mode 100644 index 00000000..3d2689bc --- /dev/null +++ b/plugins/dfsound/regs.h @@ -0,0 +1,27 @@ +/***************************************************************************
+ regs.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+void SoundOn(int start,int end,unsigned short val);
+void SoundOff(int start,int end,unsigned short val);
+void FModOn(int start,int end,unsigned short val);
+void NoiseOn(int start,int end,unsigned short val);
+void SetVolumeL(unsigned char ch,short vol);
+void SetVolumeR(unsigned char ch,short vol);
+void SetPitch(int ch,unsigned short val);
+void ReverbOn(int start,int end,unsigned short val);
+void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val);
+
diff --git a/plugins/dfsound/reverb.c b/plugins/dfsound/reverb.c new file mode 100644 index 00000000..92e31fcb --- /dev/null +++ b/plugins/dfsound/reverb.c @@ -0,0 +1,462 @@ +/***************************************************************************
+ reverb.c - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#include "stdafx.h"
+
+#define _IN_REVERB
+
+// will be included from spu.c
+#ifdef _IN_SPU
+
+////////////////////////////////////////////////////////////////////////
+// globals
+////////////////////////////////////////////////////////////////////////
+
+// REVERB info and timing vars...
+
+int * sRVBPlay = 0;
+int * sRVBEnd = 0;
+int * sRVBStart = 0;
+int iReverbOff = -1; // some delay factor for reverb
+int iReverbRepeat = 0;
+int iReverbNum = 1;
+
+////////////////////////////////////////////////////////////////////////
+// SET REVERB
+////////////////////////////////////////////////////////////////////////
+
+void SetREVERB(unsigned short val)
+{
+ switch(val)
+ {
+ case 0x0000: iReverbOff=-1; break; // off
+ case 0x007D: iReverbOff=32; iReverbNum=2; iReverbRepeat=128; break; // ok room
+
+ case 0x0033: iReverbOff=32; iReverbNum=2; iReverbRepeat=64; break; // studio small
+ case 0x00B1: iReverbOff=48; iReverbNum=2; iReverbRepeat=96; break; // ok studio medium
+ case 0x00E3: iReverbOff=64; iReverbNum=2; iReverbRepeat=128; break; // ok studio large ok
+
+ case 0x01A5: iReverbOff=128; iReverbNum=4; iReverbRepeat=32; break; // ok hall
+ case 0x033D: iReverbOff=256; iReverbNum=4; iReverbRepeat=64; break; // space echo
+ case 0x0001: iReverbOff=184; iReverbNum=3; iReverbRepeat=128; break; // echo/delay
+ case 0x0017: iReverbOff=128; iReverbNum=2; iReverbRepeat=128; break; // half echo
+ default: iReverbOff=32; iReverbNum=1; iReverbRepeat=0; break;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+// START REVERB
+////////////////////////////////////////////////////////////////////////
+
+INLINE void StartREVERB(int ch)
+{
+ if(s_chan[ch].bReverb && (spuCtrl&0x80)) // reverb possible?
+ {
+ if(iUseReverb==2) s_chan[ch].bRVBActive=1;
+ else
+ if(iUseReverb==1 && iReverbOff>0) // -> fake reverb used?
+ {
+ s_chan[ch].bRVBActive=1; // -> activate it
+ s_chan[ch].iRVBOffset=iReverbOff*45;
+ s_chan[ch].iRVBRepeat=iReverbRepeat*45;
+ s_chan[ch].iRVBNum =iReverbNum;
+ }
+ }
+ else s_chan[ch].bRVBActive=0; // else -> no reverb
+}
+
+////////////////////////////////////////////////////////////////////////
+// HELPER FOR NEILL'S REVERB: re-inits our reverb mixing buf
+////////////////////////////////////////////////////////////////////////
+
+INLINE void InitREVERB(void)
+{
+ if(iUseReverb==2)
+ {memset(sRVBStart,0,NSSIZE*2*4);}
+}
+
+////////////////////////////////////////////////////////////////////////
+// STORE REVERB
+////////////////////////////////////////////////////////////////////////
+
+INLINE void StoreREVERB(int ch,int ns)
+{
+ if(iUseReverb==0) return;
+ else
+ if(iUseReverb==2) // -------------------------------- // Neil's reverb
+ {
+ const int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000;
+ const int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000;
+
+ ns<<=1;
+
+ *(sRVBStart+ns) +=iRxl; // -> we mix all active reverb channels into an extra buffer
+ *(sRVBStart+ns+1)+=iRxr;
+ }
+ else // --------------------------------------------- // Pete's easy fake reverb
+ {
+ int * pN;int iRn,iRr=0;
+
+ // we use the half channel volume (/0x8000) for the first reverb effects, quarter for next and so on
+
+ int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x8000;
+ int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x8000;
+
+ for(iRn=1;iRn<=s_chan[ch].iRVBNum;iRn++,iRr+=s_chan[ch].iRVBRepeat,iRxl/=2,iRxr/=2)
+ {
+ pN=sRVBPlay+((s_chan[ch].iRVBOffset+iRr+ns)<<1);
+ if(pN>=sRVBEnd) pN=sRVBStart+(pN-sRVBEnd);
+
+ (*pN)+=iRxl;
+ pN++;
+ (*pN)+=iRxr;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE int g_buffer(int iOff) // get_buffer content helper: takes care about wraps
+{
+ short * p=(short *)spuMem;
+ iOff=(iOff*4)+rvb.CurrAddr;
+ while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
+ while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
+ return (int)*(p+iOff);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE void s_buffer(int iOff,int iVal) // set_buffer content helper: takes care about wraps and clipping
+{
+ short * p=(short *)spuMem;
+ iOff=(iOff*4)+rvb.CurrAddr;
+ while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
+ while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
+ if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
+ *(p+iOff)=(short)iVal;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE void s_buffer1(int iOff,int iVal) // set_buffer (+1 sample) content helper: takes care about wraps and clipping
+{
+ short * p=(short *)spuMem;
+ iOff=(iOff*4)+rvb.CurrAddr+1;
+ while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
+ while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
+ if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
+ *(p+iOff)=(short)iVal;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE int MixREVERBLeft(int ns)
+{
+ if(iUseReverb==0) return 0;
+ else
+ if(iUseReverb==2)
+ {
+ static int iCnt=0; // this func will be called with 44.1 khz
+
+ if(!rvb.StartAddr) // reverb is off
+ {
+ rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0;
+ return 0;
+ }
+
+ iCnt++;
+
+ if(iCnt&1) // we work on every second left value: downsample to 22 khz
+ {
+ if(spuCtrl&0x80) // -> reverb on? oki
+ {
+ int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1;
+
+ const int INPUT_SAMPLE_L=*(sRVBStart+(ns<<1));
+ const int INPUT_SAMPLE_R=*(sRVBStart+(ns<<1)+1);
+
+ const int IIR_INPUT_A0 = (g_buffer(rvb.IIR_SRC_A0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L;
+ const int IIR_INPUT_A1 = (g_buffer(rvb.IIR_SRC_A1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L;
+ const int IIR_INPUT_B0 = (g_buffer(rvb.IIR_SRC_B0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L;
+ const int IIR_INPUT_B1 = (g_buffer(rvb.IIR_SRC_B1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L;
+
+ const int IIR_A0 = (IIR_INPUT_A0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A0) * (32768L - rvb.IIR_ALPHA))/32768L;
+ const int IIR_A1 = (IIR_INPUT_A1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A1) * (32768L - rvb.IIR_ALPHA))/32768L;
+ const int IIR_B0 = (IIR_INPUT_B0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B0) * (32768L - rvb.IIR_ALPHA))/32768L;
+ const int IIR_B1 = (IIR_INPUT_B1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B1) * (32768L - rvb.IIR_ALPHA))/32768L;
+
+ s_buffer1(rvb.IIR_DEST_A0, IIR_A0);
+ s_buffer1(rvb.IIR_DEST_A1, IIR_A1);
+ s_buffer1(rvb.IIR_DEST_B0, IIR_B0);
+ s_buffer1(rvb.IIR_DEST_B1, IIR_B1);
+
+ ACC0 = (g_buffer(rvb.ACC_SRC_A0) * rvb.ACC_COEF_A)/32768L +
+ (g_buffer(rvb.ACC_SRC_B0) * rvb.ACC_COEF_B)/32768L +
+ (g_buffer(rvb.ACC_SRC_C0) * rvb.ACC_COEF_C)/32768L +
+ (g_buffer(rvb.ACC_SRC_D0) * rvb.ACC_COEF_D)/32768L;
+ ACC1 = (g_buffer(rvb.ACC_SRC_A1) * rvb.ACC_COEF_A)/32768L +
+ (g_buffer(rvb.ACC_SRC_B1) * rvb.ACC_COEF_B)/32768L +
+ (g_buffer(rvb.ACC_SRC_C1) * rvb.ACC_COEF_C)/32768L +
+ (g_buffer(rvb.ACC_SRC_D1) * rvb.ACC_COEF_D)/32768L;
+
+ FB_A0 = g_buffer(rvb.MIX_DEST_A0 - rvb.FB_SRC_A);
+ FB_A1 = g_buffer(rvb.MIX_DEST_A1 - rvb.FB_SRC_A);
+ FB_B0 = g_buffer(rvb.MIX_DEST_B0 - rvb.FB_SRC_B);
+ FB_B1 = g_buffer(rvb.MIX_DEST_B1 - rvb.FB_SRC_B);
+
+ s_buffer(rvb.MIX_DEST_A0, ACC0 - (FB_A0 * rvb.FB_ALPHA)/32768L);
+ s_buffer(rvb.MIX_DEST_A1, ACC1 - (FB_A1 * rvb.FB_ALPHA)/32768L);
+
+ s_buffer(rvb.MIX_DEST_B0, (rvb.FB_ALPHA * ACC0)/32768L - (FB_A0 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B0 * rvb.FB_X)/32768L);
+ s_buffer(rvb.MIX_DEST_B1, (rvb.FB_ALPHA * ACC1)/32768L - (FB_A1 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B1 * rvb.FB_X)/32768L);
+
+ rvb.iLastRVBLeft = rvb.iRVBLeft;
+ rvb.iLastRVBRight = rvb.iRVBRight;
+
+ rvb.iRVBLeft = (g_buffer(rvb.MIX_DEST_A0)+g_buffer(rvb.MIX_DEST_B0))/3;
+ rvb.iRVBRight = (g_buffer(rvb.MIX_DEST_A1)+g_buffer(rvb.MIX_DEST_B1))/3;
+
+ rvb.iRVBLeft = (rvb.iRVBLeft * rvb.VolLeft) / 0x4000;
+ rvb.iRVBRight = (rvb.iRVBRight * rvb.VolRight) / 0x4000;
+
+ rvb.CurrAddr++;
+ if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr;
+
+ return rvb.iLastRVBLeft+(rvb.iRVBLeft-rvb.iLastRVBLeft)/2;
+ }
+ else // -> reverb off
+ {
+ rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0;
+ }
+
+ rvb.CurrAddr++;
+ if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr;
+ }
+
+ return rvb.iLastRVBLeft;
+ }
+ else // easy fake reverb:
+ {
+ const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value
+ *sRVBPlay++=0; // -> init it after
+ if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds
+ return iRV; // -> return reverb mix buf val
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+INLINE int MixREVERBRight(void)
+{
+ if(iUseReverb==0) return 0;
+ else
+ if(iUseReverb==2) // Neill's reverb:
+ {
+ int i=rvb.iLastRVBRight+(rvb.iRVBRight-rvb.iLastRVBRight)/2;
+ rvb.iLastRVBRight=rvb.iRVBRight;
+ return i; // -> just return the last right reverb val (little bit scaled by the previous right val)
+ }
+ else // easy fake reverb:
+ {
+ const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value
+ *sRVBPlay++=0; // -> init it after
+ if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds
+ return iRV; // -> return reverb mix buf val
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
+/*
+-----------------------------------------------------------------------------
+PSX reverb hardware notes
+by Neill Corlett
+-----------------------------------------------------------------------------
+
+Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway
+yadda yadda.
+
+-----------------------------------------------------------------------------
+
+Basics
+------
+
+- The reverb buffer is 22khz 16-bit mono PCM.
+- It starts at the reverb address given by 1DA2, extends to
+ the end of sound RAM, and wraps back to the 1DA2 address.
+
+Setting the address at 1DA2 resets the current reverb work address.
+
+This work address ALWAYS increments every 1/22050 sec., regardless of
+whether reverb is enabled (bit 7 of 1DAA set).
+
+And the contents of the reverb buffer ALWAYS play, scaled by the
+"reverberation depth left/right" volumes (1D84/1D86).
+(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0)
+
+-----------------------------------------------------------------------------
+
+Register names
+--------------
+
+These are probably not their real names.
+These are probably not even correct names.
+We will use them anyway, because we can.
+
+1DC0: FB_SRC_A (offset)
+1DC2: FB_SRC_B (offset)
+1DC4: IIR_ALPHA (coef.)
+1DC6: ACC_COEF_A (coef.)
+1DC8: ACC_COEF_B (coef.)
+1DCA: ACC_COEF_C (coef.)
+1DCC: ACC_COEF_D (coef.)
+1DCE: IIR_COEF (coef.)
+1DD0: FB_ALPHA (coef.)
+1DD2: FB_X (coef.)
+1DD4: IIR_DEST_A0 (offset)
+1DD6: IIR_DEST_A1 (offset)
+1DD8: ACC_SRC_A0 (offset)
+1DDA: ACC_SRC_A1 (offset)
+1DDC: ACC_SRC_B0 (offset)
+1DDE: ACC_SRC_B1 (offset)
+1DE0: IIR_SRC_A0 (offset)
+1DE2: IIR_SRC_A1 (offset)
+1DE4: IIR_DEST_B0 (offset)
+1DE6: IIR_DEST_B1 (offset)
+1DE8: ACC_SRC_C0 (offset)
+1DEA: ACC_SRC_C1 (offset)
+1DEC: ACC_SRC_D0 (offset)
+1DEE: ACC_SRC_D1 (offset)
+1DF0: IIR_SRC_B1 (offset)
+1DF2: IIR_SRC_B0 (offset)
+1DF4: MIX_DEST_A0 (offset)
+1DF6: MIX_DEST_A1 (offset)
+1DF8: MIX_DEST_B0 (offset)
+1DFA: MIX_DEST_B1 (offset)
+1DFC: IN_COEF_L (coef.)
+1DFE: IN_COEF_R (coef.)
+
+The coefficients are signed fractional values.
+-32768 would be -1.0
+ 32768 would be 1.0 (if it were possible... the highest is of course 32767)
+
+The offsets are (byte/8) offsets into the reverb buffer.
+i.e. you multiply them by 8, you get byte offsets.
+You can also think of them as (samples/4) offsets.
+They appear to be signed. They can be negative.
+None of the documented presets make them negative, though.
+
+Yes, 1DF0 and 1DF2 appear to be backwards. Not a typo.
+
+-----------------------------------------------------------------------------
+
+What it does
+------------
+
+We take all reverb sources:
+- regular channels that have the reverb bit on
+- cd and external sources, if their reverb bits are on
+and mix them into one stereo 44100hz signal.
+
+Lowpass/downsample that to 22050hz. The PSX uses a proper bandlimiting
+algorithm here, but I haven't figured out the hysterically exact specifics.
+I use an 8-tap filter with these coefficients, which are nice but probably
+not the real ones:
+
+0.037828187894
+0.157538631280
+0.321159685278
+0.449322115345
+0.449322115345
+0.321159685278
+0.157538631280
+0.037828187894
+
+So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz.
+
+* IN MY EMULATION, I divide these by 2 to make it clip less.
+ (and of course the L/R output coefficients are adjusted to compensate)
+ The real thing appears to not do this.
+
+At every 22050hz tick:
+- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb
+ steady-state algorithm described below
+- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer
+ (This part may not be exactly right and I guessed at the coefs. TODO: check later.)
+ L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0])
+ R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1])
+- Advance the current buffer position by 1 sample
+
+The wet out L and R are then upsampled to 44100hz and played at the
+"reverberation depth left/right" (1D84/1D86) volume, independent of the main
+volume.
+
+-----------------------------------------------------------------------------
+
+Reverb steady-state
+-------------------
+
+The reverb steady-state algorithm is fairly clever, and of course by
+"clever" I mean "batshit insane".
+
+buffer[x] is relative to the current buffer position, not the beginning of
+the buffer. Note that all buffer offsets must wrap around so they're
+contained within the reverb work area.
+
+Clipping is performed at the end... maybe also sooner, but definitely at
+the end.
+
+IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
+IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
+IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
+IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
+
+IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA);
+IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA);
+IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA);
+IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA);
+
+buffer[IIR_DEST_A0 + 1sample] = IIR_A0;
+buffer[IIR_DEST_A1 + 1sample] = IIR_A1;
+buffer[IIR_DEST_B0 + 1sample] = IIR_B0;
+buffer[IIR_DEST_B1 + 1sample] = IIR_B1;
+
+ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A +
+ buffer[ACC_SRC_B0] * ACC_COEF_B +
+ buffer[ACC_SRC_C0] * ACC_COEF_C +
+ buffer[ACC_SRC_D0] * ACC_COEF_D;
+ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A +
+ buffer[ACC_SRC_B1] * ACC_COEF_B +
+ buffer[ACC_SRC_C1] * ACC_COEF_C +
+ buffer[ACC_SRC_D1] * ACC_COEF_D;
+
+FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A];
+FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A];
+FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B];
+FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B];
+
+buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA;
+buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA;
+buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X;
+buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X;
+
+-----------------------------------------------------------------------------
+*/
+
diff --git a/plugins/dfsound/reverb.h b/plugins/dfsound/reverb.h new file mode 100644 index 00000000..ce618187 --- /dev/null +++ b/plugins/dfsound/reverb.h @@ -0,0 +1,21 @@ +/***************************************************************************
+ reverb.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+void SetREVERB(unsigned short val);
+INLINE void StartREVERB(int ch);
+INLINE void StoreREVERB(int ch,int ns);
+
diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c new file mode 100644 index 00000000..e6dd2776 --- /dev/null +++ b/plugins/dfsound/spu.c @@ -0,0 +1,923 @@ +/*************************************************************************** + spu.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#define _IN_SPU + +#include "externals.h" +#include "cfg.h" +#include "dsoundoss.h" +#include "regs.h" + +// spu version infos/name +const unsigned char version = 1; +const unsigned char revision = 0; +const unsigned char build = 0; + +#if defined(USEALSA) +static char * libraryName = "ALSA Sound"; +#elif defined (USEOSS) +static char * libraryName = "OSS Sound"; +#else +static char * libraryName = "NULL Sound"; +#endif + +static char * libraryInfo = "P.E.Op.S. OSS Driver V1.7\nCoded by Pete Bernert and the P.E.Op.S. team\n"; + +// globals + +// psx buffer / addresses + +unsigned short regArea[10000]; +unsigned short spuMem[256*1024]; +unsigned char * spuMemC; +unsigned char * pSpuIrq=0; +unsigned char * pSpuBuffer; + +// user settings + +int iUseXA=1; +int iVolume=3; +int iXAPitch=1; +int iUseTimer=2; +int iSPUIRQWait=1; +int iDebugMode=0; +int iRecordMode=0; +int iUseReverb=2; +int iUseInterpolation=2; +int iDisStereo=0; + +// MAIN infos struct for each channel + +SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling) +REVERBInfo rvb; + +unsigned long dwNoiseVal=1; // global noise generator +int iWatchDog=0; + +unsigned short spuCtrl=0; // some vars to store psx reg infos +unsigned short spuStat=0; +unsigned short spuIrq=0; +unsigned long spuAddr=0xffffffff; // address into spu mem +int bEndThread=0; // thread handlers +int bThreadEnded=0; +int bSpuInit=0; +int bSPUIsOpen=0; + +#ifndef NOTHREADLIB +static pthread_t thread = -1; // thread id (linux) +#endif + +unsigned long dwNewChannel=0; // flags for faster testing, if new channel starts + +void (CALLBACK *irqCallback)(void)=0; // func of main emu, called on spu irq +void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0; + +// certain globals (were local before, but with the new timeproc I need em global) + +static const int f[5][2] = { { 0, 0 }, + { 60, 0 }, + { 115, -52 }, + { 98, -55 }, + { 122, -60 } }; +int SSumR[NSSIZE]; +int SSumL[NSSIZE]; +int iCycle=0; +short * pS; + +static int lastch=-1; // last channel processed on spu irq in timer mode +static int lastns=0; // last ns pos +static int iSecureStart=0; // secure start counter + +//////////////////////////////////////////////////////////////////////// +// CODE AREA +//////////////////////////////////////////////////////////////////////// + +// dirty inline func includes + +#include "reverb.c" +#include "adsr.c" + +//////////////////////////////////////////////////////////////////////// +// helpers for simple interpolation + +// +// easy interpolation on upsampling, no special filter, just "Pete's common sense" tm +// +// instead of having n equal sample values in a row like: +// ____ +// |____ +// +// we compare the current delta change with the next delta change. +// +// if curr_delta is positive, +// +// - and next delta is smaller (or changing direction): +// \. +// -__ +// +// - and next delta significant (at least twice) bigger: +// --_ +// \. +// +// - and next delta is nearly same: +// \. +// \. +// +// +// if curr_delta is negative, +// +// - and next delta is smaller (or changing direction): +// _-- +// / +// +// - and next delta significant (at least twice) bigger: +// / +// __- +// +// - and next delta is nearly same: +// / +// / +// + + +INLINE void InterpolateUp(int ch) +{ + if(s_chan[ch].SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass + { + const int id1=s_chan[ch].SB[30]-s_chan[ch].SB[29]; // curr delta to next val + const int id2=s_chan[ch].SB[31]-s_chan[ch].SB[30]; // and next delta to next-next val :) + + s_chan[ch].SB[32]=0; + + if(id1>0) // curr delta positive + { + if(id2<id1) + {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;} + else + if(id2<(id1<<1)) + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L; + else + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L; + } + else // curr delta negative + { + if(id2>id1) + {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;} + else + if(id2>(id1<<1)) + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L; + else + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L; + } + } + else + if(s_chan[ch].SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass + { + s_chan[ch].SB[32]=0; + + s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L; + if(s_chan[ch].sinc<=0x8000) + s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1)); + else s_chan[ch].SB[29]+=s_chan[ch].SB[28]; + } + else // no flags? add bigger val (if possible), calc smaller step, set flag1 + s_chan[ch].SB[29]+=s_chan[ch].SB[28]; +} + +// +// even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm +// + +INLINE void InterpolateDown(int ch) +{ + if(s_chan[ch].sinc>=0x20000L) // we would skip at least one val? + { + s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight + if(s_chan[ch].sinc>=0x30000L) // we would skip even more vals? + s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight + } +} + +//////////////////////////////////////////////////////////////////////// +// helpers for gauss interpolation + +#define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos]) +#define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3]) + +#include "gauss_i.h" + +//////////////////////////////////////////////////////////////////////// + +#include "xa.c" + +//////////////////////////////////////////////////////////////////////// +// START SOUND... called by main thread to setup a new sound on a channel +//////////////////////////////////////////////////////////////////////// + +INLINE void StartSound(int ch) +{ + StartADSR(ch); + StartREVERB(ch); + + s_chan[ch].pCurr=s_chan[ch].pStart; // set sample start + + s_chan[ch].s_1=0; // init mixing vars + s_chan[ch].s_2=0; + s_chan[ch].iSBPos=28; + + s_chan[ch].bNew=0; // init channel flags + s_chan[ch].bStop=0; + s_chan[ch].bOn=1; + + s_chan[ch].SB[29]=0; // init our interpolation helpers + s_chan[ch].SB[30]=0; + + if(iUseInterpolation>=2) // gauss interpolation? + {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;} // -> start with more decoding + else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding + + dwNewChannel&=~(1<<ch); // clear new channel bit +} + +//////////////////////////////////////////////////////////////////////// +// MAIN SPU FUNCTION +// here is the main job handler... thread, timer or direct func call +// basically the whole sound processing is done in this fat func! +//////////////////////////////////////////////////////////////////////// + +// 5 ms waiting phase, if buffer is full and no new sound has to get started +// .. can be made smaller (smallest val: 1 ms), but bigger waits give +// better performance + +#define PAUSE_W 5 +#define PAUSE_L 5000 + +//////////////////////////////////////////////////////////////////////// + +static void *MAINThread(void *arg) +{ + int s_1,s_2,fa,ns,voldiv=iVolume; + unsigned char * start;unsigned int nSample; + int ch,predict_nr,shift_factor,flags,d,s; + int gpos,bIRQReturn=0; + + while(!bEndThread) // until we are shutting down + { + // ok, at the beginning we are looking if there is + // enuff free place in the dsound/oss buffer to + // fill in new data, or if there is a new channel to start. + // if not, we wait (thread) or return (timer/spuasync) + // until enuff free place is available/a new channel gets + // started + + if(dwNewChannel) // new channel should start immedately? + { // (at least one bit 0 ... MAXCHANNEL is set?) + iSecureStart++; // -> set iSecure + if(iSecureStart>5) iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance) + } + else iSecureStart=0; // 0: no new channel should start + + while(!iSecureStart && !bEndThread && // no new start? no thread end? + (SoundGetBytesBuffered()>TESTSIZE)) // and still enuff data in sound buffer? + { + iSecureStart=0; // reset secure + + if(iUseTimer) return 0; // linux no-thread mode? bye + usleep(PAUSE_L); // else sleep for x ms (linux) + + if(dwNewChannel) iSecureStart=1; // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop + } + + //--------------------------------------------------// continue from irq handling in timer mode? + + if(lastch>=0) // will be -1 if no continue is pending + { + ch=lastch; ns=lastns; lastch=-1; // -> setup all kind of vars to continue + goto GOON; // -> directly jump to the continue point + } + + //--------------------------------------------------// + //- main channel loop -// + //--------------------------------------------------// + { + for(ch=0;ch<MAXCHAN;ch++) // loop em all... we will collect 1 ms of sound of each playing channel + { + if(s_chan[ch].bNew) StartSound(ch); // start new sound + if(!s_chan[ch].bOn) continue; // channel not playing? next + + if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq) // new psx frequency? + { + s_chan[ch].iUsedFreq=s_chan[ch].iActFreq; // -> take it and calc steps + s_chan[ch].sinc=s_chan[ch].iRawPitch<<4; + if(!s_chan[ch].sinc) s_chan[ch].sinc=1; + if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag + } + + ns=0; + while(ns<NSSIZE) // loop until 1 ms of data is reached + { + while(s_chan[ch].spos>=0x10000L) + { + if(s_chan[ch].iSBPos==28) // 28 reached? + { + start=s_chan[ch].pCurr; // set up the current pos + + if (start == (unsigned char*)-1) // special "stop" sign + { + s_chan[ch].bOn=0; // -> turn everything off + s_chan[ch].ADSRX.lVolume=0; + s_chan[ch].ADSRX.EnvelopeVol=0; + goto ENDX; // -> and done for this channel + } + + s_chan[ch].iSBPos=0; + + //////////////////////////////////////////// spu irq handler here? mmm... do it later + + s_1=s_chan[ch].s_1; + s_2=s_chan[ch].s_2; + + predict_nr=(int)*start;start++; + shift_factor=predict_nr&0xf; + predict_nr >>= 4; + flags=(int)*start;start++; + + // -------------------------------------- // + + for (nSample=0;nSample<28;start++) + { + d=(int)*start; + s=((d&0xf)<<12); + if(s&0x8000) s|=0xffff0000; + + fa=(s >> shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + s=((d & 0xf0) << 8); + + s_chan[ch].SB[nSample++]=fa; + + if(s&0x8000) s|=0xffff0000; + fa=(s>>shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + + s_chan[ch].SB[nSample++]=fa; + } + + //////////////////////////////////////////// irq check + + if(irqCallback && (spuCtrl&0x40)) // some callback and irq active? + { + if((pSpuIrq > start-16 && // irq address reached? + pSpuIrq <= start) || + ((flags&1) && // special: irq on looping addr, when stop/loop flag is set + (pSpuIrq > s_chan[ch].pLoop-16 && + pSpuIrq <= s_chan[ch].pLoop))) + { + s_chan[ch].iIrqDone=1; // -> debug flag + irqCallback(); // -> call main emu + + if(iSPUIRQWait) // -> option: wait after irq for main emu + { + DWORD dwWatchTime; + + if(iUseTimer==2) // -> special timer mode... give main emu the control + { + bIRQReturn=1; + } + else + { + dwWatchTime=timeGetTime_spu()+2500; + iWatchDog=1; // -> should we do some mutex stuff? ahh, naaa + while(iWatchDog && !bEndThread && + timeGetTime_spu()<dwWatchTime) + usleep(1000L); + } + } + } + } + + //////////////////////////////////////////// flag handler + + if((flags&4) && (!s_chan[ch].bIgnoreLoop)) + s_chan[ch].pLoop=start-16; // loop adress + + if(flags&1) // 1: stop/loop + { + // We play this block out first... + //if(!(flags&2)) // 1+2: do loop... otherwise: stop + if(flags!=3 || s_chan[ch].pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example) + { // and checking if pLoop is set avoids crashes, yeah + start = (unsigned char*)-1; + } + else + { + start = s_chan[ch].pLoop; + } + } + + s_chan[ch].pCurr=start; // store values for next cycle + s_chan[ch].s_1=s_1; + s_chan[ch].s_2=s_2; + + if(bIRQReturn) // special return for "spu irq - wait for cpu action" + { + bIRQReturn=0; + lastch=ch; + lastns=ns; + return 0; + } +GOON: ; + } + + fa=s_chan[ch].SB[s_chan[ch].iSBPos++]; // get sample data + + if((spuCtrl&0x4000)==0) fa=0; // muted? + else // else adjust + { + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + } + + if(iUseInterpolation>=2) // gauss/cubic interpolation + { + gpos = s_chan[ch].SB[28]; + gval0 = fa; + gpos = (gpos+1) & 3; + s_chan[ch].SB[28] = gpos; + } + else + if(iUseInterpolation==1) // simple interpolation + { + s_chan[ch].SB[28] = 0; + s_chan[ch].SB[29] = s_chan[ch].SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' + s_chan[ch].SB[30] = s_chan[ch].SB[31]; + s_chan[ch].SB[31] = fa; + s_chan[ch].SB[32] = 1; // -> flag: calc new interolation + } + else s_chan[ch].SB[29]=fa; // no interpolation + + s_chan[ch].spos -= 0x10000L; + } + + // noise handler... just produces some noise data + // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used... + // and sometimes the noise will be used as fmod modulation... pfff + + if(s_chan[ch].bNoise) + { + if((dwNoiseVal<<=1)&0x80000000L) + { + dwNoiseVal^=0x0040001L; + fa=((dwNoiseVal>>2)&0x7fff); + fa=-fa; + } + else fa=(dwNoiseVal>>2)&0x7fff; + + // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val + fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl&0x3f00)>>9))+1)); + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + s_chan[ch].iOldNoise=fa; + + if(iUseInterpolation<2) // no gauss/cubic interpolation? + s_chan[ch].SB[29] = fa; // -> store noise val in "current sample" slot + } //---------------------------------------- + else // NO NOISE (NORMAL SAMPLE DATA) HERE + { + if(iUseInterpolation==3) // cubic interpolation + { + long xd; + xd = ((s_chan[ch].spos) >> 1)+1; + gpos = s_chan[ch].SB[28]; + + fa = gval(3) - 3*gval(2) + 3*gval(1) - gval0; + fa *= (xd - (2<<15)) / 6; + fa >>= 15; + fa += gval(2) - gval(1) - gval(1) + gval0; + fa *= (xd - (1<<15)) >> 1; + fa >>= 15; + fa += gval(1) - gval0; + fa *= xd; + fa >>= 15; + fa = fa + gval0; + } + else + if(iUseInterpolation==2) // gauss interpolation + { + int vl, vr; + vl = (s_chan[ch].spos >> 6) & ~3; + gpos = s_chan[ch].SB[28]; + vr=(gauss[vl]*gval0)&~2047; + vr+=(gauss[vl+1]*gval(1))&~2047; + vr+=(gauss[vl+2]*gval(2))&~2047; + vr+=(gauss[vl+3]*gval(3))&~2047; + fa = vr>>11; +/* + vr=(gauss[vl]*gval0)>>9; + vr+=(gauss[vl+1]*gval(1))>>9; + vr+=(gauss[vl+2]*gval(2))>>9; + vr+=(gauss[vl+3]*gval(3))>>9; + fa = vr>>2; +*/ + } + else + if(iUseInterpolation==1) // simple interpolation + { + if(s_chan[ch].sinc<0x10000L) // -> upsampling? + InterpolateUp(ch); // --> interpolate up + else InterpolateDown(ch); // --> else down + fa=s_chan[ch].SB[29]; + } + else fa=s_chan[ch].SB[29]; // no interpolation + } + + s_chan[ch].sval = (MixADSR(ch) * fa) / 1023; // add adsr + + if(s_chan[ch].bFMod==2) // fmod freq channel + { + int NP=s_chan[ch+1].iRawPitch; + + NP=((32768L+s_chan[ch].sval)*NP)/32768L; + + if(NP>0x3fff) NP=0x3fff; + if(NP<0x1) NP=0x1; + +// mmmm... if I do this, all is screwed +// s_chan[ch+1].iRawPitch=NP; + + NP=(44100L*NP)/(4096L); // calc frequency + + s_chan[ch+1].iActFreq=NP; + s_chan[ch+1].iUsedFreq=NP; + s_chan[ch+1].sinc=(((NP/10)<<16)/4410); + if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1; + if(iUseInterpolation==1) // freq change in sipmle interpolation mode + s_chan[ch+1].SB[32]=1; + +// mmmm... set up freq decoding positions? +// s_chan[ch+1].iSBPos=28; +// s_chan[ch+1].spos=0x10000L; + } + else + { + ////////////////////////////////////////////// + // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff) + + if(s_chan[ch].iMute) + s_chan[ch].sval=0; // debug mute + else + { + SSumL[ns]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000L; + SSumR[ns]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000L; + } + + ////////////////////////////////////////////// + // now let us store sound data for reverb + + if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns); + } + + //////////////////////////////////////////////// + // ok, go on until 1 ms data of this channel is collected + + ns++; + s_chan[ch].spos += s_chan[ch].sinc; + + } +ENDX: ; + } + } + + //---------------------------------------------------// + //- here we have another 1 ms of sound data + //---------------------------------------------------// + // mix XA infos (if any) + + if(XAPlay!=XAFeed || XARepeat) MixXA(); + + /////////////////////////////////////////////////////// + // mix all channels (including reverb) into one buffer + + if(iDisStereo) // no stereo? + { + int dl,dr; + for(ns=0;ns<NSSIZE;ns++) + { + SSumL[ns]+=MixREVERBLeft(ns); + + dl=SSumL[ns]/voldiv;SSumL[ns]=0; + if(dl<-32767) dl=-32767;if(dl>32767) dl=32767; + + SSumR[ns]+=MixREVERBRight(); + + dr=SSumR[ns]/voldiv;SSumR[ns]=0; + if(dr<-32767) dr=-32767;if(dr>32767) dr=32767; + *pS++=(dl+dr)/2; + } + } + else // stereo: + for(ns=0;ns<NSSIZE;ns++) + { + SSumL[ns]+=MixREVERBLeft(ns); + + d=SSumL[ns]/voldiv;SSumL[ns]=0; + if(d<-32767) d=-32767;if(d>32767) d=32767; + *pS++=d; + + SSumR[ns]+=MixREVERBRight(); + + d=SSumR[ns]/voldiv;SSumR[ns]=0; + if(d<-32767) d=-32767;if(d>32767) d=32767; + *pS++=d; + } + + InitREVERB(); + + // feed the sound + // wanna have around 1/60 sec (16.666 ms) updates + + if(iCycle++>8) //temp fix: lowered for low latency alsa configs + { + SoundFeedStreamData((unsigned char*)pSpuBuffer, + ((unsigned char *)pS)- + ((unsigned char *)pSpuBuffer)); + pS=(short *)pSpuBuffer; + iCycle=0; + } + } + + // end of big main loop... + + bThreadEnded=1; + + return 0; +} + +// SPU ASYNC... even newer epsxe func +// 1 time every 'cycle' cycles... harhar + +void CALLBACK SPUasync(unsigned long cycle) +{ + iWatchDog=0; // clear the watchdog + + if(iUseTimer==2) // special mode, only used in Linux by this spu (or if you enable the experimental Windows mode) + { + if(!bSpuInit) return; // -> no init, no call + + MAINThread(0); // -> linux high-compat mode + } +} + +// SPU UPDATE... new epsxe func +// 1 time every 32 hsync lines +// (312/32)x50 in pal +// (262/32)x60 in ntsc + +// since epsxe 1.5.2 (linux) uses SPUupdate, not SPUasync, I will +// leave that func in the linux port, until epsxe linux is using +// the async function as well + +void CALLBACK SPUupdate(void) +{ + SPUasync(0); +} + +// XA AUDIO + +void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap) +{ + if(!iUseXA) return; // no XA? bye + if(!xap) return; + if(!xap->freq) return; // no xa freq ? bye + + FeedXA(xap); // call main XA feeder +} + +// INIT/EXIT STUFF + +// SPUINIT: this func will be called first by the main emu +long CALLBACK SPUinit(void) +{ + spuMemC=(unsigned char *)spuMem; // just small setup + memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN)); + memset((void *)&rvb,0,sizeof(REVERBInfo)); + InitADSR(); + return 0; +} + +// SETUPTIMER: init of certain buffers and threads/timers +void SetupTimer(void) +{ + memset(SSumR,0,NSSIZE*sizeof(int)); // init some mixing buffers + memset(SSumL,0,NSSIZE*sizeof(int)); + pS=(short *)pSpuBuffer; // setup soundbuffer pointer + + bEndThread=0; // init thread vars + bThreadEnded=0; + bSpuInit=1; // flag: we are inited + +#ifndef NOTHREADLIB + if(!iUseTimer) // linux: use thread + { + pthread_create(&thread, NULL, MAINThread, NULL); + } +#endif +} + +// REMOVETIMER: kill threads/timers +void RemoveTimer(void) +{ + bEndThread=1; // raise flag to end thread + +#ifndef NOTHREADLIB + if(!iUseTimer) // linux tread? + { + int i=0; + while(!bThreadEnded && i<2000) {usleep(1000L);i++;} // -> wait until thread has ended + if(thread!=-1) {pthread_cancel(thread);thread=-1;} // -> cancel thread anyway + } +#endif + + bThreadEnded=0; // no more spu is running + bSpuInit=0; +} + +// SETUPSTREAMS: init most of the spu buffers +void SetupStreams(void) +{ + int i; + + pSpuBuffer=(unsigned char *)malloc(32768); // alloc mixing buffer + + if(iUseReverb==1) i=88200*2; + else i=NSSIZE*2; + + sRVBStart = (int *)malloc(i*4); // alloc reverb buffer + memset(sRVBStart,0,i*4); + sRVBEnd = sRVBStart + i; + sRVBPlay = sRVBStart; + + XAStart = // alloc xa buffer + (uint32_t *)malloc(44100*4); + XAPlay = XAStart; + XAFeed = XAStart; + XAEnd = XAStart + 44100; + + for(i=0;i<MAXCHAN;i++) // loop sound channels + { +// we don't use mutex sync... not needed, would only +// slow us down: +// s_chan[i].hMutex=CreateMutex(NULL,FALSE,NULL); + s_chan[i].ADSRX.SustainLevel = 1024; // -> init sustain + s_chan[i].iMute=0; + s_chan[i].iIrqDone=0; + s_chan[i].pLoop=spuMemC; + s_chan[i].pStart=spuMemC; + s_chan[i].pCurr=spuMemC; + } +} + +// REMOVESTREAMS: free most buffer +void RemoveStreams(void) +{ + free(pSpuBuffer); // free mixing buffer + pSpuBuffer=NULL; + free(sRVBStart); // free reverb buffer + sRVBStart=0; + free(XAStart); // free XA buffer + XAStart=0; + +/* + int i; + for(i=0;i<MAXCHAN;i++) + { + WaitForSingleObject(s_chan[i].hMutex,2000); + ReleaseMutex(s_chan[i].hMutex); + if(s_chan[i].hMutex) + {CloseHandle(s_chan[i].hMutex);s_chan[i].hMutex=0;} + } +*/ +} + +// SPUOPEN: called by main emu after init +long SPUopen(void) +{ + if (bSPUIsOpen) return 0; // security for some stupid main emus + + iUseXA = 1; // just small setup + iVolume = 3; + iReverbOff = -1; + spuIrq = 0; + spuAddr = 0xffffffff; + bEndThread = 0; + bThreadEnded = 0; + spuMemC = (unsigned char *)spuMem; + memset((void *)s_chan, 0, (MAXCHAN + 1) * sizeof(SPUCHAN)); + pSpuIrq = 0; + iSPUIRQWait = 1; + + ReadConfig(); // read user stuff + + SetupSound(); // setup midas (before init!) + + SetupStreams(); // prepare streaming + + SetupTimer(); // timer for feeding data + + bSPUIsOpen = 1; + + return PSE_SPU_ERR_SUCCESS; +} + +// SPUCLOSE: called before shutdown +long CALLBACK SPUclose(void) +{ + if (!bSPUIsOpen) return 0; // some security + + bSPUIsOpen = 0; // no more open + + RemoveTimer(); // no more feeding + + RemoveSound(); // no more sound handling + + RemoveStreams(); // no more streaming + + return 0; +} + +// SPUSHUTDOWN: called by main emu on final exit +long CALLBACK SPUshutdown(void) +{ + return 0; +} + +// SPUTEST: we don't test, we are always fine ;) +long CALLBACK SPUtest(void) +{ + return 0; +} + +// SPUCONFIGURE: call config dialog +long CALLBACK SPUconfigure(void) +{ + StartCfgTool("CFG"); + return 0; +} + +// SPUABOUT: show about window +void CALLBACK SPUabout(void) +{ + StartCfgTool("ABOUT"); +} + +// SETUP CALLBACKS +// this functions will be called once, +// passes a callback that should be called on SPU-IRQ/cdda volume change +void CALLBACK SPUregisterCallback(void (CALLBACK *callback)(void)) +{ + irqCallback = callback; +} + +void CALLBACK SPUregisterCDDAVolume(void (CALLBACK *CDDAVcallback)(unsigned short,unsigned short)) +{ + cddavCallback = CDDAVcallback; +} + +// COMMON PLUGIN INFO FUNCS +char * CALLBACK PSEgetLibName(void) +{ + return libraryName; +} + +unsigned long CALLBACK PSEgetLibType(void) +{ + return PSE_LT_SPU; +} + +unsigned long CALLBACK PSEgetLibVersion(void) +{ + return version<<16|revision<<8|build; +} + +char * SPUgetLibInfos(void) +{ + return libraryInfo; +} diff --git a/plugins/dfsound/spu.h b/plugins/dfsound/spu.h new file mode 100644 index 00000000..a6e57b30 --- /dev/null +++ b/plugins/dfsound/spu.h @@ -0,0 +1,20 @@ +/***************************************************************************
+ spu.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+void SetupTimer(void);
+void RemoveTimer(void);
+void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap);
diff --git a/plugins/dfsound/spucfg-0.1df/dfsound.glade2 b/plugins/dfsound/spucfg-0.1df/dfsound.glade2 new file mode 100644 index 00000000..577962c9 --- /dev/null +++ b/plugins/dfsound/spucfg-0.1df/dfsound.glade2 @@ -0,0 +1,674 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkWindow" id="CfgWnd"> + <property name="border_width">10</property> + <property name="visible">True</property> + <property name="title" translatable="yes">Configure Sound</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <signal name="destroy" handler="on_CfgWnd_destroy"/> + + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkFrame" id="frame1"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkAlignment" id="alignment4"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + <property name="top_padding">6</property> + <property name="bottom_padding">6</property> + <property name="left_padding">12</property> + <property name="right_padding">12</property> + + <child> + <widget class="GtkTable" id="table1"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">6</property> + + <child> + <widget class="GtkLabel" id="label1v"> + <property name="visible">True</property> + <property name="label" translatable="yes">Volume:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="label" translatable="yes">Interpolation:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="label" translatable="yes">Reverb:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkComboBox" id="cbVolume2"> + <property name="visible">True</property> + <property name="items" translatable="yes">Low +Medium +Loud +Loudest</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkComboBox" id="cbReverb2"> + <property name="visible">True</property> + <property name="items" translatable="yes">Off +Simple +Playstation</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkComboBox" id="cbInterpolation2"> + <property name="visible">True</property> + <property name="items" translatable="yes">None +Simple +Gaussian +Cubic</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label10"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>General</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame2"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + <property name="top_padding">6</property> + <property name="bottom_padding">6</property> + <property name="left_padding">12</property> + <property name="right_padding">12</property> + + <child> + <widget class="GtkVBox" id="vbox3"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkCheckButton" id="chkEnableXA"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Enable or disable XA music.</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Enable XA</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="chkXASpeed"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Choose this if XA music is played too quickly.</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Adjust XA speed</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label11"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>XA Music</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame3"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkAlignment" id="alignment3"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + <property name="top_padding">6</property> + <property name="bottom_padding">6</property> + <property name="left_padding">12</property> + <property name="right_padding">12</property> + + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkCheckButton" id="chkHiCompat"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Use the asynchronous SPU interface.</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">High compatibility mode</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="chkIRQWait"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Wait for CPU; only useful for some games.</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">SPU IRQ Wait</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="chkDisStereo"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Play only one channel for a performance boost.</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Single channel sound</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label12"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Compatibility</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHButtonBox" id="hbuttonbox1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkButton" id="btn_close"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-close</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="AboutWnd"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="title" translatable="yes">About Sound Plugin</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <signal name="destroy" handler="on_AboutWnd_destroy"/> + + <child> + <widget class="GtkVBox" id="vbox5"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkVBox" id="vbox6"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Coded by: Pete Bernert and the P.E.Op.S. team</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes">Homepage: http://home.t-online.de/home/PeteBernert/</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">EMail: BlackDove@addcom.de</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label5"> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Version: 1.6</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes">Release date: 05.04.2003</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label13"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>PCSX-df Sound Plugin Adaption</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/plugins/dfsound/spucfg-0.1df/main.c b/plugins/dfsound/spucfg-0.1df/main.c new file mode 100644 index 00000000..d358dac8 --- /dev/null +++ b/plugins/dfsound/spucfg-0.1df/main.c @@ -0,0 +1,334 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> + +#include <glade/glade.h> +#include <gtk/gtk.h> + +#define READBINARY "rb" +#define WRITEBINARY "wb" +#define CONFIG_FILENAME "dfsound.cfg" + +void SaveConfig (GtkWidget *widget, gpointer user_datal); + +/* ADB DONE +GtkWidget *wndMain = 0; + +GtkWidget *create_CfgWnd(GladeXML * xml) +{ + wndMain = glade_xml_get_widget(xml, "CfgWnd"); + return wndMain; +} + +GtkWidget *create_AboutWnd(GladeXML * xml) +{ + wndMain = glade_xml_get_widget(xml, "AboutWnd"); + return wndMain; +}*/ + +/* This function checks for the value being outside the accepted range, + and returns the appropriate boundary value */ +int set_limit (char *p, int len, int lower, int upper) +{ + int val = 0; + + if (p) + val = atoi(p + len); + + if (val < lower) + val = lower; + if (val > upper) + val = upper; + + return val; +} + +void on_about_clicked (GtkWidget *widget, gpointer user_data) +{ + gtk_widget_destroy (widget); + exit (0); +} + +void on_config_clicked (GtkWidget *widget, gpointer user_data) +{ + gtk_widget_destroy (widget); + exit (0); +} + +int main(int argc, char *argv[]) +{ + GtkWidget *widget; + GtkWidget *wndMain; + GladeXML *xml; + FILE *in; + char t[256]; + int len, val = 0; + char *pB, *p; + char cfg[255]; + + if (argc != 2) { + printf ("Usage: cfgDFSound {ABOUT | CFG}\n"); + return 0; + } + + if (strcmp(argv[1], "CFG") != 0 && strcmp(argv[1], "ABOUT") != 0) { + printf ("Usage: cfgDFSound {ABOUT | CFG}\n"); + return 0; + } + + gtk_set_locale(); + gtk_init(&argc, &argv); + + if (strcmp(argv[1], "ABOUT") == 0) { + const char *authors[]= {"Pete Bernert and the P.E.Op.S. team", "Ryan Schultz", "Andrew Burton", NULL}; + widget = gtk_about_dialog_new (); + gtk_about_dialog_set_name (GTK_ABOUT_DIALOG (widget), "dfsound PCSX Sound Plugin"); + gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (widget), "1.6"); + gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG (widget), authors); + gtk_about_dialog_set_website (GTK_ABOUT_DIALOG (widget), "http://home.t-online.de/home/PeteBernert/"); + + g_signal_connect_data(GTK_OBJECT(widget), "response", + GTK_SIGNAL_FUNC(on_about_clicked), NULL, NULL, G_CONNECT_AFTER); + + gtk_widget_show (widget); + gtk_main(); + + return 0; + } + + xml = glade_xml_new(DATADIR "dfsound.glade2", "CfgWnd", NULL); + if (!xml) { + g_warning("We could not load the interface!"); + return 255; + } + + wndMain = glade_xml_get_widget(xml, "CfgWnd"); + + strcpy(cfg, CONFIG_FILENAME); + + in = fopen(cfg, READBINARY); + if (in) { + pB = (char *) malloc(32767); + memset(pB, 0, 32767); + len = fread(pB, 1, 32767, in); + fclose(in); + } else { + pB = 0; + printf ("Error - no configuration file\n"); + /* TODO Raise error - no configuration file */ + } + + /* ADB TODO Replace a lot of the following with common functions */ + if (pB) { + strcpy(t, "\nVolume"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 4); + } else val = 1; + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "cbVolume2")), val); + + if (pB) { + strcpy(t, "\nUseInterpolation"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 3); + } else val = 2; + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "cbInterpolation2")), val); + + if (pB) { + strcpy(t, "\nUseXA"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 1); + } else val = 1; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkEnableXA")), val); + + if (pB) { + strcpy(t, "\nXAPitch"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 1); + } else val = 0; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkXASpeed")), val); + + if (pB) { + strcpy(t, "\nHighCompMode"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 1); + } else val = 0; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkHiCompat")), val); + + if (pB) { + strcpy(t, "\nSPUIRQWait"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + + val = set_limit (p, len, 0, 1); + } else val = 1; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkIRQWait")), val); + + if (pB) { + strcpy(t, "\nDisStereo"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + + val = set_limit (p, len, 0, 1); + } else val = 0; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkDisStereo")), val); + + if (pB) { + strcpy(t, "\nUseReverb"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 2); + } else val = 2; + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "cbReverb2")), val); + + if (pB) + free(pB); + + widget = glade_xml_get_widget(xml, "CfgWnd"); + g_signal_connect_data(GTK_OBJECT(widget), "delete_event", + GTK_SIGNAL_FUNC(on_config_clicked), NULL, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "btn_close"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(SaveConfig), xml, NULL, G_CONNECT_AFTER); + + gtk_main(); + return 0; +} + + + +//////////////////////////////////////////////////////////////////////////////////////////////// + +void SetCfgVal(char *pB, char *pE, int val) +{ + char *p, *ps, *pC; + char t[32]; + + sprintf(t,"%d",val); +// printf("%s - %s - %d\n", pB, pE, val); + + p = strstr(pB, pE); + if (p) { + p = strstr(p, "="); + if (!p) + return; + p++; + while (*p && *p != '\n' && (*p < '0' || *p > '9')) + p++; + if (*p == 0 || *p == '\n') + return; + ps = p; + while (*p >= '0' && *p <= '9') + p++; + pC = (char *) malloc(32767); + strcpy(pC, p); + strcpy(ps, t); + strcat(pB, pC); + free(pC); + } else { + strcat(pB, pE); + strcat(pB, " = "); + strcat(pB, t); + strcat(pB, "\n"); + } + +} + +void SaveConfig(GtkWidget *widget, gpointer user_data) +{ + FILE *in; + GladeXML *xml; + int len, val; + char *pB; + char cfg[255]; + + pB = (char *) malloc(32767); + memset(pB, 0, 32767); + + strcpy(cfg, CONFIG_FILENAME); + + /* ADB TODO Why do we read this in to just replace it again? */ + in = fopen(cfg, READBINARY); + if (in) { + len = fread(pB, 1, 32767, in); + fclose(in); + } + + xml = (GladeXML*) user_data; + + val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "cbVolume2"))); + SetCfgVal(pB, "\nVolume", val); + + val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "cbInterpolation2"))); + SetCfgVal(pB, "\nUseInterpolation", val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "chkEnableXA"))); + SetCfgVal(pB, "\nUseXA", val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "chkXASpeed"))); + SetCfgVal(pB, "\nXAPitch", val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "chkHiCompat"))); + SetCfgVal(pB, "\nHighCompMode", val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "chkIRQWait"))); + SetCfgVal(pB, "\nSPUIRQWait", val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "chkDisStereo"))); + SetCfgVal(pB, "\nDisStereo", val); + + val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "cbReverb2"))); + SetCfgVal(pB, "\nUseReverb", val); + + if ((in = fopen(cfg, WRITEBINARY)) != NULL) { + fwrite(pB, strlen(pB), 1, in); + fclose(in); + } /* ADB TODO Error checking? */ + + free(pB); + + gtk_widget_destroy (glade_xml_get_widget (xml, "CfgWnd")); +// g_free (xml); + + /* Close the window and exit control from the plugin */ + exit (0); +} diff --git a/plugins/dfsound/stdafx.h b/plugins/dfsound/stdafx.h new file mode 100644 index 00000000..ceff1d6b --- /dev/null +++ b/plugins/dfsound/stdafx.h @@ -0,0 +1,43 @@ +/*************************************************************************** + StdAfx.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#ifdef USEOSS +#include <sys/soundcard.h> +#endif +#include <unistd.h> +#ifndef NOTHREADLIB +#include <pthread.h> +#endif +#define RRand(range) (random()%range) +#include <string.h> +#include <sys/time.h> +#include <math.h> + +#undef CALLBACK +#define CALLBACK +#define DWORD unsigned long +#define LOWORD(l) ((unsigned short)(l)) +#define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF)) + +#define INLINE inline + +#include "psemuxa.h" diff --git a/plugins/dfsound/xa.c b/plugins/dfsound/xa.c new file mode 100644 index 00000000..c9397d71 --- /dev/null +++ b/plugins/dfsound/xa.c @@ -0,0 +1,362 @@ +/*************************************************************************** + xa.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" +#define _IN_XA +#include <stdint.h> + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// XA GLOBALS +//////////////////////////////////////////////////////////////////////// + +xa_decode_t * xapGlobal=0; + +uint32_t * XAFeed = NULL; +uint32_t * XAPlay = NULL; +uint32_t * XAStart = NULL; +uint32_t * XAEnd = NULL; + +uint32_t XARepeat = 0; +uint32_t XALastVal = 0; + +int iLeftXAVol = 32767; +int iRightXAVol = 32767; + +static int gauss_ptr = 0; +static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +#define gvall0 gauss_window[gauss_ptr] +#define gvall(x) gauss_window[(gauss_ptr+x)&3] +#define gvalr0 gauss_window[4+gauss_ptr] +#define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)] + +//////////////////////////////////////////////////////////////////////// +// MIX XA +//////////////////////////////////////////////////////////////////////// + +INLINE void MixXA(void) +{ + int ns; + + for(ns=0;ns<NSSIZE && XAPlay!=XAFeed;ns++) + { + XALastVal=*XAPlay++; + if(XAPlay==XAEnd) XAPlay=XAStart; + SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767; + SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767; + } + + if(XAPlay==XAFeed && XARepeat) + { + XARepeat--; + for(;ns<NSSIZE;ns++) + { + SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767; + SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// small linux time helper... only used for watchdog +//////////////////////////////////////////////////////////////////////// + +INLINE unsigned long timeGetTime_spu() +{ + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works +} + +//////////////////////////////////////////////////////////////////////// +// FEED XA +//////////////////////////////////////////////////////////////////////// + +INLINE void FeedXA(xa_decode_t *xap) +{ + int sinc,spos,i,iSize,iPlace,vl,vr; + + if(!bSPUIsOpen) return; + + xapGlobal = xap; // store info for save states + XARepeat = 100; // set up repeat + + iSize=((44100*xap->nsamples)/xap->freq); // get size + if(!iSize) return; // none? bye + + if(XAFeed<XAPlay) iPlace=XAPlay-XAFeed; // how much space in my buf? + else iPlace=(XAEnd-XAFeed) + (XAPlay-XAStart); + + if(iPlace==0) return; // no place at all + + //----------------------------------------------------// + if(iXAPitch) // pitch change option? + { + static DWORD dwLT=0; + static DWORD dwFPS=0; + static int iFPSCnt=0; + static int iLastSize=0; + static DWORD dwL1=0; + DWORD dw=timeGetTime_spu(),dw1,dw2; + + iPlace=iSize; + + dwFPS+=dw-dwLT;iFPSCnt++; + + dwLT=dw; + + if(iFPSCnt>=10) + { + if(!dwFPS) dwFPS=1; + dw1=1000000/dwFPS; + if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1; + else dwL1=dw1; + dw2=(xap->freq*100/xap->nsamples); + if((!dw1)||((dw2+100)>=dw1)) iLastSize=0; + else + { + iLastSize=iSize*dw2/dw1; + if(iLastSize>iPlace) iLastSize=iPlace; + iSize=iLastSize; + } + iFPSCnt=0;dwFPS=0; + } + else + { + if(iLastSize) iSize=iLastSize; + } + } + //----------------------------------------------------// + + spos=0x10000L; + sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size + + if(xap->stereo) +{ + uint32_t * pS=(uint32_t *)xap->pcm; + uint32_t l=0; + + if(iXAPitch) + { + int32_t l1,l2;short s; + for(i=0;i<iSize;i++) + { + if(iUseInterpolation==2) + { + while(spos>=0x10000L) + { + l = *pS++; + gauss_window[gauss_ptr] = (short)LOWORD(l); + gauss_window[4+gauss_ptr] = (short)HIWORD(l); + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l= (vr >> 11) & 0xffff; + vr=(gauss[vl]*gvalr0)&~2047; + vr+=(gauss[vl+1]*gvalr(1))&~2047; + vr+=(gauss[vl+2]*gvalr(2))&~2047; + vr+=(gauss[vl+3]*gvalr(3))&~2047; + l |= vr << 5; + } + else + { + while(spos>=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + } + + s=(short)LOWORD(l); + l1=s; + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + s=(short)HIWORD(l); + l2=s; + l2=(l2*iPlace)/iSize; + if(l2<-32767) l2=-32767; + if(l2> 32767) l2=32767; + l=(l1&0xffff)|(l2<<16); + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i<iSize;i++) + { + if(iUseInterpolation==2) + { + while(spos>=0x10000L) + { + l = *pS++; + gauss_window[gauss_ptr] = (short)LOWORD(l); + gauss_window[4+gauss_ptr] = (short)HIWORD(l); + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l= (vr >> 11) & 0xffff; + vr=(gauss[vl]*gvalr0)&~2047; + vr+=(gauss[vl+1]*gvalr(1))&~2047; + vr+=(gauss[vl+2]*gvalr(2))&~2047; + vr+=(gauss[vl+3]*gvalr(3))&~2047; + l |= vr << 5; + } + else + { + while(spos>=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + } + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } + else + { + unsigned short * pS=(unsigned short *)xap->pcm; + uint32_t l;short s=0; + + if(iXAPitch) + { + int32_t l1; + for(i=0;i<iSize;i++) + { + if(iUseInterpolation==2) + { + while(spos>=0x10000L) + { + gauss_window[gauss_ptr] = (short)*pS++; + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l1=s= vr >> 11; + l1 &= 0xffff; + } + else + { + while(spos>=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l1=s; + } + + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + l=(l1&0xffff)|(l1<<16); + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i<iSize;i++) + { + if(iUseInterpolation==2) + { + while(spos>=0x10000L) + { + gauss_window[gauss_ptr] = (short)*pS++; + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l=s= vr >> 11; + l &= 0xffff; + } + else + { + while(spos>=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l=s; + } + + *XAFeed++=(l|(l<<16)); + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } +} + +#endif + diff --git a/plugins/dfsound/xa.h b/plugins/dfsound/xa.h new file mode 100644 index 00000000..7fd1a8e7 --- /dev/null +++ b/plugins/dfsound/xa.h @@ -0,0 +1,19 @@ +/***************************************************************************
+ xa.h - description
+ -------------------
+ begin : Wed May 15 2002
+ copyright : (C) 2002 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+INLINE void MixXA(void);
+INLINE void FeedXA(xa_decode_t *xap);
diff --git a/plugins/dfxvideo/Makefile.am b/plugins/dfxvideo/Makefile.am new file mode 100644 index 00000000..e2396901 --- /dev/null +++ b/plugins/dfxvideo/Makefile.am @@ -0,0 +1,35 @@ +STRIP_FPIC = sh $(top_srcdir)/strip_fPIC.sh + +SUFFIXES = .asm + +.asm.lo: + $(LIBTOOL) --tag=CC --mode=compile \ + $(STRIP_FPIC) $(NASM) -f elf -d ELF -I${srcdir}/ $< + +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) $(GLADE2_CFLAGS) -I/usr/X11R6/include \ + -I../../libpcsxcore -DVERSION=XVideo -DNUMBER=0.1.0 + +bindir = @libdir@/games/psemu/ +libdir = @libdir@/games/psemu/ + +lib_LTLIBRARIES = libDFXVideo.la + +libDFXVideo_la_SOURCES = gpu.c cfg.c draw.c fps.c key.c menu.c prim.c soft.c zn.c +if X86_NASM +libDFXVideo_la_SOURCES += i386.asm +INCLUDES += -DUSE_NASM=1 +endif +libDFXVideo_la_LDFLAGS = -module -avoid-version +libDFXVideo_la_LDFLAGS += -L/usr/X11R6/lib64 -L/usr/X11R6/lib \ + -lX11 -lXv -lXext -lXtst -lm + +bin_PROGRAMS = cfgDFXVideo +cfgDFXVideo_SOURCES = gpucfg-0.1df/main.c +cfgDFXVideo_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) -L/usr/X11R6/lib -lXext + +glade_DATA = gpucfg-0.1df/dfxvideo.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) diff --git a/plugins/dfxvideo/Makefile.in b/plugins/dfxvideo/Makefile.in new file mode 100644 index 00000000..26f469b0 --- /dev/null +++ b/plugins/dfxvideo/Makefile.in @@ -0,0 +1,617 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@X86_NASM_TRUE@am__append_1 = i386.asm +@X86_NASM_TRUE@am__append_2 = -DUSE_NASM=1 +bin_PROGRAMS = cfgDFXVideo$(EXEEXT) +subdir = plugins/dfxvideo +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(gladedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libDFXVideo_la_LIBADD = +am__libDFXVideo_la_SOURCES_DIST = gpu.c cfg.c draw.c fps.c key.c \ + menu.c prim.c soft.c zn.c i386.asm +@X86_NASM_TRUE@am__objects_1 = i386.lo +am_libDFXVideo_la_OBJECTS = gpu.lo cfg.lo draw.lo fps.lo key.lo \ + menu.lo prim.lo soft.lo zn.lo $(am__objects_1) +libDFXVideo_la_OBJECTS = $(am_libDFXVideo_la_OBJECTS) +libDFXVideo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libDFXVideo_la_LDFLAGS) $(LDFLAGS) -o $@ +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_cfgDFXVideo_OBJECTS = main.$(OBJEXT) +cfgDFXVideo_OBJECTS = $(am_cfgDFXVideo_OBJECTS) +am__DEPENDENCIES_1 = +cfgDFXVideo_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libDFXVideo_la_SOURCES) $(cfgDFXVideo_SOURCES) +DIST_SOURCES = $(am__libDFXVideo_la_SOURCES_DIST) \ + $(cfgDFXVideo_SOURCES) +gladeDATA_INSTALL = $(INSTALL_DATA) +DATA = $(glade_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFOPENGL = @DFOPENGL@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADE2_CFLAGS = @GLADE2_CFLAGS@ +GLADE2_LIBS = @GLADE2_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTK2_CFLAGS = @GTK2_CFLAGS@ +GTK2_LIBS = @GTK2_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NASM = @NASM@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @libdir@/games/psemu/ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@/games/psemu/ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +STRIP_FPIC = sh $(top_srcdir)/strip_fPIC.sh +SUFFIXES = .asm +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" $(GTK2_CFLAGS) \ + $(GLADE2_CFLAGS) -I/usr/X11R6/include -I../../libpcsxcore \ + -DVERSION=XVideo -DNUMBER=0.1.0 $(am__append_2) +lib_LTLIBRARIES = libDFXVideo.la +libDFXVideo_la_SOURCES = gpu.c cfg.c draw.c fps.c key.c menu.c prim.c \ + soft.c zn.c $(am__append_1) +libDFXVideo_la_LDFLAGS = -module -avoid-version -L/usr/X11R6/lib64 \ + -L/usr/X11R6/lib -lX11 -lXv -lXext -lXtst -lm +cfgDFXVideo_SOURCES = gpucfg-0.1df/main.c +cfgDFXVideo_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) -L/usr/X11R6/lib -lXext +glade_DATA = gpucfg-0.1df/dfxvideo.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) +all: all-am + +.SUFFIXES: +.SUFFIXES: .asm .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/dfxvideo/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/dfxvideo/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libDFXVideo.la: $(libDFXVideo_la_OBJECTS) $(libDFXVideo_la_DEPENDENCIES) + $(libDFXVideo_la_LINK) -rpath $(libdir) $(libDFXVideo_la_OBJECTS) $(libDFXVideo_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +cfgDFXVideo$(EXEEXT): $(cfgDFXVideo_OBJECTS) $(cfgDFXVideo_DEPENDENCIES) + @rm -f cfgDFXVideo$(EXEEXT) + $(LINK) $(cfgDFXVideo_OBJECTS) $(cfgDFXVideo_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/draw.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fps.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prim.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/soft.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zn.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +main.o: gpucfg-0.1df/main.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.o -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.o `test -f 'gpucfg-0.1df/main.c' || echo '$(srcdir)/'`gpucfg-0.1df/main.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gpucfg-0.1df/main.c' object='main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.o `test -f 'gpucfg-0.1df/main.c' || echo '$(srcdir)/'`gpucfg-0.1df/main.c + +main.obj: gpucfg-0.1df/main.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.obj -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.obj `if test -f 'gpucfg-0.1df/main.c'; then $(CYGPATH_W) 'gpucfg-0.1df/main.c'; else $(CYGPATH_W) '$(srcdir)/gpucfg-0.1df/main.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gpucfg-0.1df/main.c' object='main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.obj `if test -f 'gpucfg-0.1df/main.c'; then $(CYGPATH_W) 'gpucfg-0.1df/main.c'; else $(CYGPATH_W) '$(srcdir)/gpucfg-0.1df/main.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-gladeDATA: $(glade_DATA) + @$(NORMAL_INSTALL) + test -z "$(gladedir)" || $(MKDIR_P) "$(DESTDIR)$(gladedir)" + @list='$(glade_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(gladeDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(gladedir)/$$f'"; \ + $(gladeDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(gladedir)/$$f"; \ + done + +uninstall-gladeDATA: + @$(NORMAL_UNINSTALL) + @list='$(glade_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(gladedir)/$$f'"; \ + rm -f "$(DESTDIR)$(gladedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(gladedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-gladeDATA + +install-dvi: install-dvi-am + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-gladeDATA \ + uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-gladeDATA install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-gladeDATA uninstall-libLTLIBRARIES + + +.asm.lo: + $(LIBTOOL) --tag=CC --mode=compile \ + $(STRIP_FPIC) $(NASM) -f elf -d ELF -I${srcdir}/ $< +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/dfxvideo/cfg.c b/plugins/dfxvideo/cfg.c new file mode 100644 index 00000000..c341ef05 --- /dev/null +++ b/plugins/dfxvideo/cfg.c @@ -0,0 +1,315 @@ +/*************************************************************************** + cfg.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define _IN_CFG + +#include <sys/stat.h> +#undef FALSE +#undef TRUE +#define MAKELONG(low,high) ((unsigned long)(((unsigned short)(low)) | (((unsigned long)((unsigned short)(high))) << 16))) + +#include "externals.h" +#include "cfg.h" +#include "gpu.h" + +// CONFIG FILE helpers.... used in (non-fpse) Linux and ZN Windows + +#include <sys/stat.h> + +char * pConfigFile = NULL; + +// some helper macros: + +#define GetValue(name, var) \ + p = strstr(pB, name); \ + if (p != NULL) { \ + p+=strlen(name); \ + while ((*p == ' ') || (*p == '=')) p++; \ + if (*p != '\n') var = atoi(p); \ + } + +#define GetFloatValue(name, var) \ + p = strstr(pB, name); \ + if (p != NULL) { \ + p+=strlen(name); \ + while ((*p == ' ') || (*p == '=')) p++; \ + if (*p != '\n') var = (float)atof(p); \ + } + +#define SetValue(name, var) \ + p = strstr(pB, name); \ + if (p != NULL) { \ + p+=strlen(name); \ + while ((*p == ' ') || (*p == '=')) p++; \ + if (*p != '\n') { \ + len = sprintf(t1, "%d", var); \ + strncpy(p, t1, len); \ + if (p[len] != ' ' && p[len] != '\n' && p[len] != 0) p[len] = ' '; \ + } \ + } \ + else { \ + size+=sprintf(pB+size, "%s = %d\n", name, var); \ + } + +#define SetFloatValue(name, var) \ + p = strstr(pB, name); \ + if (p != NULL) { \ + p+=strlen(name); \ + while ((*p == ' ') || (*p == '=')) p++; \ + if (*p != '\n') { \ + len = sprintf(t1, "%.1f", (double)var); \ + strncpy(p, t1, len); \ + if (p[len] != ' ' && p[len] != '\n' && p[len] != 0) p[len] = ' '; \ + } \ + } \ + else { \ + size+=sprintf(pB+size, "%s = %.1f\n", name, (double)var); \ + } + +void ReadConfigFile() +{ + struct stat buf; + FILE *in;char t[256];int len, size; + char * pB, * p; + + if(pConfigFile) + strcpy(t,pConfigFile); + else + { + strcpy(t,"dfxvideo.cfg"); + in = fopen(t,"rb"); + if (!in) + { + strcpy(t,"cfg/dfxvideo.cfg"); + in = fopen(t,"rb"); + if(!in) sprintf(t,"%s/.pcsx/plugins/dfxvideo.cfg",getenv("HOME")); + else fclose(in); + } + else fclose(in); + } + + if (stat(t, &buf) == -1) return; + size = buf.st_size; + + in = fopen(t,"rb"); + if (!in) return; + + pB=(char *)malloc(size); + memset(pB,0,size); + + len = fread(pB, 1, size, in); + fclose(in); + + GetValue("ResX", iResX); + if(iResX<20) iResX=20; + iResX=(iResX/4)*4; + + GetValue("ResY", iResY); + if(iResY<20) iResY=20; + iResY=(iResY/4)*4; + + iWinSize=MAKELONG(iResX,iResY); + + GetValue("NoStretch", iUseNoStretchBlt); + + GetValue("Dithering", iUseDither); + + GetValue("FullScreen", iWindowMode); + if(iWindowMode!=0) iWindowMode=0; + else iWindowMode=1; + + GetValue("ShowFPS", iShowFPS); + if(iShowFPS<0) iShowFPS=0; + if(iShowFPS>1) iShowFPS=1; + + GetValue("Maintain43", iMaintainAspect); + if(iMaintainAspect<0) iMaintainAspect=0; + if(iMaintainAspect>1) iMaintainAspect=1; + + GetValue("UseFrameLimit", UseFrameLimit); + if(UseFrameLimit<0) UseFrameLimit=0; + if(UseFrameLimit>1) UseFrameLimit=1; + + GetValue("UseFrameSkip", UseFrameSkip); + if(UseFrameSkip<0) UseFrameSkip=0; + if(UseFrameSkip>1) UseFrameSkip=1; + + GetValue("FPSDetection", iFrameLimit); + if(iFrameLimit<1) iFrameLimit=1; + if(iFrameLimit>2) iFrameLimit=2; + + GetFloatValue("FrameRate", fFrameRate); + fFrameRate/=10; + if(fFrameRate<10.0f) fFrameRate=10.0f; + if(fFrameRate>1000.0f) fFrameRate=1000.0f; + + GetValue("CfgFixes", dwCfgFixes); + + GetValue("UseFixes", iUseFixes); + if(iUseFixes<0) iUseFixes=0; + if(iUseFixes>1) iUseFixes=1; + + free(pB); +} + +void ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgDFXVideo"); + if (stat(cfg, &buf) != -1) { + strcat(cfg, " "); + strcat(cfg, arg); + system(cfg); + return; + } + + strcpy(cfg, "./cfg/cfgDFXVideo"); + if (stat(cfg, &buf) != -1) { + strcat(cfg, " "); + strcat(cfg, arg); + system(cfg); + return; + } + + sprintf(cfg, "%s/.pcsx/plugins/cfg/cfgDFXVideo", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + strcat(cfg, " "); + strcat(cfg, arg); + system(cfg); + return; + } + + printf("ERROR: cfgDFXVideo file not found!\n"); +} + +void SoftDlgProc(void) +{ + ExecCfg("CFG"); +} + +void AboutDlgProc(void) +{ + char args[256]; + + sprintf(args, "ABOUT"); + ExecCfg(args); +} + +void ReadConfig(void) +{ + // defaults + iResX=640;iResY=480; + iWinSize=MAKELONG(iResX,iResY); + iColDepth=32; + iWindowMode=1; + iMaintainAspect=0; + UseFrameLimit=1; + UseFrameSkip=0; + iFrameLimit=2; + fFrameRate=200.0f; + dwCfgFixes=0; + iUseFixes=0; + iUseNoStretchBlt=1; + iUseDither=0; + iShowFPS=0; + + // read sets + ReadConfigFile(); + + // additional checks + if(!iColDepth) iColDepth=32; + if(iUseFixes) dwActFixes=dwCfgFixes; + SetFixes(); +} + +void WriteConfig(void) { + + struct stat buf; + FILE *out;char t[256];int len, size; + char * pB, * p; char t1[8]; + + if(pConfigFile) + strcpy(t,pConfigFile); + else + { + strcpy(t,"dfxvideo.cfg"); + out = fopen(t,"rb"); + if (!out) + { + strcpy(t,"cfg/dfxvideo.cfg"); + out = fopen(t,"rb"); + if(!out) sprintf(t,"%s/.pcsx/plugins/dfxvideo.cfg",getenv("HOME")); + else fclose(out); + } + else fclose(out); + } + + if (stat(t, &buf) != -1) size = buf.st_size; + else size = 0; + + out = fopen(t,"rb"); + if (!out) { + // defaults + iResX=640;iResY=480; + iColDepth=32; + iWindowMode=1; + iMaintainAspect=0; + UseFrameLimit=0; + UseFrameSkip=0; + iFrameLimit=2; + fFrameRate=200.0f; + dwCfgFixes=0; + iUseFixes=0; + iUseNoStretchBlt=1; + iUseDither=0; + iShowFPS=0; + + size = 0; + pB=(char *)malloc(4096); + memset(pB,0,4096); + } + else { + pB=(char *)malloc(size+4096); + memset(pB,0,size+4096); + + len = fread(pB, 1, size, out); + fclose(out); + } + + SetValue("ResX", iResX); + SetValue("ResY", iResY); + SetValue("NoStretch", iUseNoStretchBlt); + SetValue("Dithering", iUseDither); + SetValue("FullScreen", !iWindowMode); + SetValue("ShowFPS", iShowFPS); + SetValue("Maintain43", iMaintainAspect); + SetValue("UseFrameLimit", UseFrameLimit); + SetValue("UseFrameSkip", UseFrameSkip); + SetValue("FPSDetection", iFrameLimit); + SetFloatValue("FrameRate", fFrameRate); + SetValue("CfgFixes", (unsigned int)dwCfgFixes); + SetValue("UseFixes", iUseFixes); + + out = fopen(t,"wb"); + if (!out) return; + + len = fwrite(pB, 1, size, out); + fclose(out); + + free(pB); +} diff --git a/plugins/dfxvideo/cfg.h b/plugins/dfxvideo/cfg.h new file mode 100644 index 00000000..fa259f30 --- /dev/null +++ b/plugins/dfxvideo/cfg.h @@ -0,0 +1,28 @@ +/*************************************************************************** + cfg.h - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#ifndef _GPU_CFG_H_ +#define _GPU_CFG_H_ + +void ReadConfig(void); +void WriteConfig(void); +void ReadWinSizeConfig(void); + +void SoftDlgProc(void); +void AboutDlgProc(void); + +#endif // _GPU_CFG_H_ diff --git a/plugins/dfxvideo/draw.c b/plugins/dfxvideo/draw.c new file mode 100644 index 00000000..3b5a722c --- /dev/null +++ b/plugins/dfxvideo/draw.c @@ -0,0 +1,2079 @@ +/*************************************************************************** + draw.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define _IN_DRAW + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "prim.h" +#include "menu.h" +#include "interp.h" +#include "swap.h" + +// misc globals +int iResX; +int iResY; +long lLowerpart; +BOOL bIsFirstFrame = TRUE; +BOOL bCheckMask = FALSE; +unsigned short sSetMask = 0; +unsigned long lSetMask = 0; +int iDesktopCol = 16; +int iShowFPS = 0; +int iWinSize; +int iMaintainAspect = 0; +int iUseNoStretchBlt = 0; +int iFastFwd = 0; +int iDebugMode = 0; +int iFVDisplay = 0; +PSXPoint_t ptCursorPoint[8]; +unsigned short usCursorActive = 0; + +//unsigned int LUT16to32[65536]; +//unsigned int RGBtoYUV[65536]; + +float pixelaspect; + +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/XShm.h> +#include <X11/extensions/XTest.h> +int xv_port = -1; +int xv_id = -1; +int xv_depth = 0; +int yuv_port = -1; +int yuv_id = -1; +int use_yuv = 0; +int xv_vsync = 0; +int has_test_ext = 0; +int fake_key_timer = 0; + +XShmSegmentInfo shminfo; +int finalw,finalh; + +extern XvImage *XvShmCreateImage(Display*, XvPortID, int, char*, int, int, XShmSegmentInfo*); + +// prototypes +void hq2x_32( unsigned char * srcPtr, DWORD srcPitch, unsigned char * dstPtr, int width, int height); +void hq3x_32( unsigned char * srcPtr, DWORD srcPitch, unsigned char * dstPtr, int width, int height); + +#include <time.h> + +//////////////////////////////////////////////////////////////////////// +// generic 2xSaI helpers +//////////////////////////////////////////////////////////////////////// + +void * pSaISmallBuff=NULL; +void * pSaIBigBuff=NULL; + +#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D)) + +static __inline int GetResult1(DWORD A, DWORD B, DWORD C, DWORD D, DWORD E) +{ + int x = 0; + int y = 0; + int r = 0; + if (A == C) x+=1; else if (B == C) y+=1; + if (A == D) x+=1; else if (B == D) y+=1; + if (x <= 1) r+=1; + if (y <= 1) r-=1; + return r; +} + +static __inline int GetResult2(DWORD A, DWORD B, DWORD C, DWORD D, DWORD E) +{ + int x = 0; + int y = 0; + int r = 0; + if (A == C) x+=1; else if (B == C) y+=1; + if (A == D) x+=1; else if (B == D) y+=1; + if (x <= 1) r-=1; + if (y <= 1) r+=1; + return r; +} + +#define colorMask8 0x00FEFEFE +#define lowPixelMask8 0x00010101 +#define qcolorMask8 0x00FCFCFC +#define qlowpixelMask8 0x00030303 + +#define INTERPOLATE8(A, B) ((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8))) +#define Q_INTERPOLATE8(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) \ + + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8)))) + + +void Super2xSaI_ex8(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch<<1; + DWORD srcPitchHalf = srcPitch>>1; + int finWidth = srcPitch>>2; + DWORD line; + DWORD *dP; + DWORD *bP; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + finalw=width<<1; + finalh=height<<1; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + if(finish==finWidth) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) {iYA=0;} + else {iYA=finWidth;} + if(height>4) {iYB=finWidth;iYC=srcPitchHalf;} + else + if(height>3) {iYB=finWidth;iYC=finWidth;} + else {iYB=0;iYC=0;} + + colorB0 = *(bP- iYA - iXA); + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + colorB3 = *(bP- iYA + iXC); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA0 = *(bP + iYC - iXA); + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + colorA3 = *(bP + iYC + iXC); + + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE8(color5, color6); + } + } + else + { + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE8 (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE8 (color2, color2, color2, color3); + else + product2b = INTERPOLATE8 (color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE8 (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE8 (color6, color5, color5, color5); + else + product1b = INTERPOLATE8 (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE8(color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE8(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE8(color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE8(color2, color5); + else + product1a = color5; + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(srcPitchHalf))=product2a; + *(dP+1+(srcPitchHalf))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} + +//////////////////////////////////////////////////////////////////////// + +void Std2xSaI_ex8(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch<<1; + DWORD srcPitchHalf = srcPitch>>1; + int finWidth = srcPitch>>2; + DWORD line; + DWORD *dP; + DWORD *bP; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + + finalw=width<<1; + finalh=height<<1; + + DWORD colorA, colorB; + DWORD colorC, colorD, + colorE, colorF, colorG, colorH, + colorI, colorJ, colorK, colorL, + colorM, colorN, colorO, colorP; + DWORD product, product1, product2; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- +// Map of the pixels: I|E F|J +// G|A B|K +// H|C D|L +// M|N O|P + if(finish==finWidth) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) {iYA=0;} + else {iYA=finWidth;} + if(height>4) {iYB=finWidth;iYC=srcPitchHalf;} + else + if(height>3) {iYB=finWidth;iYC=finWidth;} + else {iYB=0;iYC=0;} + + colorI = *(bP- iYA - iXA); + colorE = *(bP- iYA); + colorF = *(bP- iYA + iXB); + colorJ = *(bP- iYA + iXC); + + colorG = *(bP - iXA); + colorA = *(bP); + colorB = *(bP + iXB); + colorK = *(bP + iXC); + + colorH = *(bP + iYB - iXA); + colorC = *(bP + iYB); + colorD = *(bP + iYB + iXB); + colorL = *(bP + iYB + iXC); + + colorM = *(bP + iYC - iXA); + colorN = *(bP + iYC); + colorO = *(bP + iYC + iXB); + colorP = *(bP + iYC + iXC); + + + if((colorA == colorD) && (colorB != colorC)) + { + if(((colorA == colorE) && (colorB == colorL)) || + ((colorA == colorC) && (colorA == colorF) && + (colorB != colorE) && (colorB == colorJ))) + { + product = colorA; + } + else + { + product = INTERPOLATE8(colorA, colorB); + } + + if(((colorA == colorG) && (colorC == colorO)) || + ((colorA == colorB) && (colorA == colorH) && + (colorG != colorC) && (colorC == colorM))) + { + product1 = colorA; + } + else + { + product1 = INTERPOLATE8(colorA, colorC); + } + product2 = colorA; + } + else + if((colorB == colorC) && (colorA != colorD)) + { + if(((colorB == colorF) && (colorA == colorH)) || + ((colorB == colorE) && (colorB == colorD) && + (colorA != colorF) && (colorA == colorI))) + { + product = colorB; + } + else + { + product = INTERPOLATE8(colorA, colorB); + } + + if(((colorC == colorH) && (colorA == colorF)) || + ((colorC == colorG) && (colorC == colorD) && + (colorA != colorH) && (colorA == colorI))) + { + product1 = colorC; + } + else + { + product1=INTERPOLATE8(colorA, colorC); + } + product2 = colorB; + } + else + if((colorA == colorD) && (colorB == colorC)) + { + if (colorA == colorB) + { + product = colorA; + product1 = colorA; + product2 = colorA; + } + else + { + register int r = 0; + product1 = INTERPOLATE8(colorA, colorC); + product = INTERPOLATE8(colorA, colorB); + + r += GetResult1 (colorA&0x00FFFFFF, colorB&0x00FFFFFF, colorG&0x00FFFFFF, colorE&0x00FFFFFF, colorI&0x00FFFFFF); + r += GetResult2 (colorB&0x00FFFFFF, colorA&0x00FFFFFF, colorK&0x00FFFFFF, colorF&0x00FFFFFF, colorJ&0x00FFFFFF); + r += GetResult2 (colorB&0x00FFFFFF, colorA&0x00FFFFFF, colorH&0x00FFFFFF, colorN&0x00FFFFFF, colorM&0x00FFFFFF); + r += GetResult1 (colorA&0x00FFFFFF, colorB&0x00FFFFFF, colorL&0x00FFFFFF, colorO&0x00FFFFFF, colorP&0x00FFFFFF); + + if (r > 0) + product2 = colorA; + else + if (r < 0) + product2 = colorB; + else + { + product2 = Q_INTERPOLATE8(colorA, colorB, colorC, colorD); + } + } + } + else + { + product2 = Q_INTERPOLATE8(colorA, colorB, colorC, colorD); + + if ((colorA == colorC) && (colorA == colorF) && + (colorB != colorE) && (colorB == colorJ)) + { + product = colorA; + } + else + if ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI)) + { + product = colorB; + } + else + { + product = INTERPOLATE8(colorA, colorB); + } + + if ((colorA == colorB) && (colorA == colorH) && + (colorG != colorC) && (colorC == colorM)) + { + product1 = colorA; + } + else + if ((colorC == colorG) && (colorC == colorD) && + (colorA != colorH) && (colorA == colorI)) + { + product1 = colorC; + } + else + { + product1 = INTERPOLATE8(colorA, colorC); + } + } + +////////////////////////// + + *dP=colorA; + *(dP+1)=product; + *(dP+(srcPitchHalf))=product1; + *(dP+1+(srcPitchHalf))=product2; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} + +//////////////////////////////////////////////////////////////////////// + +void SuperEagle_ex8(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch<<1; + DWORD srcPitchHalf = srcPitch>>1; + int finWidth = srcPitch>>2; + DWORD line; + DWORD *dP; + DWORD *bP; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA1, colorA2, + colorB1, colorB2, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + finalw=width<<1; + finalh=height<<1; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { + if(finish==finWidth) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) {iYA=0;} + else {iYA=finWidth;} + if(height>4) {iYB=finWidth;iYC=srcPitchHalf;} + else + if(height>3) {iYB=finWidth;iYC=finWidth;} + else {iYB=0;iYC=0;} + + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + + if(color2 == color6 && color5 != color3) + { + product1b = product2a = color2; + if((color1 == color2) || + (color6 == colorB2)) + { + product1a = INTERPOLATE8(color2, color5); + product1a = INTERPOLATE8(color2, product1a); + } + else + { + product1a = INTERPOLATE8(color5, color6); + } + + if((color6 == colorS2) || + (color2 == colorA1)) + { + product2b = INTERPOLATE8(color2, color3); + product2b = INTERPOLATE8(color2, product2b); + } + else + { + product2b = INTERPOLATE8(color2, color3); + } + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1a = color5; + + if ((colorB1 == color5) || + (color3 == colorS1)) + { + product1b = INTERPOLATE8(color5, color6); + product1b = INTERPOLATE8(color5, product1b); + } + else + { + product1b = INTERPOLATE8(color5, color6); + } + + if ((color3 == colorA2) || + (color4 == color5)) + { + product2a = INTERPOLATE8(color5, color2); + product2a = INTERPOLATE8(color5, product2a); + } + else + { + product2a = INTERPOLATE8(color2, color3); + } + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); + + if (r > 0) + { + product1b = product2a = color2; + product1a = product2b = INTERPOLATE8(color5, color6); + } + else + if (r < 0) + { + product2b = product1a = color5; + product1b = product2a = INTERPOLATE8(color5, color6); + } + else + { + product2b = product1a = color5; + product1b = product2a = color2; + } + } + else + { + product2b = product1a = INTERPOLATE8(color2, color6); + product2b = Q_INTERPOLATE8(color3, color3, color3, product2b); + product1a = Q_INTERPOLATE8(color5, color5, color5, product1a); + + product2a = product1b = INTERPOLATE8(color5, color3); + product2a = Q_INTERPOLATE8(color2, color2, color2, product2a); + product1b = Q_INTERPOLATE8(color6, color6, color6, product1b); + } + +//////////////////////////////// + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(srcPitchHalf))=product2a; + *(dP+1+(srcPitchHalf))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} + +///////////////////////// + +//#include <assert.h> + +static __inline void scale2x_32_def_whole(uint32_t* dst0, uint32_t* dst1, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count) +{ + + //assert(count >= 2); + + // first pixel + if (src0[0] != src2[0] && src1[0] != src1[1]) { + dst0[0] = src1[0] == src0[0] ? src0[0] : src1[0]; + dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; + dst1[0] = src1[0] == src2[0] ? src2[0] : src1[0]; + dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + } + ++src0; + ++src1; + ++src2; + dst0 += 2; + dst1 += 2; + + // central pixels + count -= 2; + while (count) { + if (src0[0] != src2[0] && src1[-1] != src1[1]) { + dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; + dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; + dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; + dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + } + + ++src0; + ++src1; + ++src2; + dst0 += 2; + dst1 += 2; + --count; + } + + // last pixel + if (src0[0] != src2[0] && src1[-1] != src1[0]) { + dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; + dst0[1] = src1[0] == src0[0] ? src0[0] : src1[0]; + dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; + dst1[1] = src1[0] == src2[0] ? src2[0] : src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + } +} + +void Scale2x_ex8(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstPtr, int width, int height) +{ + //const int srcpitch = srcPitch; + const int dstPitch = srcPitch<<1; + + int count = height; + + finalw=width<<1; + finalh=height<<1; + + uint32_t *dst0 = (uint32_t *)dstPtr; + uint32_t *dst1 = dst0 + (dstPitch >> 2); + + uint32_t *src0 = (uint32_t *)srcPtr; + uint32_t *src1 = src0 + (srcPitch >> 2); + uint32_t *src2 = src1 + (srcPitch >> 2); + scale2x_32_def_whole(dst0, dst1, src0, src0, src1, width); + + count -= 2; + while(count) { + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + scale2x_32_def_whole(dst0, dst1, src0, src0, src1, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + scale2x_32_def_whole(dst0, dst1, src0, src1, src1, width); + +} + +//////////////////////////////////////////////////////////////////////// + +static __inline void scale3x_32_def_whole(uint32_t* dst0, uint32_t* dst1, uint32_t* dst2, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count) +{ + //assert(count >= 2); + + //first pixel + if (src0[0] != src2[0] && src1[0] != src1[1]) { + dst0[0] = src1[0]; + dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; + dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; + dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; + dst1[1] = src1[0]; + dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; + dst2[0] = src1[0]; + dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0]; + dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst0[2] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + dst1[2] = src1[0]; + dst2[0] = src1[0]; + dst2[1] = src1[0]; + dst2[2] = src1[0]; + } + ++src0; + ++src1; + ++src2; + dst0 += 3; + dst1 += 3; + dst2 += 3; + + //central pixels + count -= 2; + while (count) { + if (src0[0] != src2[0] && src1[-1] != src1[1]) { + dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; + dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; + dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; + dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + dst1[1] = src1[0]; + dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; + dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; + dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; + dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst0[2] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + dst1[2] = src1[0]; + dst2[0] = src1[0]; + dst2[1] = src1[0]; + dst2[2] = src1[0]; + } + + ++src0; + ++src1; + ++src2; + dst0 += 3; + dst1 += 3; + dst2 += 3; + --count; + } + + // last pixel + if (src0[0] != src2[0] && src1[-1] != src1[0]) { + dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; + dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; + dst0[2] = src1[0]; + dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + dst1[1] = src1[0]; + dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; + dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; + dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; + dst2[2] = src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst0[2] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + dst1[2] = src1[0]; + dst2[0] = src1[0]; + dst2[1] = src1[0]; + dst2[2] = src1[0]; + } +} + + +void Scale3x_ex8(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstPtr, int width, int height) +{ + int count = height; + + int dstPitch = srcPitch*3; + int dstRowPixels = dstPitch>>2; + + finalw=width*3; + finalh=height*3; + + uint32_t *dst0 = (uint32_t *)dstPtr; + uint32_t *dst1 = dst0 + dstRowPixels; + uint32_t *dst2 = dst1 + dstRowPixels; + + uint32_t *src0 = (uint32_t *)srcPtr; + uint32_t *src1 = src0 + (srcPitch >> 2); + uint32_t *src2 = src1 + (srcPitch >> 2); + scale3x_32_def_whole(dst0, dst1, dst2, src0, src0, src2, width); + + count -= 2; + while(count) { + dst0 += dstRowPixels*3; + dst1 += dstRowPixels*3; + dst2 += dstRowPixels*3; + + scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + + dst0 += dstRowPixels*3; + dst1 += dstRowPixels*3; + dst2 += dstRowPixels*3; + + scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src1, width); +} + + +//////////////////////////////////////////////////////////////////////// + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + + +//////////////////////////////////////////////////////////////////////// +// X STUFF :) +//////////////////////////////////////////////////////////////////////// + + +static Cursor cursor; +XVisualInfo vi; +static XVisualInfo *myvisual; +Display *display; +static Colormap colormap; +Window window; +static GC hGC; +static XImage * Ximage; +static XvImage * XCimage; +static XImage * XFimage; +static XImage * XPimage=0 ; +char * Xpixels; +char * pCaptionText; + +static int fx=0; + + +static Atom xv_intern_atom_if_exists( Display *display, char const * atom_name ) +{ + XvAttribute * attributes; + int attrib_count,i; + Atom xv_atom = None; + + attributes = XvQueryPortAttributes( display, xv_port, &attrib_count ); + if( attributes!=NULL ) + { + for ( i = 0; i < attrib_count; ++i ) + { + if ( strcmp(attributes[i].name, atom_name ) == 0 ) + { + xv_atom = XInternAtom( display, atom_name, False ); + break; // found what we want, break out + } + } + XFree( attributes ); + } + + return xv_atom; +} + + + +// close display + +void DestroyDisplay(void) +{ + if(display) + { + XFreeColormap(display, colormap); + if(hGC) + { + XFreeGC(display,hGC); + hGC = 0; + } + if(Ximage) + { + XDestroyImage(Ximage); + Ximage=0; + } + if(XCimage) + { + XFree(XCimage); + XCimage=0; + } + if(XFimage) + { + XDestroyImage(XFimage); + XFimage=0; + } + + XShmDetach(display,&shminfo); + shmdt(shminfo.shmaddr); + shmctl(shminfo.shmid,IPC_RMID,NULL); + + Atom atom_vsync = xv_intern_atom_if_exists(display, "XV_SYNC_TO_VBLANK"); + if (atom_vsync != None) { + XvSetPortAttribute(display, xv_port, atom_vsync, xv_vsync); + } + + XSync(display,False); + + XCloseDisplay(display); + } +} + +static int depth=0; +int root_window_id=0; + + +// Create display + +void CreateDisplay(void) +{ + XSetWindowAttributes winattr; + int myscreen; + Screen * screen; + XEvent event; + XSizeHints hints; + XWMHints wm_hints; + MotifWmHints mwmhints; + Atom mwmatom; + + Atom delwindow; + + XGCValues gcv; + int i; + + int ret, j, p; + int formats; + unsigned int p_num_adaptors=0, p_num_ports=0; + + XvAdaptorInfo *ai; + XvImageFormatValues *fo; + + // Open display + display = XOpenDisplay(NULL); + + if (!display) + { + fprintf (stderr,"Failed to open display!!!\n"); + DestroyDisplay(); + return; + } + + myscreen=DefaultScreen(display); + + // desktop fullscreen switch + if (!iWindowMode) fx = 1; + + screen=DefaultScreenOfDisplay(display); + + pixelaspect = ((float)DisplayWidth(display, myscreen) / (float)DisplayWidthMM(display, myscreen)) / + ((float)DisplayHeight(display, myscreen) / (float)DisplayHeightMM(display, myscreen)); + + root_window_id=RootWindow(display,DefaultScreen(display)); + + //Look for an Xvideo RGB port + ret = XvQueryAdaptors(display, root_window_id, &p_num_adaptors, &ai); + if (ret != Success) { + if (ret == XvBadExtension) + printf("XvBadExtension returned at XvQueryExtension.\n"); + else + if (ret == XvBadAlloc) + printf("XvBadAlloc returned at XvQueryExtension.\n"); + else + printf("other error happaned at XvQueryAdaptors.\n"); + + exit(-1); + } + + depth = DefaultDepth(display, myscreen); + + for (i = 0; i < p_num_adaptors; i++) { + p_num_ports = ai[i].base_id + ai[i].num_ports; + for (p = ai[i].base_id; p < p_num_ports; p++) { + fo = XvListImageFormats(display, p, &formats); + for (j = 0; j < formats; j++) { + //backup YUV mode + //hmm, should I bother check guid == 55595659-0000-0010-8000-00aa00389b71? + //and check byte order? fo[j].byte_order == LSBFirst +#ifdef __BIG_ENDIAN__ + if ( fo[j].type == XvYUV && fo[j].bits_per_pixel == 16 && fo[j].format == XvPacked && strncmp("YUYV", fo[j].component_order, 5) == 0 ) +#else + if ( fo[j].type == XvYUV && fo[j].bits_per_pixel == 16 && fo[j].format == XvPacked && strncmp("UYVY", fo[j].component_order, 5) == 0 ) +#endif + { + yuv_port = p; + yuv_id = fo[j].id; + } + if (fo[j].type == XvRGB && fo[j].bits_per_pixel == 32) + { + xv_port = p; + xv_id = fo[j].id; + xv_depth = fo[j].depth; + printf("RGB mode found. id: %x, depth: %d\n", xv_id, xv_depth); + + if (xv_depth != depth) { + printf("Warning: Depth does not match screen depth (%d)\n", depth); + } + else { + //break out of loops + j = formats; + p = p_num_ports; + i = p_num_adaptors; + } + } + } + if (fo) + XFree(fo); + } + } + if (p_num_adaptors > 0) + XvFreeAdaptorInfo(ai); + if (xv_port == -1 && yuv_port == -1) + { + printf("RGB & YUV not found. Quitting.\n"); + exit(-1); + } + else if (xv_port == -1 && yuv_port != -1) + { + use_yuv = 1; + printf("RGB not found. Using YUV.\n"); + xv_port = yuv_port; + xv_id = yuv_id; + } + else if (xv_depth && xv_depth != depth && yuv_port != -1) + { + use_yuv = 1; + printf("Acceptable RGB mode not found. Using YUV.\n"); + xv_port = yuv_port; + xv_id = yuv_id; + } + + Atom atom_vsync = xv_intern_atom_if_exists(display, "XV_SYNC_TO_VBLANK"); + if (atom_vsync != None) { + XvGetPortAttribute(display, xv_port, atom_vsync, &xv_vsync); + XvSetPortAttribute(display, xv_port, atom_vsync, 0); + } + +myvisual = 0; + +if(XMatchVisualInfo(display,myscreen, depth, TrueColor, &vi)) + myvisual = &vi; + +if (!myvisual) +{ + fprintf(stderr,"Failed to obtain visual!\n"); + DestroyDisplay(); + return; +} + +/* + if(myvisual->red_mask==0x00007c00 && + myvisual->green_mask==0x000003e0 && + myvisual->blue_mask==0x0000001f) + {iColDepth=15;} + else + if(myvisual->red_mask==0x0000f800 && + myvisual->green_mask==0x000007e0 && + myvisual->blue_mask==0x0000001f) + {iColDepth=16;} + else +*/ + if(myvisual->red_mask==0x00ff0000 && + myvisual->green_mask==0x0000ff00 && + myvisual->blue_mask==0x000000ff) + {iColDepth=32;} + else + { + fprintf(stderr,"COLOR DEPTH NOT SUPPORTED!\n"); + fprintf(stderr,"r: %08lx\n",myvisual->red_mask); + fprintf(stderr,"g: %08lx\n",myvisual->green_mask); + fprintf(stderr,"b: %08lx\n",myvisual->blue_mask); + DestroyDisplay(); + return; + } + + // pffff... much work for a simple blank cursor... oh, well... + if(iWindowMode) cursor=XCreateFontCursor(display,XC_trek); + else + { + Pixmap p1,p2; + XImage * img; + XColor b,w; + char * idata; + XGCValues GCv; + GC GCc; + + memset(&b,0,sizeof(XColor)); + memset(&w,0,sizeof(XColor)); + idata=(char *)malloc(8); + memset(idata,0,8); + + p1=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); + p2=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); + + img = XCreateImage(display,myvisual->visual, + 1,XYBitmap,0,idata,8,8,8,1); + + GCv.function = GXcopy; + GCv.foreground = ~0; + GCv.background = 0; + GCv.plane_mask = AllPlanes; + GCc = XCreateGC(display,p1, + (GCFunction|GCForeground|GCBackground|GCPlaneMask),&GCv); + + XPutImage(display, p1,GCc,img,0,0,0,0,8,8); + XPutImage(display, p2,GCc,img,0,0,0,0,8,8); + XFreeGC(display, GCc); + + cursor = XCreatePixmapCursor(display,p1,p2,&b,&w,0,0); + + XFreePixmap(display,p1); + XFreePixmap(display,p2); + XDestroyImage(img); // will free idata as well + } + + colormap=XCreateColormap(display,root_window_id, + myvisual->visual,AllocNone); + + winattr.background_pixel=0; + winattr.border_pixel=WhitePixelOfScreen(screen); + winattr.bit_gravity=ForgetGravity; + winattr.win_gravity=NorthWestGravity; + winattr.backing_store=NotUseful; + + winattr.override_redirect=False; + winattr.save_under=False; + winattr.event_mask=0; + winattr.do_not_propagate_mask=0; + winattr.colormap=colormap; + winattr.cursor=None; + + window=XCreateWindow(display,root_window_id, + 0,0,iResX,iResY, + 0,myvisual->depth, + InputOutput,myvisual->visual, + CWBorderPixel | CWBackPixel | + CWEventMask | CWDontPropagate | + CWColormap | CWCursor, + &winattr); + + if(!window) + { + fprintf(stderr,"Failed in XCreateWindow()!!!\n"); + DestroyDisplay(); + return; + } + + delwindow = XInternAtom(display,"WM_DELETE_WINDOW",0); + XSetWMProtocols(display, window, &delwindow, 1); + + hints.flags=USPosition|USSize; + hints.base_width = iResX; + hints.base_height = iResY; + + wm_hints.input=1; + wm_hints.flags=InputHint; + + XSetWMHints(display,window,&wm_hints); + XSetWMNormalHints(display,window,&hints); + if(pCaptionText) + XStoreName(display,window,pCaptionText); + else XStoreName(display,window,"P.E.Op.S SoftX PSX Gpu"); + + XDefineCursor(display,window,cursor); + + // hack to get rid of window title bar + if (fx) + { + mwmhints.flags=MWM_HINTS_DECORATIONS; + mwmhints.decorations=0; + mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0); + XChangeProperty(display,window,mwmatom,mwmatom,32, + PropModeReplace,(unsigned char *)&mwmhints,4); + } + + // key stuff + XSelectInput(display, + window, + FocusChangeMask | ExposureMask | + KeyPressMask | KeyReleaseMask + ); + + XMapRaised(display,window); + XClearWindow(display,window); + XWindowEvent(display,window,ExposureMask,&event); + + if (fx) // fullscreen + { + XResizeWindow(display,window,screen->width,screen->height); + + hints.min_width = hints.max_width = hints.base_width = screen->width; + hints.min_height= hints.max_height = hints.base_height = screen->height; + + XSetWMNormalHints(display,window,&hints); + + // set the window layer for GNOME + { + XEvent xev; + + memset(&xev, 0, sizeof(xev)); + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = 1; + xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0); + xev.xclient.window = window; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", 0); + xev.xclient.data.l[2] = 0; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + + XSendEvent(display, root_window_id, 0, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); + } + } + + gcv.graphics_exposures = False; + hGC = XCreateGC(display,window, + GCGraphicsExposures, &gcv); + if(!hGC) + { + fprintf(stderr,"No gfx context!!!\n"); + DestroyDisplay(); + } + + + + Xpixels = (char *)malloc(220*15*4); + memset(Xpixels,255,220*15*4); + XFimage = XCreateImage(display,myvisual->visual, + depth, ZPixmap, 0, + (char *)Xpixels, + 220, 15, + depth>16 ? 32 : 16, + 0); + + Xpixels = (char *)malloc(8*8*4); + memset(Xpixels,0,8*8*4); + XCimage = XvCreateImage(display,xv_port,xv_id, + (char *)Xpixels, 8, 8); + + +/* +Allocate max that could be needed: +Big(est?) PSX res: 640x512 +32bpp (times 4) +2xsai func= 3xwidth,3xheight += approx 11.8mb +*/ +shminfo.shmid = shmget(IPC_PRIVATE, 640*512*4*3*3, IPC_CREAT | 0777); +shminfo.shmaddr = shmat(shminfo.shmid, 0, 0); +shminfo.readOnly = 0; + + if (!XShmAttach(display, &shminfo)) { + printf("XShmAttach failed !\n"); + exit (-1); + } + + { + int a,b,c,d; + has_test_ext = XTestQueryExtension(display, &a, &b, &c, &d); + } +} + +void (*p2XSaIFunc) (unsigned char *, DWORD, unsigned char *, int, int); +unsigned char *pBackBuffer = 0; + +void BlitScreen32(unsigned char *surf, int32_t x, int32_t y) +{ + unsigned char *pD; + unsigned int startxy; + uint32_t lu; + unsigned short s; + unsigned short row, column; + unsigned short dx = PreviousPSXDisplay.Range.x1; + unsigned short dy = PreviousPSXDisplay.DisplayMode.y; + + //int32_t lPitch = (dx + PreviousPSXDisplay.Range.x0) << 2; + int32_t lPitch = PSXDisplay.DisplayMode.x << 2; + + uint32_t *destpix; + + if (PSXDisplay.RGB24) + { + for (column = 0; column < dy; column++) + { + startxy = ((1024) * (column + y)) + x; + pD = (unsigned char *)&psxVuw[startxy]; + destpix = (uint32_t *)(surf + (column * lPitch)); + for (row = 0; row < dx; row++) + { + lu = *((uint32_t *)pD); + destpix[row] = + 0xff000000 | (RED(lu) << 16) | (GREEN(lu) << 8) | (BLUE(lu)); + pD += 3; + } + } + } + else + { + for (column = 0;column<dy;column++) + { + startxy = (1024 * (column + y)) + x; + destpix = (uint32_t *)(surf + (column * lPitch)); + for (row = 0; row < dx; row++) + { + s = GETLE16(&psxVuw[startxy++]); + destpix[row] = + (((s << 19) & 0xf80000) | ((s << 6) & 0xf800) | ((s >> 7) & 0xf8)) | 0xff000000; + } + } + } +} + +void BlitToYUV(unsigned char * surf,int32_t x,int32_t y) +{ + unsigned char * pD; + unsigned int startxy; + uint32_t lu;unsigned short s; + unsigned short row,column; + unsigned short dx=PreviousPSXDisplay.Range.x1; + unsigned short dy=PreviousPSXDisplay.DisplayMode.y; + int Y,U,V, R,G,B; + + //int32_t lPitch=(dx+PreviousPSXDisplay.Range.x0)<<2; + int32_t lPitch=PSXDisplay.DisplayMode.x<<2; + uint32_t *destpix; + + if(PSXDisplay.RGB24) + { + for(column=0;column<dy;column++) + { + startxy=((1024)*(column+y))+x; + pD=(unsigned char *)&psxVuw[startxy]; + destpix=(uint32_t*)(surf+(column*lPitch)); + for(row=0;row<dx;row++) + { + lu=*((uint32_t *)pD); + + R = RED(lu); + G = GREEN(lu); + B = BLUE(lu); + + Y = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235); + U = min(abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13, 240); + V = min(abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13, 240); + + destpix[row] = +#ifdef __BIG_ENDIAN__ + Y << 24 | U << 16 | Y << 8 | V; +#else + Y << 24 | V << 16 | Y << 8 | U; +#endif + pD+=3; + } + } + } + else + { + for(column=0;column<dy;column++) + { + startxy=((1024)*(column+y))+x; + destpix=(uint32_t*)(surf+(column*lPitch)); + for(row=0;row<dx;row++) + { + s=GETLE16(&psxVuw[startxy++]); + + R = (s << 3) &0xf8; + G = (s >> 2) &0xf8; + B = (s >> 7) &0xf8; + + Y = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235); + U = min(abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13, 240); + V = min(abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13, 240); + + destpix[row] = +#ifdef __BIG_ENDIAN__ + Y << 24 | U << 16 | Y << 8 | V; +#else + Y << 24 | V << 16 | Y << 8 | U; +#endif + } + } + } +} + +//dst will have half the pitch (32bit to 16bit) +void RGB2YUV(uint32_t *s, int width, int height, uint32_t *d) +{ + int x,y; + int R,G,B, Y1,Y2,U,V; + + for (y=0; y<height; y++) { + for(x=0; x<width>>1; x++) { + R = (*s >> 16) & 0xff; + G = (*s >> 8) & 0xff; + B = *s & 0xff; + s++; + + Y1 = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235); + U = min(abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13, 240); + V = min(abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13, 240); + + R = (*s >> 16) & 0xff; + G = (*s >> 8) & 0xff; + B = *s & 0xff; + s++; + + Y2 = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235); + +#ifdef __BIG_ENDIAN__ + *d = V | Y2 << 8 | U << 16 | Y1 << 24; +#else + *d = U | Y1 << 8 | V << 16 | Y2 << 24; +#endif + d++; + } + } +} + +void ShowGunCursor(unsigned char * surf,int iPitch) +{ + unsigned short dx=(unsigned short)PreviousPSXDisplay.Range.x1; + unsigned short dy=(unsigned short)PreviousPSXDisplay.DisplayMode.y; + int x,y,iPlayer,sx,ex,sy,ey; + + if(iColDepth==32) iPitch=iPitch<<2; + else iPitch=iPitch<<1; + + if(PreviousPSXDisplay.Range.y0) // centering needed? + { + surf+=PreviousPSXDisplay.Range.y0*iPitch; + dy-=PreviousPSXDisplay.Range.y0; + } + + if(iColDepth==32) // 32 bit color depth + { + const uint32_t crCursorColor32[8]={0xffff0000,0xff00ff00,0xff0000ff,0xffff00ff,0xffffff00,0xff00ffff,0xffffffff,0xff7f7f7f}; + + surf+=PreviousPSXDisplay.Range.x0<<2; // -> add x left border + + for(iPlayer=0;iPlayer<8;iPlayer++) // -> loop all possible players + { + if(usCursorActive&(1<<iPlayer)) // -> player active? + { + const int ty=(ptCursorPoint[iPlayer].y*dy)/256; // -> calculate the cursor pos in the current display + const int tx=(ptCursorPoint[iPlayer].x*dx)/512; + sx=tx-5;if(sx<0) {if(sx&1) sx=1; else sx=0;} + sy=ty-5;if(sy<0) {if(sy&1) sy=1; else sy=0;} + ex=tx+6;if(ex>dx) ex=dx; + ey=ty+6;if(ey>dy) ey=dy; + + for(x=tx,y=sy;y<ey;y+=2) // -> do dotted y line + *((uint32_t *)((surf)+(y*iPitch)+x*4))=crCursorColor32[iPlayer]; + for(y=ty,x=sx;x<ex;x+=2) // -> do dotted x line + *((uint32_t *)((surf)+(y*iPitch)+x*4))=crCursorColor32[iPlayer]; + } + } + } + else // 16 bit color depth + { + const unsigned short crCursorColor16[8]={0xf800,0x07c0,0x001f,0xf81f,0xffc0,0x07ff,0xffff,0x7bdf}; + + surf+=PreviousPSXDisplay.Range.x0<<1; // -> same stuff as above + + for(iPlayer=0;iPlayer<8;iPlayer++) + { + if(usCursorActive&(1<<iPlayer)) + { + const int ty=(ptCursorPoint[iPlayer].y*dy)/256; + const int tx=(ptCursorPoint[iPlayer].x*dx)/512; + sx=tx-5;if(sx<0) {if(sx&1) sx=1; else sx=0;} + sy=ty-5;if(sy<0) {if(sy&1) sy=1; else sy=0;} + ex=tx+6;if(ex>dx) ex=dx; + ey=ty+6;if(ey>dy) ey=dy; + + for(x=tx,y=sy;y<ey;y+=2) + *((unsigned short *)((surf)+(y*iPitch)+x*2))=crCursorColor16[iPlayer]; + for(y=ty,x=sx;x<ex;x+=2) + *((unsigned short *)((surf)+(y*iPitch)+x*2))=crCursorColor16[iPlayer]; + } + } + } +} + +extern time_t tStart; + +//Note: dest w,h are both input and output variables +inline void MaintainAspect(unsigned int *dx,unsigned int *dy,unsigned int *dw,unsigned int *dh) +{ + //Currently just 4/3 aspect ratio + int t; + + if (*dw * 3 > (float)*dh * pixelaspect * 4) { + t = (float)*dh * pixelaspect * 4.0f / 3; //new width aspect + *dx = (*dw - t) / 2; //centering + *dw = t; + } else { + t = (float)(*dw * 3) / (float)(4.0f * pixelaspect); + *dy = (*dh - t) / 2; + *dh = t; + } +} + + +void DoBufferSwap(void) +{ + Screen *screen; + Window _dw; + XvImage *xvi; + unsigned int dstx,dsty,srcy=0; + unsigned int _d, _w, _h; //don't care about _d + + finalw = PSXDisplay.DisplayMode.x; + finalh = PSXDisplay.DisplayMode.y; + + if (finalw == 0 || finalh == 0) + return; + + // disable screensaver + if (has_test_ext && fake_key_timer < time(NULL)) { + XTestFakeRelativeMotionEvent(display, 1, 0, 0); + fake_key_timer = time(NULL) + 55; + } + + XSync(display,False); + + if(use_yuv) { + if (iUseNoStretchBlt==0 || finalw > 320 || finalh > 256) { + BlitToYUV((unsigned char *)shminfo.shmaddr, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); + finalw <<= 1; + } else { + BlitScreen32((unsigned char *)pBackBuffer, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); + p2XSaIFunc(pBackBuffer, finalw<<2, (unsigned char *)pSaIBigBuff,finalw,finalh); + RGB2YUV( (uint32_t*)pSaIBigBuff, finalw, finalh, (uint32_t*)shminfo.shmaddr); + } + } else if(iUseNoStretchBlt==0 || finalw > 320 || finalh > 256) { + BlitScreen32((unsigned char *)shminfo.shmaddr, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); + } else { + BlitScreen32((unsigned char *)pBackBuffer, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); + p2XSaIFunc(pBackBuffer, finalw<<2, (unsigned char *)shminfo.shmaddr,finalw,finalh); + } + + XGetGeometry(display, window, &_dw, (int *)&_d, (int *)&_d, &_w, &_h, &_d, &_d); + if (use_yuv) { + xvi = XvShmCreateImage(display, yuv_port, yuv_id, 0, finalw, finalh, &shminfo); + } else + xvi = XvShmCreateImage(display, xv_port, xv_id, 0, finalw, finalh, &shminfo); + + xvi->data = shminfo.shmaddr; + + screen=DefaultScreenOfDisplay(display); + //screennum = DefaultScreen(display); + + if (!iWindowMode) { + _w = screen->width; + _h = screen->height; + } + + dstx = 0; + dsty = 0; + + if (iMaintainAspect) + MaintainAspect(&dstx, &dsty, &_w, &_h); + + if (ulKeybits&KEY_SHOWFPS) //to avoid flicker, don't paint overtop FPS bar + { + srcy = 15 * finalh / _h; + dsty += 15; + } + + XvShmPutImage(display, xv_port, window, hGC, xvi, + 0,srcy, //src x,y + finalw,finalh, //src w,h + dstx,dsty, //dst x,y + _w,_h, //dst w,h + 1 + ); + + if(ulKeybits&KEY_SHOWFPS) //DisplayText(); // paint menu text + { + if(szDebugText[0] && ((time(NULL) - tStart) < 2)) + { + strcpy(szDispBuf,szDebugText); + } + else + { + szDebugText[0]=0; + strcat(szDispBuf,szMenuBuf); + } + + //XPutImage(display,window,hGC, XFimage, + // 0, 0, 0, 0, 220,15); + XFree(xvi); + xvi = XvCreateImage(display, xv_port, xv_id, XFimage->data, 220, 15); + XvPutImage(display, xv_port, window, hGC, xvi, + 0,0, //src x,y + 220,15, //src w,h + 0,0, //dst x,y + 220,15 //dst w,h + ); + + XDrawString(display,window,hGC,2,13,szDispBuf,strlen(szDispBuf)); + } + + //if(XPimage) DisplayPic(); + + + XFree(xvi); +} + +void DoClearScreenBuffer(void) // CLEAR DX BUFFER +{ + Window _dw; + unsigned int _d, _w, _h; //don't care about _d + + XGetGeometry(display, window, &_dw, (int *)&_d, (int *)&_d, &_w, &_h, &_d, &_d); + + XvPutImage(display, xv_port, window, hGC, XCimage, + 0, 0, 8, 8, 0, 0, _w, _h); + //XSync(display,False); +} + +void DoClearFrontBuffer(void) // CLEAR DX BUFFER +{/* + XPutImage(display,window,hGC, XCimage, + 0, 0, 0, 0, iResX, iResY); + XSync(display,False);*/ +} + +int Xinitialize() +{ + iDesktopCol=32; + + + if(iUseNoStretchBlt>0) + { + pBackBuffer=(unsigned char *)malloc(640*512*sizeof(uint32_t)); + memset(pBackBuffer,0,640*512*sizeof(uint32_t)); + if (use_yuv) { + pSaIBigBuff=malloc(640*512*4*3*3); + memset(pSaIBigBuff,0,640*512*4*3*3); + } + } + + p2XSaIFunc=NULL; + + if(iUseNoStretchBlt==1) + { + p2XSaIFunc=Std2xSaI_ex8; + } + + if(iUseNoStretchBlt==2) + { + p2XSaIFunc=Super2xSaI_ex8; + } + + if(iUseNoStretchBlt==3) + { + p2XSaIFunc=SuperEagle_ex8; + } + + if(iUseNoStretchBlt==4) + { + p2XSaIFunc=Scale2x_ex8; + } + if(iUseNoStretchBlt==5) + { + p2XSaIFunc=Scale3x_ex8; + } + if(iUseNoStretchBlt==6) + { + p2XSaIFunc=hq2x_32; + } + if(iUseNoStretchBlt==7) + { + p2XSaIFunc=hq3x_32; + } + + bUsingTWin=FALSE; + + InitMenu(); + + bIsFirstFrame = FALSE; // done + + if(iShowFPS) + { + iShowFPS=0; + ulKeybits|=KEY_SHOWFPS; + szDispBuf[0]=0; + BuildDispMenu(0); + } + + return 0; +} + +void Xcleanup() // X CLEANUP +{ + CloseMenu(); + + if(iUseNoStretchBlt>0) + { + if(pBackBuffer) free(pBackBuffer); + pBackBuffer=0; + if(pSaIBigBuff) free(pSaIBigBuff); + pSaIBigBuff=0; + } +} + +unsigned long ulInitDisplay(void) +{ + CreateDisplay(); // x stuff + Xinitialize(); // init x + return (unsigned long)display; +} + +void CloseDisplay(void) +{ + Xcleanup(); // cleanup dx + DestroyDisplay(); +} + +void CreatePic(unsigned char * pMem) +{ + unsigned char * p=(unsigned char *)malloc(128*96*4); + unsigned char * ps; int x,y; + + ps=p; + + if(iDesktopCol==16) + { + unsigned short s; + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + s=(*(pMem+0))>>3; + s|=((*(pMem+1))&0xfc)<<3; + s|=((*(pMem+2))&0xf8)<<8; + pMem+=3; + *((unsigned short *)(ps+y*256+x*2))=s; + } + } + } + else + if(iDesktopCol==15) + { + unsigned short s; + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + s=(*(pMem+0))>>3; + s|=((*(pMem+1))&0xfc)<<2; + s|=((*(pMem+2))&0xf8)<<7; + pMem+=3; + *((unsigned short *)(ps+y*256+x*2))=s; + } + } + } + else + if(iDesktopCol==32) + { + uint32_t l; + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + l= *(pMem+0); + l|=(*(pMem+1))<<8; + l|=(*(pMem+2))<<16; + pMem+=3; + *((uint32_t *)(ps+y*512+x*4))=l; + } + } + } + + XPimage = XCreateImage(display,myvisual->visual, + depth, ZPixmap, 0, + (char *)p, + 128, 96, + depth>16 ? 32 : 16, + 0); +} + +void DestroyPic(void) +{ + if(XPimage) + { /* + XPutImage(display,window,hGC, XCimage, + 0, 0, 0, 0, iResX, iResY);*/ + XDestroyImage(XPimage); + XPimage=0; + } +} + +void DisplayPic(void) +{ + XPutImage(display,window,hGC, XPimage, + 0, 0, iResX-128, 0,128,96); +} + +void ShowGpuPic(void) +{ +} + +void ShowTextGpuPic(void) +{ +} + +static void hq2x_32_def(uint32_t * dst0, uint32_t * dst1, const uint32_t * src0, const uint32_t * src1, const uint32_t * src2, unsigned count) +{ + static unsigned char cache_vert_mask[640]; + unsigned char cache_horiz_mask = 0; + + unsigned i; + unsigned char mask; + uint32_t c[9]; + + if (src0 == src1) //processing first row + memset(cache_vert_mask, 0, count); + + for(i=0;i<count;++i) { + c[1] = src0[0]; + c[4] = src1[0]; + c[7] = src2[0]; + + if (i>0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i<count-1) { + c[2] = src0[1]; + c[5] = src1[1]; + c[8] = src2[1]; + } else { + c[2] = c[1]; + c[5] = c[4]; + c[8] = c[7]; + } + + mask = 0; + + mask |= interp_32_diff(c[0], c[4]) << 0; + mask |= cache_vert_mask[i]; + mask |= interp_32_diff(c[2], c[4]) << 2; + mask |= cache_horiz_mask; + cache_horiz_mask = interp_32_diff(c[5], c[4]) << 3; + mask |= cache_horiz_mask << 1; // << 3 << 1 == << 4 + mask |= interp_32_diff(c[6], c[4]) << 5; + cache_vert_mask[i] = interp_32_diff(c[7], c[4]) << 1; + mask |= cache_vert_mask[i] << 5; // << 1 << 5 == << 6 + mask |= interp_32_diff(c[8], c[4]) << 7; + + + switch (mask) { +#include "hq2x.h" + } + + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 2; + dst1 += 2; + } +} + +void hq2x_32( unsigned char * srcPtr, DWORD srcPitch, unsigned char * dstPtr, int width, int height) +{ + const int dstPitch = srcPitch<<1; + + int count = height; + + finalw=width*2; + finalh=height*2; + + uint32_t *dst0 = (uint32_t *)dstPtr; + uint32_t *dst1 = dst0 + (dstPitch >> 2); + + uint32_t *src0 = (uint32_t *)srcPtr; + uint32_t *src1 = src0 + (srcPitch >> 2); + uint32_t *src2 = src1 + (srcPitch >> 2); + hq2x_32_def(dst0, dst1, src0, src0, src1, width); + + + count -= 2; + while(count) { + dst0 += dstPitch >> 1; //next 2 lines (dstPitch / 4 char per int * 2) + dst1 += dstPitch >> 1; + hq2x_32_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2x_32_def(dst0, dst1, src0, src1, src1, width); +} + +static void hq3x_32_def(uint32_t* dst0, uint32_t* dst1, uint32_t* dst2, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count) +{ + static unsigned char cache_vert_mask[640]; + unsigned char cache_horiz_mask = 0; + + unsigned i; + unsigned char mask; + uint32_t c[9]; + + if (src0 == src1) //processing first row + memset(cache_vert_mask, 0, count); + + for(i=0;i<count;++i) { + c[1] = src0[0]; + c[4] = src1[0]; + c[7] = src2[0]; + + if (i>0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i<count-1) { + c[2] = src0[1]; + c[5] = src1[1]; + c[8] = src2[1]; + } else { + c[2] = c[1]; + c[5] = c[4]; + c[8] = c[7]; + } + + mask = 0; + + mask |= interp_32_diff(c[0], c[4]) << 0; + mask |= cache_vert_mask[i]; + mask |= interp_32_diff(c[2], c[4]) << 2; + mask |= cache_horiz_mask; + cache_horiz_mask = interp_32_diff(c[5], c[4]) << 3; + mask |= cache_horiz_mask << 1; // << 3 << 1 == << 4 + mask |= interp_32_diff(c[6], c[4]) << 5; + cache_vert_mask[i] = interp_32_diff(c[7], c[4]) << 1; + mask |= cache_vert_mask[i] << 5; // << 1 << 5 == << 6 + mask |= interp_32_diff(c[8], c[4]) << 7; + + switch (mask) { +#include "hq3x.h" + } + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 3; + dst1 += 3; + dst2 += 3; + } +} + +void hq3x_32( unsigned char * srcPtr, DWORD srcPitch, unsigned char * dstPtr, int width, int height) +{ + int count = height; + + int dstPitch = srcPitch*3; + int dstRowPixels = dstPitch>>2; + + finalw=width*3; + finalh=height*3; + + uint32_t *dst0 = (uint32_t *)dstPtr; + uint32_t *dst1 = dst0 + dstRowPixels; + uint32_t *dst2 = dst1 + dstRowPixels; + + uint32_t *src0 = (uint32_t *)srcPtr; + uint32_t *src1 = src0 + (srcPitch >> 2); + uint32_t *src2 = src1 + (srcPitch >> 2); + hq3x_32_def(dst0, dst1, dst2, src0, src0, src2, width); + + count -= 2; + while(count) { + dst0 += dstRowPixels * 3; + dst1 += dstRowPixels * 3; + dst2 += dstRowPixels * 3; + + hq3x_32_def(dst0, dst1, dst2, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstRowPixels * 3; + dst1 += dstRowPixels * 3; + dst2 += dstRowPixels * 3; + + hq3x_32_def(dst0, dst1, dst2, src0, src1, src1, width); + +} diff --git a/plugins/dfxvideo/draw.h b/plugins/dfxvideo/draw.h new file mode 100644 index 00000000..2454a1f4 --- /dev/null +++ b/plugins/dfxvideo/draw.h @@ -0,0 +1,46 @@ +/*************************************************************************** + draw.h - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#ifndef _GPU_DRAW_H_ +#define _GPU_DRAW_H_ + +void DoBufferSwap(void); +void DoClearScreenBuffer(void); +void DoClearFrontBuffer(void); +unsigned long ulInitDisplay(void); +void CloseDisplay(void); +void CreatePic(unsigned char * pMem); +void DestroyPic(void); +void DisplayPic(void); +void ShowGpuPic(void); +void ShowTextGpuPic(void); + +typedef struct { +#define MWM_HINTS_DECORATIONS 2 + long flags; + long functions; + long decorations; + long input_mode; +} MotifWmHints; + +#ifdef _WINDOWS +void MoveScanLineArea(HWND hwnd); +#endif + +/////////////////////////////////////////////////////////////////////// + +#endif // _GPU_DRAW_H_ diff --git a/plugins/dfxvideo/externals.h b/plugins/dfxvideo/externals.h new file mode 100644 index 00000000..3ef27236 --- /dev/null +++ b/plugins/dfxvideo/externals.h @@ -0,0 +1,314 @@ +/*************************************************************************** + externals.h - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define INFO_TW 0 +#define INFO_DRAWSTART 1 +#define INFO_DRAWEND 2 +#define INFO_DRAWOFF 3 + +#define SHADETEXBIT(x) ((x>>24) & 0x1) +#define SEMITRANSBIT(x) ((x>>25) & 0x1) +#define PSXRGB(r,g,b) ((g<<10)|(b<<5)|r) + +#define DATAREGISTERMODES unsigned short + +#define DR_NORMAL 0 +#define DR_VRAMTRANSFER 1 + + +#define GPUSTATUS_ODDLINES 0x80000000 +#define GPUSTATUS_DMABITS 0x60000000 // Two bits +#define GPUSTATUS_READYFORCOMMANDS 0x10000000 +#define GPUSTATUS_READYFORVRAM 0x08000000 +#define GPUSTATUS_IDLE 0x04000000 +#define GPUSTATUS_DISPLAYDISABLED 0x00800000 +#define GPUSTATUS_INTERLACED 0x00400000 +#define GPUSTATUS_RGB24 0x00200000 +#define GPUSTATUS_PAL 0x00100000 +#define GPUSTATUS_DOUBLEHEIGHT 0x00080000 +#define GPUSTATUS_WIDTHBITS 0x00070000 // Three bits +#define GPUSTATUS_MASKENABLED 0x00001000 +#define GPUSTATUS_MASKDRAWN 0x00000800 +#define GPUSTATUS_DRAWINGALLOWED 0x00000400 +#define GPUSTATUS_DITHER 0x00000200 + +#define GPUIsBusy (lGPUstatusRet &= ~GPUSTATUS_IDLE) +#define GPUIsIdle (lGPUstatusRet |= GPUSTATUS_IDLE) + +#define GPUIsNotReadyForCommands (lGPUstatusRet &= ~GPUSTATUS_READYFORCOMMANDS) +#define GPUIsReadyForCommands (lGPUstatusRet |= GPUSTATUS_READYFORCOMMANDS) + +#define __X11_C_ +//X11 render +#define __inline inline +#define CALLBACK + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +/*#include <GL/gl.h> +#include <GL/glx.h> */ +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <math.h> +#include <X11/cursorfont.h> +#include <stdint.h> + +///////////////////////////////////////////////////////////////////////////// + +typedef struct VRAMLOADTTAG +{ + short x; + short y; + short Width; + short Height; + short RowsRemaining; + short ColsRemaining; + unsigned short *ImagePtr; +} VRAMLoad_t; + +///////////////////////////////////////////////////////////////////////////// + +typedef struct PSXPOINTTAG +{ + int32_t x; + int32_t y; +} PSXPoint_t; + +typedef struct PSXSPOINTTAG +{ + short x; + short y; +} PSXSPoint_t; + +typedef struct PSXRECTTAG +{ + short x0; + short x1; + short y0; + short y1; +} PSXRect_t; + +// linux defines for some windows stuff + +#define FALSE 0 +#define TRUE 1 +#define BOOL unsigned short +#define LOWORD(l) ((unsigned short)(l)) +#define HIWORD(l) ((unsigned short)(((uint32_t)(l) >> 16) & 0xFFFF)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define DWORD uint32_t +#define __int64 long long int + +typedef struct RECTTAG +{ + int left; + int top; + int right; + int bottom; +}RECT; + + + +///////////////////////////////////////////////////////////////////////////// + +typedef struct TWINTAG +{ + PSXRect_t Position; +} TWin_t; + +///////////////////////////////////////////////////////////////////////////// + +typedef struct PSXDISPLAYTAG +{ + PSXPoint_t DisplayModeNew; + PSXPoint_t DisplayMode; + PSXPoint_t DisplayPosition; + PSXPoint_t DisplayEnd; + + int32_t Double; + int32_t Height; + int32_t PAL; + int32_t InterlacedNew; + int32_t Interlaced; + int32_t RGB24New; + int32_t RGB24; + PSXSPoint_t DrawOffset; + int32_t Disabled; + PSXRect_t Range; + +} PSXDisplay_t; + +///////////////////////////////////////////////////////////////////////////// + +// draw.c + +#ifndef _IN_DRAW + +extern char * pCaptionText; + +extern int iResX; +extern int iResY; +extern int32_t GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP; +extern int32_t GlobalTextREST,GlobalTextABR,GlobalTextPAGE; +extern short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3; +extern long lLowerpart; +extern BOOL bIsFirstFrame; +extern int iWinSize; +extern BOOL bCheckMask; +extern unsigned short sSetMask; +extern unsigned long lSetMask; +extern BOOL bDeviceOK; +extern short g_m1; +extern short g_m2; +extern short g_m3; +extern short DrawSemiTrans; +extern int iUseGammaVal; +extern int iMaintainAspect; +extern int iDesktopCol; +extern int iUseNoStretchBlt; +extern int iShowFPS; +extern int iFastFwd; +extern int iDebugMode; +extern int iFVDisplay; +extern PSXPoint_t ptCursorPoint[]; +extern unsigned short usCursorActive; + + +#endif + +// prim.c + +#ifndef _IN_PRIMDRAW + +extern BOOL bUsingTWin; +extern TWin_t TWin; +//extern unsigned long clutid; +extern void (*primTableJ[256])(unsigned char *); +extern void (*primTableSkip[256])(unsigned char *); +extern unsigned short usMirror; +extern int iDither; +extern uint32_t dwCfgFixes; +extern uint32_t dwActFixes; +extern int iUseFixes; +extern int iUseDither; +extern BOOL bDoVSyncUpdate; +extern int32_t drawX; +extern int32_t drawY; +extern int32_t drawW; +extern int32_t drawH; + +#endif + +// gpu.c + +#ifndef _IN_GPU + +extern VRAMLoad_t VRAMWrite; +extern VRAMLoad_t VRAMRead; +extern DATAREGISTERMODES DataWriteMode; +extern DATAREGISTERMODES DataReadMode; +extern int iColDepth; +extern int iWindowMode; +extern char szDispBuf[]; +extern char szMenuBuf[]; +extern char szDebugText[]; +extern short sDispWidths[]; +extern BOOL bDebugText; +//extern unsigned int iMaxDMACommandCounter; +//extern unsigned long dwDMAChainStop; +extern PSXDisplay_t PSXDisplay; +extern PSXDisplay_t PreviousPSXDisplay; +extern BOOL bSkipNextFrame; +extern long lGPUstatusRet; +//extern long drawingLines; +extern unsigned char * psxVSecure; +extern unsigned char * psxVub; +extern signed char * psxVsb; +extern unsigned short * psxVuw; +extern signed short * psxVsw; +extern uint32_t * psxVul; +extern int32_t * psxVsl; +extern unsigned short * psxVuw_eom; +extern BOOL bChangeWinMode; +extern long lSelectedSlot; +extern BOOL bInitCap; +extern DWORD dwLaceCnt; +extern uint32_t lGPUInfoVals[]; +extern uint32_t ulStatusControl[]; + +#endif + +// menu.c + +#ifndef _IN_MENU + +extern uint32_t dwCoreFlags; + +#endif + +// key.c + +#ifndef _IN_KEY + +extern unsigned long ulKeybits; + +#endif + +// fps.c + +#ifndef _IN_FPS + +extern int UseFrameLimit; +extern int UseFrameSkip; +extern float fFrameRate; +extern int iFrameLimit; +extern float fFrameRateHz; +extern float fps_skip; +extern float fps_cur; + +#endif + +// key.c + +#ifndef _IN_KEY + +#endif + +// cfg.c + +#ifndef _IN_CFG + +extern char * pConfigFile; + +#endif + +// zn.c + +#ifndef _IN_ZN + +extern uint32_t dwGPUVersion; +extern int iGPUHeight; +extern int iGPUHeightMask; +extern int GlobalTextIL; +extern int iTileCheat; + +#endif + + diff --git a/plugins/dfxvideo/fps.c b/plugins/dfxvideo/fps.c new file mode 100644 index 00000000..2edcd30b --- /dev/null +++ b/plugins/dfxvideo/fps.c @@ -0,0 +1,357 @@ +/*************************************************************************** + fps.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define _IN_FPS + +#include <unistd.h> + +#include "externals.h" +#include "fps.h" +#include "gpu.h" + +// FPS stuff +float fFrameRateHz=0; +DWORD dwFrameRateTicks=16; +float fFrameRate; +int iFrameLimit; +int UseFrameLimit=0; +int UseFrameSkip=0; + +// FPS skipping / limit +BOOL bInitCap = TRUE; +float fps_skip = 0; +float fps_cur = 0; + +#define MAXLACE 16 + +void CheckFrameRate(void) +{ + if(UseFrameSkip) // skipping mode? + { + if(!(dwActFixes&0x80)) // not old skipping mode? + { + dwLaceCnt++; // -> store cnt of vsync between frames + if(dwLaceCnt>=MAXLACE && UseFrameLimit) // -> if there are many laces without screen toggling, + { // do std frame limitation + if(dwLaceCnt==MAXLACE) bInitCap=TRUE; + FrameCap(); + } + } + else if(UseFrameLimit) FrameCap(); + calcfps(); // -> calc fps display in skipping mode + } + else // non-skipping mode: + { + if(UseFrameLimit) FrameCap(); // -> do it + if(ulKeybits&KEY_SHOWFPS) calcfps(); // -> and calc fps display + } +} + +#define TIMEBASE 100000 + +unsigned long timeGetTime() +{ + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return tv.tv_sec * 100000 + tv.tv_usec/10; // to do that, but at least it works +} + +void FrameCap (void) +{ + static unsigned long curticks, lastticks, _ticks_since_last_update; + static unsigned int TicksToWait = 0; + int overslept=0, tickstogo=0; + BOOL Waiting = TRUE; + + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + if((_ticks_since_last_update > TicksToWait) || + (curticks <lastticks)) + { + lastticks = curticks; + overslept = _ticks_since_last_update - TicksToWait; + if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks) + TicksToWait=0; + else + TicksToWait=dwFrameRateTicks - overslept; + } + else + { + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + tickstogo = TicksToWait - _ticks_since_last_update; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks) || tickstogo < overslept) + { + Waiting = FALSE; + lastticks = curticks; + overslept = _ticks_since_last_update - TicksToWait; + TicksToWait = dwFrameRateTicks - overslept; + return; + } + if (tickstogo >= 200 && !(dwActFixes&16)) + usleep(tickstogo*10 - 200); + } + } + } +} + +#define MAXSKIP 120 + +void FrameSkip(void) +{ + static int iNumSkips=0,iAdditionalSkip=0; // number of additional frames to skip + static DWORD dwLastLace=0; // helper var for frame limitation + static DWORD curticks, lastticks, _ticks_since_last_update; + int tickstogo=0; + static int overslept=0; + + if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely + + if(iNumSkips) // we are in skipping mode? + { + dwLastLace+=dwLaceCnt; // -> calc frame limit helper (number of laces) + bSkipNextFrame = TRUE; // -> we skip next frame + iNumSkips--; // -> ok, one done + } + else // ok, no additional skipping has to be done... + { // we check now, if some limitation is needed, or a new skipping has to get started + DWORD dwWaitTime; + + if(bInitCap || bSkipNextFrame) // first time or we skipped before? + { + if(UseFrameLimit && !bInitCap) // frame limit wanted and not first time called? + { + DWORD dwT=_ticks_since_last_update; // -> that's the time of the last drawn frame + dwLastLace+=dwLaceCnt; // -> and that's the number of updatelace since the start of the last drawn frame + + curticks = timeGetTime(); // -> now we calc the time of the last drawn frame + the time we spent skipping + _ticks_since_last_update= dwT+curticks - lastticks; + + dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed + + if(_ticks_since_last_update<dwWaitTime) // -> we were too fast? + { + if((dwWaitTime-_ticks_since_last_update)> // -> some more security, to prevent + (60*dwFrameRateTicks)) // wrong waiting times + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update<dwWaitTime) // -> loop until we have reached the real psx time + { // (that's the additional limitation, yup) + curticks = timeGetTime(); + _ticks_since_last_update = dwT+curticks - lastticks; + } + } + else // we were still too slow ?!!? + { + if(iAdditionalSkip<MAXSKIP) // -> well, somewhen we really have to stop skipping on very slow systems + { + iAdditionalSkip++; // -> inc our watchdog var + dwLaceCnt=0; // -> reset lace count + lastticks = timeGetTime(); + return; // -> done, we will skip next frame to get more speed + } + } + } + + bInitCap=FALSE; // -> ok, we have inited the frameskip func + iAdditionalSkip=0; // -> init additional skip + bSkipNextFrame=FALSE; // -> we don't skip the next frame + lastticks = timeGetTime(); // -> we store the start time of the next frame + dwLaceCnt=0; // -> and we start to count the laces + dwLastLace=0; + _ticks_since_last_update=0; + return; // -> done, the next frame will get drawn + } + + bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first + + curticks = timeGetTime(); // get the current time (we are now at the end of one drawn frame) + _ticks_since_last_update = curticks - lastticks; + + dwLastLace=dwLaceCnt; // store curr count (frame limitation helper) + dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time' + if (dwWaitTime >= overslept) + dwWaitTime-=overslept; + + if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame... + { + if(UseFrameLimit) // if limitation, we skip just next frame, + { // and decide after, if we need to do more + iNumSkips=0; + } + else + { + iNumSkips=_ticks_since_last_update/dwWaitTime; // -> calc number of frames to skip to catch up + iNumSkips--; // -> since we already skip next frame, one down + if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP; // -> well, somewhere we have to draw a line + } + bSkipNextFrame = TRUE; // -> signal for skipping the next frame + } + else // we were faster than real psx? fine :) + if(UseFrameLimit) // frame limit used? so we wait til the 'real psx time' has been reached + { + if(dwLaceCnt>MAXLACE) // -> security check + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update<dwWaitTime) // -> just do a waiting loop... + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + tickstogo = dwWaitTime - _ticks_since_last_update; + if (tickstogo-overslept >= 200 && !(dwActFixes&16)) + usleep(tickstogo*10 - 200); + } + } + overslept = _ticks_since_last_update - dwWaitTime; + if (overslept < 0) + overslept = 0; + lastticks = timeGetTime(); // ok, start time of the next frame + } + + dwLaceCnt=0; // init lace counter +} + +void calcfps(void) +{ + static unsigned long curticks,_ticks_since_last_update,lastticks; + static long fps_cnt = 0; + static unsigned long fps_tck = 1; + static long fpsskip_cnt = 0; + static unsigned long fpsskip_tck = 1; + + { + curticks = timeGetTime(); + _ticks_since_last_update=curticks-lastticks; + + if(UseFrameSkip && !UseFrameLimit && _ticks_since_last_update) + fps_skip=min(fps_skip,((float)TIMEBASE/(float)_ticks_since_last_update+1.0f)); + + lastticks = curticks; + } + + if(UseFrameSkip && UseFrameLimit) + { + fpsskip_tck += _ticks_since_last_update; + + if(++fpsskip_cnt==2) + { + fps_skip = (float)2000/(float)fpsskip_tck; + fps_skip +=6.0f; + fpsskip_cnt = 0; + fpsskip_tck = 1; + } + } + + fps_tck += _ticks_since_last_update; + + if(++fps_cnt==20) + { + fps_cur = (float)(TIMEBASE*20)/(float)fps_tck; + + fps_cnt = 0; + fps_tck = 1; + + //if(UseFrameLimit && fps_cur>fFrameRateHz) // optical adjust ;) avoids flickering fps display + //fps_cur=fFrameRateHz; + } + +} + +void PCFrameCap (void) +{ + static unsigned long curticks, lastticks, _ticks_since_last_update; + static unsigned long TicksToWait = 0; + BOOL Waiting = TRUE; + + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = (TIMEBASE/ (unsigned long)fFrameRateHz); + } + } +} + +void PCcalcfps(void) +{ + static unsigned long curticks,_ticks_since_last_update,lastticks; + static long fps_cnt = 0; + static float fps_acc = 0; + float CurrentFPS=0; + + curticks = timeGetTime(); + _ticks_since_last_update=curticks-lastticks; + if(_ticks_since_last_update) + CurrentFPS=(float)TIMEBASE/(float)_ticks_since_last_update; + else CurrentFPS = 0; + lastticks = curticks; + + fps_acc += CurrentFPS; + + if(++fps_cnt==10) + { + fps_cur = fps_acc / 10; + fps_acc = 0; + fps_cnt = 0; + } + + fps_skip=CurrentFPS+1.0f; +} + +void SetAutoFrameCap(void) +{ + if(iFrameLimit==1) + { + fFrameRateHz = fFrameRate; + dwFrameRateTicks=(TIMEBASE*100 / (unsigned long)(fFrameRateHz*100)); + return; + } + + if(dwActFixes&32) + { + if (PSXDisplay.Interlaced) + fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f; + else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f; + } + else + { + fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f; + dwFrameRateTicks=(TIMEBASE*100 / (unsigned long)(fFrameRateHz*100)); + } +} + +void SetFPSHandler(void) +{ +} + +void InitFPS(void) +{ + if(!fFrameRate) fFrameRate=200.0f; + if(fFrameRateHz==0) fFrameRateHz=fFrameRate; // set user framerate + dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); +} diff --git a/plugins/dfxvideo/fps.h b/plugins/dfxvideo/fps.h new file mode 100644 index 00000000..ff7e72b0 --- /dev/null +++ b/plugins/dfxvideo/fps.h @@ -0,0 +1,31 @@ +/***************************************************************************
+ fps.h - description
+ -------------------
+ begin : Sun Oct 28 2001
+ copyright : (C) 2001 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#ifndef _FPS_INTERNALS_H
+#define _FPS_INTERNALS_H
+
+void FrameCap(void);
+void FrameSkip(void);
+void calcfps(void);
+void PCFrameCap (void);
+void PCcalcfps(void);
+void SetAutoFrameCap(void);
+void SetFPSHandler(void);
+void InitFPS(void);
+void CheckFrameRate(void);
+
+#endif // _FPS_INTERNALS_H
diff --git a/plugins/dfxvideo/gpu.c b/plugins/dfxvideo/gpu.c new file mode 100644 index 00000000..33a83213 --- /dev/null +++ b/plugins/dfxvideo/gpu.c @@ -0,0 +1,1907 @@ +/*************************************************************************** + gpu.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define _IN_GPU + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "cfg.h" +#include "prim.h" +#include "stdint.h" +#include "psemu_plugin_defs.h" +#include "menu.h" +#include "key.h" +#include "fps.h" +#include "swap.h" + +//////////////////////////////////////////////////////////////////////// +// PPDK developer must change libraryName field and can change revision and build +//////////////////////////////////////////////////////////////////////// + +const unsigned char version = 1; // do not touch - library for PSEmu 1.x +const unsigned char revision = 1; +const unsigned char build = 17; // increase that with each version + +static char *libraryName = "XVideo Driver"; +static char *libraryInfo = "P.E.Op.S. Xvideo Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n"; + +static char *PluginAuthor = "Pete Bernert and the P.E.Op.S. team"; + +//////////////////////////////////////////////////////////////////////// +// memory image of the PSX vram +//////////////////////////////////////////////////////////////////////// + +unsigned char *psxVSecure; +unsigned char *psxVub; +signed char *psxVsb; +unsigned short *psxVuw; +unsigned short *psxVuw_eom; +signed short *psxVsw; +uint32_t *psxVul; +int32_t *psxVsl; + +//////////////////////////////////////////////////////////////////////// +// GPU globals +//////////////////////////////////////////////////////////////////////// + +static long lGPUdataRet; +long lGPUstatusRet; +char szDispBuf[64]; +char szMenuBuf[36]; +char szDebugText[512]; +uint32_t ulStatusControl[256]; + +static uint32_t gpuDataM[256]; +static unsigned char gpuCommand = 0; +static long gpuDataC = 0; +static long gpuDataP = 0; + +VRAMLoad_t VRAMWrite; +VRAMLoad_t VRAMRead; +DATAREGISTERMODES DataWriteMode; +DATAREGISTERMODES DataReadMode; + +BOOL bSkipNextFrame = FALSE; +DWORD dwLaceCnt=0; +int iColDepth; +int iWindowMode; +short sDispWidths[8] = {256,320,512,640,368,384,512,640}; +PSXDisplay_t PSXDisplay; +PSXDisplay_t PreviousPSXDisplay; +long lSelectedSlot=0; +BOOL bChangeWinMode=FALSE; +BOOL bDoLazyUpdate=FALSE; +uint32_t lGPUInfoVals[16]; + +//////////////////////////////////////////////////////////////////////// +// some misc external display funcs +//////////////////////////////////////////////////////////////////////// + +#include <time.h> +time_t tStart; + +void CALLBACK GPUdisplayText(char * pText) // some debug func +{ + if(!pText) {szDebugText[0]=0;return;} + if(strlen(pText)>511) return; + time(&tStart); + strcpy(szDebugText,pText); +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUdisplayFlags(unsigned long dwFlags) // some info func +{ + dwCoreFlags=dwFlags; + BuildDispMenu(0); +} + +//////////////////////////////////////////////////////////////////////// +// stuff to make this a true PDK module +//////////////////////////////////////////////////////////////////////// + +char * CALLBACK PSEgetLibName(void) +{ + return libraryName; +} + +unsigned long CALLBACK PSEgetLibType(void) +{ + return PSE_LT_GPU; +} + +unsigned long CALLBACK PSEgetLibVersion(void) +{ + return version<<16|revision<<8|build; +} + +char * GPUgetLibInfos(void) +{ + return libraryInfo; +} + +//////////////////////////////////////////////////////////////////////// +// Snapshot func +//////////////////////////////////////////////////////////////////////// + +static char * pGetConfigInfos(int iCfg) +{ + char szO[2][4]={"off","on "}; + char szTxt[256]; + char * pB = (char *)malloc(32767); + + if (!pB) return NULL; + *pB = 0; + //----------------------------------------------------// + sprintf(szTxt,"Plugin: %s %d.%d.%d\r\n",libraryName,version,revision,build); + strcat(pB,szTxt); + sprintf(szTxt,"Author: %s\r\n\r\n",PluginAuthor); + strcat(pB,szTxt); + //----------------------------------------------------// + if(iCfg && iWindowMode) + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize)); + else + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY); + strcat(pB,szTxt); + if(iWindowMode && iCfg) + strcpy(szTxt,"Window mode\r\n"); + else + if(iWindowMode) + sprintf(szTxt,"Window mode - [%d Bit]\r\n",iDesktopCol); + else + sprintf(szTxt,"Fullscreen - [%d Bit]\r\n",iColDepth); + strcat(pB,szTxt); + + sprintf(szTxt,"Stretch mode: %d\r\n",iUseNoStretchBlt); + strcat(pB,szTxt); + sprintf(szTxt,"Dither mode: %d\r\n\r\n",iUseDither); + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Framerate:\r\n- FPS limit: %s\r\n",szO[UseFrameLimit]); + strcat(pB,szTxt); + sprintf(szTxt,"- Frame skipping: %s",szO[UseFrameSkip]); + strcat(pB,szTxt); + if(iFastFwd) strcat(pB," (fast forward)"); + strcat(pB,"\r\n"); + if(iFrameLimit==2) + strcpy(szTxt,"- FPS limit: Auto\r\n\r\n"); + else sprintf(szTxt,"- FPS limit: %.1f\r\n\r\n",fFrameRate); + strcat(pB,szTxt); + //----------------------------------------------------// + strcpy(szTxt,"Misc:\r\n- MaintainAspect: "); + if(iMaintainAspect == 0) strcat(szTxt,"disabled"); + else + if(iMaintainAspect == 1) strcat(szTxt,"enabled"); + strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + sprintf(szTxt,"- Game fixes: %s [%08x]\r\n",szO[iUseFixes],dwCfgFixes); + strcat(pB,szTxt); + //----------------------------------------------------// + return pB; +} + +static void DoTextSnapShot(int iNum) +{ + FILE *txtfile; + char szTxt[256]; + char *pB; + + sprintf(szTxt,"%s/pcsx%04d.txt",getenv("HOME"),iNum); + + if ((txtfile = fopen(szTxt, "wb")) == NULL) + return; + + pB = pGetConfigInfos(0); + if (pB) + { + fwrite(pB, strlen(pB), 1, txtfile); + free(pB); + } + fclose(txtfile); +} + +void CALLBACK GPUmakeSnapshot(void) +{ + FILE *bmpfile; + char filename[256]; + unsigned char header[0x36]; + long size, height; + unsigned char line[1024 * 3]; + short i, j; + unsigned char empty[2] = {0,0}; + unsigned short color; + unsigned long snapshotnr = 0; + unsigned char *pD; + + height = PreviousPSXDisplay.DisplayMode.y; + + size = height * PreviousPSXDisplay.Range.x1 * 3 + 0x38; + + // fill in proper values for BMP + + // hardcoded BMP header + memset(header, 0, 0x36); + header[0] = 'B'; + header[1] = 'M'; + header[2] = size & 0xff; + header[3] = (size >> 8) & 0xff; + header[4] = (size >> 16) & 0xff; + header[5] = (size >> 24) & 0xff; + header[0x0a] = 0x36; + header[0x0e] = 0x28; + header[0x12] = PreviousPSXDisplay.Range.x1 % 256; + header[0x13] = PreviousPSXDisplay.Range.x1 / 256; + header[0x16] = height % 256; + header[0x17] = height / 256; + header[0x1a] = 0x01; + header[0x1c] = 0x18; + header[0x26] = 0x12; + header[0x27] = 0x0B; + header[0x2A] = 0x12; + header[0x2B] = 0x0B; + + // increment snapshot value & try to get filename + do + { + snapshotnr++; + sprintf(filename, "%s/pcsx%04ld.bmp", getenv("HOME"), snapshotnr); + + bmpfile = fopen(filename,"rb"); + if (bmpfile == NULL) + break; + + fclose(bmpfile); + } + while(TRUE); + + // try opening new snapshot file + if ((bmpfile = fopen(filename,"wb")) == NULL) + return; + + fwrite(header, 0x36, 1, bmpfile); + for (i = height + PSXDisplay.DisplayPosition.y - 1; i >= PSXDisplay.DisplayPosition.y; i--) + { + pD = (unsigned char *)&psxVuw[i * 1024 + PSXDisplay.DisplayPosition.x]; + for (j = 0; j < PreviousPSXDisplay.Range.x1; j++) + { + if (PSXDisplay.RGB24) + { + uint32_t lu = *(uint32_t *)pD; + line[j * 3 + 2] = RED(lu); + line[j * 3 + 1] = GREEN(lu); + line[j * 3 + 0] = BLUE(lu); + pD += 3; + } + else + { + color = GETLE16(pD); + line[j * 3 + 2] = (color << 3) & 0xf1; + line[j * 3 + 1] = (color >> 2) & 0xf1; + line[j * 3 + 0] = (color >> 7) & 0xf1; + pD += 2; + } + } + fwrite(line, PreviousPSXDisplay.Range.x1 * 3, 1, bmpfile); + } + fwrite(empty, 0x2, 1, bmpfile); + fclose(bmpfile); + + DoTextSnapShot(snapshotnr); +} + +//////////////////////////////////////////////////////////////////////// +// INIT, will be called after lib load... well, just do some var init... +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUinit() // GPU INIT +{ + memset(ulStatusControl,0,256*sizeof(uint32_t)); // init save state scontrol field + + szDebugText[0] = 0; // init debug text buffer + + psxVSecure = (unsigned char *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security + if (!psxVSecure) + return -1; + + //!!! ATTENTION !!! + psxVub=psxVSecure + 512 * 1024; // security offset into double sized psx vram! + + psxVsb=(signed char *)psxVub; // different ways of accessing PSX VRAM + psxVsw=(signed short *)psxVub; + psxVsl=(int32_t *)psxVub; + psxVuw=(unsigned short *)psxVub; + psxVul=(uint32_t *)psxVub; + + psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram + + memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024)); + memset(lGPUInfoVals,0x00,16*sizeof(uint32_t)); + + SetFPSHandler(); + + PSXDisplay.RGB24 = FALSE; // init some stuff + PSXDisplay.Interlaced = FALSE; + PSXDisplay.DrawOffset.x = 0; + PSXDisplay.DrawOffset.y = 0; + PSXDisplay.DisplayMode.x= 320; + PSXDisplay.DisplayMode.y= 240; + PreviousPSXDisplay.DisplayMode.x= 320; + PreviousPSXDisplay.DisplayMode.y= 240; + PSXDisplay.Disabled = FALSE; + PreviousPSXDisplay.Range.x0 =0; + PreviousPSXDisplay.Range.y0 =0; + PSXDisplay.Range.x0=0; + PSXDisplay.Range.x1=0; + PreviousPSXDisplay.DisplayModeNew.y=0; + PSXDisplay.Double = 1; + lGPUdataRet = 0x400; + + DataWriteMode = DR_NORMAL; + + // Reset transfer values, to prevent mis-transfer of data + memset(&VRAMWrite, 0, sizeof(VRAMLoad_t)); + memset(&VRAMRead, 0, sizeof(VRAMLoad_t)); + + // device initialised already ! + lGPUstatusRet = 0x14802000; + GPUIsIdle; + GPUIsReadyForCommands; + bDoVSyncUpdate = TRUE; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// Here starts all... +//////////////////////////////////////////////////////////////////////// + + +long GPUopen(unsigned long * disp,char * CapText,char * CfgFile) +{ + unsigned long d; + + pCaptionText=CapText; + + + ReadConfig(); // read registry + + InitFPS(); + + bIsFirstFrame = TRUE; // we have to init later + bDoVSyncUpdate = TRUE; + + d=ulInitDisplay(); // setup x + + if(disp) + *disp=d; // wanna x pointer? ok + + if(d) return 0; + return -1; +} + + +//////////////////////////////////////////////////////////////////////// +// time to leave... +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUclose() // GPU CLOSE +{ + + ReleaseKeyHandler(); // de-subclass window + + CloseDisplay(); // shutdown direct draw + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// I shot the sheriff +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUshutdown() // GPU SHUTDOWN +{ + free(psxVSecure); + + return 0; // nothinh to do +} + +//////////////////////////////////////////////////////////////////////// +// Update display (swap buffers) +//////////////////////////////////////////////////////////////////////// + +void updateDisplay(void) // UPDATE DISPLAY +{ + if(PSXDisplay.Disabled) // disable? + { + DoClearFrontBuffer(); // -> clear frontbuffer + return; // -> and bye + } + + if(dwActFixes&32) // pc fps calculation fix + { + if(UseFrameLimit) PCFrameCap(); // -> brake + if(UseFrameSkip || ulKeybits&KEY_SHOWFPS) + PCcalcfps(); + } + + if(ulKeybits&KEY_SHOWFPS) // make fps display buf + { + sprintf(szDispBuf,"FPS %06.1f",fps_cur); + } + + if(iFastFwd) // fastfwd ? + { + static int fpscount; UseFrameSkip=1; + + if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip + if(fpscount%6) // -> skip 6/7 frames + bSkipNextFrame = TRUE; + else bSkipNextFrame = FALSE; + fpscount++; + if(fpscount >= (int)fFrameRateHz) fpscount = 0; + return; + } + + if(UseFrameSkip) // skip ? + { + if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip + if(dwActFixes&0xa0) // -> pc fps calculation fix/old skipping fix + { + if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) // -> skip max one in a row + {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;} + else bSkipNextFrame = FALSE; + } + else FrameSkip(); + } + else // no skip ? + { + DoBufferSwap(); // -> swap + } +} + +//////////////////////////////////////////////////////////////////////// +// roughly emulated screen centering bits... not complete !!! +//////////////////////////////////////////////////////////////////////// + +void ChangeDispOffsetsX(void) // X CENTER +{ + long lx,l; + + if(!PSXDisplay.Range.x1) return; + + l=PreviousPSXDisplay.DisplayMode.x; + + l*=(long)PSXDisplay.Range.x1; + l/=2560;lx=l;l&=0xfffffff8; + + if(l==PreviousPSXDisplay.Range.y1) return; // abusing range.y1 for + PreviousPSXDisplay.Range.y1=(short)l; // storing last x range and test + + if(lx>=PreviousPSXDisplay.DisplayMode.x) + { + PreviousPSXDisplay.Range.x1= + (short)PreviousPSXDisplay.DisplayMode.x; + PreviousPSXDisplay.Range.x0=0; + } + else + { + PreviousPSXDisplay.Range.x1=(short)l; + + PreviousPSXDisplay.Range.x0= + (PSXDisplay.Range.x0-500)/8; + + if(PreviousPSXDisplay.Range.x0<0) + PreviousPSXDisplay.Range.x0=0; + + if((PreviousPSXDisplay.Range.x0+lx)> + PreviousPSXDisplay.DisplayMode.x) + { + PreviousPSXDisplay.Range.x0= + (short)(PreviousPSXDisplay.DisplayMode.x-lx); + PreviousPSXDisplay.Range.x0+=2; //??? + + PreviousPSXDisplay.Range.x1+=(short)(lx-l); + + PreviousPSXDisplay.Range.x1-=2; // makes linux stretching easier + + } + + + // some linux alignment security + PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0>>1; + PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0<<1; + PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1>>1; + PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1<<1; + + + DoClearScreenBuffer(); + } + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void ChangeDispOffsetsY(void) // Y CENTER +{ + int iT,iO=PreviousPSXDisplay.Range.y0; + int iOldYOffset=PreviousPSXDisplay.DisplayModeNew.y; + +// new + + if((PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)>iGPUHeight) + { + int dy1=iGPUHeight-PreviousPSXDisplay.DisplayModeNew.x; + int dy2=(PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)-iGPUHeight; + + if(dy1>=dy2) + { + PreviousPSXDisplay.DisplayModeNew.y=-dy2; + } + else + { + PSXDisplay.DisplayPosition.y=0; + PreviousPSXDisplay.DisplayModeNew.y=-dy1; + } + } + else PreviousPSXDisplay.DisplayModeNew.y=0; + +// eon + + if(PreviousPSXDisplay.DisplayModeNew.y!=iOldYOffset) // if old offset!=new offset: recalc height + { + PSXDisplay.Height = PSXDisplay.Range.y1 - + PSXDisplay.Range.y0 + + PreviousPSXDisplay.DisplayModeNew.y; + PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; + } + +// + + if(PSXDisplay.PAL) iT=48; else iT=28; + + if(PSXDisplay.Range.y0>=iT) + { + PreviousPSXDisplay.Range.y0= + (short)((PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double); + if(PreviousPSXDisplay.Range.y0<0) + PreviousPSXDisplay.Range.y0=0; + PSXDisplay.DisplayModeNew.y+= + PreviousPSXDisplay.Range.y0; + } + else + PreviousPSXDisplay.Range.y0=0; + + if(iO!=PreviousPSXDisplay.Range.y0) + { + DoClearScreenBuffer(); + } +} + +//////////////////////////////////////////////////////////////////////// +// check if update needed +//////////////////////////////////////////////////////////////////////// + +void updateDisplayIfChanged(void) // UPDATE DISPLAY IF CHANGED +{ + if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) && + (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x)) + { + if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) && + (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew)) return; + } + + PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos + + PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y; + PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x; + PreviousPSXDisplay.DisplayMode.x= // previous will hold + min(640,PSXDisplay.DisplayMode.x); // max 640x512... that's + PreviousPSXDisplay.DisplayMode.y= // the size of my + min(512,PSXDisplay.DisplayMode.y); // back buffer surface + PSXDisplay.Interlaced = PSXDisplay.InterlacedNew; + + PSXDisplay.DisplayEnd.x= // calc end of display + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + ChangeDispOffsetsX(); + + if(iFrameLimit==2) SetAutoFrameCap(); // -> set it + + if(UseFrameSkip) updateDisplay(); // stupid stuff when frame skipping enabled +} + +//////////////////////////////////////////////////////////////////////// + +#include "draw.h" + +void ChangeWindowMode(void) // TOGGLE FULLSCREEN - WINDOW +{ + extern Display *display; + extern Window window; + extern int root_window_id; + Screen *screen; + XSizeHints hints; + MotifWmHints mwmhints; + Atom mwmatom; + + screen=DefaultScreenOfDisplay(display); + iWindowMode=!iWindowMode; + + if(!iWindowMode) // fullscreen + { + mwmhints.flags=MWM_HINTS_DECORATIONS; + mwmhints.functions=0; + mwmhints.decorations=0; + mwmhints.input_mode=0; + mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0); + XChangeProperty(display,window,mwmatom,mwmatom,32, + PropModeReplace,(unsigned char *)&mwmhints,5); + + XResizeWindow(display,window,screen->width,screen->height); + + hints.min_width = hints.max_width = hints.base_width = screen->width; + hints.min_height= hints.max_height = hints.base_height = screen->height; + + XSetWMNormalHints(display,window,&hints); + + { + XEvent xev; + + memset(&xev, 0, sizeof(xev)); + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = 1; + xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0); + xev.xclient.window = window; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", 0); + xev.xclient.data.l[2] = 0; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + + XSendEvent(display, root_window_id, 0, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); + } + } else { + { + XEvent xev; + + memset(&xev, 0, sizeof(xev)); + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = 1; + xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0); + xev.xclient.window = window; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 0; + xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", 0); + xev.xclient.data.l[2] = 0; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + + XSendEvent(display, root_window_id, 0, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); + } + + mwmhints.flags=MWM_HINTS_DECORATIONS; + mwmhints.functions=0; + mwmhints.decorations=1; + mwmhints.input_mode=0; + mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0); + + //This shouldn't work on 64 bit longs, but it does...in fact, it breaks when I change all the mwmhints to int. + //I don't pretend to understand it. + XChangeProperty(display,window,mwmatom,mwmatom,32, + PropModeReplace,(unsigned char *)&mwmhints,5); + + hints.flags=USPosition|USSize; + hints.base_width = iResX; + hints.base_height = iResY; + XSetWMNormalHints(display,window,&hints); + + XResizeWindow(display,window,iResX,iResY); +} + + DoClearScreenBuffer(); + + bChangeWinMode=FALSE; + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// gun cursor func: player=0-7, x=0-511, y=0-255 +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUcursor(int iPlayer,int x,int y) +{ + if(iPlayer<0) return; + if(iPlayer>7) return; + + usCursorActive|=(1<<iPlayer); + + if(x<0) x=0; + if(x>511) x=511; + if(y<0) y=0; + if(y>255) y=255; + + ptCursorPoint[iPlayer].x=x; + ptCursorPoint[iPlayer].y=y; +} + +//////////////////////////////////////////////////////////////////////// +// update lace is called evry VSync +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUupdateLace(void) // VSYNC +{ + if(!(dwActFixes&1)) + lGPUstatusRet^=0x80000000; // odd/even bit + + if(!(dwActFixes&32)) // std fps limitation? + CheckFrameRate(); + + if(PSXDisplay.Interlaced) // interlaced mode? + { + if(bDoVSyncUpdate && PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0) + { + updateDisplay(); + } + } + else // non-interlaced? + { + if(dwActFixes&64) // lazy screen update fix + { + if(bDoLazyUpdate && !UseFrameSkip) + updateDisplay(); + bDoLazyUpdate=FALSE; + } + else + { + if(bDoVSyncUpdate && !UseFrameSkip) // some primitives drawn? + updateDisplay(); // -> update display + } + } + + if(bChangeWinMode) ChangeWindowMode(); // toggle full - window mode + + bDoVSyncUpdate=FALSE; // vsync done +} + +//////////////////////////////////////////////////////////////////////// +// process read request from GPU status register +//////////////////////////////////////////////////////////////////////// + + +uint32_t CALLBACK GPUreadStatus(void) // READ STATUS +{ + if(dwActFixes&1) + { + static int iNumRead=0; // odd/even hack + if((iNumRead++)==2) + { + iNumRead=0; + lGPUstatusRet^=0x80000000; // interlaced bit toggle... we do it on every 3 read status... needed by some games (like ChronoCross) with old epsxe versions (1.5.2 and older) + } + } + + return lGPUstatusRet; +} + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU status register +// these are always single packet commands. +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteStatus(uint32_t gdata) // WRITE STATUS +{ + uint32_t lCommand=(gdata>>24)&0xff; + + ulStatusControl[lCommand]=gdata; // store command for freezing + + switch(lCommand) + { + //--------------------------------------------------// + // reset gpu + case 0x00: + memset(lGPUInfoVals,0x00,16*sizeof(uint32_t)); + lGPUstatusRet=0x14802000; + PSXDisplay.Disabled=1; + DataWriteMode=DataReadMode=DR_NORMAL; + PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0; + drawX=drawY=0;drawW=drawH=0; + sSetMask=0;lSetMask=0;bCheckMask=FALSE; + usMirror=0; + GlobalTextAddrX=0;GlobalTextAddrY=0; + GlobalTextTP=0;GlobalTextABR=0; + PSXDisplay.RGB24=FALSE; + PSXDisplay.Interlaced=FALSE; + bUsingTWin = FALSE; + return; + //--------------------------------------------------// + // dis/enable display + case 0x03: + + PreviousPSXDisplay.Disabled = PSXDisplay.Disabled; + PSXDisplay.Disabled = (gdata & 1); + + if(PSXDisplay.Disabled) + lGPUstatusRet|=GPUSTATUS_DISPLAYDISABLED; + else lGPUstatusRet&=~GPUSTATUS_DISPLAYDISABLED; + return; + + //--------------------------------------------------// + // setting transfer mode + case 0x04: + gdata &= 0x03; // Only want the lower two bits + + DataWriteMode=DataReadMode=DR_NORMAL; + if(gdata==0x02) DataWriteMode=DR_VRAMTRANSFER; + if(gdata==0x03) DataReadMode =DR_VRAMTRANSFER; + lGPUstatusRet&=~GPUSTATUS_DMABITS; // Clear the current settings of the DMA bits + lGPUstatusRet|=(gdata << 29); // Set the DMA bits according to the received data + + return; + //--------------------------------------------------// + // setting display position + case 0x05: + { + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + +//////// +/* + PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff); + if (PSXDisplay.DisplayPosition.y & 0x200) + PSXDisplay.DisplayPosition.y |= 0xfffffc00; + if(PSXDisplay.DisplayPosition.y<0) + { + PreviousPSXDisplay.DisplayModeNew.y=PSXDisplay.DisplayPosition.y/PSXDisplay.Double; + PSXDisplay.DisplayPosition.y=0; + } + else PreviousPSXDisplay.DisplayModeNew.y=0; +*/ + +// new + if(iGPUHeight==1024) + { + if(dwGPUVersion==2) + PSXDisplay.DisplayPosition.y = (short)((gdata>>12)&0x3ff); + else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff); + } + else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x1ff); + + // store the same val in some helper var, we need it on later compares + PreviousPSXDisplay.DisplayModeNew.x=PSXDisplay.DisplayPosition.y; + + if((PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)>iGPUHeight) + { + int dy1=iGPUHeight-PSXDisplay.DisplayPosition.y; + int dy2=(PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)-iGPUHeight; + + if(dy1>=dy2) + { + PreviousPSXDisplay.DisplayModeNew.y=-dy2; + } + else + { + PSXDisplay.DisplayPosition.y=0; + PreviousPSXDisplay.DisplayModeNew.y=-dy1; + } + } + else PreviousPSXDisplay.DisplayModeNew.y=0; +// eon + + PSXDisplay.DisplayPosition.x = (short)(gdata & 0x3ff); + PSXDisplay.DisplayEnd.x= + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y + PreviousPSXDisplay.DisplayModeNew.y; + PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y + PreviousPSXDisplay.DisplayModeNew.y; + + bDoVSyncUpdate=TRUE; + + if (!(PSXDisplay.Interlaced)) // stupid frame skipping option + { + if(UseFrameSkip) updateDisplay(); + if(dwActFixes&64) bDoLazyUpdate=TRUE; + } + }return; + //--------------------------------------------------// + // setting width + case 0x06: + + PSXDisplay.Range.x0=(short)(gdata & 0x7ff); + PSXDisplay.Range.x1=(short)((gdata>>12) & 0xfff); + + PSXDisplay.Range.x1-=PSXDisplay.Range.x0; + + ChangeDispOffsetsX(); + + return; + //--------------------------------------------------// + // setting height + case 0x07: + { + + PSXDisplay.Range.y0=(short)(gdata & 0x3ff); + PSXDisplay.Range.y1=(short)((gdata>>10) & 0x3ff); + + PreviousPSXDisplay.Height = PSXDisplay.Height; + + PSXDisplay.Height = PSXDisplay.Range.y1 - + PSXDisplay.Range.y0 + + PreviousPSXDisplay.DisplayModeNew.y; + + if(PreviousPSXDisplay.Height!=PSXDisplay.Height) + { + PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; + + ChangeDispOffsetsY(); + + updateDisplayIfChanged(); + } + return; + } + //--------------------------------------------------// + // setting display infos + case 0x08: + + PSXDisplay.DisplayModeNew.x = + sDispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)]; + + if (gdata&0x04) PSXDisplay.Double=2; + else PSXDisplay.Double=1; + + PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double; + + ChangeDispOffsetsY(); + + PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC + PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor + PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace + + lGPUstatusRet&=~GPUSTATUS_WIDTHBITS; // Clear the width bits + lGPUstatusRet|= + (((gdata & 0x03) << 17) | + ((gdata & 0x40) << 10)); // Set the width bits + + if(PSXDisplay.InterlacedNew) + { + if(!PSXDisplay.Interlaced) + { + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + } + lGPUstatusRet|=GPUSTATUS_INTERLACED; + } + else lGPUstatusRet&=~GPUSTATUS_INTERLACED; + + if (PSXDisplay.PAL) + lGPUstatusRet|=GPUSTATUS_PAL; + else lGPUstatusRet&=~GPUSTATUS_PAL; + + if (PSXDisplay.Double==2) + lGPUstatusRet|=GPUSTATUS_DOUBLEHEIGHT; + else lGPUstatusRet&=~GPUSTATUS_DOUBLEHEIGHT; + + if (PSXDisplay.RGB24New) + lGPUstatusRet|=GPUSTATUS_RGB24; + else lGPUstatusRet&=~GPUSTATUS_RGB24; + + updateDisplayIfChanged(); + + return; + //--------------------------------------------------// + // ask about GPU version and other stuff + case 0x10: + + gdata&=0xff; + + switch(gdata) + { + case 0x02: + lGPUdataRet=lGPUInfoVals[INFO_TW]; // tw infos + return; + case 0x03: + lGPUdataRet=lGPUInfoVals[INFO_DRAWSTART]; // draw start + return; + case 0x04: + lGPUdataRet=lGPUInfoVals[INFO_DRAWEND]; // draw end + return; + case 0x05: + case 0x06: + lGPUdataRet=lGPUInfoVals[INFO_DRAWOFF]; // draw offset + return; + case 0x07: + if(dwGPUVersion==2) + lGPUdataRet=0x01; + else lGPUdataRet=0x02; // gpu type + return; + case 0x08: + case 0x0F: // some bios addr? + lGPUdataRet=0xBFC03720; + return; + } + return; + //--------------------------------------------------// + } +} + +//////////////////////////////////////////////////////////////////////// +// vram read/write helpers, needed by LEWPY's optimized vram read/write :) +//////////////////////////////////////////////////////////////////////// + +__inline void FinishedVRAMWrite(void) +{ +/* +// NEWX + if(!PSXDisplay.Interlaced && UseFrameSkip) // stupid frame skipping + { + VRAMWrite.Width +=VRAMWrite.x; + VRAMWrite.Height+=VRAMWrite.y; + if(VRAMWrite.x<PSXDisplay.DisplayEnd.x && + VRAMWrite.Width >=PSXDisplay.DisplayPosition.x && + VRAMWrite.y<PSXDisplay.DisplayEnd.y && + VRAMWrite.Height>=PSXDisplay.DisplayPosition.y) + updateDisplay(); + } +*/ + + // Set register to NORMAL operation + DataWriteMode = DR_NORMAL; + // Reset transfer values, to prevent mis-transfer of data + VRAMWrite.x = 0; + VRAMWrite.y = 0; + VRAMWrite.Width = 0; + VRAMWrite.Height = 0; + VRAMWrite.ColsRemaining = 0; + VRAMWrite.RowsRemaining = 0; +} + +__inline void FinishedVRAMRead(void) +{ + // Set register to NORMAL operation + DataReadMode = DR_NORMAL; + // Reset transfer values, to prevent mis-transfer of data + VRAMRead.x = 0; + VRAMRead.y = 0; + VRAMRead.Width = 0; + VRAMRead.Height = 0; + VRAMRead.ColsRemaining = 0; + VRAMRead.RowsRemaining = 0; + + // Indicate GPU is no longer ready for VRAM data in the STATUS REGISTER + lGPUstatusRet&=~GPUSTATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// core read from vram +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize) +{ + int i; + + if(DataReadMode!=DR_VRAMTRANSFER) return; + + GPUIsBusy; + + // adjust read ptr, if necessary + while(VRAMRead.ImagePtr>=psxVuw_eom) + VRAMRead.ImagePtr-=iGPUHeight*1024; + while(VRAMRead.ImagePtr<psxVuw) + VRAMRead.ImagePtr+=iGPUHeight*1024; + + for(i=0;i<iSize;i++) + { + // do 2 seperate 16bit reads for compatibility (wrap issues) + if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0)) + { + // lower 16 bit + lGPUdataRet=(uint32_t)GETLE16(VRAMRead.ImagePtr); + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining --; + + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + + // higher 16 bit (always, even if it's an odd width) + lGPUdataRet|=(uint32_t)GETLE16(VRAMRead.ImagePtr)<<16; + PUTLE32(pMem, lGPUdataRet); pMem++; + + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining--; + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + } + else {FinishedVRAMRead();goto ENDREAD;} + } + +ENDREAD: + GPUIsIdle; +} + + +//////////////////////////////////////////////////////////////////////// + +uint32_t CALLBACK GPUreadData(void) +{ + uint32_t l; + GPUreadDataMem(&l,1); + return lGPUdataRet; +} + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU data register +// extra table entries for fixing polyline troubles +//////////////////////////////////////////////////////////////////////// + +const unsigned char primTableCX[256] = +{ + // 00 + 0,0,3,0,0,0,0,0, + // 08 + 0,0,0,0,0,0,0,0, + // 10 + 0,0,0,0,0,0,0,0, + // 18 + 0,0,0,0,0,0,0,0, + // 20 + 4,4,4,4,7,7,7,7, + // 28 + 5,5,5,5,9,9,9,9, + // 30 + 6,6,6,6,9,9,9,9, + // 38 + 8,8,8,8,12,12,12,12, + // 40 + 3,3,3,3,0,0,0,0, + // 48 +// 5,5,5,5,6,6,6,6, // FLINE + 254,254,254,254,254,254,254,254, + // 50 + 4,4,4,4,0,0,0,0, + // 58 +// 7,7,7,7,9,9,9,9, // GLINE + 255,255,255,255,255,255,255,255, + // 60 + 3,3,3,3,4,4,4,4, + // 68 + 2,2,2,2,3,3,3,3, // 3=SPRITE1??? + // 70 + 2,2,2,2,3,3,3,3, + // 78 + 2,2,2,2,3,3,3,3, + // 80 + 4,0,0,0,0,0,0,0, + // 88 + 0,0,0,0,0,0,0,0, + // 90 + 0,0,0,0,0,0,0,0, + // 98 + 0,0,0,0,0,0,0,0, + // a0 + 3,0,0,0,0,0,0,0, + // a8 + 0,0,0,0,0,0,0,0, + // b0 + 0,0,0,0,0,0,0,0, + // b8 + 0,0,0,0,0,0,0,0, + // c0 + 3,0,0,0,0,0,0,0, + // c8 + 0,0,0,0,0,0,0,0, + // d0 + 0,0,0,0,0,0,0,0, + // d8 + 0,0,0,0,0,0,0,0, + // e0 + 0,1,1,1,1,1,1,0, + // e8 + 0,0,0,0,0,0,0,0, + // f0 + 0,0,0,0,0,0,0,0, + // f8 + 0,0,0,0,0,0,0,0 +}; + +void CALLBACK GPUwriteDataMem(uint32_t * pMem, int iSize) +{ + unsigned char command; + uint32_t gdata=0; + int i=0; + GPUIsBusy; + GPUIsNotReadyForCommands; + +STARTVRAM: + + if(DataWriteMode==DR_VRAMTRANSFER) + { + BOOL bFinished=FALSE; + + // make sure we are in vram + while(VRAMWrite.ImagePtr>=psxVuw_eom) + VRAMWrite.ImagePtr-=iGPUHeight*1024; + while(VRAMWrite.ImagePtr<psxVuw) + VRAMWrite.ImagePtr+=iGPUHeight*1024; + + // now do the loop + while(VRAMWrite.ColsRemaining>0) + { + while(VRAMWrite.RowsRemaining>0) + { + if(i>=iSize) {goto ENDVRAM;} + i++; + + gdata=GETLE32(pMem); pMem++; + + PUTLE16(VRAMWrite.ImagePtr, (unsigned short)gdata); VRAMWrite.ImagePtr++; + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + + if(VRAMWrite.RowsRemaining <= 0) + { + VRAMWrite.ColsRemaining--; + if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width + { + gdata=(gdata&0xFFFF)|(((uint32_t)GETLE16(VRAMWrite.ImagePtr))<<16); + FinishedVRAMWrite(); + bDoVSyncUpdate=TRUE; + goto ENDVRAM; + } + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + } + + PUTLE16(VRAMWrite.ImagePtr, (unsigned short)(gdata>>16)); VRAMWrite.ImagePtr++; + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + } + + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining--; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + bFinished=TRUE; + } + + FinishedVRAMWrite(); + if(bFinished) bDoVSyncUpdate=TRUE; + } + +ENDVRAM: + + if(DataWriteMode==DR_NORMAL) + { + void (* *primFunc)(unsigned char *); + if(bSkipNextFrame) primFunc=primTableSkip; + else primFunc=primTableJ; + + for(;i<iSize;) + { + if(DataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM; + + gdata=GETLE32(pMem); pMem++; i++; + + if(gpuDataC == 0) + { + command = (unsigned char)((gdata>>24) & 0xff); + +//if(command>=0xb0 && command<0xc0) auxprintf("b0 %x!!!!!!!!!\n",command); + + if(primTableCX[command]) + { + gpuDataC = primTableCX[command]; + gpuCommand = command; + PUTLE32(&gpuDataM[0], gdata); + gpuDataP = 1; + } + else continue; + } + else + { + PUTLE32(&gpuDataM[gpuDataP], gdata); + if(gpuDataC>128) + { + if((gpuDataC==254 && gpuDataP>=3) || + (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1))) + { + if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000) + gpuDataP=gpuDataC-1; + } + } + gpuDataP++; + } + + if(gpuDataP == gpuDataC) + { + gpuDataC=gpuDataP=0; + primFunc[gpuCommand]((unsigned char *)gpuDataM); + } + } + } + + lGPUdataRet=gdata; + + GPUIsReadyForCommands; + GPUIsIdle; +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteData(uint32_t gdata) +{ + PUTLE32(&gdata, gdata); + GPUwriteDataMem(&gdata,1); +} + +//////////////////////////////////////////////////////////////////////// +// this functions will be removed soon (or 'soonish')... not really needed, but some emus want them +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetMode(unsigned long gdata) +{ +// Peops does nothing here... +// DataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL; +// DataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL; +} + +long CALLBACK GPUgetMode(void) +{ + long iT=0; + + if(DataWriteMode==DR_VRAMTRANSFER) iT|=0x1; + if(DataReadMode ==DR_VRAMTRANSFER) iT|=0x2; + return iT; +} + +//////////////////////////////////////////////////////////////////////// +// call config dlg +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUconfigure(void) +{ + SoftDlgProc(); + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// sets all kind of act fixes +//////////////////////////////////////////////////////////////////////// + +void SetFixes(void) + { + if(dwActFixes&0x02) sDispWidths[4]=384; + else sDispWidths[4]=368; + } + +//////////////////////////////////////////////////////////////////////// +// process gpu commands +//////////////////////////////////////////////////////////////////////// + +unsigned long lUsedAddr[3]; + +__inline BOOL CheckForEndlessLoop(unsigned long laddr) +{ + if(laddr==lUsedAddr[1]) return TRUE; + if(laddr==lUsedAddr[2]) return TRUE; + + if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr; + else lUsedAddr[2]=laddr; + lUsedAddr[0]=laddr; + return FALSE; +} + +long CALLBACK GPUdmaChain(uint32_t * baseAddrL, uint32_t addr) +{ + uint32_t dmaMem; + unsigned char * baseAddrB; + short count;unsigned int DMACommandCounter = 0; + + GPUIsBusy; + + lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff; + + baseAddrB = (unsigned char*) baseAddrL; + + do + { + if(iGPUHeight==512) addr&=0x1FFFFC; + if(DMACommandCounter++ > 2000000) break; + if(CheckForEndlessLoop(addr)) break; + + count = baseAddrB[addr+3]; + + dmaMem=addr+4; + + if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); + + addr = GETLE32(&baseAddrL[addr>>2])&0xffffff; + } + while (addr != 0xffffff); + + GPUIsIdle; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// show about dlg +//////////////////////////////////////////////////////////////////////// + + +void CALLBACK GPUabout(void) // ABOUT +{ + AboutDlgProc(); + return; +} + +//////////////////////////////////////////////////////////////////////// +// We are ever fine ;) +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUtest(void) +{ + // if test fails this function should return negative value for error (unable to continue) + // and positive value for warning (can continue but output might be crappy) + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// Freeze +//////////////////////////////////////////////////////////////////////// + +typedef struct GPUFREEZETAG +{ + uint32_t ulFreezeVersion; // should be always 1 for now (set by main emu) + uint32_t ulStatus; // current gpu status + uint32_t ulControl[256]; // latest control register values + unsigned char psxVRam[1024*1024*2]; // current VRam image (full 2 MB for ZN) +} GPUFreeze_t; + +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUfreeze(uint32_t ulGetFreezeData,GPUFreeze_t * pF) +{ + //----------------------------------------------------// + if(ulGetFreezeData==2) // 2: info, which save slot is selected? (just for display) + { + long lSlotNum=*((long *)pF); + if(lSlotNum<0) return 0; + if(lSlotNum>8) return 0; + lSelectedSlot=lSlotNum+1; + BuildDispMenu(0); + return 1; + } + //----------------------------------------------------// + if(!pF) return 0; // some checks + if(pF->ulFreezeVersion!=1) return 0; + + if(ulGetFreezeData==1) // 1: get data + { + pF->ulStatus=lGPUstatusRet; + memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t)); + memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2); + + return 1; + } + + if(ulGetFreezeData!=0) return 0; // 0: set data + + lGPUstatusRet=pF->ulStatus; + memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t)); + memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2); + +// RESET TEXTURE STORE HERE, IF YOU USE SOMETHING LIKE THAT + + GPUwriteStatus(ulStatusControl[0]); + GPUwriteStatus(ulStatusControl[1]); + GPUwriteStatus(ulStatusControl[2]); + GPUwriteStatus(ulStatusControl[3]); + GPUwriteStatus(ulStatusControl[8]); // try to repair things + GPUwriteStatus(ulStatusControl[6]); + GPUwriteStatus(ulStatusControl[7]); + GPUwriteStatus(ulStatusControl[5]); + GPUwriteStatus(ulStatusControl[4]); + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// SAVE STATE DISPLAY STUFF +//////////////////////////////////////////////////////////////////////// + +// font 0-9, 24x20 pixels, 1 byte = 4 dots +// 00 = black +// 01 = white +// 10 = red +// 11 = transparent + +unsigned char cFont[10][120]= +{ +// 0 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 1 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x05,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x05,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 2 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 3 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 4 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x54,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x05,0x14,0x00,0x00, + 0x80,0x00,0x14,0x14,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 5 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x54,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 6 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x54,0x00,0x00, + 0x80,0x00,0x15,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 7 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 8 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 9 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x15,0x00,0x00, + 0x80,0x00,0x05,0x55,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x05,0x50,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +} +}; + +//////////////////////////////////////////////////////////////////////// + +void PaintPicDot(unsigned char * p,unsigned char c) +{ + + if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;} // black + if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;} // white + if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;} // red + // transparent +} + +//////////////////////////////////////////////////////////////////////// +// the main emu allocs 128x96x3 bytes, and passes a ptr +// to it in pMem... the plugin has to fill it with +// 8-8-8 bit BGR screen data (Win 24 bit BMP format +// without header). +// Beware: the func can be called at any time, +// so you have to use the frontbuffer to get a fully +// rendered picture + +// LINUX version: + +extern char * Xpixels; + +void GPUgetScreenPic(unsigned char * pMem) +{ +/* + unsigned short c;unsigned char * pf;int x,y; + + float XS=(float)iResX/128; + float YS=(float)iResY/96; + + pf=pMem; + memset(pMem, 0, 128*96*3); + + if(Xpixels) + { + unsigned char * ps=(unsigned char *)Xpixels; + { + long lPitch=iResX<<2; + uint32_t sx; + + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + sx=*((uint32_t *)((ps)+ + (((int)((float)y*YS))*lPitch)+ + ((int)((float)x*XS))*4)); + *(pf+0)=(sx&0xff); + *(pf+1)=(sx&0xff00)>>8; + *(pf+2)=(sx&0xff0000)>>16; + pf+=3; + } + } + } + } + + + ///////////////////////////////////////////////////////////////////// + // generic number/border painter + + pf=pMem+(103*3); // offset to number rect + + for(y=0;y<20;y++) // loop the number rect pixel + { + for(x=0;x<6;x++) + { + c=cFont[lSelectedSlot][x+y*6]; // get 4 char dot infos at once (number depends on selected slot) + PaintPicDot(pf,(c&0xc0)>>6);pf+=3; // paint the dots into the rect + PaintPicDot(pf,(c&0x30)>>4);pf+=3; + PaintPicDot(pf,(c&0x0c)>>2);pf+=3; + PaintPicDot(pf,(c&0x03)); pf+=3; + } + pf+=104*3; // next rect y line + } + + pf=pMem; // ptr to first pos in 128x96 pic + for(x=0;x<128;x++) // loop top/bottom line + { + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0x00;*pf++=0x00; // paint it red + *(pf+(95*128*3))=0xff;*pf++=0xff; + } + pf=pMem; // ptr to first pos + for(y=0;y<96;y++) // loop left/right line + { + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0x00;*pf++=0x00; // paint it red + *(pf+(127*3))=0xff;*pf++=0xff; + pf+=127*3; // offset to next line + } +*/ +} + + +//////////////////////////////////////////////////////////////////////// +// func will be called with 128x96x3 BGR data. +// the plugin has to store the data and display +// it in the upper right corner. +// If the func is called with a NULL ptr, you can +// release your picture data and stop displaying +// the screen pic + +void CALLBACK GPUshowScreenPic(unsigned char * pMem) +{ + DestroyPic(); // destroy old pic data + if(pMem==0) return; // done + CreatePic(pMem); // create new pic... don't free pMem or something like that... just read from it +} + +//////////////////////////////////////////////////////////////////////// diff --git a/plugins/dfxvideo/gpu.h b/plugins/dfxvideo/gpu.h new file mode 100644 index 00000000..e8730f27 --- /dev/null +++ b/plugins/dfxvideo/gpu.h @@ -0,0 +1,60 @@ +/*************************************************************************** + gpu.h - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#ifndef _GPU_INTERNALS_H +#define _GPU_INTERNALS_H + +#define OPAQUEON 10 +#define OPAQUEOFF 11 + +#define KEY_RESETTEXSTORE 1 +#define KEY_SHOWFPS 2 +#define KEY_RESETOPAQUE 4 +#define KEY_RESETDITHER 8 +#define KEY_RESETFILTER 16 +#define KEY_RESETADVBLEND 32 +//#define KEY_BLACKWHITE 64 +#define KEY_BADTEXTURES 128 +#define KEY_CHECKTHISOUT 256 + +#if !defined(__BIG_ENDIAN__) || defined(__x86_64__) || defined(__i386__) +#ifndef __LITTLE_ENDIAN__ +#define __LITTLE_ENDIAN__ +#endif +#endif + +#ifdef __LITTLE_ENDIAN__ +#define RED(x) (x & 0xff) +#define BLUE(x) ((x>>16) & 0xff) +#define GREEN(x) ((x>>8) & 0xff) +#define COLOR(x) (x & 0xffffff) +#elif defined __BIG_ENDIAN__ +#define RED(x) ((x>>24) & 0xff) +#define BLUE(x) ((x>>8) & 0xff) +#define GREEN(x) ((x>>16) & 0xff) +#define COLOR(x) SWAP32(x & 0xffffff) +#endif + +///////////////////////////////////////////////////////////////////////////// + +void updateDisplay(void); +void SetAutoFrameCap(void); +void SetFixes(void); + +///////////////////////////////////////////////////////////////////////////// + +#endif // _GPU_INTERNALS_H diff --git a/plugins/dfxvideo/gpucfg-0.1df/dfxvideo.glade2 b/plugins/dfxvideo/gpucfg-0.1df/dfxvideo.glade2 new file mode 100644 index 00000000..3eba6be9 --- /dev/null +++ b/plugins/dfxvideo/gpucfg-0.1df/dfxvideo.glade2 @@ -0,0 +1,798 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--*- mode: xml -*--> +<glade-interface> + <widget class="GtkWindow" id="CfgWnd"> + <property name="visible">True</property> + <property name="border_width">10</property> + <property name="title" translatable="yes">Configure X11 Video</property> + <property name="modal">True</property> + <signal name="destroy" handler="on_CfgWnd_destroy"/> + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkFrame" id="frame1"> + <property name="visible">True</property> + <child> + <widget class="GtkAlignment" id="alignment4"> + <property name="visible">True</property> + <property name="top_padding">6</property> + <property name="bottom_padding">6</property> + <property name="left_padding">12</property> + <property name="right_padding">12</property> + <child> + <widget class="GtkVBox" id="vbox7"> + <property name="visible">True</property> + <child> + <widget class="GtkTable" id="table1"> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">2</property> + <property name="column_spacing">30</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="label14"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Initial Window Size:</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label15"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Stretching:</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label16"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Dithering:</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="resCombo2"> + <property name="visible">True</property> + <property name="active">2</property> + <property name="items" translatable="yes">320x240 +640x480 +800x600 +1024x768 +1152x864 +1280x1024 +1600x1200</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="stretchCombo2"> + <property name="visible">True</property> + <property name="active">0</property> + <property name="items" translatable="yes">0: None +1: 2xSai +2: 2xSuperSai +3: SuperEagle +4: Scale2x +5: Scale3x +6: HQ2X +7: HQ3X</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="ditherCombo2"> + <property name="visible">True</property> + <property name="active">1</property> + <property name="items" translatable="yes">0: Off (fastest) +1: Game dependant +2: Always</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <child> + <widget class="GtkCheckButton" id="maintain43"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Maintain 4:3 Aspect Ratio</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFullscreen"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Toggle windowed/fullscreen mode.</property> + <property name="label" translatable="yes">Fullscreen</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label10"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Screen</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkFrame" id="frame2"> + <property name="visible">True</property> + <child> + <widget class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="top_padding">6</property> + <property name="bottom_padding">6</property> + <property name="left_padding">12</property> + <property name="right_padding">12</property> + <child> + <widget class="GtkVBox" id="vbox3"> + <property name="visible">True</property> + <child> + <widget class="GtkCheckButton" id="checkShowFPS"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Toggle whether the FPS will be shown.</property> + <property name="label" translatable="yes">Show FPS</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkAutoFPSLimit"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Enable this if games display too quickly.</property> + <property name="label" translatable="yes">Autodetect FPS limit</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFrameSkip"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Skip frames when rendering.</property> + <property name="label" translatable="yes">Enable frame skipping</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table2"> + <property name="visible">True</property> + <property name="n_rows">1</property> + <property name="n_columns">2</property> + <property name="column_spacing">12</property> + <child> + <widget class="GtkCheckButton" id="checkSetFPS"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Set FPS</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="entryFPS"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="width_chars">4</property> + <property name="text" translatable="yes">200.0</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label11"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Framerate</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkFrame" id="frame3"> + <property name="visible">True</property> + <child> + <widget class="GtkAlignment" id="alignment3"> + <property name="visible">True</property> + <property name="top_padding">6</property> + <property name="bottom_padding">6</property> + <property name="left_padding">12</property> + <property name="right_padding">12</property> + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="visible">True</property> + <child> + <widget class="GtkCheckButton" id="checkUseFixes"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Use game fixes</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="alignment5"> + <property name="visible">True</property> + <property name="left_padding">19</property> + <child> + <widget class="GtkTable" id="table_fixes"> + <property name="visible">True</property> + <property name="n_rows">10</property> + <property name="n_columns">2</property> + <property name="column_spacing">16</property> + <child> + <widget class="GtkLabel" id="label22"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">better g-colors, worse textures</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">9</property> + <property name="bottom_attach">10</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label21"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Needed by Dark Forces</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">8</property> + <property name="bottom_attach">9</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFix10"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Draw quads with triangles</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">9</property> + <property name="bottom_attach">10</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFix9"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Repeated flat tex triangles</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">8</property> + <property name="bottom_attach">9</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFix5"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Disable CPU Saving</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFix1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Odd/even bit hack</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label17"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">For precise framerate</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label18"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Better FPS limit in some</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFix6"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">PC FPS calculation</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Pandemonium 2</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFix7"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Lazy screen update</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Skip every second frame</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">7</property> + <property name="bottom_attach">8</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFix8"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Old frame skipping</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">7</property> + <property name="bottom_attach">8</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFix2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Expand screen width</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFix3"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Ignore brightness color</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkFix4"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Disable coordinate check</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label24"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Chrono Cross</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label25"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Capcom fighting games</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label26"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Black screens in Lunar</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label27"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Compatibility mode</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label12"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Compatibility</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkHButtonBox" id="hbuttonbox1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <widget class="GtkButton" id="btn_close"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label">gtk-close</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + </child> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkWindow" id="AboutWnd"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="title" translatable="yes">About X11 Video Plugin</property> + <property name="modal">True</property> + <signal name="destroy" handler="on_AboutWnd_destroy"/> + <child> + <widget class="GtkVBox" id="vbox5"> + <property name="visible">True</property> + <child> + <widget class="GtkVBox" id="vbox6"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Coded by: Pete Bernert and the P.E.Op.S. team</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes">Homepage: http://home.t-online.de/home/PeteBernert/</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">EMail: BlackDove@addcom.de</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label5"> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Version: 1.15</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes">Release date: 2003</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">4</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label13"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>PCSX-df Video Plugin Adaption</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">5</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">XVideo Support: Stephen Chao</property> + </widget> + <packing> + <property name="position">6</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/plugins/dfxvideo/gpucfg-0.1df/main.c b/plugins/dfxvideo/gpucfg-0.1df/main.c new file mode 100644 index 00000000..670a8351 --- /dev/null +++ b/plugins/dfxvideo/gpucfg-0.1df/main.c @@ -0,0 +1,409 @@ +#include <gtk/gtk.h> +#include <glade/glade.h> + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> + +void SaveConfig (GtkWidget *widget, gpointer user_datal); + +#define READBINARY "rb" +#define WRITEBINARY "wb" +#define CONFIG_FILENAME "dfxvideo.cfg" + +/* ADB */ +enum { + VIDMODE_320x200, + VIDMODE_640x480, + VIDMODE_800x600, + VIDMODE_1024x768 +}; /* Video_modes */ + +/*ADB static GtkWidget * wndMain=0;*/ + + +/* This function checks for the value being outside the accepted range, + and returns the appropriate boundary value */ +int set_limit (char *p, int len, int lower, int upper) +{ + int val = 0; + + if (p) + val = atoi(p + len); + /* printf("Checking for val %d greater than %d and lower than %d, ", val, lower, upper);*/ + if (val < lower) + val = lower; + if (val > upper) + val = upper; + /* printf ("val is now %d\n", val);*/ + return val; +} + +void on_about_clicked (GtkWidget *widget, gpointer user_data) +{ + gtk_widget_destroy (widget); + exit (0); +} + +void on_config_clicked (GtkWidget *widget, gpointer user_data) +{ + gtk_widget_destroy (widget); + exit (0); +} + +void set_widget_sensitive (GtkWidget *widget, gpointer user_data) +{ + gtk_widget_set_sensitive (widget, (int)user_data); +} + +void on_use_fixes_toggled (GtkWidget *widget, gpointer user_data) +{ + GtkWidget *check, *table_fixes; + GladeXML *xml; + xml = (GladeXML*) user_data; + check = glade_xml_get_widget (xml, "checkUseFixes"); + + table_fixes = glade_xml_get_widget (xml, "table_fixes"); + + /* Set the state of each of the fixes to the value of the use fixes toggle */ + gtk_container_foreach (GTK_CONTAINER (table_fixes), (GtkCallback) set_widget_sensitive, + (void *)gtk_toggle_button_get_active (check)); +} + +int +main (int argc, char *argv[]) +{ + GtkWidget *CfgWnd, *widget; + GladeXML *xml; + FILE *in;char t[256];int len,val; + float valf; + char * pB, * p; + char cfg[255]; + int i; + char tempstr[50]; + + if (argc!=2) { + printf("Usage: cfgDFXVideo {ABOUT | CFG}\n"); + return 0; + } + if(strcmp(argv[1],"CFG")!=0 && strcmp(argv[1],"ABOUT")!=0) { + printf("Usage: cfgDFXVideo {ABOUT | CFG}\n"); + return 0; + } + + gtk_set_locale (); + gtk_init (&argc, &argv); + + + if (strcmp(argv[1], "ABOUT") == 0) { + const char *authors[]= {"Pete Bernert and the P.E.Op.S. team", "Ryan Schultz", "Andrew Burton", NULL}; + widget = gtk_about_dialog_new (); + gtk_about_dialog_set_name (GTK_ABOUT_DIALOG (widget), "P.E.Op.S PCSX Video Plugin"); + gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (widget), "1.15"); + gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG (widget), authors); + gtk_about_dialog_set_website (GTK_ABOUT_DIALOG (widget), "http://home.t-online.de/home/PeteBernert/"); + + g_signal_connect_data(GTK_OBJECT(widget), "response", + GTK_SIGNAL_FUNC(on_about_clicked), NULL, NULL, G_CONNECT_AFTER); + + gtk_widget_show (widget); + gtk_main(); + + return 0; + } + + xml = glade_xml_new(DATADIR "dfxvideo.glade2", "CfgWnd", NULL); + if (!xml) { + g_warning("We could not load the interface!"); + return -1; + } + + /*ADB wndMain = glade_xml_get_widget(xml, "CfgWnd");*/ + + strcpy(cfg, CONFIG_FILENAME); + + in = fopen(cfg,READBINARY); + /* ADB TODO This is bad - asking for problems; need to read in line by line */ + if(in) + { + pB=(char *)malloc(32767); + memset(pB,0,32767); + len = fread(pB, 1, 32767, in); + fclose(in); + } + else{ pB=0;printf("Couldn't find config file %s\n", cfg);} +/* ADB TODO Parse this like we parse the config file in PCSX - use common functions! */ + val=1; + if(pB) + { + strcpy(t,"\nResX");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 1024); + } + + /* ADB TODO Replace this with calls to the enum video_modes above */ + if (val == 1024) val = 3; + if (val == 800) val = 2; + if (val == 640) val = 1; + if (val == 320) val = 0; + + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "resCombo2")), val); + + val=0; + if(pB) + { + strcpy(t,"\nNoStretch");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 9); + } + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "stretchCombo2")), val); + + val=0; + if(pB) + { + strcpy(t,"\nUseDither");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 2); + } + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "ditherCombo2")), val); + + val=0; + if(pB) + { + strcpy(t,"\nMaintain43");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 1); + } + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "maintain43")), val); + + val=0; //ADB Leave - these are default values + if(pB) + { + strcpy(t,"\nFullScreen");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 1); + } + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkFullscreen")), val); + + val=0; + if(pB) + { + strcpy(t,"\nShowFPS");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 1); + } + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkShowFPS")), val); + + val=1; + if(pB) + { + strcpy(t,"\nUseFrameLimit");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 1); + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkAutoFPSLimit")), val); + + val=0; + if(pB) + { + strcpy(t,"\nFPSDetection");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 1, 2); + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkSetFPS")), !(val-1)); + + val=0; + if(pB) + { + strcpy(t,"\nUseFrameSkip");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + val = set_limit (p, len, 0, 1); + } + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkFrameSkip")), val); + + valf=200; + if(pB) + { + strcpy(t,"\nFrameRate");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) valf=(float)atoi(p+len) / 10; + if(valf<1) valf=1; + if(valf>500) valf=500; + } + sprintf(tempstr,"%.1f",valf); + gtk_entry_set_text(glade_xml_get_widget(xml, "entryFPS"),tempstr); + + val=0; + if(pB) + { + strcpy(t,"\nUseFixes");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 1); + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkUseFixes")), val); + + + if(pB) + { + strcpy(t,"\nCfgFixes");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if (p) + val = atoi(p + len); + } + + for (i=0; i<10; i++) + { + sprintf(tempstr, "checkFix%d", i+1); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, tempstr)), (val>>i)&1 ); + } + + + if(pB) free(pB); + + widget = glade_xml_get_widget(xml, "CfgWnd"); + g_signal_connect_data(GTK_OBJECT(widget), "delete_event", + GTK_SIGNAL_FUNC(on_config_clicked), NULL, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "btn_close"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(SaveConfig), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "checkUseFixes"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(on_use_fixes_toggled), xml, NULL, G_CONNECT_AFTER); + + on_use_fixes_toggled (widget, (gpointer) xml); + + gtk_main (); + return 0; +} + + +void SetCfgVal(char * pB,char * pE,int val) +{ + char * p, *ps, *pC;char t[32]; + + sprintf(t,"%d",val); + + p=strstr(pB,pE); + if(p) + { + p=strstr(p,"="); + if(!p) return; + p++; + while(*p && *p!='\n' && (*p<'0' || *p>'9')) p++; + if(*p==0 || *p=='\n') return; + ps=p; + while(*p>='0' && *p<='9') p++; + pC=(char *)malloc(32767); + strcpy(pC,p); + strcpy(ps,t); + strcat(pB,pC); + free(pC); + } + else + { + strcat(pB,pE); + strcat(pB," = "); + strcat(pB,t); + strcat(pB,"\n"); + } +} + +void SaveConfig(GtkWidget *widget, gpointer user_data) +{ + FILE *in;int len,val;char * pB; + GladeXML *xml; + char cfg[255]; + char tempstr[50]; + int i; + struct stat buf; + + pB=(char *)malloc(32767); + memset(pB,0,32767); + + strcpy(cfg, CONFIG_FILENAME); + + /* ADB TODO Why do we read this in just to replace it again? */ + in = fopen(cfg,READBINARY); + if(in) + { + len = fread(pB, 1, 32767, in); + fclose(in); + } + xml = (GladeXML*) user_data; + + val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "resCombo2"))); + +// SetCfgVal(pB,"\nRes",val); + +/* ADB TODO Replace with constants and enums */ + if (val == 0) { SetCfgVal(pB,"\nResX",320); SetCfgVal(pB,"\nResY",240); } + if (val == 1) { SetCfgVal(pB,"\nResX",640); SetCfgVal(pB,"\nResY",480); } + if (val == 2) { SetCfgVal(pB,"\nResX",800); SetCfgVal(pB,"\nResY",600); } + if (val == 3) { SetCfgVal(pB,"\nResX",1024); SetCfgVal(pB,"\nResY",768); } + + val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "stretchCombo2"))); + SetCfgVal(pB,"\nNoStretch",val); + + val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "ditherCombo2"))); + SetCfgVal(pB,"\nUseDither",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "maintain43"))); + SetCfgVal(pB,"\nMaintain43",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkFullscreen"))); + SetCfgVal(pB,"\nFullScreen",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkShowFPS"))); + SetCfgVal(pB,"\nShowFPS",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkAutoFPSLimit"))); + SetCfgVal(pB,"\nUseFrameLimit",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkSetFPS"))); + SetCfgVal(pB,"\nFPSDetection",(!val)+1); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkFrameSkip"))); + SetCfgVal(pB,"\nUseFrameSkip",val); + + //Framerate stored *10 + val = atof(gtk_entry_get_text(glade_xml_get_widget(xml, "entryFPS"))) * 10; + SetCfgVal(pB,"\nFrameRate",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkUseFixes"))); + SetCfgVal(pB,"\nUseFixes",val); + + + val = 0; + for (i=0; i<10; i++) + { + sprintf(tempstr, "checkFix%d", i+1); + if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, tempstr))) ) + val |= 1 << i; + } + + SetCfgVal(pB,"\nCfgFixes",val); + + + + if((in=fopen(cfg, WRITEBINARY))!=NULL) + { + fwrite(pB,strlen(pB),1,in); + fclose(in); + } + + free(pB); + + gtk_widget_destroy (glade_xml_get_widget (xml, "CfgWnd")); +// g_free (xml); + + /* Close the window and exit control from the plugin */ + exit (0); +} diff --git a/plugins/dfxvideo/hq2x.h b/plugins/dfxvideo/hq2x.h new file mode 100644 index 00000000..e69b8e1a --- /dev/null +++ b/plugins/dfxvideo/hq2x.h @@ -0,0 +1,1870 @@ +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst1[0] +#define P3 dst1[1] +#define MUR interp_32_diff(c[1], c[5]) +#define MDR interp_32_diff(c[5], c[7]) +#define MDL interp_32_diff(c[7], c[3]) +#define MUL interp_32_diff(c[3], c[1]) +#define IC(p0) c[p0] +#define I11(p0,p1) interp_32_11(c[p0], c[p1]) +#define I211(p0,p1,p2) interp_32_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) interp_32_31(c[p0], c[p1]) +#define I332(p0,p1,p2) interp_32_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) interp_32_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) interp_32_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) interp_32_53(c[p0], c[p1]) +#define I611(p0,p1,p2) interp_32_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) interp_32_71(c[p0], c[p1]) +#define I772(p0,p1,p2) interp_32_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) interp_32_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) interp_32_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) interp_32_151(c[p0], c[p1]) + +case 0 : +case 1 : +case 4 : +case 5 : +case 32 : +case 33 : +case 36 : +case 37 : +case 128 : +case 129 : +case 132 : +case 133 : +case 160 : +case 161 : +case 164 : +case 165 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 2 : +case 34 : +case 130 : +case 162 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 3 : +case 35 : +case 131 : +case 163 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 6 : +case 38 : +case 134 : +case 166 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 7 : +case 39 : +case 135 : +case 167 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 8 : +case 12 : +case 136 : +case 140 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); +} break; +case 9 : +case 13 : +case 137 : +case 141 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); +} break; +case 10 : +case 138 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 11 : +case 139 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 14 : +case 142 : +{ + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 15 : +case 143 : +{ + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 16 : +case 17 : +case 48 : +case 49 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); +} break; +case 18 : +case 50 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 19 : +case 51 : +{ + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P0 = I31(4, 3); + P1 = I31(4, 2); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 20 : +case 21 : +case 52 : +case 53 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); +} break; +case 22 : +case 54 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 23 : +case 55 : +{ + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P0 = I31(4, 3); + P1 = IC(4); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 24 : +case 66 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 25 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 26 : +case 31 : +case 95 : +{ + P2 = I31(4, 6); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 27 : +case 75 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 28 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 29 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 30 : +case 86 : +{ + P0 = I31(4, 0); + P2 = I31(4, 6); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 40 : +case 44 : +case 168 : +case 172 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); +} break; +case 41 : +case 45 : +case 169 : +case 173 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); +} break; +case 42 : +case 170 : +{ + P1 = I31(4, 2); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 43 : +case 171 : +{ + P1 = I31(4, 2); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 46 : +case 174 : +{ + P1 = I31(4, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 47 : +case 175 : +{ + P1 = I31(4, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 56 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 57 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 58 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 59 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 60 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 61 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 62 : +{ + P0 = I31(4, 0); + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 63 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 64 : +case 65 : +case 68 : +case 69 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 67 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 70 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 71 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 72 : +case 76 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 73 : +case 77 : +{ + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P0 = I31(4, 1); + P2 = I31(4, 6); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 74 : +case 107 : +case 123 : +{ + P1 = I31(4, 2); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 78 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 79 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 80 : +case 81 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 82 : +case 214 : +case 222 : +{ + P0 = I31(4, 0); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 83 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 84 : +case 85 : +{ + P0 = I211(4, 1, 3); + P2 = I31(4, 6); + if (MDR) { + P1 = I31(4, 1); + P3 = I31(4, 8); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 87 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 88 : +case 248 : +case 250 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 89 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 90 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 91 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 92 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 93 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 94 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 96 : +case 97 : +case 100 : +case 101 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 98 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 99 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 102 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 103 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 104 : +case 108 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 105 : +case 109 : +{ + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P0 = I31(4, 1); + P2 = IC(4); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 106 : +case 120 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 110 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 111 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 112 : +case 113 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + if (MDR) { + P2 = I31(4, 3); + P3 = I31(4, 8); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 114 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 115 : +{ + P0 = I31(4, 3); + P2 = I31(4, 3); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 116 : +case 117 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I31(4, 3); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 118 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 119 : +{ + P2 = I31(4, 3); + P3 = I31(4, 8); + if (MUR) { + P0 = I31(4, 3); + P1 = IC(4); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 121 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 122 : +{ + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 124 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 125 : +{ + P1 = I31(4, 1); + P3 = I31(4, 8); + if (MDL) { + P0 = I31(4, 1); + P2 = IC(4); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 126 : +{ + P0 = I31(4, 0); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 127 : +{ + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 144 : +case 145 : +case 176 : +case 177 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); +} break; +case 146 : +case 178 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + if (MUR) { + P1 = I31(4, 2); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 147 : +case 179 : +{ + P0 = I31(4, 3); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 148 : +case 149 : +case 180 : +case 181 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); +} break; +case 150 : +case 182 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + if (MUR) { + P1 = IC(4); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 151 : +case 183 : +{ + P0 = I31(4, 3); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 152 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 153 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 154 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 155 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 156 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 157 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 158 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 159 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 184 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 185 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 186 : +{ + P2 = I31(4, 7); + P3 = I31(4, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 187 : +{ + P1 = I31(4, 2); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 188 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 189 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 190 : +{ + P0 = I31(4, 0); + P2 = I31(4, 7); + if (MUR) { + P1 = IC(4); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 191 : +{ + P2 = I31(4, 7); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 192 : +case 193 : +case 196 : +case 197 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 194 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 195 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 198 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 199 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 200 : +case 204 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + if (MDL) { + P2 = I31(4, 6); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 201 : +case 205 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } +} break; +case 202 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 203 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 206 : +{ + P1 = I31(4, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 207 : +{ + P2 = I31(4, 6); + P3 = I31(4, 5); + if (MUL) { + P0 = IC(4); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 208 : +case 209 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 210 : +case 216 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 211 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 212 : +case 213 : +{ + P0 = I211(4, 1, 3); + P2 = I31(4, 6); + if (MDR) { + P1 = I31(4, 1); + P3 = IC(4); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 215 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 217 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 218 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 219 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 220 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 221 : +{ + P0 = I31(4, 1); + P2 = I31(4, 6); + if (MDR) { + P1 = I31(4, 1); + P3 = IC(4); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 223 : +{ + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 224 : +case 225 : +case 228 : +case 229 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 226 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 227 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 230 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 231 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 232 : +case 236 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + if (MDL) { + P2 = IC(4); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 233 : +case 237 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } +} break; +case 234 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 235 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 238 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + if (MDL) { + P2 = IC(4); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 239 : +{ + P1 = I31(4, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 240 : +case 241 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + if (MDR) { + P2 = I31(4, 3); + P3 = IC(4); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 242 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 243 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + if (MDR) { + P2 = I31(4, 3); + P3 = IC(4); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 244 : +case 245 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 246 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 247 : +{ + P0 = I31(4, 3); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 249 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 251 : +{ + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 252 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 253 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 254 : +{ + P0 = I31(4, 0); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 255 : +{ + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef MUR +#undef MDR +#undef MDL +#undef MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 diff --git a/plugins/dfxvideo/hq3x.h b/plugins/dfxvideo/hq3x.h new file mode 100644 index 00000000..4809b794 --- /dev/null +++ b/plugins/dfxvideo/hq3x.h @@ -0,0 +1,2970 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 2004 Andrea Mazzoleni + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +/* + * This effect is a rewritten implementation of the hq effect made by Maxim Stepin + */ + +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst0[2] +#define P3 dst1[0] +#define P4 dst1[1] +#define P5 dst1[2] +#define P6 dst2[0] +#define P7 dst2[1] +#define P8 dst2[2] +#define MUR interp_32_diff(c[1], c[5]) +#define MDR interp_32_diff(c[5], c[7]) +#define MDL interp_32_diff(c[7], c[3]) +#define MUL interp_32_diff(c[3], c[1]) +#define IC(p0) c[p0] +#define I11(p0,p1) interp_32_11(c[p0], c[p1]) +#define I211(p0,p1,p2) interp_32_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) interp_32_31(c[p0], c[p1]) +#define I332(p0,p1,p2) interp_32_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) interp_32_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) interp_32_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) interp_32_53(c[p0], c[p1]) +#define I611(p0,p1,p2) interp_32_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) interp_32_71(c[p0], c[p1]) +#define I772(p0,p1,p2) interp_32_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) interp_32_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) interp_32_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) interp_32_151(c[p0], c[p1]) + +case 0 : +case 1 : +case 4 : +case 5 : +case 32 : +case 33 : +case 36 : +case 37 : +case 128 : +case 129 : +case 132 : +case 133 : +case 160 : +case 161 : +case 164 : +case 165 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); + +} break; +case 2 : +case 34 : +case 130 : +case 162 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +} break; +case 3 : +case 35 : +case 131 : +case 163 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +} break; +case 6 : +case 38 : +case 134 : +case 166 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4,5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +} break; +case 7 : +case 39 : +case 135 : +case 167 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4,5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +} break; +case 8 : +case 12 : +case 136 : +case 140 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +} break; +case 9 : +case 13 : +case 137 : +case 141 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +} break; +case 10 : +case 138 : +{ +P2 = I31(4, 2); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +if (MUL) { + P0 = I31(4, 0); + P1 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); + P3 = I71(4, 3); +} +} break; +case 11 : +case 139 : +{ +P2 = I31(4, 2); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); + P3 = I71(4, 3); +} +} break; +case 14 : +case 142 : +{ +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +if (MUL) { + P0 = I31(4, 0); + P1 = IC(4); + P2 = I31(4,5); + P3 = IC(4); +} else { + P0 = I11(1, 3); + P1 = I31(1, 4); + P2 = I211(4, 1, 5); + P3 = I31(4, 3); +} +} break; +case 15 : +case 143 : +{ +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P2 = I31(4,5); + P3 = IC(4); +} else { + P0 = I11(1, 3); + P1 = I31(1, 4); + P2 = I211(4, 1, 5); + P3 = I31(4, 3); +} +} break; +case 16 : +case 17 : +case 48 : +case 49 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +} break; +case 18 : +case 50 : +{ +P0 = I31(4, 0); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +if (MUR) { + P1 = IC(4); + P2 = I31(4, 2); + P5 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 19 : +case 51 : +{ +P3 = I31(4, 3); +P4 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +if (MUR) { + P0 = I31(4, 3); + P1 = IC(4); + P2 = I31(4, 2); + P5 = IC(4); +} else { + P0 = I211(4, 1, 3); + P1 = I31(1, 4); + P2 = I11(1, 5); + P5 = I31(4,5); +} +} break; +case 20 : +case 21 : +case 52 : +case 53 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +} break; +case 22 : +case 54 : +{ +P0 = I31(4, 0); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 23 : +case 55 : +{ +P3 = I31(4, 3); +P4 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +if (MUR) { + P0 = I31(4, 3); + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P0 = I211(4, 1, 3); + P1 = I31(1, 4); + P2 = I11(1, 5); + P5 = I31(4,5); +} +} break; +case 24 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 8); +} break; +case 25 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 8); +} break; +case 26 : +case 31 : +{ +P1 = IC(4); +P4 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 8); +if (MUL) { + P0 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P3 = I71(4, 3); +} +if (MUR) { + P2 = IC(4); + P5 = IC(4); +} else { + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 27 : +{ +P2 = I31(4, 2); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 8); +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); + P3 = I71(4, 3); +} +} break; +case 28 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 8); +} break; +case 29 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 8); +} break; +case 30 : +{ +P0 = I31(4, 0); +P3 = IC(4); +P4 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 8); +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 40 : +case 44 : +case 168 : +case 172 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +} break; +case 41 : +case 45 : +case 169 : +case 173 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +} break; +case 42 : +case 170 : +{ +P2 = I31(4, 2); +P4 = IC(4); +P5 = I31(4,5); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +if (MUL) { + P0 = I31(4, 0); + P1 = IC(4); + P3 = IC(4); + P6 = I31(4, 7); +} else { + P0 = I11(1, 3); + P1 = I31(4,1); + P3 = I31(3, 4); + P6 = I211(4, 3, 7); +} +} break; +case 43 : +case 171 : +{ +P2 = I31(4, 2); +P4 = IC(4); +P5 = I31(4,5); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); + P6 = I31(4, 7); +} else { + P0 = I11(1, 3); + P1 = I31(4,1); + P3 = I31(3, 4); + P6 = I211(4, 3, 7); +} +} break; +case 46 : +case 174 : +{ +P1 = IC(4); +P2 = I31(4,5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +} break; +case 47 : +case 175 : +{ +P1 = IC(4); +P2 = I31(4,5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I211(4, 5, 7); +if (MUL) { + P0 = IC(4); +} else { + P0 = I211(4, 1, 3); +} +} break; +case 56 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +} break; +case 57 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +} break; +case 58 : +{ +P1 = IC(4); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 59 : +{ +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); + P3 = I71(4, 3); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 60 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +} break; +case 61 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +} break; +case 62 : +{ +P0 = I31(4, 0); +P3 = IC(4); +P4 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 63 : +{ +P1 = IC(4); +P3 = IC(4); +P4 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 8); +if (MUL) { + P0 = IC(4); +} else { + P0 = I211(4, 1, 3); +} +if (MUR) { + P2 = IC(4); + P5 = IC(4); +} else { + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 64 : +case 65 : +case 68 : +case 69 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4, 8); +} break; +case 66 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4, 8); +} break; +case 67 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4, 8); +} break; +case 70 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4,5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4, 8); +} break; +case 71 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4,5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4, 8); +} break; +case 72 : +case 76 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P4 = IC(4); +P5 = I31(4,5); +P8 = I31(4, 8); +if (MDL) { + P3 = IC(4); + P6 = I31(4, 6); + P7 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +} break; +case 73 : +case 77 : +{ +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P4 = IC(4); +P5 = I31(4,5); +P8 = I31(4, 8); +if (MDL) { + P0 = I31(4,1); + P3 = IC(4); + P6 = I31(4, 6); + P7 = IC(4); +} else { + P0 = I211(4, 1, 3); + P3 = I31(3, 4); + P6 = I11(3, 7); + P7 = I31(4, 7); +} +} break; +case 74 : +case 107 : +{ +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P8 = I31(4, 8); +if (MDL) { + P6 = IC(4); + P7 = IC(4); +} else { + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +if (MUL) { + P0 = IC(4); + P1 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); +} +} break; +case 75 : +{ +P2 = I31(4, 2); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4, 8); +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); + P3 = I71(4, 3); +} +} break; +case 78 : +{ +P1 = IC(4); +P2 = I31(4,5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P7 = IC(4); +P8 = I31(4, 8); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +} break; +case 79 : +{ +P2 = I31(4,5); +P4 = IC(4); +P5 = I31(4,5); +P7 = IC(4); +P8 = I31(4, 8); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); + P3 = I71(4, 3); +} +} break; +case 80 : +case 81 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P5 = IC(4); + P7 = IC(4); + P8 = I31(4, 8); +} else { + P5 = I71(4, 5); + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +} break; +case 82 : +case 214 : +{ +P0 = I31(4, 0); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P7 = IC(4); + P8 = IC(4); +} else { + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +if (MUR) { + P1 = IC(4); + P2 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); +} +} break; +case 83 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = IC(4); +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 84 : +case 85 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P2 = I31(4,1); + P5 = IC(4); + P7 = IC(4); + P8 = I31(4, 8); +} else { + P2 = I211(4, 1, 5); + P5 = I31(5, 4); + P7 = I31(4, 7); + P8 = I11(5, 7); +} +} break; +case 86 : +{ +P0 = I31(4, 0); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4, 8); +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 87 : +{ +P0 = I31(4, 3); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I31(4, 6); +P7 = IC(4); +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 88 : +case 248 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4, 2); +P4 = IC(4); +P7 = IC(4); +if (MDL) { + P3 = IC(4); + P6 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); +} +if (MDR) { + P5 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P8 = I772(5, 7, 4); +} +} break; +case 89 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P7 = IC(4); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +} break; +case 90 : +{ +P1 = IC(4); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P7 = IC(4); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 91 : +{ +P4 = IC(4); +P5 = IC(4); +P7 = IC(4); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); + P3 = I71(4, 3); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 92 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P7 = IC(4); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +} break; +case 93 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P7 = IC(4); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +} break; +case 94 : +{ +P3 = IC(4); +P4 = IC(4); +P7 = IC(4); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 95 : +{ +P1 = IC(4); +P4 = IC(4); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4, 8); +if (MUL) { + P0 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P3 = I71(4, 3); +} +if (MUR) { + P2 = IC(4); + P5 = IC(4); +} else { + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 96 : +case 97 : +case 100 : +case 101 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4, 8); +} break; +case 98 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4, 8); +} break; +case 99 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4, 8); +} break; +case 102 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4,5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4, 8); +} break; +case 103 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4,5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4, 8); +} break; +case 104 : +case 108 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P4 = IC(4); +P5 = I31(4,5); +P8 = I31(4, 8); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +} break; +case 105 : +case 109 : +{ +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P4 = IC(4); +P5 = I31(4,5); +P8 = I31(4, 8); +if (MDL) { + P0 = I31(4,1); + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P0 = I211(4, 1, 3); + P3 = I31(3, 4); + P6 = I11(3, 7); + P7 = I31(4, 7); +} +} break; +case 106 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4, 2); +P4 = IC(4); +P5 = I31(4,5); +P8 = I31(4, 8); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +} break; +case 110 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4,5); +P4 = IC(4); +P5 = I31(4,5); +P8 = I31(4, 8); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +} break; +case 111 : +{ +P1 = IC(4); +P2 = I31(4,5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P8 = I31(4, 8); +if (MDL) { + P6 = IC(4); + P7 = IC(4); +} else { + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +if (MUL) { + P0 = IC(4); +} else { + P0 = I211(4, 1, 3); +} +} break; +case 112 : +case 113 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +if (MDR) { + P5 = IC(4); + P6 = I31(4, 3); + P7 = IC(4); + P8 = I31(4, 8); +} else { + P5 = I31(4,5); + P6 = I211(4, 3, 7); + P7 = I31(7, 4); + P8 = I11(5, 7); +} +} break; +case 114 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 3); +P7 = IC(4); +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 115 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 3); +P7 = IC(4); +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 116 : +case 117 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 3); +P7 = IC(4); +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +} break; +case 118 : +{ +P0 = I31(4, 0); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4, 8); +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 119 : +{ +P3 = I31(4, 3); +P4 = IC(4); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4, 8); +if (MUR) { + P0 = I31(4, 3); + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P0 = I211(4, 1, 3); + P1 = I31(1, 4); + P2 = I11(1, 5); + P5 = I31(4,5); +} +} break; +case 120 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4, 2); +P4 = IC(4); +P5 = IC(4); +P8 = I31(4, 8); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +} break; +case 121 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4, 2); +P4 = IC(4); +P5 = IC(4); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +} break; +case 122 : +{ +P1 = IC(4); +P4 = IC(4); +P5 = IC(4); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +if (MDR) { + P8 = I31(4, 8); +} else { + P8 = I211(4, 5, 7); +} +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 123 : +{ +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P8 = I31(4, 8); +if (MDL) { + P6 = IC(4); + P7 = IC(4); +} else { + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +if (MUL) { + P0 = IC(4); + P1 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); +} +} break; +case 124 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4,1); +P4 = IC(4); +P5 = IC(4); +P8 = I31(4, 8); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +} break; +case 125 : +{ +P1 = I31(4,1); +P2 = I31(4,1); +P4 = IC(4); +P5 = IC(4); +P8 = I31(4, 8); +if (MDL) { + P0 = I31(4,1); + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P0 = I211(4, 1, 3); + P3 = I31(3, 4); + P6 = I11(3, 7); + P7 = I31(4, 7); +} +} break; +case 126 : +{ +P0 = I31(4, 0); +P4 = IC(4); +P8 = I31(4, 8); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 127 : +{ +P4 = IC(4); +P8 = I31(4, 8); +if (MDL) { + P6 = IC(4); + P7 = IC(4); +} else { + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); +} else { + P0 = I211(4, 1, 3); + P1 = I71(4, 1); + P3 = I71(4, 3); +} +if (MUR) { + P2 = IC(4); + P5 = IC(4); +} else { + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 144 : +case 145 : +case 176 : +case 177 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I31(4, 7); +} break; +case 146 : +case 178 : +{ +P0 = I31(4, 0); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +if (MUR) { + P1 = IC(4); + P2 = I31(4, 2); + P5 = IC(4); + P8 = I31(4, 7); +} else { + P1 = I31(4,1); + P2 = I11(1, 5); + P5 = I31(5, 4); + P8 = I211(4, 5, 7); +} +} break; +case 147 : +case 179 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I31(4, 7); +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 148 : +case 149 : +case 180 : +case 181 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I31(4, 7); +} break; +case 150 : +case 182 : +{ +P0 = I31(4, 0); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); + P8 = I31(4, 7); +} else { + P1 = I31(4,1); + P2 = I11(1, 5); + P5 = I31(5, 4); + P8 = I211(4, 5, 7); +} +} break; +case 151 : +case 183 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I211(4, 3, 7); +P7 = I31(4, 7); +P8 = I31(4, 7); +if (MUR) { + P2 = IC(4); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 152 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 7); +} break; +case 153 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 7); +} break; +case 154 : +{ +P1 = IC(4); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 7); +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 155 : +{ +P2 = I31(4, 2); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 7); +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); + P3 = I71(4, 3); +} +} break; +case 156 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 7); +} break; +case 157 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 7); +} break; +case 158 : +{ +P3 = IC(4); +P4 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 7); +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); + P5 = I71(4, 5); +} +} break; +case 159 : +{ +P1 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +P7 = I31(4, 7); +P8 = I31(4, 7); +if (MUL) { + P0 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P3 = I71(4, 3); +} +if (MUR) { + P2 = IC(4); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 184 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 7); +} break; +case 185 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 7); +} break; +case 186 : +{ +P1 = IC(4); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 7); +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 187 : +{ +P2 = I31(4, 2); +P4 = IC(4); +P5 = IC(4); +P7 = I31(4, 7); +P8 = I31(4, 7); +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); + P6 = I31(4, 7); +} else { + P0 = I11(1, 3); + P1 = I31(4,1); + P3 = I31(3, 4); + P6 = I211(4, 3, 7); +} +} break; +case 188 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 7); +} break; +case 189 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 7); +} break; +case 190 : +{ +P0 = I31(4, 0); +P3 = IC(4); +P4 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); + P8 = I31(4, 7); +} else { + P1 = I31(4,1); + P2 = I11(1, 5); + P5 = I31(5, 4); + P8 = I211(4, 5, 7); +} +} break; +case 191 : +{ +P1 = IC(4); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 7); +P7 = I31(4, 7); +P8 = I31(4, 7); +if (MUL) { + P0 = IC(4); +} else { + P0 = I211(4, 1, 3); +} +if (MUR) { + P2 = IC(4); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 192 : +case 193 : +case 196 : +case 197 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4,5); +} break; +case 194 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4,5); +} break; +case 195 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4,5); +} break; +case 198 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4,5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4,5); +} break; +case 199 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4,5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4,5); +} break; +case 200 : +case 204 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P4 = IC(4); +P5 = I31(4,5); +if (MDL) { + P3 = IC(4); + P6 = I31(4, 6); + P7 = IC(4); + P8 = I31(4,5); +} else { + P3 = I31(4, 3); + P6 = I11(3, 7); + P7 = I31(7, 4); + P8 = I211(4, 5, 7); +} +} break; +case 201 : +case 205 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P7 = IC(4); +P8 = I31(4,5); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +} break; +case 202 : +{ +P1 = IC(4); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P7 = IC(4); +P8 = I31(4,5); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +} break; +case 203 : +{ +P2 = I31(4, 2); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4,5); +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); + P3 = I71(4, 3); +} +} break; +case 206 : +{ +P1 = IC(4); +P2 = I31(4,5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P7 = IC(4); +P8 = I31(4,5); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +} break; +case 207 : +{ +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 6); +P7 = IC(4); +P8 = I31(4,5); +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P2 = I31(4,5); + P3 = IC(4); +} else { + P0 = I11(1, 3); + P1 = I31(1, 4); + P2 = I211(4, 1, 5); + P3 = I31(4, 3); +} +} break; +case 208 : +case 209 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +} break; +case 210 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +} break; +case 211 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +} break; +case 212 : +case 213 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P2 = I31(4,1); + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P2 = I211(4, 1, 5); + P5 = I31(5, 4); + P7 = I31(4, 7); + P8 = I11(5, 7); +} +} break; +case 215 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P7 = IC(4); + P8 = IC(4); +} else { + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +if (MUR) { + P2 = IC(4); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 216 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +} break; +case 217 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +} break; +case 218 : +{ +P1 = IC(4); +P3 = IC(4); +P4 = IC(4); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MDR) { + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 219 : +{ +P2 = I31(4, 2); +P4 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +if (MUL) { + P0 = IC(4); + P1 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); + P3 = I71(4, 3); +} +} break; +case 220 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +if (MDL) { + P6 = I31(4, 6); +} else { + P6 = I211(4, 3, 7); +} +if (MDR) { + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +} break; +case 221 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P2 = I31(4,1); + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P2 = I211(4, 1, 5); + P5 = I31(5, 4); + P7 = I31(4, 7); + P8 = I11(5, 7); +} +} break; +case 222 : +{ +P0 = I31(4, 0); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P7 = IC(4); + P8 = IC(4); +} else { + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +if (MUR) { + P1 = IC(4); + P2 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); +} +} break; +case 223 : +{ +P4 = IC(4); +P6 = I31(4, 6); +if (MDR) { + P7 = IC(4); + P8 = IC(4); +} else { + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +if (MUL) { + P0 = IC(4); + P3 = IC(4); +} else { + P0 = I772(1, 3, 4); + P3 = I71(4, 3); +} +if (MUR) { + P1 = IC(4); + P2 = IC(4); + P5 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I211(4, 1, 5); + P5 = I71(4, 5); +} +} break; +case 224 : +case 225 : +case 228 : +case 229 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4,5); +} break; +case 226 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4,5); +} break; +case 227 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4,5); +} break; +case 230 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4,5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4,5); +} break; +case 231 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4,5); +P3 = I31(4, 3); +P4 = IC(4); +P5 = I31(4,5); +P6 = I31(4, 3); +P7 = IC(4); +P8 = I31(4,5); +} break; +case 232 : +case 236 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P4 = IC(4); +P5 = I31(4,5); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); + P8 = I31(4,5); +} else { + P3 = I31(4, 3); + P6 = I11(3, 7); + P7 = I31(7, 4); + P8 = I211(4, 5, 7); +} +} break; +case 233 : +case 237 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I211(4, 1, 5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P7 = IC(4); +P8 = I31(4,5); +if (MDL) { + P6 = IC(4); +} else { + P6 = I211(4, 3, 7); +} +} break; +case 234 : +{ +P1 = IC(4); +P2 = I31(4, 2); +P4 = IC(4); +P5 = I31(4,5); +P8 = I31(4,5); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); + P7 = I71(4, 7); +} +if (MUL) { + P0 = I31(4, 0); +} else { + P0 = I211(4, 1, 3); +} +} break; +case 235 : +{ +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P7 = IC(4); +P8 = I31(4,5); +if (MDL) { + P6 = IC(4); +} else { + P6 = I211(4, 3, 7); +} +if (MUL) { + P0 = IC(4); + P1 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); +} +} break; +case 238 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4,5); +P4 = IC(4); +P5 = I31(4,5); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); + P8 = I31(4,5); +} else { + P3 = I31(4, 3); + P6 = I11(3, 7); + P7 = I31(7, 4); + P8 = I211(4, 5, 7); +} +} break; +case 239 : +{ +P1 = IC(4); +P2 = I31(4,5); +P3 = IC(4); +P4 = IC(4); +P5 = I31(4,5); +P7 = IC(4); +P8 = I31(4,5); +if (MDL) { + P6 = IC(4); +} else { + P6 = I211(4, 3, 7); +} +if (MUL) { + P0 = IC(4); +} else { + P0 = I211(4, 1, 3); +} +} break; +case 240 : +case 241 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +if (MDR) { + P5 = IC(4); + P6 = I31(4, 3); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I31(4,5); + P6 = I211(4, 3, 7); + P7 = I31(7, 4); + P8 = I11(5, 7); +} +} break; +case 242 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P3 = I31(4, 3); +P4 = IC(4); +P6 = I31(4, 3); +if (MDR) { + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P7 = I71(4, 7); + P8 = I772(5, 7, 4); +} +if (MUR) { + P2 = I31(4, 2); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 243 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P2 = I31(4, 2); +P3 = I31(4, 3); +P4 = IC(4); +if (MDR) { + P5 = IC(4); + P6 = I31(4, 3); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I31(4,5); + P6 = I211(4, 3, 7); + P7 = I31(7, 4); + P8 = I11(5, 7); +} +} break; +case 244 : +case 245 : +{ +P0 = I211(4, 1, 3); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 3); +P7 = IC(4); +if (MDR) { + P8 = IC(4); +} else { + P8 = I211(4, 5, 7); +} +} break; +case 246 : +{ +P0 = I31(4, 0); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 3); +P7 = IC(4); +if (MDR) { + P8 = IC(4); +} else { + P8 = I211(4, 5, 7); +} +if (MUR) { + P1 = IC(4); + P2 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); +} +} break; +case 247 : +{ +P0 = I31(4, 3); +P1 = IC(4); +P3 = I31(4, 3); +P4 = IC(4); +P5 = IC(4); +P6 = I31(4, 3); +P7 = IC(4); +if (MDR) { + P8 = IC(4); +} else { + P8 = I211(4, 5, 7); +} +if (MUR) { + P2 = IC(4); +} else { + P2 = I211(4, 1, 5); +} +} break; +case 249 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4, 2); +P3 = IC(4); +P4 = IC(4); +P7 = IC(4); +if (MDL) { + P6 = IC(4); +} else { + P6 = I211(4, 3, 7); +} +if (MDR) { + P5 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P8 = I772(5, 7, 4); +} +} break; +case 250 : +{ +P0 = I31(4, 0); +P1 = IC(4); +P2 = I31(4, 2); +P4 = IC(4); +P7 = IC(4); +if (MDL) { + P3 = IC(4); + P6 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); +} +if (MDR) { + P5 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P8 = I772(5, 7, 4); +} +} break; +case 251 : +{ +P2 = I31(4, 2); +P4 = IC(4); +if (MDL) { + P3 = IC(4); + P6 = IC(4); + P7 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I211(4, 3, 7); + P7 = I71(4, 7); +} +if (MDR) { + P5 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P8 = I772(5, 7, 4); +} +if (MUL) { + P0 = IC(4); + P1 = IC(4); +} else { + P0 = I772(1, 3, 4); + P1 = I71(4, 1); +} +} break; +case 252 : +{ +P0 = I31(4, 0); +P1 = I31(4,1); +P2 = I31(4,1); +P4 = IC(4); +P5 = IC(4); +P7 = IC(4); +if (MDL) { + P3 = IC(4); + P6 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); +} +if (MDR) { + P8 = IC(4); +} else { + P8 = I211(4, 5, 7); +} +} break; +case 253 : +{ +P0 = I31(4,1); +P1 = I31(4,1); +P2 = I31(4,1); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P7 = IC(4); +if (MDL) { + P6 = IC(4); +} else { + P6 = I211(4, 3, 7); +} +if (MDR) { + P8 = IC(4); +} else { + P8 = I211(4, 5, 7); +} +} break; +case 254 : +{ +P0 = I31(4, 0); +P4 = IC(4); +if (MDL) { + P3 = IC(4); + P6 = IC(4); +} else { + P3 = I71(4, 3); + P6 = I772(3, 7, 4); +} +if (MDR) { + P5 = IC(4); + P7 = IC(4); + P8 = IC(4); +} else { + P5 = I71(4, 5); + P7 = I71(4, 7); + P8 = I211(4, 5, 7); +} +if (MUR) { + P1 = IC(4); + P2 = IC(4); +} else { + P1 = I71(4, 1); + P2 = I772(1, 5, 4); +} +} break; +case 255 : +{ +P1 = IC(4); +P3 = IC(4); +P4 = IC(4); +P5 = IC(4); +P7 = IC(4); +if (MDL) { + P6 = IC(4); +} else { + P6 = I211(4, 3, 7); +} +if (MDR) { + P8 = IC(4); +} else { + P8 = I211(4, 5, 7); +} +if (MUL) { + P0 = IC(4); +} else { + P0 = I211(4, 1, 3); +} +if (MUR) { + P2 = IC(4); +} else { + P2 = I211(4, 1, 5); +} +} break; + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef P4 +#undef P5 +#undef P6 +#undef P7 +#undef P8 +#undef MUR +#undef MDR +#undef MDL +#undef MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 diff --git a/plugins/dfxvideo/i386.asm b/plugins/dfxvideo/i386.asm new file mode 100644 index 00000000..86d6e231 --- /dev/null +++ b/plugins/dfxvideo/i386.asm @@ -0,0 +1,67 @@ +; i386.asm - description +; ------------------- +; begin : Sun Nov 08 2001 +; copyright : (C) 2001 by Pete Bernert +; email : BlackDove@addcom.de + +; ported from inline gcc to nasm by linuzappz + + +; This program is free software; you can redistribute it and/or modify * +; it under the terms of the GNU General Public License as published by * +; the Free Software Foundation; either version 2 of the License, or * +; (at your option) any later version. See also the license.txt file for * +; additional informations. * + + +bits 32 + +section .text + +%include "macros.inc" + +NEWSYM i386_BGR24to16 + push ebp + mov ebp, esp + push ebx + push edx + + mov eax, [ebp+8] ; this can hold the G value + mov ebx, eax ; this can hold the R value + mov edx, eax ; this can hold the B value + shr ebx, 3 ; move the R value + and edx, 00f80000h ; mask the B value + shr edx, 9 ; move the B value + and eax, 00f800h ; mask the G value + shr eax, 6 ; move the G value + and ebx, 0000001fh ; mask the R value + or eax, ebx ; add R to G value + or eax, edx ; add B to RG value + pop edx + pop ebx + mov esp, ebp + pop ebp + ret + +NEWSYM i386_shl10idiv + push ebp + mov ebp, esp + push ebx + push edx + + mov eax, [ebp+8] + mov ebx, [ebp+12] + mov edx, eax + shl eax, 10 + sar edx, 22 + idiv ebx + + pop edx + pop ebx + mov esp, ebp + pop ebp + ret +%ifidn __OUTPUT_FORMAT__,elf +section .note.GNU-stack noalloc noexec nowrite progbits +%endif + diff --git a/plugins/dfxvideo/interp.h b/plugins/dfxvideo/interp.h new file mode 100644 index 00000000..30432371 --- /dev/null +++ b/plugins/dfxvideo/interp.h @@ -0,0 +1,298 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 2003 Andrea Mazzoleni + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +#ifndef __INTERP_H +#define __INTERP_H + +/***************************************************************************/ +/* Basic types */ + +/***************************************************************************/ +/* interpolation */ + +static unsigned interp_mask[2]; +static unsigned interp_bits_per_pixel; + +#define INTERP_16_MASK_1(v) (v & interp_mask[0]) +#define INTERP_16_MASK_2(v) (v & interp_mask[1]) + +static __inline unsigned short interp_16_521(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*2 + INTERP_16_MASK_1(p3)*1) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*2 + INTERP_16_MASK_2(p3)*1) / 8); +} + +static __inline unsigned short interp_16_332(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)*2) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)*2) / 8); +} + +static __inline unsigned short interp_16_611(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*6 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*6 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 8); +} + +static __inline unsigned short interp_16_71(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*7 + INTERP_16_MASK_1(p2)) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*7 + INTERP_16_MASK_2(p2)) / 8); +} + +static __inline unsigned short interp_16_211(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*2 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 4) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*2 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 4); +} + +static __inline unsigned short interp_16_772(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1(((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2))*7 + INTERP_16_MASK_1(p3)*2) / 16) + | INTERP_16_MASK_2(((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2))*7 + INTERP_16_MASK_2(p3)*2) / 16); +} + +static __inline unsigned short interp_16_11(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2)) / 2) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2)) / 2); +} + +static __inline unsigned short interp_16_31(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)) / 4) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)) / 4); +} + +static __inline unsigned short interp_16_1411(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*14 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 16) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*14 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 16); +} + +static __inline unsigned short interp_16_431(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*4 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*4 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)) / 8); +} + +static __inline unsigned short interp_16_53(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*3) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*3) / 8); +} + +static __inline unsigned short interp_16_151(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*15 + INTERP_16_MASK_1(p2)) / 16) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*15 + INTERP_16_MASK_2(p2)) / 16); +} + +static __inline unsigned short interp_16_97(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*9 + INTERP_16_MASK_1(p2)*7) / 16) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*9 + INTERP_16_MASK_2(p2)*7) / 16); +} + +#define INTERP_32_MASK_1(v) (v & 0xFF00FF) +#define INTERP_32_MASK_2(v) (v & 0x00FF00) + +static __inline unsigned int interp_32_521(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*2 + INTERP_32_MASK_1(p3)*1) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*2 + INTERP_32_MASK_2(p3)*1) / 8); +} + +static __inline unsigned int interp_32_332(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)*2) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)*2) / 8); +} + +static __inline unsigned int interp_32_211(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*2 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 4) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*2 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 4); +} + +static __inline unsigned int interp_32_611(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*6 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*6 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 8); +} + +static __inline unsigned int interp_32_71(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*7 + INTERP_32_MASK_1(p2)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*7 + INTERP_32_MASK_2(p2)) / 8); +} + +static __inline unsigned int interp_32_772(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1(((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2))*7 + INTERP_32_MASK_1(p3)*2) / 16) + | INTERP_32_MASK_2(((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2))*7 + INTERP_32_MASK_2(p3)*2) / 16); +} + +static __inline unsigned int interp_32_11(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2)) / 2) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2)) / 2); +} + +static __inline unsigned int interp_32_31(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)) / 4) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)) / 4); +} + +static __inline unsigned int interp_32_1411(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*14 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*14 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 16); +} + +static __inline unsigned int interp_32_431(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*4 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*4 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)) / 8); +} + +static __inline unsigned int interp_32_53(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*3) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*3) / 8); +} + +static __inline unsigned int interp_32_151(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*15 + INTERP_32_MASK_1(p2)) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*15 + INTERP_32_MASK_2(p2)) / 16); +} + +static __inline unsigned int interp_32_97(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*9 + INTERP_32_MASK_1(p2)*7) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*9 + INTERP_32_MASK_2(p2)*7) / 16); +} + +/***************************************************************************/ +/* diff */ + +#define INTERP_Y_LIMIT (0x30*4) +#define INTERP_U_LIMIT (0x07*4) +#define INTERP_V_LIMIT (0x06*8) + +inline static int interp_16_diff(unsigned short p1, unsigned short p2) +{ + int r, g, b; + int y, u, v; + + if (p1 == p2) + return 0; + + if (interp_bits_per_pixel == 16) { + b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; + g = (int)((p1 & 0x7E0) - (p2 & 0x7E0)) >> 3; + r = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8; + } else { + b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; + g = (int)((p1 & 0x3E0) - (p2 & 0x3E0)) >> 2; + r = (int)((p1 & 0x7C00) - (p2 & 0x7C00)) >> 7; + } + + y = r + g + b; + u = r - b; + v = -r + 2*g - b; + + if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) + return 1; + + if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) + return 1; + + if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) + return 1; + + return 0; +} + +inline static int interp_32_diff(unsigned int p1, unsigned int p2) +{ + int r, g, b; + int y, u, v; + + if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8)) + return 0; + + b = (int)((p1 & 0xFF) - (p2 & 0xFF)); + g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8; + r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16; + + y = r + g + b; + u = r - b; + v = -r + 2*g - b; + + if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) + return 1; + + if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) + return 1; + + if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) + return 1; + + return 0; +} + +#if 0 + +static void interp_set(unsigned bits_per_pixel) +{ + interp_bits_per_pixel = bits_per_pixel; + + switch (bits_per_pixel) { + case 15 : + interp_mask[0] = 0x7C1F; + interp_mask[1] = 0x03E0; + break; + case 16 : + interp_mask[0] = 0xF81F; + interp_mask[1] = 0x07E0; + break; + case 32 : + interp_mask[0] = 0xFF00FF; + interp_mask[1] = 0x00FF00; + break; + } +} + +#endif + +#endif diff --git a/plugins/dfxvideo/key.c b/plugins/dfxvideo/key.c new file mode 100644 index 00000000..f4485a38 --- /dev/null +++ b/plugins/dfxvideo/key.c @@ -0,0 +1,92 @@ +/*************************************************************************** + key.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define _IN_KEY + +#include "externals.h" +#include "menu.h" +#include "gpu.h" +#include "draw.h" +#include "key.h" + +#define VK_INSERT 65379 +#define VK_HOME 65360 +#define VK_PRIOR 65365 +#define VK_NEXT 65366 +#define VK_END 65367 +#define VK_DEL 65535 +#define VK_F5 65474 + +void GPUmakeSnapshot(void); + +unsigned long ulKeybits=0; + +void GPUkeypressed(int keycode) +{ + switch(keycode) + { + case 0xFFC9: //X11 key: F12 + case ((1<<29) | 0xFF0D): //special keycode from pcsx-df: alt-enter + bChangeWinMode=TRUE; + break; + case VK_F5: + GPUmakeSnapshot(); + break; + + case VK_INSERT: + if(iUseFixes) {iUseFixes=0;dwActFixes=0;} + else {iUseFixes=1;dwActFixes=dwCfgFixes;} + SetFixes(); + if(iFrameLimit==2) SetAutoFrameCap(); + break; + + case VK_DEL: + if(ulKeybits&KEY_SHOWFPS) + { + ulKeybits&=~KEY_SHOWFPS; + DoClearScreenBuffer(); + } + else + { + ulKeybits|=KEY_SHOWFPS; + szDispBuf[0]=0; + BuildDispMenu(0); + } + break; + + case VK_PRIOR: BuildDispMenu(-1); break; + case VK_NEXT: BuildDispMenu( 1); break; + case VK_END: SwitchDispMenu(1); break; + case VK_HOME: SwitchDispMenu(-1); break; + case 0x60: + { + iFastFwd = 1 - iFastFwd; + bSkipNextFrame = FALSE; + UseFrameSkip = iFastFwd; + BuildDispMenu(0); + break; + } + } +} + +void SetKeyHandler(void) +{ +} + +void ReleaseKeyHandler(void) +{ +} diff --git a/plugins/dfxvideo/key.h b/plugins/dfxvideo/key.h new file mode 100644 index 00000000..5f85cb6f --- /dev/null +++ b/plugins/dfxvideo/key.h @@ -0,0 +1,24 @@ +/*************************************************************************** + key.h - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#ifndef _KEY_INTERNALS_H +#define _KEY_INTERNALS_H + +void SetKeyHandler(void); +void ReleaseKeyHandler(void); + +#endif // _KEY_INTERNALS_H diff --git a/plugins/dfxvideo/macros.inc b/plugins/dfxvideo/macros.inc new file mode 100644 index 00000000..47829285 --- /dev/null +++ b/plugins/dfxvideo/macros.inc @@ -0,0 +1,40 @@ +; macros.inc - description +; ------------------- +; begin : Sun Nov 08 2001 +; based on ZSNES macros.mac +; email : linuzappz@pcsx.net + +; This program is free software; you can redistribute it and/or modify * +; it under the terms of the GNU General Public License as published by * +; the Free Software Foundation; either version 2 of the License, or * +; (at your option) any later version. See also the license.txt file for * +; additional informations. * + + +%ifdef __WIN32__ + +%imacro EXTSYM 1-* +%rep %0 + extern _%1 + %define %1 _%1 +%rotate 1 +%endrep +%endmacro + +%imacro NEWSYM 1 + global _%1 + _%1: + %1: +%endmacro + +%else + +%define EXTSYM extern + +%imacro NEWSYM 1 + global %1 + %1: +%endmacro + +%endif + diff --git a/plugins/dfxvideo/menu.c b/plugins/dfxvideo/menu.c new file mode 100644 index 00000000..33d111d9 --- /dev/null +++ b/plugins/dfxvideo/menu.c @@ -0,0 +1,167 @@ +/*************************************************************************** + menu.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define _IN_MENU + +#include "externals.h" +#include "draw.h" +#include "menu.h" +#include "gpu.h" + +unsigned long dwCoreFlags = 0; + +// create lists/stuff for fonts (actually there are no more lists, but I am too lazy to change the func names ;) +void InitMenu(void) +{ +} + +// kill existing lists/fonts +void CloseMenu(void) +{ + DestroyPic(); +} + +// DISPLAY FPS/MENU TEXT + +#include <time.h> +extern time_t tStart; + +int iMPos=0; // menu arrow pos + +void DisplayText(void) // DISPLAY TEXT +{ +} + +// Build Menu buffer (== Dispbuffer without FPS)... +void BuildDispMenu(int iInc) +{ + if(!(ulKeybits&KEY_SHOWFPS)) return; // mmm, cheater ;) + + iMPos+=iInc; // up or down + if(iMPos<0) iMPos=3; // wrap around + if(iMPos>3) iMPos=0; + + strcpy(szMenuBuf," FL FS DI GF "); // main menu items + + if(UseFrameLimit) // set marks + { + if(iFrameLimit==1) szMenuBuf[2] = '+'; + else szMenuBuf[2] = '*'; + } + if(iFastFwd) szMenuBuf[7] = '~'; + else + if(UseFrameSkip) szMenuBuf[7] = '*'; + + if(iUseDither) // set marks + { + if(iUseDither==1) szMenuBuf[12] = '+'; + else szMenuBuf[12] = '*'; + } + + if(dwActFixes) szMenuBuf[17] = '*'; + + if(dwCoreFlags&1) szMenuBuf[23] = 'A'; + if(dwCoreFlags&2) szMenuBuf[23] = 'M'; + + if(dwCoreFlags&0xff00) //A/M/G/D + { + if((dwCoreFlags&0x0f00)==0x0000) // D + szMenuBuf[23] = 'D'; + else + if((dwCoreFlags&0x0f00)==0x0100) // A + szMenuBuf[23] = 'A'; + else + if((dwCoreFlags&0x0f00)==0x0200) // M + szMenuBuf[23] = 'M'; + else + if((dwCoreFlags&0x0f00)==0x0300) // G + szMenuBuf[23] = 'G'; + + szMenuBuf[24]='0'+(char)((dwCoreFlags&0xf000)>>12); // number + } + + + if(lSelectedSlot) szMenuBuf[26] = '0'+(char)lSelectedSlot; + + szMenuBuf[(iMPos+1)*5]='<'; // set arrow + +} + +// Some menu action... +void SwitchDispMenu(int iStep) // SWITCH DISP MENU +{ + if(!(ulKeybits&KEY_SHOWFPS)) return; // tststs + + switch(iMPos) + { + case 0: // frame limit + { + int iType=0; + bInitCap = TRUE; + + if(UseFrameLimit) iType=iFrameLimit; + iType+=iStep; + if(iType<0) iType=2; + if(iType>2) iType=0; + if(iType==0) UseFrameLimit=0; + else + { + UseFrameLimit=1; + iFrameLimit=iType; + SetAutoFrameCap(); + } + } break; + + case 1: // frame skip + bInitCap = TRUE; + if(iStep>0) + { + if(!UseFrameSkip) {UseFrameSkip=1;iFastFwd = 0;} + else + { + if(!iFastFwd) iFastFwd=1; + else {UseFrameSkip=0;iFastFwd = 0;} + } + } + else + { + if(!UseFrameSkip) {UseFrameSkip=1;iFastFwd = 1;} + else + { + if(iFastFwd) iFastFwd=0; + else {UseFrameSkip=0;iFastFwd = 0;} + } + } + bSkipNextFrame=FALSE; + break; + + case 2: // dithering + iUseDither+=iStep; + if(iUseDither<0) iUseDither=2; + if(iUseDither>2) iUseDither=0; + break; + + case 3: // special fixes + if(iUseFixes) {iUseFixes=0;dwActFixes=0;} + else {iUseFixes=1;dwActFixes=dwCfgFixes;} + SetFixes(); + if(iFrameLimit==2) SetAutoFrameCap(); + break; + } + + BuildDispMenu(0); // update info +} diff --git a/plugins/dfxvideo/menu.h b/plugins/dfxvideo/menu.h new file mode 100644 index 00000000..ac244180 --- /dev/null +++ b/plugins/dfxvideo/menu.h @@ -0,0 +1,27 @@ +/*************************************************************************** + menu.h - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#ifndef _GPU_MENU_H_ +#define _GPU_MENU_H_ + +void DisplayText(void); +void CloseMenu(void); +void InitMenu(void); +void BuildDispMenu(int iInc); +void SwitchDispMenu(int iStep); + +#endif // _GPU_MENU_H_ diff --git a/plugins/dfxvideo/prim.c b/plugins/dfxvideo/prim.c new file mode 100644 index 00000000..d1f8c7b0 --- /dev/null +++ b/plugins/dfxvideo/prim.c @@ -0,0 +1,1652 @@ +/*************************************************************************** + prim.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define _IN_PRIMDRAW + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "soft.h" +#include "swap.h" + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +BOOL bUsingTWin=FALSE; +TWin_t TWin; +//unsigned long clutid; // global clut +unsigned short usMirror=0; // sprite mirror +int iDither=0; +int32_t drawX; +int32_t drawY; +int32_t drawW; +int32_t drawH; +uint32_t dwCfgFixes; +uint32_t dwActFixes=0; +int iUseFixes; +int iUseDither=0; +BOOL bDoVSyncUpdate=FALSE; + +//////////////////////////////////////////////////////////////////////// +// Some ASM color convertion by LEWPY +//////////////////////////////////////////////////////////////////////// + +#ifdef USE_NASM + +#define BGR24to16 i386_BGR24to16 +__inline unsigned short BGR24to16 (uint32_t BGR); + +#else + +__inline unsigned short BGR24to16 (uint32_t BGR) +{ + return (unsigned short)(((BGR>>3)&0x1f)|((BGR&0xf80000)>>9)|((BGR&0xf800)>>6)); +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// Update global TP infos +//////////////////////////////////////////////////////////////////////// + +__inline void UpdateGlobalTP(unsigned short gdata) +{ + GlobalTextAddrX = (gdata << 6) & 0x3c0; // texture addr + + if(iGPUHeight==1024) + { + if(dwGPUVersion==2) + { + GlobalTextAddrY =((gdata & 0x60 ) << 3); + GlobalTextIL =(gdata & 0x2000) >> 13; + GlobalTextABR = (unsigned short)((gdata >> 7) & 0x3); + GlobalTextTP = (gdata >> 9) & 0x3; + if(GlobalTextTP==3) GlobalTextTP=2; + usMirror =0; + lGPUstatusRet = (lGPUstatusRet & 0xffffe000 ) | (gdata & 0x1fff ); + + // tekken dithering? right now only if dithering is forced by user + if(iUseDither==2) iDither=2; else iDither=0; + + return; + } + else + { + GlobalTextAddrY = (unsigned short)(((gdata << 4) & 0x100) | ((gdata >> 2) & 0x200)); + } + } + else GlobalTextAddrY = (gdata << 4) & 0x100; + + usMirror=gdata&0x3000; + + if(iUseDither==2) + { + iDither=2; + } + else + { + if(gdata&200) iDither=iUseDither; else iDither=0; + } + + GlobalTextTP = (gdata >> 7) & 0x3; // tex mode (4,8,15) + + if(GlobalTextTP==3) GlobalTextTP=2; // seen in Wild9 :( + + GlobalTextABR = (gdata >> 5) & 0x3; // blend mode + + lGPUstatusRet&=~0x07ff; // Clear the necessary bits + lGPUstatusRet|=(gdata & 0x07ff); // set the necessary bits +} + +//////////////////////////////////////////////////////////////////////// + +__inline void SetRenderMode(uint32_t DrawAttributes) +{ + DrawSemiTrans = (SEMITRANSBIT(DrawAttributes)) ? TRUE : FALSE; + + if(SHADETEXBIT(DrawAttributes)) + {g_m1=g_m2=g_m3=128;} + else + { + if((dwActFixes&4) && ((DrawAttributes&0x00ffffff)==0)) + DrawAttributes|=0x007f7f7f; + + g_m1=(short)(DrawAttributes&0xff); + g_m2=(short)((DrawAttributes>>8)&0xff); + g_m3=(short)((DrawAttributes>>16)&0xff); + } +} + +//////////////////////////////////////////////////////////////////////// + +// oki, here are the psx gpu coord rules: poly coords are +// 11 bit signed values (-1024...1023). If the x or y distance +// exceeds 1024, the polygon will not be drawn. +// Since quads are treated as two triangles by the real gpu, +// this 'discard rule' applies to each of the quad's triangle +// (so one triangle can be drawn, the other one discarded). +// Also, y drawing is wrapped at 512 one time, +// then it will get negative (and therefore not drawn). The +// 'CheckCoord' funcs are a simple (not comlete!) approach to +// do things right, I will add a better detection soon... the +// current approach will be easier to do in hw/accel plugins, imho + +// 11 bit signed +#define SIGNSHIFT 21 +#define CHKMAX_X 1024 +#define CHKMAX_Y 512 + +void AdjustCoord4() +{ + lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT); + lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT); + lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT); + lx3=(short)(((int)lx3<<SIGNSHIFT)>>SIGNSHIFT); + ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT); + ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT); + ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT); + ly3=(short)(((int)ly3<<SIGNSHIFT)>>SIGNSHIFT); +} + +void AdjustCoord3() +{ + lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT); + lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT); + lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT); + ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT); + ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT); + ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT); +} + +void AdjustCoord2() +{ + lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT); + lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT); + ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT); + ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT); +} + +void AdjustCoord1() +{ + lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT); + ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT); + + if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512) + lx0+=2048; + + if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512) + ly0+=2048; +} + +//////////////////////////////////////////////////////////////////////// +// special checks... nascar, syphon filter 2, mgs +//////////////////////////////////////////////////////////////////////// + +// xenogears FT4: not removed correctly right now... the tri 0,1,2 +// should get removed, the tri 1,2,3 should stay... pfff + +// x -466 1023 180 1023 +// y 20 -228 222 -100 + +// 0 __1 +// \ / \ +// 2___3 + +__inline BOOL CheckCoord4() +{ + if(lx0<0) + { + if(((lx1-lx0)>CHKMAX_X) || + ((lx2-lx0)>CHKMAX_X)) + { + if(lx3<0) + { + if((lx1-lx3)>CHKMAX_X) return TRUE; + if((lx2-lx3)>CHKMAX_X) return TRUE; + } + } + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + if((lx2-lx1)>CHKMAX_X) return TRUE; + if((lx3-lx1)>CHKMAX_X) return TRUE; + } + if(lx2<0) + { + if((lx0-lx2)>CHKMAX_X) return TRUE; + if((lx1-lx2)>CHKMAX_X) return TRUE; + if((lx3-lx2)>CHKMAX_X) return TRUE; + } + if(lx3<0) + { + if(((lx1-lx3)>CHKMAX_X) || + ((lx2-lx3)>CHKMAX_X)) + { + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + if((lx2-lx0)>CHKMAX_X) return TRUE; + } + } + } + + + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + if((ly2-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + if((ly2-ly1)>CHKMAX_Y) return TRUE; + if((ly3-ly1)>CHKMAX_Y) return TRUE; + } + if(ly2<0) + { + if((ly0-ly2)>CHKMAX_Y) return TRUE; + if((ly1-ly2)>CHKMAX_Y) return TRUE; + if((ly3-ly2)>CHKMAX_Y) return TRUE; + } + if(ly3<0) + { + if((ly1-ly3)>CHKMAX_Y) return TRUE; + if((ly2-ly3)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + +__inline BOOL CheckCoord3() +{ + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + if((lx2-lx0)>CHKMAX_X) return TRUE; + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + if((lx2-lx1)>CHKMAX_X) return TRUE; + } + if(lx2<0) + { + if((lx0-lx2)>CHKMAX_X) return TRUE; + if((lx1-lx2)>CHKMAX_X) return TRUE; + } + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + if((ly2-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + if((ly2-ly1)>CHKMAX_Y) return TRUE; + } + if(ly2<0) + { + if((ly0-ly2)>CHKMAX_Y) return TRUE; + if((ly1-ly2)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + + +__inline BOOL CheckCoord2() +{ + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + } + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + +__inline BOOL CheckCoordL(short slx0,short sly0,short slx1,short sly1) +{ + if(slx0<0) + { + if((slx1-slx0)>CHKMAX_X) return TRUE; + } + if(slx1<0) + { + if((slx0-slx1)>CHKMAX_X) return TRUE; + } + if(sly0<0) + { + if((sly1-sly0)>CHKMAX_Y) return TRUE; + } + if(sly1<0) + { + if((sly0-sly1)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + + +//////////////////////////////////////////////////////////////////////// +// mask stuff... used in silent hill +//////////////////////////////////////////////////////////////////////// + +void cmdSTP(unsigned char * baseAddr) +{ + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + lGPUstatusRet&=~0x1800; // Clear the necessary bits + lGPUstatusRet|=((gdata & 0x03) << 11); // Set the necessary bits + + if(gdata&1) {sSetMask=0x8000;lSetMask=0x80008000;} + else {sSetMask=0; lSetMask=0; } + + if(gdata&2) bCheckMask=TRUE; + else bCheckMask=FALSE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: Set texture page infos +//////////////////////////////////////////////////////////////////////// + +void cmdTexturePage(unsigned char * baseAddr) +{ + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + UpdateGlobalTP((unsigned short)gdata); + GlobalTextREST = (gdata&0x00ffffff)>>9; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: turn on/off texture window +//////////////////////////////////////////////////////////////////////// + +void cmdTextureWindow(unsigned char *baseAddr) +{ + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + uint32_t YAlign,XAlign; + + lGPUInfoVals[INFO_TW]=gdata&0xFFFFF; + + if(gdata & 0x020) + TWin.Position.y1 = 8; // xxxx1 + else if (gdata & 0x040) + TWin.Position.y1 = 16; // xxx10 + else if (gdata & 0x080) + TWin.Position.y1 = 32; // xx100 + else if (gdata & 0x100) + TWin.Position.y1 = 64; // x1000 + else if (gdata & 0x200) + TWin.Position.y1 = 128; // 10000 + else + TWin.Position.y1 = 256; // 00000 + + // Texture window size is determined by the least bit set of the relevant 5 bits + + if (gdata & 0x001) + TWin.Position.x1 = 8; // xxxx1 + else if (gdata & 0x002) + TWin.Position.x1 = 16; // xxx10 + else if (gdata & 0x004) + TWin.Position.x1 = 32; // xx100 + else if (gdata & 0x008) + TWin.Position.x1 = 64; // x1000 + else if (gdata & 0x010) + TWin.Position.x1 = 128; // 10000 + else + TWin.Position.x1 = 256; // 00000 + + // Re-calculate the bit field, because we can't trust what is passed in the data + + + YAlign = (uint32_t)(32 - (TWin.Position.y1 >> 3)); + XAlign = (uint32_t)(32 - (TWin.Position.x1 >> 3)); + + // Absolute position of the start of the texture window + + TWin.Position.y0 = (short)(((gdata >> 15) & YAlign) << 3); + TWin.Position.x0 = (short)(((gdata >> 10) & XAlign) << 3); + + if((TWin.Position.x0 == 0 && // tw turned off + TWin.Position.y0 == 0 && + TWin.Position.x1 == 0 && + TWin.Position.y1 == 0) || + (TWin.Position.x1 == 256 && + TWin.Position.y1 == 256)) + { + bUsingTWin = FALSE; // -> just do it + } + else // otherwise + { + bUsingTWin = TRUE; // -> tw turned on + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: start of drawing area... primitives will be clipped inside +//////////////////////////////////////////////////////////////////////// + + + +void cmdDrawAreaStart(unsigned char * baseAddr) +{ + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + drawX = gdata & 0x3ff; // for soft drawing + + if(dwGPUVersion==2) + { + lGPUInfoVals[INFO_DRAWSTART]=gdata&0x3FFFFF; + drawY = (gdata>>12)&0x3ff; + if(drawY>=1024) drawY=1023; // some security + } + else + { + lGPUInfoVals[INFO_DRAWSTART]=gdata&0xFFFFF; + drawY = (gdata>>10)&0x3ff; + if(drawY>=512) drawY=511; // some security + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: end of drawing area... primitives will be clipped inside +//////////////////////////////////////////////////////////////////////// + +void cmdDrawAreaEnd(unsigned char * baseAddr) +{ + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + drawW = gdata & 0x3ff; // for soft drawing + + if(dwGPUVersion==2) + { + lGPUInfoVals[INFO_DRAWEND]=gdata&0x3FFFFF; + drawH = (gdata>>12)&0x3ff; + if(drawH>=1024) drawH=1023; // some security + } + else + { + lGPUInfoVals[INFO_DRAWEND]=gdata&0xFFFFF; + drawH = (gdata>>10)&0x3ff; + if(drawH>=512) drawH=511; // some security + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw offset... will be added to prim coords +//////////////////////////////////////////////////////////////////////// + +void cmdDrawOffset(unsigned char * baseAddr) +{ + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + PSXDisplay.DrawOffset.x = (short)(gdata & 0x7ff); + + if(dwGPUVersion==2) + { + lGPUInfoVals[INFO_DRAWOFF]=gdata&0x7FFFFF; + PSXDisplay.DrawOffset.y = (short)((gdata>>12) & 0x7ff); + } + else + { + lGPUInfoVals[INFO_DRAWOFF]=gdata&0x3FFFFF; + PSXDisplay.DrawOffset.y = (short)((gdata>>11) & 0x7ff); + } + + PSXDisplay.DrawOffset.y=(short)(((int)PSXDisplay.DrawOffset.y<<21)>>21); + PSXDisplay.DrawOffset.x=(short)(((int)PSXDisplay.DrawOffset.x<<21)>>21); +} + +//////////////////////////////////////////////////////////////////////// +// cmd: load image to vram +//////////////////////////////////////////////////////////////////////// + +void primLoadImage(unsigned char * baseAddr) +{ + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + VRAMWrite.x = GETLEs16(&sgpuData[2])&0x3ff; + VRAMWrite.y = GETLEs16(&sgpuData[3])&iGPUHeightMask; + VRAMWrite.Width = GETLEs16(&sgpuData[4]); + VRAMWrite.Height = GETLEs16(&sgpuData[5]); + + DataWriteMode = DR_VRAMTRANSFER; + + VRAMWrite.ImagePtr = psxVuw + (VRAMWrite.y<<10) + VRAMWrite.x; + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining = VRAMWrite.Height; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: vram -> psx mem +//////////////////////////////////////////////////////////////////////// + +void primStoreImage(unsigned char * baseAddr) +{ + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + VRAMRead.x = GETLEs16(&sgpuData[2])&0x03ff; + VRAMRead.y = GETLEs16(&sgpuData[3])&iGPUHeightMask; + VRAMRead.Width = GETLEs16(&sgpuData[4]); + VRAMRead.Height = GETLEs16(&sgpuData[5]); + + VRAMRead.ImagePtr = psxVuw + (VRAMRead.y<<10) + VRAMRead.x; + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining = VRAMRead.Height; + + DataReadMode = DR_VRAMTRANSFER; + + lGPUstatusRet |= GPUSTATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: blkfill - NO primitive! Doesn't care about draw areas... +//////////////////////////////////////////////////////////////////////// + +void primBlkFill(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + short sX = GETLEs16(&sgpuData[2]); + short sY = GETLEs16(&sgpuData[3]); + short sW = GETLEs16(&sgpuData[4]) & 0x3ff; + short sH = GETLEs16(&sgpuData[5]) & 0x3ff; + + sW = (sW+15) & ~15; + + // Increase H & W if they are one short of full values, because they never can be full values + if (sH >= 1023) sH=1024; + if (sW >= 1023) sW=1024; + + // x and y of end pos + sW+=sX; + sH+=sY; + + FillSoftwareArea(sX, sY, sW, sH, BGR24to16(GETLE32(&gpuData[0]))); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: move image vram -> vram +//////////////////////////////////////////////////////////////////////// + +void primMoveImage(unsigned char * baseAddr) +{ + short *sgpuData = ((short *) baseAddr); + + short imageY0,imageX0,imageY1,imageX1,imageSX,imageSY,i,j; + + imageX0 = GETLEs16(&sgpuData[2])&0x03ff; + imageY0 = GETLEs16(&sgpuData[3])&iGPUHeightMask; + imageX1 = GETLEs16(&sgpuData[4])&0x03ff; + imageY1 = GETLEs16(&sgpuData[5])&iGPUHeightMask; + imageSX = GETLEs16(&sgpuData[6]); + imageSY = GETLEs16(&sgpuData[7]); + + if((imageX0 == imageX1) && (imageY0 == imageY1)) return; + if(imageSX<=0) return; + if(imageSY<=0) return; + + // ZN SF2: screwed moves + // + // move sgpuData[2],sgpuData[3],sgpuData[4],sgpuData[5],sgpuData[6],sgpuData[7] + // + // move 365 182 32723 -21846 17219 15427 + // move 127 160 147 -1 20817 13409 + // move 141 165 16275 -21862 -32126 13442 + // move 161 136 24620 -1 16962 13388 + // move 168 138 32556 -13090 -29556 15500 + // + // and here's the hack for it: + + if(iGPUHeight==1024 && GETLEs16(&sgpuData[7])>1024) return; + + if((imageY0+imageSY)>iGPUHeight || + (imageX0+imageSX)>1024 || + (imageY1+imageSY)>iGPUHeight || + (imageX1+imageSX)>1024) + { + int i,j; + for(j=0;j<imageSY;j++) + for(i=0;i<imageSX;i++) + psxVuw [(1024*((imageY1+j)&iGPUHeightMask))+((imageX1+i)&0x3ff)]= + psxVuw[(1024*((imageY0+j)&iGPUHeightMask))+((imageX0+i)&0x3ff)]; + + bDoVSyncUpdate=TRUE; + + return; + } + + if(imageSX&1) // not dword aligned? slower func + { + unsigned short *SRCPtr, *DSTPtr; + unsigned short LineOffset; + + SRCPtr = psxVuw + (1024*imageY0) + imageX0; + DSTPtr = psxVuw + (1024*imageY1) + imageX1; + + LineOffset = 1024 - imageSX; + + for(j=0;j<imageSY;j++) + { + for(i=0;i<imageSX;i++) *DSTPtr++ = *SRCPtr++; + SRCPtr += LineOffset; + DSTPtr += LineOffset; + } + } + else // dword aligned + { + uint32_t *SRCPtr, *DSTPtr; + unsigned short LineOffset; + int dx=imageSX>>1; + + SRCPtr = (uint32_t *)(psxVuw + (1024*imageY0) + imageX0); + DSTPtr = (uint32_t *)(psxVuw + (1024*imageY1) + imageX1); + + LineOffset = 512 - dx; + + for(j=0;j<imageSY;j++) + { + for(i=0;i<dx;i++) *DSTPtr++ = *SRCPtr++; + SRCPtr += LineOffset; + DSTPtr += LineOffset; + } + } + + imageSX+=imageX1; + imageSY+=imageY1; + +/* + if(!PSXDisplay.Interlaced) // stupid frame skip stuff + { + if(UseFrameSkip && + imageX1<PSXDisplay.DisplayEnd.x && + imageSX>=PSXDisplay.DisplayPosition.x && + imageY1<PSXDisplay.DisplayEnd.y && + imageSY>=PSXDisplay.DisplayPosition.y) + updateDisplay(); + } +*/ + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw free-size Tile +//////////////////////////////////////////////////////////////////////// + +//#define SMALLDEBUG +//#include <dbgout.h> + +void primTileS(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t*)baseAddr); + short *sgpuData = ((short *) baseAddr); + short sW = GETLEs16(&sgpuData[4]) & 0x3ff; + short sH = GETLEs16(&sgpuData[5]) & iGPUHeightMask; // mmm... limit tiles to 0x1ff or height? + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + // x and y of start + ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; + ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; + lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; + lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + if(!(iTileCheat && sH==32 && GETLE32(&gpuData[0])==0x60ffffff)) // special cheat for certain ZiNc games + FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, + BGR24to16(GETLE32(&gpuData[0]))); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw 1 dot Tile (point) +//////////////////////////////////////////////////////////////////////// + +void primTile1(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t*)baseAddr); + short *sgpuData = ((short *) baseAddr); + short sH = 1; + short sW = 1; + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + // x and y of start + ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; + ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; + lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; + lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, + BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw 8 dot Tile (small rect) +//////////////////////////////////////////////////////////////////////// + +void primTile8(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t*)baseAddr); + short *sgpuData = ((short *) baseAddr); + short sH = 8; + short sW = 8; + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + // x and y of start + ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; + ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; + lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; + lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, + BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw 16 dot Tile (medium rect) +//////////////////////////////////////////////////////////////////////// + +void primTile16(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t*)baseAddr); + short *sgpuData = ((short *) baseAddr); + short sH = 16; + short sW = 16; + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + // x and y of start + ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; + ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; + lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; + lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, + BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: small sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt8(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + SetRenderMode(GETLE32(&gpuData[0])); + + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,8,8); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,8,8); + else DrawSoftwareSprite(baseAddr,8,8, + baseAddr[8], + baseAddr[9]); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: medium sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt16(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + SetRenderMode(GETLE32(&gpuData[0])); + + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,16,16); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,16,16); + else DrawSoftwareSprite(baseAddr,16,16, + baseAddr[8], + baseAddr[9]); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: free-size sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +// func used on texture coord wrap +void primSprtSRest(unsigned char * baseAddr,unsigned short type) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + unsigned short sTypeRest=0; + + short s; + short sX = GETLEs16(&sgpuData[2]); + short sY = GETLEs16(&sgpuData[3]); + short sW = GETLEs16(&sgpuData[6]) & 0x3ff; + short sH = GETLEs16(&sgpuData[7]) & 0x1ff; + short tX = baseAddr[8]; + short tY = baseAddr[9]; + + switch(type) + { + case 1: + s=256-baseAddr[8]; + sW-=s; + sX+=s; + tX=0; + break; + case 2: + s=256-baseAddr[9]; + sH-=s; + sY+=s; + tY=0; + break; + case 3: + s=256-baseAddr[8]; + sW-=s; + sX+=s; + tX=0; + s=256-baseAddr[9]; + sH-=s; + sY+=s; + tY=0; + break; + case 4: + s=512-baseAddr[8]; + sW-=s; + sX+=s; + tX=0; + break; + case 5: + s=512-baseAddr[9]; + sH-=s; + sY+=s; + tY=0; + break; + case 6: + s=512-baseAddr[8]; + sW-=s; + sX+=s; + tX=0; + s=512-baseAddr[9]; + sH-=s; + sY+=s; + tY=0; + break; + } + + SetRenderMode(GETLE32(&gpuData[0])); + + if(tX+sW>256) {sW=256-tX;sTypeRest+=1;} + if(tY+sH>256) {sH=256-tY;sTypeRest+=2;} + + lx0 = sX; + ly0 = sY; + + if(!(dwActFixes&8)) AdjustCoord1(); + + DrawSoftwareSprite(baseAddr,sW,sH,tX,tY); + + if(sTypeRest && type<4) + { + if(sTypeRest&1 && type==1) primSprtSRest(baseAddr,4); + if(sTypeRest&2 && type==2) primSprtSRest(baseAddr,5); + if(sTypeRest==3 && type==3) primSprtSRest(baseAddr,6); + } + +} + +//////////////////////////////////////////////////////////////////////// + +void primSprtS(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + short sW,sH; + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + sW = GETLEs16(&sgpuData[6]) & 0x3ff; + sH = GETLEs16(&sgpuData[7]) & 0x1ff; + + SetRenderMode(GETLE32(&gpuData[0])); + + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sW,sH); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,sW,sH); + else + { + unsigned short sTypeRest=0; + short tX=baseAddr[8]; + short tY=baseAddr[9]; + + if(tX+sW>256) {sW=256-tX;sTypeRest+=1;} + if(tY+sH>256) {sH=256-tY;sTypeRest+=2;} + + DrawSoftwareSprite(baseAddr,sW,sH,tX,tY); + + if(sTypeRest) + { + if(sTypeRest&1) primSprtSRest(baseAddr,1); + if(sTypeRest&2) primSprtSRest(baseAddr,2); + if(sTypeRest==3) primSprtSRest(baseAddr,3); + } + + } + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyF4(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[4]); + ly1 = GETLEs16(&sgpuData[5]); + lx2 = GETLEs16(&sgpuData[6]); + ly2 = GETLEs16(&sgpuData[7]); + lx3 = GETLEs16(&sgpuData[8]); + ly3 = GETLEs16(&sgpuData[9]); + + if(!(dwActFixes&8)) + { + AdjustCoord4(); + if(CheckCoord4()) return; + } + + offsetPSX4(); + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + drawPoly4F(GETLE32(&gpuData[0])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyG4(unsigned char * baseAddr) +{ + uint32_t *gpuData = (uint32_t *)baseAddr; + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[6]); + ly1 = GETLEs16(&sgpuData[7]); + lx2 = GETLEs16(&sgpuData[10]); + ly2 = GETLEs16(&sgpuData[11]); + lx3 = GETLEs16(&sgpuData[14]); + ly3 = GETLEs16(&sgpuData[15]); + + if(!(dwActFixes&8)) + { + AdjustCoord4(); + if(CheckCoord4()) return; + } + + offsetPSX4(); + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + drawPoly4G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), + GETLE32(&gpuData[4]), GETLE32(&gpuData[6])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +void primPolyFT3(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[6]); + ly1 = GETLEs16(&sgpuData[7]); + lx2 = GETLEs16(&sgpuData[10]); + ly2 = GETLEs16(&sgpuData[11]); + + lLowerpart=GETLE32(&gpuData[4])>>16; + UpdateGlobalTP((unsigned short)lLowerpart); + + if(!(dwActFixes&8)) + { + AdjustCoord3(); + if(CheckCoord3()) return; + } + + offsetPSX3(); + SetRenderMode(GETLE32(&gpuData[0])); + + drawPoly3FT(baseAddr); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +void primPolyFT4(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[6]); + ly1 = GETLEs16(&sgpuData[7]); + lx2 = GETLEs16(&sgpuData[10]); + ly2 = GETLEs16(&sgpuData[11]); + lx3 = GETLEs16(&sgpuData[14]); + ly3 = GETLEs16(&sgpuData[15]); + + lLowerpart=GETLE32(&gpuData[4])>>16; + UpdateGlobalTP((unsigned short)lLowerpart); + + if(!(dwActFixes&8)) + { + AdjustCoord4(); + if(CheckCoord4()) return; + } + + offsetPSX4(); + + SetRenderMode(GETLE32(&gpuData[0])); + + drawPoly4FT(baseAddr); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT3(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[8]); + ly1 = GETLEs16(&sgpuData[9]); + lx2 = GETLEs16(&sgpuData[14]); + ly2 = GETLEs16(&sgpuData[15]); + + lLowerpart=GETLE32(&gpuData[5])>>16; + UpdateGlobalTP((unsigned short)lLowerpart); + + if(!(dwActFixes&8)) + { + AdjustCoord3(); + if(CheckCoord3()) return; + } + + offsetPSX3(); + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + if(SHADETEXBIT(GETLE32(&gpuData[0]))) + { + gpuData[0] = (gpuData[0]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); + gpuData[3] = (gpuData[3]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); + gpuData[6] = (gpuData[6]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); + } + + drawPoly3GT(baseAddr); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyG3(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[6]); + ly1 = GETLEs16(&sgpuData[7]); + lx2 = GETLEs16(&sgpuData[10]); + ly2 = GETLEs16(&sgpuData[11]); + + if(!(dwActFixes&8)) + { + AdjustCoord3(); + if(CheckCoord3()) return; + } + + offsetPSX3(); + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + drawPoly3G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), GETLE32(&gpuData[4])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT4(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[8]); + ly1 = GETLEs16(&sgpuData[9]); + lx2 = GETLEs16(&sgpuData[14]); + ly2 = GETLEs16(&sgpuData[15]); + lx3 = GETLEs16(&sgpuData[20]); + ly3 = GETLEs16(&sgpuData[21]); + + lLowerpart=GETLE32(&gpuData[5])>>16; + UpdateGlobalTP((unsigned short)lLowerpart); + + if(!(dwActFixes&8)) + { + AdjustCoord4(); + if(CheckCoord4()) return; + } + + offsetPSX4(); + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + if(SHADETEXBIT(GETLE32(&gpuData[0]))) + { + gpuData[0] = (gpuData[0]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); + gpuData[3] = (gpuData[3]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); + gpuData[6] = (gpuData[6]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); + gpuData[9] = (gpuData[9]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); + } + + drawPoly4GT(baseAddr); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyF3(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[4]); + ly1 = GETLEs16(&sgpuData[5]); + lx2 = GETLEs16(&sgpuData[6]); + ly2 = GETLEs16(&sgpuData[7]); + + if(!(dwActFixes&8)) + { + AdjustCoord3(); + if(CheckCoord3()) return; + } + + offsetPSX3(); + SetRenderMode(GETLE32(&gpuData[0])); + + drawPoly3F(GETLE32(&gpuData[0])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping shaded polylines +//////////////////////////////////////////////////////////////////////// + +void primLineGSkip(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + int iMax=255; + int i=2; + + ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); + lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); + + while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=4)) + { + i++; + ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); + lx1 = (short)(GETLE32(&gpuData[i]) & 0xffff); + i++;if(i>iMax) break; + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: shaded polylines +//////////////////////////////////////////////////////////////////////// + +void primLineGEx(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + int iMax=255; + uint32_t lc0,lc1; + short slx0,slx1,sly0,sly1;int i=2;BOOL bDraw=TRUE; + + sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); + slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); + + if(!(dwActFixes&8)) + { + slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT); + sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT); + } + + lc1 = gpuData[0] & 0xffffff; + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=4)) + { + sly0=sly1; slx0=slx1; lc0=lc1; + lc1=GETLE32(&gpuData[i]) & 0xffffff; + + i++; + + // no check needed on gshaded polyline positions + // if((gpuData[i] & 0xF000F000) == 0x50005000) break; + + sly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); + slx1 = (short)(GETLE32(&gpuData[i]) & 0xffff); + + if(!(dwActFixes&8)) + { + slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT); + sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT); + if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE; + } + + if ((lx0 != lx1) || (ly0 != ly1)) + { + ly0=sly0; + lx0=slx0; + ly1=sly1; + lx1=slx1; + + offsetPSX2(); + if(bDraw) DrawSoftwareLineShade(lc0, lc1); + } + i++; + if(i>iMax) break; + } + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: shaded polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineG2(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[6]); + ly1 = GETLEs16(&sgpuData[7]); + + if(!(dwActFixes&8)) + { + AdjustCoord2(); + if(CheckCoord2()) return; + } + + if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;} + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + offsetPSX2(); + DrawSoftwareLineShade(GETLE32(&gpuData[0]),GETLE32(&gpuData[2])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping flat polylines +//////////////////////////////////////////////////////////////////////// + +void primLineFSkip(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + int i=2,iMax=255; + + ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); + lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); + + while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=3)) + { + ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); + lx1 = (short)(GETLE32(&gpuData[i]) & 0xffff); + i++;if(i>iMax) break; + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: drawing flat polylines +//////////////////////////////////////////////////////////////////////// + +void primLineFEx(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + int iMax; + short slx0,slx1,sly0,sly1;int i=2;BOOL bDraw=TRUE; + + iMax=255; + + sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); + slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); + if(!(dwActFixes&8)) + { + slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT); + sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT); + } + + SetRenderMode(GETLE32(&gpuData[0])); + + while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=3)) + { + sly0 = sly1;slx0=slx1; + sly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); + slx1 = (short)(GETLE32(&gpuData[i]) & 0xffff); + if(!(dwActFixes&8)) + { + slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT); + sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT); + + if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE; + } + + ly0=sly0; + lx0=slx0; + ly1=sly1; + lx1=slx1; + + offsetPSX2(); + if(bDraw) DrawSoftwareLineFlat(GETLE32(&gpuData[0])); + + i++;if(i>iMax) break; + } + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: drawing flat polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineF2(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[4]); + ly1 = GETLEs16(&sgpuData[5]); + + if(!(dwActFixes&8)) + { + AdjustCoord2(); + if(CheckCoord2()) return; + } + + if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;} + + offsetPSX2(); + SetRenderMode(GETLE32(&gpuData[0])); + + DrawSoftwareLineFlat(GETLE32(&gpuData[0])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: well, easiest command... not implemented +//////////////////////////////////////////////////////////////////////// + +void primNI(unsigned char *bA) +{ +} + +//////////////////////////////////////////////////////////////////////// +// cmd func ptr table +//////////////////////////////////////////////////////////////////////// + + +void (*primTableJ[256])(unsigned char *) = +{ + // 00 + primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI, + // 08 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 10 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 18 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 20 + primPolyF3,primPolyF3,primPolyF3,primPolyF3,primPolyFT3,primPolyFT3,primPolyFT3,primPolyFT3, + // 28 + primPolyF4,primPolyF4,primPolyF4,primPolyF4,primPolyFT4,primPolyFT4,primPolyFT4,primPolyFT4, + // 30 + primPolyG3,primPolyG3,primPolyG3,primPolyG3,primPolyGT3,primPolyGT3,primPolyGT3,primPolyGT3, + // 38 + primPolyG4,primPolyG4,primPolyG4,primPolyG4,primPolyGT4,primPolyGT4,primPolyGT4,primPolyGT4, + // 40 + primLineF2,primLineF2,primLineF2,primLineF2,primNI,primNI,primNI,primNI, + // 48 + primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx, + // 50 + primLineG2,primLineG2,primLineG2,primLineG2,primNI,primNI,primNI,primNI, + // 58 + primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx, + // 60 + primTileS,primTileS,primTileS,primTileS,primSprtS,primSprtS,primSprtS,primSprtS, + // 68 + primTile1,primTile1,primTile1,primTile1,primNI,primNI,primNI,primNI, + // 70 + primTile8,primTile8,primTile8,primTile8,primSprt8,primSprt8,primSprt8,primSprt8, + // 78 + primTile16,primTile16,primTile16,primTile16,primSprt16,primSprt16,primSprt16,primSprt16, + // 80 + primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 88 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 90 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 98 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a0 + primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c0 + primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // e0 + primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI, + // e8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI +}; + +//////////////////////////////////////////////////////////////////////// +// cmd func ptr table for skipping +//////////////////////////////////////////////////////////////////////// + +void (*primTableSkip[256])(unsigned char *) = +{ + // 00 + primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI, + // 08 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 10 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 18 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 20 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 28 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 30 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 38 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 40 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 48 + primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip, + // 50 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 58 + primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip, + // 60 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 68 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 70 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 78 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 80 + primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 88 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 90 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 98 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a0 + primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c0 + primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // e0 + primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI, + // e8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI +}; diff --git a/plugins/dfxvideo/prim.h b/plugins/dfxvideo/prim.h new file mode 100644 index 00000000..c37c12b0 --- /dev/null +++ b/plugins/dfxvideo/prim.h @@ -0,0 +1,24 @@ +/*************************************************************************** + prim.h - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#ifndef _PRIMDRAW_H_ +#define _PRIMDRAW_H_ + +void UploadScreen (long Position); +void PrepareFullScreenUpload (long Position); + +#endif // _PRIMDRAW_H_ diff --git a/plugins/dfxvideo/soft.c b/plugins/dfxvideo/soft.c new file mode 100644 index 00000000..0a55693a --- /dev/null +++ b/plugins/dfxvideo/soft.c @@ -0,0 +1,8484 @@ +/*************************************************************************** + soft.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define _IN_SOFT + +#include "externals.h" +#include "soft.h" + +//#define VC_INLINE +#include "gpu.h" +#include "prim.h" +#include "menu.h" +#include "swap.h" + + +//////////////////////////////////////////////////////////////////////////////////// +// "NO EDGE BUFFER" POLY VERSION... FUNCS BASED ON FATMAP.TXT FROM MRI / Doomsday +//////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////// +// defines +//////////////////////////////////////////////////////////////////////////////////// + +// switches for painting textured quads as 2 triangles (small glitches, but better shading!) +// can be toggled by game fix 0x200 in version 1.17 anyway, so let the defines enabled! + +#define POLYQUAD3 +#define POLYQUAD3GT + +// fast solid loops... a bit more additional code, of course + +#define FASTSOLID + +// psx blending mode 3 with 25% incoming color (instead 50% without the define) + +#define HALFBRIGHTMODE3 + +// color decode defines + +#define XCOL1(x) (x & 0x1f) +#define XCOL2(x) (x & 0x3e0) +#define XCOL3(x) (x & 0x7c00) + +#define XCOL1D(x) (x & 0x1f) +#define XCOL2D(x) ((x>>5) & 0x1f) +#define XCOL3D(x) ((x>>10) & 0x1f) + +#define X32TCOL1(x) ((x & 0x001f001f)<<7) +#define X32TCOL2(x) ((x & 0x03e003e0)<<2) +#define X32TCOL3(x) ((x & 0x7c007c00)>>3) + +#define X32COL1(x) (x & 0x001f001f) +#define X32COL2(x) ((x>>5) & 0x001f001f) +#define X32COL3(x) ((x>>10) & 0x001f001f) + +#define X32ACOL1(x) (x & 0x001e001e) +#define X32ACOL2(x) ((x>>5) & 0x001e001e) +#define X32ACOL3(x) ((x>>10) & 0x001e001e) + +#define X32BCOL1(x) (x & 0x001c001c) +#define X32BCOL2(x) ((x>>5) & 0x001c001c) +#define X32BCOL3(x) ((x>>10) & 0x001c001c) + +#define X32PSXCOL(r,g,b) ((g<<10)|(b<<5)|r) + +#define XPSXCOL(r,g,b) ((g&0x7c00)|(b&0x3e0)|(r&0x1f)) + +//////////////////////////////////////////////////////////////////////////////////// +// soft globals +//////////////////////////////////////////////////////////////////////////////////// + +short g_m1=255,g_m2=255,g_m3=255; +short DrawSemiTrans=FALSE; +short Ymin; +short Ymax; + +short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3; // global psx vertex coords +int32_t GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP; +int32_t GlobalTextREST,GlobalTextABR,GlobalTextPAGE; + +//////////////////////////////////////////////////////////////////////// +// POLYGON OFFSET FUNCS +//////////////////////////////////////////////////////////////////////// + +void offsetPSXLine(void) +{ + short x0,x1,y0,y1,dx,dy;float px,py; + + x0 = lx0+1+PSXDisplay.DrawOffset.x; + x1 = lx1+1+PSXDisplay.DrawOffset.x; + y0 = ly0+1+PSXDisplay.DrawOffset.y; + y1 = ly1+1+PSXDisplay.DrawOffset.y; + + dx=x1-x0; + dy=y1-y0; + + // tricky line width without sqrt + + if(dx>=0) + { + if(dy>=0) + { + px=0.5f; + if(dx>dy) py=-0.5f; + else if(dx<dy) py= 0.5f; + else py= 0.0f; + } + else + { + py=-0.5f; + dy=-dy; + if(dx>dy) px= 0.5f; + else if(dx<dy) px=-0.5f; + else px= 0.0f; + } + } + else + { + if(dy>=0) + { + py=0.5f; + dx=-dx; + if(dx>dy) px=-0.5f; + else if(dx<dy) px= 0.5f; + else px= 0.0f; + } + else + { + px=-0.5f; + if(dx>dy) py=-0.5f; + else if(dx<dy) py= 0.5f; + else py= 0.0f; + } + } + + lx0=(short)((float)x0-px); + lx3=(short)((float)x0+py); + + ly0=(short)((float)y0-py); + ly3=(short)((float)y0-px); + + lx1=(short)((float)x1-py); + lx2=(short)((float)x1+px); + + ly1=(short)((float)y1+px); + ly2=(short)((float)y1+py); +} + +void offsetPSX2(void) +{ + lx0 += PSXDisplay.DrawOffset.x; + ly0 += PSXDisplay.DrawOffset.y; + lx1 += PSXDisplay.DrawOffset.x; + ly1 += PSXDisplay.DrawOffset.y; +} + +void offsetPSX3(void) +{ + lx0 += PSXDisplay.DrawOffset.x; + ly0 += PSXDisplay.DrawOffset.y; + lx1 += PSXDisplay.DrawOffset.x; + ly1 += PSXDisplay.DrawOffset.y; + lx2 += PSXDisplay.DrawOffset.x; + ly2 += PSXDisplay.DrawOffset.y; +} + +void offsetPSX4(void) +{ + lx0 += PSXDisplay.DrawOffset.x; + ly0 += PSXDisplay.DrawOffset.y; + lx1 += PSXDisplay.DrawOffset.x; + ly1 += PSXDisplay.DrawOffset.y; + lx2 += PSXDisplay.DrawOffset.x; + ly2 += PSXDisplay.DrawOffset.y; + lx3 += PSXDisplay.DrawOffset.x; + ly3 += PSXDisplay.DrawOffset.y; +} + +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +// PER PIXEL FUNCS +//////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + + +unsigned char dithertable[16] = +{ + 7, 0, 6, 1, + 2, 5, 3, 4, + 1, 6, 0, 7, + 4, 3, 5, 2 +}; + +void Dither16(unsigned short * pdest,uint32_t r,uint32_t g,uint32_t b,unsigned short sM) +{ + unsigned char coeff; + unsigned char rlow, glow, blow; + int x,y; + + x=pdest-psxVuw; + y=x>>10; + x-=(y<<10); + + coeff = dithertable[(y&3)*4+(x&3)]; + + rlow = r&7; glow = g&7; blow = b&7; + + r>>=3; g>>=3; b>>=3; + + if ((r < 0x1F) && rlow > coeff) r++; + if ((g < 0x1F) && glow > coeff) g++; + if ((b < 0x1F) && blow > coeff) b++; + + PUTLE16(pdest, ((unsigned short)b<<10) | + ((unsigned short)g<<5) | + (unsigned short)r | sM); +} + +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + +__inline void GetShadeTransCol_Dither(unsigned short * pdest, int32_t m1, int32_t m2, int32_t m3) +{ + int32_t r,g,b; + + if(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; + + if(DrawSemiTrans) + { + r=((XCOL1D(GETLE16(pdest)))<<3); + b=((XCOL2D(GETLE16(pdest)))<<3); + g=((XCOL3D(GETLE16(pdest)))<<3); + + if(GlobalTextABR==0) + { + r=(r>>1)+(m1>>1); + b=(b>>1)+(m2>>1); + g=(g>>1)+(m3>>1); + } + else + if(GlobalTextABR==1) + { + r+=m1; + b+=m2; + g+=m3; + } + else + if(GlobalTextABR==2) + { + r-=m1; + b-=m2; + g-=m3; + if(r&0x80000000) r=0; + if(b&0x80000000) b=0; + if(g&0x80000000) g=0; + } + else + { +#ifdef HALFBRIGHTMODE3 + r+=(m1>>2); + b+=(m2>>2); + g+=(m3>>2); +#else + r+=(m1>>1); + b+=(m2>>1); + g+=(m3>>1); +#endif + } + } + else + { + r=m1; + b=m2; + g=m3; + } + + if(r&0x7FFFFF00) r=0xff; + if(b&0x7FFFFF00) b=0xff; + if(g&0x7FFFFF00) g=0xff; + + Dither16(pdest,r,b,g,sSetMask); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetShadeTransCol(unsigned short * pdest,unsigned short color) +{ + if(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; + + if(DrawSemiTrans) + { + int32_t r,g,b; + + if(GlobalTextABR==0) + { + PUTLE16(pdest, (((GETLE16(pdest)&0x7bde)>>1)+(((color)&0x7bde)>>1))|sSetMask);//0x8000; + return; +/* + r=(XCOL1(*pdest)>>1)+((XCOL1(color))>>1); + b=(XCOL2(*pdest)>>1)+((XCOL2(color))>>1); + g=(XCOL3(*pdest)>>1)+((XCOL3(color))>>1); +*/ + } + else + if(GlobalTextABR==1) + { + r=(XCOL1(GETLE16(pdest)))+((XCOL1(color))); + b=(XCOL2(GETLE16(pdest)))+((XCOL2(color))); + g=(XCOL3(GETLE16(pdest)))+((XCOL3(color))); + } + else + if(GlobalTextABR==2) + { + r=(XCOL1(GETLE16(pdest)))-((XCOL1(color))); + b=(XCOL2(GETLE16(pdest)))-((XCOL2(color))); + g=(XCOL3(GETLE16(pdest)))-((XCOL3(color))); + if(r&0x80000000) r=0; + if(b&0x80000000) b=0; + if(g&0x80000000) g=0; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(XCOL1(GETLE16(pdest)))+((XCOL1(color))>>2); + b=(XCOL2(GETLE16(pdest)))+((XCOL2(color))>>2); + g=(XCOL3(GETLE16(pdest)))+((XCOL3(color))>>2); +#else + r=(XCOL1(GETLE16(pdest)))+((XCOL1(color))>>1); + b=(XCOL2(GETLE16(pdest)))+((XCOL2(color))>>1); + g=(XCOL3(GETLE16(pdest)))+((XCOL3(color))>>1); +#endif + } + + if(r&0x7FFFFFE0) r=0x1f; + if(b&0x7FFFFC00) b=0x3e0; + if(g&0x7FFF8000) g=0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|sSetMask);//0x8000; + } + else PUTLE16(pdest, color|sSetMask); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetShadeTransCol32(uint32_t * pdest,uint32_t color) +{ + if(DrawSemiTrans) + { + int32_t r,g,b; + + if(GlobalTextABR==0) + { + if(!bCheckMask) + { + PUTLE32(pdest, (((GETLE32(pdest)&0x7bde7bde)>>1)+(((color)&0x7bde7bde)>>1))|lSetMask);//0x80008000; + return; + } + r=(X32ACOL1(GETLE32(pdest))>>1)+((X32ACOL1(color))>>1); + b=(X32ACOL2(GETLE32(pdest))>>1)+((X32ACOL2(color))>>1); + g=(X32ACOL3(GETLE32(pdest))>>1)+((X32ACOL3(color))>>1); + } + else + if(GlobalTextABR==1) + { + r=(X32COL1(GETLE32(pdest)))+((X32COL1(color))); + b=(X32COL2(GETLE32(pdest)))+((X32COL2(color))); + g=(X32COL3(GETLE32(pdest)))+((X32COL3(color))); + } + else + if(GlobalTextABR==2) + { + int32_t sr,sb,sg,src,sbc,sgc,c; + src=XCOL1(color);sbc=XCOL2(color);sgc=XCOL3(color); + c=GETLE32(pdest)>>16; + sr=(XCOL1(c))-src; if(sr&0x8000) sr=0; + sb=(XCOL2(c))-sbc; if(sb&0x8000) sb=0; + sg=(XCOL3(c))-sgc; if(sg&0x8000) sg=0; + r=((int32_t)sr)<<16;b=((int32_t)sb)<<11;g=((int32_t)sg)<<6; + c=LOWORD(GETLE32(pdest)); + sr=(XCOL1(c))-src; if(sr&0x8000) sr=0; + sb=(XCOL2(c))-sbc; if(sb&0x8000) sb=0; + sg=(XCOL3(c))-sgc; if(sg&0x8000) sg=0; + r|=sr;b|=sb>>5;g|=sg>>10; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(X32COL1(GETLE32(pdest)))+((X32BCOL1(color))>>2); + b=(X32COL2(GETLE32(pdest)))+((X32BCOL2(color))>>2); + g=(X32COL3(GETLE32(pdest)))+((X32BCOL3(color))>>2); +#else + r=(X32COL1(GETLE32(pdest)))+((X32ACOL1(color))>>1); + b=(X32COL2(GETLE32(pdest)))+((X32ACOL2(color))>>1); + g=(X32COL3(GETLE32(pdest)))+((X32ACOL3(color))>>1); +#endif + } + + if(r&0x7FE00000) r=0x1f0000|(r&0xFFFF); + if(r&0x7FE0) r=0x1f |(r&0xFFFF0000); + if(b&0x7FE00000) b=0x1f0000|(b&0xFFFF); + if(b&0x7FE0) b=0x1f |(b&0xFFFF0000); + if(g&0x7FE00000) g=0x1f0000|(g&0xFFFF); + if(g&0x7FE0) g=0x1f |(g&0xFFFF0000); + + if(bCheckMask) + { + uint32_t ma=GETLE32(pdest); + PUTLE32(pdest, (X32PSXCOL(r,g,b))|lSetMask);//0x80008000; + if(ma&0x80000000) PUTLE32(pdest, (ma&0xFFFF0000)|(*pdest&0xFFFF)); + if(ma&0x00008000) PUTLE32(pdest, (ma&0xFFFF) |(*pdest&0xFFFF0000)); + return; + } + PUTLE32(pdest, (X32PSXCOL(r,g,b))|lSetMask);//0x80008000; + } + else + { + if(bCheckMask) + { + uint32_t ma=GETLE32(pdest); + PUTLE32(pdest, color|lSetMask);//0x80008000; + if(ma&0x80000000) PUTLE32(pdest, (ma&0xFFFF0000)|(GETLE32(pdest)&0xFFFF)); + if(ma&0x00008000) PUTLE32(pdest, (ma&0xFFFF) |(GETLE32(pdest)&0xFFFF0000)); + return; + } + + PUTLE32(pdest, color|lSetMask);//0x80008000; + } +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG(unsigned short * pdest,unsigned short color) +{ + int32_t r,g,b;unsigned short l; + + if(color==0) return; + + if(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; + + l=sSetMask|(color&0x8000); + + if(DrawSemiTrans && (color&0x8000)) + { + if(GlobalTextABR==0) + { + unsigned short d; + d =(GETLE16(pdest)&0x7bde)>>1; + color =((color) &0x7bde)>>1; + r=(XCOL1(d))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(d))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(d))+((((XCOL3(color)))* g_m3)>>7); + +/* + r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_m3)>>7); +*/ + } + else + if(GlobalTextABR==1) + { + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color)))* g_m3)>>7); + } + else + if(GlobalTextABR==2) + { + r=(XCOL1(GETLE16(pdest)))-((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))-((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))-((((XCOL3(color)))* g_m3)>>7); + if(r&0x80000000) r=0; + if(b&0x80000000) b=0; + if(g&0x80000000) g=0; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>2)* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>2)* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>2)* g_m3)>>7); +#else + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>1)* g_m3)>>7); +#endif + } + } + else + { + r=((XCOL1(color))* g_m1)>>7; + b=((XCOL2(color))* g_m2)>>7; + g=((XCOL3(color))* g_m3)>>7; + } + + if(r&0x7FFFFFE0) r=0x1f; + if(b&0x7FFFFC00) b=0x3e0; + if(g&0x7FFF8000) g=0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|l); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG_S(unsigned short * pdest,unsigned short color) +{ + int32_t r,g,b;unsigned short l; + + if(color==0) return; + + l=sSetMask|(color&0x8000); + + r=((XCOL1(color))* g_m1)>>7; + b=((XCOL2(color))* g_m2)>>7; + g=((XCOL3(color))* g_m3)>>7; + + if(r&0x7FFFFFE0) r=0x1f; + if(b&0x7FFFFC00) b=0x3e0; + if(g&0x7FFF8000) g=0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|l); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG_SPR(unsigned short * pdest,unsigned short color) +{ + int32_t r,g,b;unsigned short l; + + if(color==0) return; + + if(bCheckMask && (GETLE16(pdest) & 0x8000)) return; + + l=sSetMask|(color&0x8000); + + if(DrawSemiTrans && (color&0x8000)) + { + if(GlobalTextABR==0) + { + unsigned short d; + d =(GETLE16(pdest)&0x7bde)>>1; + color =((color) &0x7bde)>>1; + r=(XCOL1(d))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(d))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(d))+((((XCOL3(color)))* g_m3)>>7); + +/* + r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_m3)>>7); +*/ + } + else + if(GlobalTextABR==1) + { + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color)))* g_m3)>>7); + } + else + if(GlobalTextABR==2) + { + r=(XCOL1(GETLE16(pdest)))-((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))-((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))-((((XCOL3(color)))* g_m3)>>7); + if(r&0x80000000) r=0; + if(b&0x80000000) b=0; + if(g&0x80000000) g=0; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>2)* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>2)* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>2)* g_m3)>>7); +#else + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>1)* g_m3)>>7); +#endif + } + } + else + { + r=((XCOL1(color))* g_m1)>>7; + b=((XCOL2(color))* g_m2)>>7; + g=((XCOL3(color))* g_m3)>>7; + } + + if(r&0x7FFFFFE0) r=0x1f; + if(b&0x7FFFFC00) b=0x3e0; + if(g&0x7FFF8000) g=0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|l); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG32(uint32_t * pdest,uint32_t color) +{ + int32_t r,g,b,l; + + if(color==0) return; + + l=lSetMask|(color&0x80008000); + + if(DrawSemiTrans && (color&0x80008000)) + { + if(GlobalTextABR==0) + { + r=((((X32TCOL1(GETLE32(pdest)))+((X32COL1(color)) * g_m1))&0xFF00FF00)>>8); + b=((((X32TCOL2(GETLE32(pdest)))+((X32COL2(color)) * g_m2))&0xFF00FF00)>>8); + g=((((X32TCOL3(GETLE32(pdest)))+((X32COL3(color)) * g_m3))&0xFF00FF00)>>8); + } + else + if(GlobalTextABR==1) + { + r=(X32COL1(GETLE32(pdest)))+(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); + } + else + if(GlobalTextABR==2) + { + int32_t t; + r=(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); + t=(GETLE32(pdest)&0x001f0000)-(r&0x003f0000); if(t&0x80000000) t=0; + r=(GETLE32(pdest)&0x0000001f)-(r&0x0000003f); if(r&0x80000000) r=0; + r|=t; + + b=(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); + t=((GETLE32(pdest)>>5)&0x001f0000)-(b&0x003f0000); if(t&0x80000000) t=0; + b=((GETLE32(pdest)>>5)&0x0000001f)-(b&0x0000003f); if(b&0x80000000) b=0; + b|=t; + + g=(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); + t=((GETLE32(pdest)>>10)&0x001f0000)-(g&0x003f0000); if(t&0x80000000) t=0; + g=((GETLE32(pdest)>>10)&0x0000001f)-(g&0x0000003f); if(g&0x80000000) g=0; + g|=t; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(X32COL1(GETLE32(pdest)))+(((((X32BCOL1(color))>>2)* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32BCOL2(color))>>2)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32BCOL3(color))>>2)* g_m3)&0xFF80FF80)>>7); +#else + r=(X32COL1(GETLE32(pdest)))+(((((X32ACOL1(color))>>1)* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32ACOL2(color))>>1)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32ACOL3(color))>>1)* g_m3)&0xFF80FF80)>>7); +#endif + } + + if(!(color&0x8000)) + { + r=(r&0xffff0000)|((((X32COL1(color))* g_m1)&0x0000FF80)>>7); + b=(b&0xffff0000)|((((X32COL2(color))* g_m2)&0x0000FF80)>>7); + g=(g&0xffff0000)|((((X32COL3(color))* g_m3)&0x0000FF80)>>7); + } + if(!(color&0x80000000)) + { + r=(r&0xffff)|((((X32COL1(color))* g_m1)&0xFF800000)>>7); + b=(b&0xffff)|((((X32COL2(color))* g_m2)&0xFF800000)>>7); + g=(g&0xffff)|((((X32COL3(color))* g_m3)&0xFF800000)>>7); + } + + } + else + { + r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; + b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; + g=(((X32COL3(color))* g_m3)&0xFF80FF80)>>7; + } + + if(r&0x7FE00000) r=0x1f0000|(r&0xFFFF); + if(r&0x7FE0) r=0x1f |(r&0xFFFF0000); + if(b&0x7FE00000) b=0x1f0000|(b&0xFFFF); + if(b&0x7FE0) b=0x1f |(b&0xFFFF0000); + if(g&0x7FE00000) g=0x1f0000|(g&0xFFFF); + if(g&0x7FE0) g=0x1f |(g&0xFFFF0000); + + if(bCheckMask) + { + uint32_t ma=GETLE32(pdest); + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|l); + + if((color&0xffff)==0 ) PUTLE32(pdest, (ma&0xffff)|(GETLE32(pdest)&0xffff0000)); + if((color&0xffff0000)==0) PUTLE32(pdest, (ma&0xffff0000)|(GETLE32(pdest)&0xffff)); + if(ma&0x80000000) PUTLE32(pdest, (ma&0xFFFF0000)|(GETLE32(pdest)&0xFFFF)); + if(ma&0x00008000) PUTLE32(pdest, (ma&0xFFFF) |(GETLE32(pdest)&0xFFFF0000)); + + return; + } + if((color&0xffff)==0 ) {PUTLE32(pdest, (GETLE32(pdest)&0xffff)|(((X32PSXCOL(r,g,b))|l)&0xffff0000));return;} + if((color&0xffff0000)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|l)&0xffff));return;} + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|l); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG32_S(uint32_t * pdest,uint32_t color) +{ + int32_t r,g,b; + + if(color==0) return; + + r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; + b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; + g=(((X32COL3(color))* g_m3)&0xFF80FF80)>>7; + + if(r&0x7FE00000) r=0x1f0000|(r&0xFFFF); + if(r&0x7FE0) r=0x1f |(r&0xFFFF0000); + if(b&0x7FE00000) b=0x1f0000|(b&0xFFFF); + if(b&0x7FE0) b=0x1f |(b&0xFFFF0000); + if(g&0x7FE00000) g=0x1f0000|(g&0xFFFF); + if(g&0x7FE0) g=0x1f |(g&0xFFFF0000); + + if((color&0xffff)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff0000));return;} + if((color&0xffff0000)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff));return;} + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000)); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG32_SPR(uint32_t * pdest,uint32_t color) +{ + int32_t r,g,b; + + if(color==0) return; + + if(DrawSemiTrans && (color&0x80008000)) + { + if(GlobalTextABR==0) + { + r=((((X32TCOL1(GETLE32(pdest)))+((X32COL1(color)) * g_m1))&0xFF00FF00)>>8); + b=((((X32TCOL2(GETLE32(pdest)))+((X32COL2(color)) * g_m2))&0xFF00FF00)>>8); + g=((((X32TCOL3(GETLE32(pdest)))+((X32COL3(color)) * g_m3))&0xFF00FF00)>>8); + } + else + if(GlobalTextABR==1) + { + r=(X32COL1(GETLE32(pdest)))+(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); + } + else + if(GlobalTextABR==2) + { + int32_t t; + r=(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); + t=(GETLE32(pdest)&0x001f0000)-(r&0x003f0000); if(t&0x80000000) t=0; + r=(GETLE32(pdest)&0x0000001f)-(r&0x0000003f); if(r&0x80000000) r=0; + r|=t; + + b=(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); + t=((GETLE32(pdest)>>5)&0x001f0000)-(b&0x003f0000); if(t&0x80000000) t=0; + b=((GETLE32(pdest)>>5)&0x0000001f)-(b&0x0000003f); if(b&0x80000000) b=0; + b|=t; + + g=(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); + t=((GETLE32(pdest)>>10)&0x001f0000)-(g&0x003f0000); if(t&0x80000000) t=0; + g=((GETLE32(pdest)>>10)&0x0000001f)-(g&0x0000003f); if(g&0x80000000) g=0; + g|=t; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(X32COL1(GETLE32(pdest)))+(((((X32BCOL1(color))>>2)* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32BCOL2(color))>>2)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32BCOL3(color))>>2)* g_m3)&0xFF80FF80)>>7); +#else + r=(X32COL1(GETLE32(pdest)))+(((((X32ACOL1(color))>>1)* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32ACOL2(color))>>1)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32ACOL3(color))>>1)* g_m3)&0xFF80FF80)>>7); +#endif + } + + if(!(color&0x8000)) + { + r=(r&0xffff0000)|((((X32COL1(color))* g_m1)&0x0000FF80)>>7); + b=(b&0xffff0000)|((((X32COL2(color))* g_m2)&0x0000FF80)>>7); + g=(g&0xffff0000)|((((X32COL3(color))* g_m3)&0x0000FF80)>>7); + } + if(!(color&0x80000000)) + { + r=(r&0xffff)|((((X32COL1(color))* g_m1)&0xFF800000)>>7); + b=(b&0xffff)|((((X32COL2(color))* g_m2)&0xFF800000)>>7); + g=(g&0xffff)|((((X32COL3(color))* g_m3)&0xFF800000)>>7); + } + + } + else + { + r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; + b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; + g=(((X32COL3(color))* g_m3)&0xFF80FF80)>>7; + } + + if(r&0x7FE00000) r=0x1f0000|(r&0xFFFF); + if(r&0x7FE0) r=0x1f |(r&0xFFFF0000); + if(b&0x7FE00000) b=0x1f0000|(b&0xFFFF); + if(b&0x7FE0) b=0x1f |(b&0xFFFF0000); + if(g&0x7FE00000) g=0x1f0000|(g&0xFFFF); + if(g&0x7FE0) g=0x1f |(g&0xFFFF0000); + + if(bCheckMask) + { + uint32_t ma=GETLE32(pdest); + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000)); + + if((color&0xffff)==0 ) PUTLE32(pdest, (ma&0xffff)|(GETLE32(pdest)&0xffff0000)); + if((color&0xffff0000)==0) PUTLE32(pdest, (ma&0xffff0000)|(GETLE32(pdest)&0xffff)); + if(ma&0x80000000) PUTLE32(pdest, (ma&0xFFFF0000)|(GETLE32(pdest)&0xFFFF)); + if(ma&0x00008000) PUTLE32(pdest, (ma&0xFFFF) |(GETLE32(pdest)&0xFFFF0000)); + + return; + } + if((color&0xffff)==0 ) {PUTLE32(pdest, (GETLE32(pdest)&0xffff)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff0000));return;} + if((color&0xffff0000)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff));return;} + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000)); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColGX_Dither(unsigned short * pdest,unsigned short color,int32_t m1,int32_t m2,int32_t m3) +{ + int32_t r,g,b; + + if(color==0) return; + + if(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; + + m1=(((XCOL1D(color)))*m1)>>4; + m2=(((XCOL2D(color)))*m2)>>4; + m3=(((XCOL3D(color)))*m3)>>4; + + if(DrawSemiTrans && (color&0x8000)) + { + r=((XCOL1D(GETLE16(pdest)))<<3); + b=((XCOL2D(GETLE16(pdest)))<<3); + g=((XCOL3D(GETLE16(pdest)))<<3); + + if(GlobalTextABR==0) + { + r=(r>>1)+(m1>>1); + b=(b>>1)+(m2>>1); + g=(g>>1)+(m3>>1); + } + else + if(GlobalTextABR==1) + { + r+=m1; + b+=m2; + g+=m3; + } + else + if(GlobalTextABR==2) + { + r-=m1; + b-=m2; + g-=m3; + if(r&0x80000000) r=0; + if(b&0x80000000) b=0; + if(g&0x80000000) g=0; + } + else + { +#ifdef HALFBRIGHTMODE3 + r+=(m1>>2); + b+=(m2>>2); + g+=(m3>>2); +#else + r+=(m1>>1); + b+=(m2>>1); + g+=(m3>>1); +#endif + } + } + else + { + r=m1; + b=m2; + g=m3; + } + + if(r&0x7FFFFF00) r=0xff; + if(b&0x7FFFFF00) b=0xff; + if(g&0x7FFFFF00) g=0xff; + + Dither16(pdest,r,b,g,sSetMask|(color&0x8000)); + +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColGX(unsigned short * pdest,unsigned short color,short m1,short m2,short m3) +{ + int32_t r,g,b;unsigned short l; + + if(color==0) return; + + if(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; + + l=sSetMask|(color&0x8000); + + if(DrawSemiTrans && (color&0x8000)) + { + if(GlobalTextABR==0) + { + unsigned short d; + d =(GETLE16(pdest)&0x7bde)>>1; + color =((color) &0x7bde)>>1; + r=(XCOL1(d))+((((XCOL1(color)))* m1)>>7); + b=(XCOL2(d))+((((XCOL2(color)))* m2)>>7); + g=(XCOL3(d))+((((XCOL3(color)))* m3)>>7); +/* + r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* m1)>>7); + b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* m2)>>7); + g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* m3)>>7); +*/ + } + else + if(GlobalTextABR==1) + { + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color)))* m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color)))* m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color)))* m3)>>7); + } + else + if(GlobalTextABR==2) + { + r=(XCOL1(GETLE16(pdest)))-((((XCOL1(color)))* m1)>>7); + b=(XCOL2(GETLE16(pdest)))-((((XCOL2(color)))* m2)>>7); + g=(XCOL3(GETLE16(pdest)))-((((XCOL3(color)))* m3)>>7); + if(r&0x80000000) r=0; + if(b&0x80000000) b=0; + if(g&0x80000000) g=0; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>2)* m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>2)* m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>2)* m3)>>7); +#else + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>1)* m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>1)* m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>1)* m3)>>7); +#endif + } + } + else + { + r=((XCOL1(color))* m1)>>7; + b=((XCOL2(color))* m2)>>7; + g=((XCOL3(color))* m3)>>7; + } + + if(r&0x7FFFFFE0) r=0x1f; + if(b&0x7FFFFC00) b=0x3e0; + if(g&0x7FFF8000) g=0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|l); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColGX_S(unsigned short * pdest,unsigned short color,short m1,short m2,short m3) +{ + int32_t r,g,b; + + if(color==0) return; + + r=((XCOL1(color))* m1)>>7; + b=((XCOL2(color))* m2)>>7; + g=((XCOL3(color))* m3)>>7; + + if(r&0x7FFFFFE0) r=0x1f; + if(b&0x7FFFFC00) b=0x3e0; + if(g&0x7FFF8000) g=0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|sSetMask|(color&0x8000)); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColGX32_S(uint32_t * pdest,uint32_t color,short m1,short m2,short m3) +{ + int32_t r,g,b; + + if(color==0) return; + + r=(((X32COL1(color))* m1)&0xFF80FF80)>>7; + b=(((X32COL2(color))* m2)&0xFF80FF80)>>7; + g=(((X32COL3(color))* m3)&0xFF80FF80)>>7; + + if(r&0x7FE00000) r=0x1f0000|(r&0xFFFF); + if(r&0x7FE0) r=0x1f |(r&0xFFFF0000); + if(b&0x7FE00000) b=0x1f0000|(b&0xFFFF); + if(b&0x7FE0) b=0x1f |(b&0xFFFF0000); + if(g&0x7FE00000) g=0x1f0000|(g&0xFFFF); + if(g&0x7FE0) g=0x1f |(g&0xFFFF0000); + + if((color&0xffff)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff0000));return;} + if((color&0xffff0000)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff));return;} + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000)); +} + +//////////////////////////////////////////////////////////////////////// +// FILL FUNCS +//////////////////////////////////////////////////////////////////////// + +void FillSoftwareAreaTrans(short x0,short y0,short x1, // FILL AREA TRANS + short y1,unsigned short col) +{ + short j,i,dx,dy; + + if(y0>y1) return; + if(x0>x1) return; + + if(x1<drawX) return; + if(y1<drawY) return; + if(x0>drawW) return; + if(y0>drawH) return; + + x1=min(x1,drawW+1); + y1=min(y1,drawH+1); + x0=max(x0,drawX); + y0=max(y0,drawY); + + if(y0>=iGPUHeight) return; + if(x0>1023) return; + + if(y1>iGPUHeight) y1=iGPUHeight; + if(x1>1024) x1=1024; + + dx=x1-x0;dy=y1-y0; + + if(dx==1 && dy==1 && x0==1020 && y0==511) // special fix for pinball game... emu protection??? + { +/* +m->v 1020 511 1 1 +writedatamem 0x00000000 1 +tile1 newcol 7fff (orgcol 0xffffff), oldvram 0 +v->m 1020 511 1 1 +readdatamem 0x00007fff 1 +m->v 1020 511 1 1 +writedatamem 0x00000000 1 +tile1 newcol 8000 (orgcol 0xffffff), oldvram 0 +v->m 1020 511 1 1 +readdatamem 0x00008000 1 +*/ + + static int iCheat=0; + col+=iCheat; + if(iCheat==1) iCheat=0; else iCheat=1; + } + + + if(dx&1) // slow fill + { + unsigned short *DSTPtr; + unsigned short LineOffset; + DSTPtr = psxVuw + (1024*y0) + x0; + LineOffset = 1024 - dx; + for(i=0;i<dy;i++) + { + for(j=0;j<dx;j++) + GetShadeTransCol(DSTPtr++,col); + DSTPtr += LineOffset; + } + } + else // fast fill + { + uint32_t *DSTPtr; + unsigned short LineOffset; + uint32_t lcol=lSetMask|(((uint32_t)(col))<<16)|col; + dx>>=1; + DSTPtr = (uint32_t *)(psxVuw + (1024*y0) + x0); + LineOffset = 512 - dx; + + if(!bCheckMask && !DrawSemiTrans) + { + for(i=0;i<dy;i++) + { + for(j=0;j<dx;j++) { PUTLE32(DSTPtr, lcol); DSTPtr++; } + DSTPtr += LineOffset; + } + } + else + { + for(i=0;i<dy;i++) + { + for(j=0;j<dx;j++) + GetShadeTransCol32(DSTPtr++,lcol); + DSTPtr += LineOffset; + } + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void FillSoftwareArea(short x0,short y0,short x1, // FILL AREA (BLK FILL) + short y1,unsigned short col) // no draw area check here! +{ + short j,i,dx,dy; + + if(y0>y1) return; + if(x0>x1) return; + + if(y0>=iGPUHeight) return; + if(x0>1023) return; + + if(y1>iGPUHeight) y1=iGPUHeight; + if(x1>1024) x1=1024; + + dx=x1-x0;dy=y1-y0; + if(dx&1) + { + unsigned short *DSTPtr; + unsigned short LineOffset; + + DSTPtr = psxVuw + (1024*y0) + x0; + LineOffset = 1024 - dx; + + for(i=0;i<dy;i++) + { + for(j=0;j<dx;j++) { PUTLE16(DSTPtr, col); DSTPtr++; } + DSTPtr += LineOffset; + } + } + else + { + uint32_t *DSTPtr; + unsigned short LineOffset; + uint32_t lcol=(((int32_t)col)<<16)|col; + dx>>=1; + DSTPtr = (uint32_t *)(psxVuw + (1024*y0) + x0); + LineOffset = 512 - dx; + + for(i=0;i<dy;i++) + { + for(j=0;j<dx;j++) { PUTLE32(DSTPtr, lcol); DSTPtr++; } + DSTPtr += LineOffset; + } + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// EDGE INTERPOLATION +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +typedef struct SOFTVTAG +{ + int x,y; + int u,v; + int32_t R,G,B; +} soft_vertex; + +static soft_vertex vtx[4]; +static soft_vertex * left_array[4], * right_array[4]; +static int left_section, right_section; +static int left_section_height, right_section_height; +static int left_x, delta_left_x, right_x, delta_right_x; +static int left_u, delta_left_u, left_v, delta_left_v; +static int right_u, delta_right_u, right_v, delta_right_v; +static int left_R, delta_left_R, right_R, delta_right_R; +static int left_G, delta_left_G, right_G, delta_right_G; +static int left_B, delta_left_B, right_B, delta_right_B; + +#ifdef USE_NASM + +// NASM version (external): +#define shl10idiv i386_shl10idiv + +__inline int shl10idiv(int x, int y); + +#else + +__inline int shl10idiv(int x, int y) +{ + __int64 bi=x; + bi<<=10; + return bi/y; +} + +#endif + +#if 0 + +// GNUC long long int version: + +__inline int shl10idiv(int x, int y) +{ + long long int bi=x; + bi<<=10; + return bi/y; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__inline int RightSection_F(void) +{ + soft_vertex * v1 = right_array[ right_section ]; + soft_vertex * v2 = right_array[ right_section-1 ]; + + int height = v2->y - v1->y; + if(height == 0) return 0; + delta_right_x = (v2->x - v1->x) / height; + right_x = v1->x; + + right_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline int LeftSection_F(void) +{ + soft_vertex * v1 = left_array[ left_section ]; + soft_vertex * v2 = left_array[ left_section-1 ]; + + int height = v2->y - v1->y; + if(height == 0) return 0; + delta_left_x = (v2->x - v1->x) / height; + left_x = v1->x; + + left_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL NextRow_F(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_F() <= 0) {return TRUE;} + } + else + { + left_x += delta_left_x; + } + + if(--right_section_height<=0) + { + if(--right_section<=0) {return TRUE;} + if(RightSection_F() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL SetupSections_F(short x1, short y1, short x2, short y2, short x3, short y3) +{ + soft_vertex * v1, * v2, * v3; + int height,longest; + + v1 = vtx; v1->x=x1<<16;v1->y=y1; + v2 = vtx+1; v2->x=x2<<16;v2->y=y2; + v3 = vtx+2; v3->x=x3<<16;v3->y=y3; + + if(v1->y > v2->y) { soft_vertex * v = v1; v1 = v2; v2 = v; } + if(v1->y > v3->y) { soft_vertex * v = v1; v1 = v3; v3 = v; } + if(v2->y > v3->y) { soft_vertex * v = v2; v2 = v3; v3 = v; } + + height = v3->y - v1->y; + if(height == 0) {return FALSE;} + longest = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest == 0) {return FALSE;} + + if(longest < 0) + { + right_array[0] = v3; + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + left_array[0] = v3; + left_array[1] = v1; + left_section = 1; + + if(LeftSection_F() <= 0) return FALSE; + if(RightSection_F() <= 0) + { + right_section--; + if(RightSection_F() <= 0) return FALSE; + } + } + else + { + left_array[0] = v3; + left_array[1] = v2; + left_array[2] = v1; + left_section = 2; + right_array[0] = v3; + right_array[1] = v1; + right_section = 1; + + if(RightSection_F() <= 0) return FALSE; + if(LeftSection_F() <= 0) + { + left_section--; + if(LeftSection_F() <= 0) return FALSE; + } + } + + Ymin=v1->y; + Ymax=min(v3->y-1,drawH); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__inline int RightSection_G(void) +{ + soft_vertex * v1 = right_array[ right_section ]; + soft_vertex * v2 = right_array[ right_section-1 ]; + + int height = v2->y - v1->y; + if(height == 0) return 0; + delta_right_x = (v2->x - v1->x) / height; + right_x = v1->x; + + right_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline int LeftSection_G(void) +{ + soft_vertex * v1 = left_array[ left_section ]; + soft_vertex * v2 = left_array[ left_section-1 ]; + + int height = v2->y - v1->y; + if(height == 0) return 0; + delta_left_x = (v2->x - v1->x) / height; + left_x = v1->x; + + delta_left_R = ((v2->R - v1->R)) / height; + left_R = v1->R; + delta_left_G = ((v2->G - v1->G)) / height; + left_G = v1->G; + delta_left_B = ((v2->B - v1->B)) / height; + left_B = v1->B; + + left_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL NextRow_G(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_G() <= 0) {return TRUE;} + } + else + { + left_x += delta_left_x; + left_R += delta_left_R; + left_G += delta_left_G; + left_B += delta_left_B; + } + + if(--right_section_height<=0) + { + if(--right_section<=0) {return TRUE;} + if(RightSection_G() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL SetupSections_G(short x1,short y1,short x2,short y2,short x3,short y3,int32_t rgb1, int32_t rgb2, int32_t rgb3) +{ + soft_vertex * v1, * v2, * v3; + int height,longest,temp; + + v1 = vtx; v1->x=x1<<16;v1->y=y1; + v1->R=(rgb1) & 0x00ff0000; + v1->G=(rgb1<<8) & 0x00ff0000; + v1->B=(rgb1<<16) & 0x00ff0000; + v2 = vtx+1; v2->x=x2<<16;v2->y=y2; + v2->R=(rgb2) & 0x00ff0000; + v2->G=(rgb2<<8) & 0x00ff0000; + v2->B=(rgb2<<16) & 0x00ff0000; + v3 = vtx+2; v3->x=x3<<16;v3->y=y3; + v3->R=(rgb3) & 0x00ff0000; + v3->G=(rgb3<<8) & 0x00ff0000; + v3->B=(rgb3<<16) & 0x00ff0000; + + if(v1->y > v2->y) { soft_vertex * v = v1; v1 = v2; v2 = v; } + if(v1->y > v3->y) { soft_vertex * v = v1; v1 = v3; v3 = v; } + if(v2->y > v3->y) { soft_vertex * v = v2; v2 = v3; v3 = v; } + + height = v3->y - v1->y; + if(height == 0) {return FALSE;} + temp=(((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest == 0) {return FALSE;} + + if(longest < 0) + { + right_array[0] = v3; + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + left_array[0] = v3; + left_array[1] = v1; + left_section = 1; + + if(LeftSection_G() <= 0) return FALSE; + if(RightSection_G() <= 0) + { + right_section--; + if(RightSection_G() <= 0) return FALSE; + } + if(longest > -0x1000) longest = -0x1000; + } + else + { + left_array[0] = v3; + left_array[1] = v2; + left_array[2] = v1; + left_section = 2; + right_array[0] = v3; + right_array[1] = v1; + right_section = 1; + + if(RightSection_G() <= 0) return FALSE; + if(LeftSection_G() <= 0) + { + left_section--; + if(LeftSection_G() <= 0) return FALSE; + } + if(longest < 0x1000) longest = 0x1000; + } + + Ymin=v1->y; + Ymax=min(v3->y-1,drawH); + + delta_right_R=shl10idiv(temp*((v3->R - v1->R)>>10)+((v1->R - v2->R)<<6),longest); + delta_right_G=shl10idiv(temp*((v3->G - v1->G)>>10)+((v1->G - v2->G)<<6),longest); + delta_right_B=shl10idiv(temp*((v3->B - v1->B)>>10)+((v1->B - v2->B)<<6),longest); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__inline int RightSection_FT(void) +{ + soft_vertex * v1 = right_array[ right_section ]; + soft_vertex * v2 = right_array[ right_section-1 ]; + + int height = v2->y - v1->y; + if(height == 0) return 0; + delta_right_x = (v2->x - v1->x) / height; + right_x = v1->x; + + right_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline int LeftSection_FT(void) +{ + soft_vertex * v1 = left_array[ left_section ]; + soft_vertex * v2 = left_array[ left_section-1 ]; + + int height = v2->y - v1->y; + if(height == 0) return 0; + delta_left_x = (v2->x - v1->x) / height; + left_x = v1->x; + + delta_left_u = ((v2->u - v1->u)) / height; + left_u = v1->u; + delta_left_v = ((v2->v - v1->v)) / height; + left_v = v1->v; + + left_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL NextRow_FT(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_FT() <= 0) {return TRUE;} + } + else + { + left_x += delta_left_x; + left_u += delta_left_u; + left_v += delta_left_v; + } + + if(--right_section_height<=0) + { + if(--right_section<=0) {return TRUE;} + if(RightSection_FT() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL SetupSections_FT(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3) +{ + soft_vertex * v1, * v2, * v3; + int height,longest,temp; + + v1 = vtx; v1->x=x1<<16;v1->y=y1; + v1->u=tx1<<16;v1->v=ty1<<16; + v2 = vtx+1; v2->x=x2<<16;v2->y=y2; + v2->u=tx2<<16;v2->v=ty2<<16; + v3 = vtx+2; v3->x=x3<<16;v3->y=y3; + v3->u=tx3<<16;v3->v=ty3<<16; + + if(v1->y > v2->y) { soft_vertex * v = v1; v1 = v2; v2 = v; } + if(v1->y > v3->y) { soft_vertex * v = v1; v1 = v3; v3 = v; } + if(v2->y > v3->y) { soft_vertex * v = v2; v2 = v3; v3 = v; } + + height = v3->y - v1->y; + if(height == 0) {return FALSE;} + + temp=(((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + + if(longest == 0) {return FALSE;} + + if(longest < 0) + { + right_array[0] = v3; + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + left_array[0] = v3; + left_array[1] = v1; + left_section = 1; + + if(LeftSection_FT() <= 0) return FALSE; + if(RightSection_FT() <= 0) + { + right_section--; + if(RightSection_FT() <= 0) return FALSE; + } + if(longest > -0x1000) longest = -0x1000; + } + else + { + left_array[0] = v3; + left_array[1] = v2; + left_array[2] = v1; + left_section = 2; + right_array[0] = v3; + right_array[1] = v1; + right_section = 1; + + if(RightSection_FT() <= 0) return FALSE; + if(LeftSection_FT() <= 0) + { + left_section--; + if(LeftSection_FT() <= 0) return FALSE; + } + if(longest < 0x1000) longest = 0x1000; + } + + Ymin=v1->y; + Ymax=min(v3->y-1,drawH); + + delta_right_u=shl10idiv(temp*((v3->u - v1->u)>>10)+((v1->u - v2->u)<<6),longest); + delta_right_v=shl10idiv(temp*((v3->v - v1->v)>>10)+((v1->v - v2->v)<<6),longest); + +/* +Mmm... adjust neg tex deltas... will sometimes cause slight +texture distortions + + longest>>=16; + if(longest) + { + if(longest<0) longest=-longest; + if(delta_right_u<0) + delta_right_u-=delta_right_u/longest; + if(delta_right_v<0) + delta_right_v-=delta_right_v/longest; + } +*/ + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__inline int RightSection_GT(void) +{ + soft_vertex * v1 = right_array[ right_section ]; + soft_vertex * v2 = right_array[ right_section-1 ]; + + int height = v2->y - v1->y; + if(height == 0) return 0; + delta_right_x = (v2->x - v1->x) / height; + right_x = v1->x; + + right_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline int LeftSection_GT(void) +{ + soft_vertex * v1 = left_array[ left_section ]; + soft_vertex * v2 = left_array[ left_section-1 ]; + + int height = v2->y - v1->y; + if(height == 0) return 0; + delta_left_x = (v2->x - v1->x) / height; + left_x = v1->x; + + delta_left_u = ((v2->u - v1->u)) / height; + left_u = v1->u; + delta_left_v = ((v2->v - v1->v)) / height; + left_v = v1->v; + + delta_left_R = ((v2->R - v1->R)) / height; + left_R = v1->R; + delta_left_G = ((v2->G - v1->G)) / height; + left_G = v1->G; + delta_left_B = ((v2->B - v1->B)) / height; + left_B = v1->B; + + left_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL NextRow_GT(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_GT() <= 0) {return TRUE;} + } + else + { + left_x += delta_left_x; + left_u += delta_left_u; + left_v += delta_left_v; + left_R += delta_left_R; + left_G += delta_left_G; + left_B += delta_left_B; + } + + if(--right_section_height<=0) + { + if(--right_section<=0) {return TRUE;} + if(RightSection_GT() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL SetupSections_GT(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, int32_t rgb1, int32_t rgb2, int32_t rgb3) +{ + soft_vertex * v1, * v2, * v3; + int height,longest,temp; + + v1 = vtx; v1->x=x1<<16;v1->y=y1; + v1->u=tx1<<16;v1->v=ty1<<16; + v1->R=(rgb1) & 0x00ff0000; + v1->G=(rgb1<<8) & 0x00ff0000; + v1->B=(rgb1<<16) & 0x00ff0000; + + v2 = vtx+1; v2->x=x2<<16;v2->y=y2; + v2->u=tx2<<16;v2->v=ty2<<16; + v2->R=(rgb2) & 0x00ff0000; + v2->G=(rgb2<<8) & 0x00ff0000; + v2->B=(rgb2<<16) & 0x00ff0000; + + v3 = vtx+2; v3->x=x3<<16;v3->y=y3; + v3->u=tx3<<16;v3->v=ty3<<16; + v3->R=(rgb3) & 0x00ff0000; + v3->G=(rgb3<<8) & 0x00ff0000; + v3->B=(rgb3<<16) & 0x00ff0000; + + if(v1->y > v2->y) { soft_vertex * v = v1; v1 = v2; v2 = v; } + if(v1->y > v3->y) { soft_vertex * v = v1; v1 = v3; v3 = v; } + if(v2->y > v3->y) { soft_vertex * v = v2; v2 = v3; v3 = v; } + + height = v3->y - v1->y; + if(height == 0) {return FALSE;} + + temp=(((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + + if(longest == 0) {return FALSE;} + + if(longest < 0) + { + right_array[0] = v3; + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + left_array[0] = v3; + left_array[1] = v1; + left_section = 1; + + if(LeftSection_GT() <= 0) return FALSE; + if(RightSection_GT() <= 0) + { + right_section--; + if(RightSection_GT() <= 0) return FALSE; + } + + if(longest > -0x1000) longest = -0x1000; + } + else + { + left_array[0] = v3; + left_array[1] = v2; + left_array[2] = v1; + left_section = 2; + right_array[0] = v3; + right_array[1] = v1; + right_section = 1; + + if(RightSection_GT() <= 0) return FALSE; + if(LeftSection_GT() <= 0) + { + left_section--; + if(LeftSection_GT() <= 0) return FALSE; + } + if(longest < 0x1000) longest = 0x1000; + } + + Ymin=v1->y; + Ymax=min(v3->y-1,drawH); + + delta_right_R=shl10idiv(temp*((v3->R - v1->R)>>10)+((v1->R - v2->R)<<6),longest); + delta_right_G=shl10idiv(temp*((v3->G - v1->G)>>10)+((v1->G - v2->G)<<6),longest); + delta_right_B=shl10idiv(temp*((v3->B - v1->B)>>10)+((v1->B - v2->B)<<6),longest); + + delta_right_u=shl10idiv(temp*((v3->u - v1->u)>>10)+((v1->u - v2->u)<<6),longest); + delta_right_v=shl10idiv(temp*((v3->v - v1->v)>>10)+((v1->v - v2->v)<<6),longest); + + +/* +Mmm... adjust neg tex deltas... will sometimes cause slight +texture distortions + longest>>=16; + if(longest) + { + if(longest<0) longest=-longest; + if(delta_right_u<0) + delta_right_u-=delta_right_u/longest; + if(delta_right_v<0) + delta_right_v-=delta_right_v/longest; + } +*/ + + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__inline int RightSection_F4(void) +{ + soft_vertex * v1 = right_array[ right_section ]; + soft_vertex * v2 = right_array[ right_section-1 ]; + + int height = v2->y - v1->y; + right_section_height = height; + right_x = v1->x; + if(height == 0) + { + return 0; + } + delta_right_x = (v2->x - v1->x) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline int LeftSection_F4(void) +{ + soft_vertex * v1 = left_array[ left_section ]; + soft_vertex * v2 = left_array[ left_section-1 ]; + + int height = v2->y - v1->y; + left_section_height = height; + left_x = v1->x; + if(height == 0) + { + return 0; + } + delta_left_x = (v2->x - v1->x) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL NextRow_F4(void) +{ + if(--left_section_height<=0) + { + if(--left_section > 0) + while(LeftSection_F4()<=0) + { + if(--left_section <= 0) break; + } + } + else + { + left_x += delta_left_x; + } + + if(--right_section_height<=0) + { + if(--right_section > 0) + while(RightSection_F4()<=0) + { + if(--right_section<=0) break; + } + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL SetupSections_F4(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4) +{ + soft_vertex * v1, * v2, * v3, * v4; + int height,width,longest1,longest2; + + v1 = vtx; v1->x=x1<<16;v1->y=y1; + v2 = vtx+1; v2->x=x2<<16;v2->y=y2; + v3 = vtx+2; v3->x=x3<<16;v3->y=y3; + v4 = vtx+3; v4->x=x4<<16;v4->y=y4; + + if(v1->y > v2->y) { soft_vertex * v = v1; v1 = v2; v2 = v; } + if(v1->y > v3->y) { soft_vertex * v = v1; v1 = v3; v3 = v; } + if(v1->y > v4->y) { soft_vertex * v = v1; v1 = v4; v4 = v; } + if(v2->y > v3->y) { soft_vertex * v = v2; v2 = v3; v3 = v; } + if(v2->y > v4->y) { soft_vertex * v = v2; v2 = v4; v4 = v; } + if(v3->y > v4->y) { soft_vertex * v = v3; v3 = v4; v4 = v; } + + height = v4->y - v1->y; if(height == 0) height =1; + width = (v4->x - v1->x)>>16; + longest1 = (((v2->y - v1->y) << 16) / height) * width + (v1->x - v2->x); + longest2 = (((v3->y - v1->y) << 16) / height) * width + (v1->x - v3->x); + + if(longest1 < 0) // 2 is right + { + if(longest2 < 0) // 3 is right + { + left_array[0] = v4; + left_array[1] = v1; + left_section = 1; + + height = v3->y - v1->y; if(height == 0) height=1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest1 >= 0) + { + right_array[0] = v4; // 1 + right_array[1] = v3; // 3 + right_array[2] = v1; // 4 + right_section = 2; + } + else + { + height = v4->y - v2->y; if(height == 0) height=1; + longest1 = (((v3->y - v2->y) << 16) / height) * ((v4->x - v2->x)>>16) + (v2->x - v3->x); + if(longest1 >= 0) + { + right_array[0] = v4; // 1 + right_array[1] = v2; // 2 + right_array[2] = v1; // 4 + right_section = 2; + } + else + { + right_array[0] = v4; // 1 + right_array[1] = v3; // 2 + right_array[2] = v2; // 3 + right_array[3] = v1; // 4 + right_section = 3; + } + } + } + else + { + left_array[0] = v4; + left_array[1] = v3; // 1 + left_array[2] = v1; // 2 + left_section = 2; // 3 + right_array[0] = v4; // 4 + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + } + } + else + { + if(longest2 < 0) + { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 3 + left_section = 2; // 4 + right_array[0] = v4; + right_array[1] = v3; + right_array[2] = v1; + right_section = 2; + } + else + { + right_array[0] = v4; + right_array[1] = v1; + right_section = 1; + + height = v3->y - v1->y; if(height == 0) height=1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest1<0) + { + left_array[0] = v4; // 1 + left_array[1] = v3; // 3 + left_array[2] = v1; // 4 + left_section = 2; + } + else + { + height = v4->y - v2->y; if(height == 0) height=1; + longest1 = (((v3->y - v2->y) << 16) / height) * ((v4->x - v2->x)>>16) + (v2->x - v3->x); + if(longest1<0) + { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 4 + left_section = 2; + } + else + { + left_array[0] = v4; // 1 + left_array[1] = v3; // 2 + left_array[2] = v2; // 3 + left_array[3] = v1; // 4 + left_section = 3; + } + } + } + } + + while(LeftSection_F4()<=0) + { + if(--left_section <= 0) break; + } + + while(RightSection_F4()<=0) + { + if(--right_section <= 0) break; + } + + Ymin=v1->y; + Ymax=min(v4->y-1,drawH); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__inline int RightSection_FT4(void) +{ + soft_vertex * v1 = right_array[ right_section ]; + soft_vertex * v2 = right_array[ right_section-1 ]; + + int height = v2->y - v1->y; + right_section_height = height; + right_x = v1->x; + right_u = v1->u; + right_v = v1->v; + if(height == 0) + { + return 0; + } + delta_right_x = (v2->x - v1->x) / height; + delta_right_u = (v2->u - v1->u) / height; + delta_right_v = (v2->v - v1->v) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline int LeftSection_FT4(void) +{ + soft_vertex * v1 = left_array[ left_section ]; + soft_vertex * v2 = left_array[ left_section-1 ]; + + int height = v2->y - v1->y; + left_section_height = height; + left_x = v1->x; + left_u = v1->u; + left_v = v1->v; + if(height == 0) + { + return 0; + } + delta_left_x = (v2->x - v1->x) / height; + delta_left_u = (v2->u - v1->u) / height; + delta_left_v = (v2->v - v1->v) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL NextRow_FT4(void) +{ + if(--left_section_height<=0) + { + if(--left_section > 0) + while(LeftSection_FT4()<=0) + { + if(--left_section <= 0) break; + } + } + else + { + left_x += delta_left_x; + left_u += delta_left_u; + left_v += delta_left_v; + } + + if(--right_section_height<=0) + { + if(--right_section > 0) + while(RightSection_FT4()<=0) + { + if(--right_section<=0) break; + } + } + else + { + right_x += delta_right_x; + right_u += delta_right_u; + right_v += delta_right_v; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL SetupSections_FT4(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4) +{ + soft_vertex * v1, * v2, * v3, * v4; + int height,width,longest1,longest2; + + v1 = vtx; v1->x=x1<<16;v1->y=y1; + v1->u=tx1<<16;v1->v=ty1<<16; + + v2 = vtx+1; v2->x=x2<<16;v2->y=y2; + v2->u=tx2<<16;v2->v=ty2<<16; + + v3 = vtx+2; v3->x=x3<<16;v3->y=y3; + v3->u=tx3<<16;v3->v=ty3<<16; + + v4 = vtx+3; v4->x=x4<<16;v4->y=y4; + v4->u=tx4<<16;v4->v=ty4<<16; + + if(v1->y > v2->y) { soft_vertex * v = v1; v1 = v2; v2 = v; } + if(v1->y > v3->y) { soft_vertex * v = v1; v1 = v3; v3 = v; } + if(v1->y > v4->y) { soft_vertex * v = v1; v1 = v4; v4 = v; } + if(v2->y > v3->y) { soft_vertex * v = v2; v2 = v3; v3 = v; } + if(v2->y > v4->y) { soft_vertex * v = v2; v2 = v4; v4 = v; } + if(v3->y > v4->y) { soft_vertex * v = v3; v3 = v4; v4 = v; } + + height = v4->y - v1->y; if(height == 0) height =1; + width = (v4->x - v1->x)>>16; + longest1 = (((v2->y - v1->y) << 16) / height) * width + (v1->x - v2->x); + longest2 = (((v3->y - v1->y) << 16) / height) * width + (v1->x - v3->x); + + if(longest1 < 0) // 2 is right + { + if(longest2 < 0) // 3 is right + { + left_array[0] = v4; + left_array[1] = v1; + left_section = 1; + + height = v3->y - v1->y; if(height == 0) height=1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest1 >= 0) + { + right_array[0] = v4; // 1 + right_array[1] = v3; // 3 + right_array[2] = v1; // 4 + right_section = 2; + } + else + { + height = v4->y - v2->y; if(height == 0) height=1; + longest1 = (((v3->y - v2->y) << 16) / height) * ((v4->x - v2->x)>>16) + (v2->x - v3->x); + if(longest1 >= 0) + { + right_array[0] = v4; // 1 + right_array[1] = v2; // 2 + right_array[2] = v1; // 4 + right_section = 2; + } + else + { + right_array[0] = v4; // 1 + right_array[1] = v3; // 2 + right_array[2] = v2; // 3 + right_array[3] = v1; // 4 + right_section = 3; + } + } + } + else + { + left_array[0] = v4; + left_array[1] = v3; // 1 + left_array[2] = v1; // 2 + left_section = 2; // 3 + right_array[0] = v4; // 4 + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + } + } + else + { + if(longest2 < 0) + { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 3 + left_section = 2; // 4 + right_array[0] = v4; + right_array[1] = v3; + right_array[2] = v1; + right_section = 2; + } + else + { + right_array[0] = v4; + right_array[1] = v1; + right_section = 1; + + height = v3->y - v1->y; if(height == 0) height=1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest1<0) + { + left_array[0] = v4; // 1 + left_array[1] = v3; // 3 + left_array[2] = v1; // 4 + left_section = 2; + } + else + { + height = v4->y - v2->y; if(height == 0) height=1; + longest1 = (((v3->y - v2->y) << 16) / height) * ((v4->x - v2->x)>>16) + (v2->x - v3->x); + if(longest1<0) + { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 4 + left_section = 2; + } + else + { + left_array[0] = v4; // 1 + left_array[1] = v3; // 2 + left_array[2] = v2; // 3 + left_array[3] = v1; // 4 + left_section = 3; + } + } + } + } + + while(LeftSection_FT4()<=0) + { + if(--left_section <= 0) break; + } + + while(RightSection_FT4()<=0) + { + if(--right_section <= 0) break; + } + + Ymin=v1->y; + Ymax=min(v4->y-1,drawH); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__inline int RightSection_GT4(void) +{ + soft_vertex * v1 = right_array[ right_section ]; + soft_vertex * v2 = right_array[ right_section-1 ]; + + int height = v2->y - v1->y; + right_section_height = height; + right_x = v1->x; + right_u = v1->u; + right_v = v1->v; + right_R = v1->R; + right_G = v1->G; + right_B = v1->B; + + if(height == 0) + { + return 0; + } + delta_right_x = (v2->x - v1->x) / height; + delta_right_u = (v2->u - v1->u) / height; + delta_right_v = (v2->v - v1->v) / height; + delta_right_R = (v2->R - v1->R) / height; + delta_right_G = (v2->G - v1->G) / height; + delta_right_B = (v2->B - v1->B) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline int LeftSection_GT4(void) +{ + soft_vertex * v1 = left_array[ left_section ]; + soft_vertex * v2 = left_array[ left_section-1 ]; + + int height = v2->y - v1->y; + left_section_height = height; + left_x = v1->x; + left_u = v1->u; + left_v = v1->v; + left_R = v1->R; + left_G = v1->G; + left_B = v1->B; + + if(height == 0) + { + return 0; + } + delta_left_x = (v2->x - v1->x) / height; + delta_left_u = (v2->u - v1->u) / height; + delta_left_v = (v2->v - v1->v) / height; + delta_left_R = (v2->R - v1->R) / height; + delta_left_G = (v2->G - v1->G) / height; + delta_left_B = (v2->B - v1->B) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL NextRow_GT4(void) +{ + if(--left_section_height<=0) + { + if(--left_section > 0) + while(LeftSection_GT4()<=0) + { + if(--left_section <= 0) break; + } + } + else + { + left_x += delta_left_x; + left_u += delta_left_u; + left_v += delta_left_v; + left_R += delta_left_R; + left_G += delta_left_G; + left_B += delta_left_B; + } + + if(--right_section_height<=0) + { + if(--right_section > 0) + while(RightSection_GT4()<=0) + { + if(--right_section<=0) break; + } + } + else + { + right_x += delta_right_x; + right_u += delta_right_u; + right_v += delta_right_v; + right_R += delta_right_R; + right_G += delta_right_G; + right_B += delta_right_B; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL SetupSections_GT4(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4,int32_t rgb1,int32_t rgb2,int32_t rgb3,int32_t rgb4) +{ + soft_vertex * v1, * v2, * v3, * v4; + int height,width,longest1,longest2; + + v1 = vtx; v1->x=x1<<16;v1->y=y1; + v1->u=tx1<<16;v1->v=ty1<<16; + v1->R=(rgb1) & 0x00ff0000; + v1->G=(rgb1<<8) & 0x00ff0000; + v1->B=(rgb1<<16) & 0x00ff0000; + + v2 = vtx+1; v2->x=x2<<16;v2->y=y2; + v2->u=tx2<<16;v2->v=ty2<<16; + v2->R=(rgb2) & 0x00ff0000; + v2->G=(rgb2<<8) & 0x00ff0000; + v2->B=(rgb2<<16) & 0x00ff0000; + + v3 = vtx+2; v3->x=x3<<16;v3->y=y3; + v3->u=tx3<<16;v3->v=ty3<<16; + v3->R=(rgb3) & 0x00ff0000; + v3->G=(rgb3<<8) & 0x00ff0000; + v3->B=(rgb3<<16) & 0x00ff0000; + + v4 = vtx+3; v4->x=x4<<16;v4->y=y4; + v4->u=tx4<<16;v4->v=ty4<<16; + v4->R=(rgb4) & 0x00ff0000; + v4->G=(rgb4<<8) & 0x00ff0000; + v4->B=(rgb4<<16) & 0x00ff0000; + + if(v1->y > v2->y) { soft_vertex * v = v1; v1 = v2; v2 = v; } + if(v1->y > v3->y) { soft_vertex * v = v1; v1 = v3; v3 = v; } + if(v1->y > v4->y) { soft_vertex * v = v1; v1 = v4; v4 = v; } + if(v2->y > v3->y) { soft_vertex * v = v2; v2 = v3; v3 = v; } + if(v2->y > v4->y) { soft_vertex * v = v2; v2 = v4; v4 = v; } + if(v3->y > v4->y) { soft_vertex * v = v3; v3 = v4; v4 = v; } + + height = v4->y - v1->y; if(height == 0) height =1; + width = (v4->x - v1->x)>>16; + longest1 = (((v2->y - v1->y) << 16) / height) * width + (v1->x - v2->x); + longest2 = (((v3->y - v1->y) << 16) / height) * width + (v1->x - v3->x); + + if(longest1 < 0) // 2 is right + { + if(longest2 < 0) // 3 is right + { + left_array[0] = v4; + left_array[1] = v1; + left_section = 1; + + height = v3->y - v1->y; if(height == 0) height=1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest1 >= 0) + { + right_array[0] = v4; // 1 + right_array[1] = v3; // 3 + right_array[2] = v1; // 4 + right_section = 2; + } + else + { + height = v4->y - v2->y; if(height == 0) height=1; + longest1 = (((v3->y - v2->y) << 16) / height) * ((v4->x - v2->x)>>16) + (v2->x - v3->x); + if(longest1 >= 0) + { + right_array[0] = v4; // 1 + right_array[1] = v2; // 2 + right_array[2] = v1; // 4 + right_section = 2; + } + else + { + right_array[0] = v4; // 1 + right_array[1] = v3; // 2 + right_array[2] = v2; // 3 + right_array[3] = v1; // 4 + right_section = 3; + } + } + } + else + { + left_array[0] = v4; + left_array[1] = v3; // 1 + left_array[2] = v1; // 2 + left_section = 2; // 3 + right_array[0] = v4; // 4 + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + } + } + else + { + if(longest2 < 0) + { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 3 + left_section = 2; // 4 + right_array[0] = v4; + right_array[1] = v3; + right_array[2] = v1; + right_section = 2; + } + else + { + right_array[0] = v4; + right_array[1] = v1; + right_section = 1; + + height = v3->y - v1->y; if(height == 0) height=1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest1<0) + { + left_array[0] = v4; // 1 + left_array[1] = v3; // 3 + left_array[2] = v1; // 4 + left_section = 2; + } + else + { + height = v4->y - v2->y; if(height == 0) height=1; + longest1 = (((v3->y - v2->y) << 16) / height) * ((v4->x - v2->x)>>16) + (v2->x - v3->x); + if(longest1<0) + { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 4 + left_section = 2; + } + else + { + left_array[0] = v4; // 1 + left_array[1] = v3; // 2 + left_array[2] = v2; // 3 + left_array[3] = v1; // 4 + left_section = 3; + } + } + } + } + + while(LeftSection_GT4()<=0) + { + if(--left_section <= 0) break; + } + + while(RightSection_GT4()<=0) + { + if(--right_section <= 0) break; + } + + Ymin=v1->y; + Ymax=min(v4->y-1,drawH); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// POLY FUNCS +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// POLY 3/4 FLAT SHADED +//////////////////////////////////////////////////////////////////////// + +__inline void drawPoly3Fi(short x1,short y1,short x2,short y2,short x3,short y3,int32_t rgb) +{ + int i,j,xmin,xmax,ymin,ymax; + unsigned short color;uint32_t lcolor; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_F(x1,y1,x2,y2,x3,y3)) return; + + ymax=Ymax; + + color = ((rgb & 0x00f80000)>>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); + lcolor=lSetMask|(((uint32_t)(color))<<16)|color; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_F()) return; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + color |=sSetMask; + for (i=ymin;i<=ymax;i++) + { + xmin=left_x >> 16; if(drawX>xmin) xmin=drawX; + xmax=(right_x >> 16)-1; if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + PUTLE32(((uint32_t *)&psxVuw[(i<<10)+j]), lcolor); + } + if(j==xmax) PUTLE16(&psxVuw[(i<<10)+j], color); + + if(NextRow_F()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=left_x >> 16; if(drawX>xmin) xmin=drawX; + xmax=(right_x >> 16)-1; if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + GetShadeTransCol32((uint32_t *)&psxVuw[(i<<10)+j],lcolor); + } + if(j==xmax) + GetShadeTransCol(&psxVuw[(i<<10)+j],color); + + if(NextRow_F()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3F(int32_t rgb) +{ + drawPoly3Fi(lx0,ly0,lx1,ly1,lx2,ly2,rgb); +} + +#ifdef POLYQUAD3FS + +void drawPoly4F_TRI(int32_t rgb) +{ + drawPoly3Fi(lx1,ly1,lx3,ly3,lx2,ly2,rgb); + drawPoly3Fi(lx0,ly0,lx1,ly1,lx2,ly2,rgb); +} + +#endif + +// more exact: + +void drawPoly4F(int32_t rgb) +{ + int i,j,xmin,xmax,ymin,ymax; + unsigned short color;uint32_t lcolor; + + if(lx0>drawW && lx1>drawW && lx2>drawW && lx3>drawW) return; + if(ly0>drawH && ly1>drawH && ly2>drawH && ly3>drawH) return; + if(lx0<drawX && lx1<drawX && lx2<drawX && lx3<drawX) return; + if(ly0<drawY && ly1<drawY && ly2<drawY && ly3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_F4(lx0,ly0,lx1,ly1,lx2,ly2,lx3,ly3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_F4()) return; + + color = ((rgb & 0x00f80000)>>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); + lcolor= lSetMask|(((uint32_t)(color))<<16)|color; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + color |=sSetMask; + for (i=ymin;i<=ymax;i++) + { + xmin=left_x >> 16; if(drawX>xmin) xmin=drawX; + xmax=(right_x >> 16)-1; if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + PUTLE32(((uint32_t *)&psxVuw[(i<<10)+j]), lcolor); + } + if(j==xmax) PUTLE16(&psxVuw[(i<<10)+j], color); + + if(NextRow_F4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=left_x >> 16; if(drawX>xmin) xmin=drawX; + xmax=(right_x >> 16)-1; if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + GetShadeTransCol32((uint32_t *)&psxVuw[(i<<10)+j],lcolor); + } + if(j==xmax) GetShadeTransCol(&psxVuw[(i<<10)+j],color); + + if(NextRow_F4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3/4 F-SHADED TEX PAL 4 +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx4(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3,short clX, short clY) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,XAdjust; + int32_t clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx4_IL(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3,short clX, short clY) +{ + int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,XAdjust; + int32_t clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=(GlobalTextAddrY<<10)+GlobalTextAddrX; + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + XAdjust=((posX+difX)>>16); + + TXV=(posY+difY)>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC2= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + XAdjust=((posX+difX)>>16); + + TXV=(posY+difY)>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC2= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx4_TW(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3,short clX, short clY) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,XAdjust; + int32_t clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + YAdjust+=(TWin.Position.y0<<11)+(TWin.Position.x0>>1); + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16);//-1; //!!!!!!!!!!!!!!!! + if(xmax>xmin) xmax--; + + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef POLYQUAD3 + +void drawPoly4TEx4_TRI(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4,short clX, short clY) +{ + drawPoly3TEx4(x2,y2,x3,y3,x4,y4, + tx2,ty2,tx3,ty3,tx4,ty4, + clX,clY); + drawPoly3TEx4(x1,y1,x2,y2,x4,y4, + tx1,ty1,tx2,ty2,tx4,ty4, + clX,clY); +} + +#endif + +// more exact: + +void drawPoly4TEx4(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4,short clX, short clY) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT4()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + + } + if(NextRow_FT4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx4_IL(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4,short clX, short clY) +{ + int32_t num; + int32_t i,j=0,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV; + int32_t difX, difY, difX2, difY2; + int32_t posX=0,posY=0,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT4()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<10)+GlobalTextAddrX; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + XAdjust=((posX+difX)>>16); + + TXV=(posY+difY)>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC2= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + XAdjust=(posX>>16); + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + + } + if(NextRow_FT4()) return; + } +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + XAdjust=((posX+difX)>>16); + + TXV=(posY+difY)>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC2= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx4_TW(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4,short clX, short clY) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT4()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + YAdjust+=(TWin.Position.y0<<11)+(TWin.Position.x0>>1); + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx4_TW_S(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4,short clX, short clY) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT4()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + YAdjust+=(TWin.Position.y0<<11)+(TWin.Position.x0>>1); + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_SPR((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_SPR(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } +} +//////////////////////////////////////////////////////////////////////// +// POLY 3 F-SHADED TEX PAL 8 +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx8(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3,short clX, short clY) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + + } + if(NextRow_FT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx8_IL(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3,short clX, short clY) +{ + int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV,TXU; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=(GlobalTextAddrY<<10)+GlobalTextAddrX; + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + TXU=posX>>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + TXU=(posX+difX)>>16; + TXV=(posY+difY)>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC2= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + TXU=posX>>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + TXU=posX>>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + TXU=(posX+difX)>>16; + TXV=(posY+difY)>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC2= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + TXU=posX>>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + + } + if(NextRow_FT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx8_TW(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3,short clX, short clY) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + YAdjust+=(TWin.Position.y0<<11)+(TWin.Position.x0); + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16);//-1; //!!!!!!!!!!!!!!!! + if(xmax>xmin) xmax--; + + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + + } + if(NextRow_FT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef POLYQUAD3 + +void drawPoly4TEx8_TRI(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4,short clX, short clY) +{ + drawPoly3TEx8(x2,y2,x3,y3,x4,y4, + tx2,ty2,tx3,ty3,tx4,ty4, + clX,clY); + + drawPoly3TEx8(x1,y1,x2,y2,x4,y4, + tx1,ty1,tx2,ty2,tx4,ty4, + clX,clY); +} + +#endif + +// more exact: + +void drawPoly4TEx8(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4,short clX, short clY) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT4()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx8_IL(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4,short clX, short clY) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV,TXU; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT4()) return; + + clutP=(clY<<10)+clX; + + YAdjust=(GlobalTextAddrY<<10)+GlobalTextAddrX; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + TXU=posX>>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + TXU=(posX+difX)>>16; + TXV=(posY+difY)>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC2= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + TXU=posX>>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + TXU=posX>>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + TXU=(posX+difX)>>16; + TXV=(posY+difY)>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC2= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + TXU=posX>>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx8_TW(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4,short clX, short clY) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT4()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + YAdjust+=(TWin.Position.y0<<11)+(TWin.Position.x0); + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } + return; + } + +#endif + + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx8_TW_S(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4,short clX, short clY) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT4()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + YAdjust+=(TWin.Position.y0<<11)+(TWin.Position.x0); + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } + return; + } + +#endif + + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_SPR((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_SPR(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3 F-SHADED TEX 15 BIT +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TD(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT()) return; + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[((((posY+difY)>>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX])); + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[((((posY+difY)>>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX])); + } + if(NextRow_FT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TD_TW(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT()) return; + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[(((((posY+difY)>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[(((((posY+difY)>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + } + if(NextRow_FT()) + { + return; + } + } +} + + +//////////////////////////////////////////////////////////////////////// + +#ifdef POLYQUAD3 + +void drawPoly4TD_TRI(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4) +{ + drawPoly3TD(x2,y2,x3,y3,x4,y4, + tx2,ty2,tx3,ty3,tx4,ty4); + drawPoly3TD(x1,y1,x2,y2,x4,y4, + tx1,ty1,tx2,ty2,tx4,ty4); +} + +#endif + +// more exact: + +void drawPoly4TD(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT4()) return; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[((((posY+difY)>>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX])); + } + if(NextRow_FT4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[((((posY+difY)>>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX])); + } + if(NextRow_FT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TD_TW(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT4()) return; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[(((((posY+difY)>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY)<<10)+TWin.Position.y0+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + } + if(NextRow_FT4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[(((((posY+difY)>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + } + if(NextRow_FT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TD_TW_S(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_FT4()) return; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[(((((posY+difY)>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY)<<10)+TWin.Position.y0+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + } + if(NextRow_FT4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColG32_SPR((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[(((((posY+difY)>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_SPR(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + } + if(NextRow_FT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3/4 G-SHADED +//////////////////////////////////////////////////////////////////////// + +__inline void drawPoly3Gi(short x1,short y1,short x2,short y2,short x3,short y3,int32_t rgb1, int32_t rgb2, int32_t rgb3) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_G(x1,y1,x2,y2,x3,y3,rgb1,rgb2,rgb3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_G()) return; + + difR=delta_right_R; + difG=delta_right_G; + difB=delta_right_B; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && iDither!=2) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1;if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<xmax;j+=2) + { + PUTLE32(((uint32_t *)&psxVuw[(i<<10)+j]), + ((((cR1+difR) <<7)&0x7c000000)|(((cG1+difG) << 2)&0x03e00000)|(((cB1+difB)>>3)&0x001f0000)| + (((cR1) >> 9)&0x7c00)|(((cG1) >> 14)&0x03e0)|(((cB1) >> 19)&0x001f))|lSetMask); + + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + PUTLE16(&psxVuw[(i<<10)+j], (((cR1 >> 9)&0x7c00)|((cG1 >> 14)&0x03e0)|((cB1 >> 19)&0x001f))|sSetMask); + } + if(NextRow_G()) return; + } + return; + } + +#endif + + if(iDither==2) + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1;if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<=xmax;j++) + { + GetShadeTransCol_Dither(&psxVuw[(i<<10)+j],(cB1>>16),(cG1>>16),(cR1>>16)); + + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_G()) return; + } + else + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1;if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<=xmax;j++) + { + GetShadeTransCol(&psxVuw[(i<<10)+j],((cR1 >> 9)&0x7c00)|((cG1 >> 14)&0x03e0)|((cB1 >> 19)&0x001f)); + + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_G()) return; + } + +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3G(int32_t rgb1, int32_t rgb2, int32_t rgb3) +{ + drawPoly3Gi(lx0,ly0,lx1,ly1,lx2,ly2,rgb1,rgb2,rgb3); +} + +// draw two g-shaded tris for right psx shading emulation + +void drawPoly4G(int32_t rgb1, int32_t rgb2, int32_t rgb3, int32_t rgb4) +{ + drawPoly3Gi(lx1,ly1,lx3,ly3,lx2,ly2, + rgb2,rgb4,rgb3); + drawPoly3Gi(lx0,ly0,lx1,ly1,lx2,ly2, + rgb1,rgb2,rgb3); +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3/4 G-SHADED TEX PAL4 +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx4(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short clX, short clY,int32_t col1, int32_t col2, int32_t col3) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_GT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + + difR=delta_right_R; + difG=delta_right_G; + difB=delta_right_B; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=((left_x) >> 16); + xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16, + (cB1>>16)|((cB1+difB)&0xff0000), + (cG1>>16)|((cG1+difG)&0xff0000), + (cR1>>16)|((cR1+difR)&0xff0000)); + posX+=difX2; + posY+=difY2; + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + } + } + if(NextRow_GT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<=xmax;j++) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + posX+=difX; + posY+=difY; + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_GT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx4_IL(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short clX, short clY,int32_t col1, int32_t col2, int32_t col3) +{ + int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_GT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=(GlobalTextAddrY<<10)+GlobalTextAddrX; + + difR=delta_right_R; + difG=delta_right_G; + difB=delta_right_B; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=((left_x) >> 16); + xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + XAdjust=((posX+difX)>>16); + + TXV=(posY+difY)>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC2= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16, + (cB1>>16)|((cB1+difB)&0xff0000), + (cG1>>16)|((cG1+difG)&0xff0000), + (cR1>>16)|((cR1+difR)&0xff0000)); + posX+=difX2; + posY+=difY2; + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + } + } + if(NextRow_GT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<=xmax;j++) + { + XAdjust=(posX>>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + posX+=difX; + posY+=difY; + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_GT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx4_TW(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short clX, short clY,int32_t col1, int32_t col2, int32_t col3) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_GT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + YAdjust+=(TWin.Position.y0<<11)+(TWin.Position.x0>>1); + + difR=delta_right_R; + difG=delta_right_G; + difB=delta_right_B; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=((left_x) >> 16); + xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16, + (cB1>>16)|((cB1+difB)&0xff0000), + (cG1>>16)|((cG1+difG)&0xff0000), + (cR1>>16)|((cR1+difR)&0xff0000)); + posX+=difX2; + posY+=difY2; + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + } + } + if(NextRow_GT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<=xmax;j++) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + posX+=difX; + posY+=difY; + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_GT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +// note: the psx is doing g-shaded quads as two g-shaded tris, +// like the following func... sadly texturing is not 100% +// correct that way, so small texture distortions can +// happen... + +void drawPoly4TGEx4_TRI_IL(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4, + short clX, short clY, + int32_t col1, int32_t col2, int32_t col3, int32_t col4) +{ + drawPoly3TGEx4_IL(x2,y2,x3,y3,x4,y4, + tx2,ty2,tx3,ty3,tx4,ty4, + clX,clY, + col2,col4,col3); + drawPoly3TGEx4_IL(x1,y1,x2,y2,x4,y4, + tx1,ty1,tx2,ty2,tx4,ty4, + clX,clY, + col1,col2,col3); +} + +#ifdef POLYQUAD3GT + +void drawPoly4TGEx4_TRI(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4, + short clX, short clY, + int32_t col1, int32_t col2, int32_t col3, int32_t col4) +{ + drawPoly3TGEx4(x2,y2,x3,y3,x4,y4, + tx2,ty2,tx3,ty3,tx4,ty4, + clX,clY, + col2,col4,col3); + drawPoly3TGEx4(x1,y1,x2,y2,x4,y4, + tx1,ty1,tx2,ty2,tx4,ty4, + clX,clY, + col1,col2,col3); +} + +#endif + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TGEx4(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4, + short clX, short clY, + int32_t col1, int32_t col2, int32_t col4, int32_t col3) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4,col1,col2,col3,col4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_GT4()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + cR1=left_R; + cG1=left_G; + cB1=left_B; + difR=(right_R-cR1)/num; + difG=(right_G-cG1)/num; + difB=(right_B-cB1)/num; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16, + (cB1>>16)|((cB1+difB)&0xff0000), + (cG1>>16)|((cG1+difG)&0xff0000), + (cR1>>16)|((cR1+difR)&0xff0000)); + posX+=difX2; + posY+=difY2; + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + } + } + if(NextRow_GT4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + cR1=left_R; + cG1=left_G; + cB1=left_B; + difR=(right_R-cR1)/num; + difG=(right_G-cG1)/num; + difB=(right_B-cB1)/num; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<=xmax;j++) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + posX+=difX; + posY+=difY; + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_GT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TGEx4_TW(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4, + short clX, short clY, + int32_t col1, int32_t col2, int32_t col3, int32_t col4) +{ + drawPoly3TGEx4_TW(x2,y2,x3,y3,x4,y4, + tx2,ty2,tx3,ty3,tx4,ty4, + clX,clY, + col2,col4,col3); + + drawPoly3TGEx4_TW(x1,y1,x2,y2,x4,y4, + tx1,ty1,tx2,ty2,tx4,ty4, + clX,clY, + col1,col2,col3); +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3/4 G-SHADED TEX PAL8 +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx8(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short clX, short clY,int32_t col1, int32_t col2, int32_t col3) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_GT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + + difR=delta_right_R; + difG=delta_right_G; + difB=delta_right_B; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+((posX>>16))]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (((posX+difX)>>16))]; + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16, + (cB1>>16)|((cB1+difB)&0xff0000), + (cG1>>16)|((cG1+difG)&0xff0000), + (cR1>>16)|((cR1+difR)&0xff0000)); + posX+=difX2; + posY+=difY2; + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+((posX>>16))]; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + } + } + if(NextRow_GT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<=xmax;j++) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+((posX>>16))]; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + posX+=difX; + posY+=difY; + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_GT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx8_IL(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short clX, short clY,int32_t col1, int32_t col2, int32_t col3) +{ + int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV,TXU; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_GT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=(GlobalTextAddrY<<10)+GlobalTextAddrX; + + difR=delta_right_R; + difG=delta_right_G; + difB=delta_right_B; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<xmax;j+=2) + { + TXU=posX>>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + TXU=(posX+difX)>>16; + TXV=(posY+difY)>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC2= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16, + (cB1>>16)|((cB1+difB)&0xff0000), + (cG1>>16)|((cG1+difG)&0xff0000), + (cR1>>16)|((cR1+difR)&0xff0000)); + posX+=difX2; + posY+=difY2; + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + { + TXU=posX>>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + } + } + if(NextRow_GT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<=xmax;j++) + { + TXU=posX>>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + posX+=difX; + posY+=difY; + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_GT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx8_TW(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short clX, short clY,int32_t col1, int32_t col2, int32_t col3) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_GT()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + YAdjust+=(TWin.Position.y0<<11)+(TWin.Position.x0); + + difR=delta_right_R; + difG=delta_right_G; + difB=delta_right_B; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16, + (cB1>>16)|((cB1+difB)&0xff0000), + (cG1>>16)|((cG1+difG)&0xff0000), + (cR1>>16)|((cR1+difR)&0xff0000)); + posX+=difX2; + posY+=difY2; + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + } + } + if(NextRow_GT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<=xmax;j++) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + posX+=difX; + posY+=difY; + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_GT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +// note: two g-shaded tris: small texture distortions can happen + +void drawPoly4TGEx8_TRI_IL(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4, + short clX, short clY, + int32_t col1, int32_t col2, int32_t col3, int32_t col4) +{ + drawPoly3TGEx8_IL(x2,y2,x3,y3,x4,y4, + tx2,ty2,tx3,ty3,tx4,ty4, + clX,clY, + col2,col4,col3); + drawPoly3TGEx8_IL(x1,y1,x2,y2,x4,y4, + tx1,ty1,tx2,ty2,tx4,ty4, + clX,clY, + col1,col2,col3); +} + +#ifdef POLYQUAD3GT + +void drawPoly4TGEx8_TRI(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4, + short clX, short clY, + int32_t col1, int32_t col2, int32_t col3, int32_t col4) +{ + drawPoly3TGEx8(x2,y2,x3,y3,x4,y4, + tx2,ty2,tx3,ty3,tx4,ty4, + clX,clY, + col2,col4,col3); + drawPoly3TGEx8(x1,y1,x2,y2,x4,y4, + tx1,ty1,tx2,ty2,tx4,ty4, + clX,clY, + col1,col2,col3); +} + +#endif + +void drawPoly4TGEx8(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4, + short clX, short clY, + int32_t col1, int32_t col2, int32_t col4, int32_t col3) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4,col1,col2,col3,col4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_GT4()) return; + + clutP=(clY<<10)+clX; + + YAdjust=((GlobalTextAddrY)<<11)+(GlobalTextAddrX<<1); + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + cR1=left_R; + cG1=left_G; + cB1=left_B; + difR=(right_R-cR1)/num; + difG=(right_G-cG1)/num; + difB=(right_B-cB1)/num; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16, + (cB1>>16)|((cB1+difB)&0xff0000), + (cG1>>16)|((cG1+difG)&0xff0000), + (cR1>>16)|((cR1+difR)&0xff0000)); + posX+=difX2; + posY+=difY2; + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + } + } + if(NextRow_GT4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + cR1=left_R; + cG1=left_G; + cB1=left_B; + difR=(right_R-cR1)/num; + difG=(right_G-cG1)/num; + difB=(right_B-cB1)/num; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<=xmax;j++) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + posX+=difX; + posY+=difY; + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_GT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TGEx8_TW(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4, + short clX, short clY, + int32_t col1, int32_t col2, int32_t col3, int32_t col4) +{ + drawPoly3TGEx8_TW(x2,y2,x3,y3,x4,y4, + tx2,ty2,tx3,ty3,tx4,ty4, + clX,clY, + col2,col4,col3); + drawPoly3TGEx8_TW(x1,y1,x2,y2,x4,y4, + tx1,ty1,tx2,ty2,tx4,ty4, + clX,clY, + col1,col2,col3); +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3 G-SHADED TEX 15 BIT +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGD(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3,int32_t col1, int32_t col2, int32_t col3) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_GT()) return; + + difR=delta_right_R; + difG=delta_right_G; + difB=delta_right_B; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[((((posY+difY)>>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX]), + (cB1>>16)|((cB1+difB)&0xff0000), + (cG1>>16)|((cG1+difG)&0xff0000), + (cR1>>16)|((cR1+difR)&0xff0000)); + posX+=difX2; + posY+=difY2; + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), + (cB1>>16),(cG1>>16),(cR1>>16)); + } + if(NextRow_GT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<=xmax;j++) + { + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), + (cB1>>16),(cG1>>16),(cR1>>16)); + posX+=difX; + posY+=difY; + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_GT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGD_TW(short x1, short y1, short x2, short y2, short x3, short y3, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3,int32_t col1, int32_t col2, int32_t col3) +{ + int i,j,xmin,xmax,ymin,ymax; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + int32_t difX, difY,difX2, difY2; + int32_t posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_GT()) return; + + difR=delta_right_R; + difG=delta_right_G; + difB=delta_right_B; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[(((((posY+difY)>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]), + (cB1>>16)|((cB1+difB)&0xff0000), + (cG1>>16)|((cG1+difG)&0xff0000), + (cR1>>16)|((cR1+difR)&0xff0000)); + posX+=difX2; + posY+=difY2; + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]), + (cB1>>16),(cG1>>16),(cR1>>16)); + } + if(NextRow_GT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! + if(drawW<xmax) xmax=drawW; + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + + for(j=xmin;j<=xmax;j++) + { + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]), + (cB1>>16),(cG1>>16),(cR1>>16)); + posX+=difX; + posY+=difY; + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_GT()) + { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +// note: two g-shaded tris: small texture distortions can happen + +#ifdef POLYQUAD3GT + +void drawPoly4TGD_TRI(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4, int32_t col1, int32_t col2, int32_t col3, int32_t col4) +{ + drawPoly3TGD(x2,y2,x3,y3,x4,y4, + tx2,ty2,tx3,ty3,tx4,ty4, + col2,col4,col3); + drawPoly3TGD(x1,y1,x2,y2,x4,y4, + tx1,ty1,tx2,ty2,tx4,ty4, + col1,col2,col3); +} + +#endif + +void drawPoly4TGD(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4, int32_t col1, int32_t col2, int32_t col4, int32_t col3) +{ + int32_t num; + int32_t i,j,xmin,xmax,ymin,ymax; + int32_t cR1,cG1,cB1; + int32_t difR,difB,difG,difR2,difB2,difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1<drawX && x2<drawX && x3<drawX && x4<drawX) return; + if(y1<drawY && y2<drawY && y3<drawY && y4<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4,col1,col2,col3,col4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin<drawY;ymin++) + if(NextRow_GT4()) return; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + cR1=left_R; + cG1=left_G; + cB1=left_B; + difR=(right_R-cR1)/num; + difG=(right_G-cG1)/num; + difB=(right_B-cB1)/num; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<xmax;j+=2) + { + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + (((int32_t)GETLE16(&psxVuw[((((posY+difY)>>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX]), + (cB1>>16)|((cB1+difB)&0xff0000), + (cG1>>16)|((cG1+difG)&0xff0000), + (cR1>>16)|((cR1+difR)&0xff0000)); + posX+=difX2; + posY+=difY2; + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), + (cB1>>16),(cG1>>16),(cR1>>16)); + } + if(NextRow_GT4()) return; + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16); + + if(xmax>=xmin) + { + posX=left_u; + posY=left_v; + + num=(xmax-xmin); + if(num==0) num=1; + difX=(right_u-posX)/num; + difY=(right_v-posY)/num; + difX2=difX<<1; + difY2=difY<<1; + + cR1=left_R; + cG1=left_G; + cB1=left_B; + difR=(right_R-cR1)/num; + difG=(right_G-cG1)/num; + difB=(right_B-cB1)/num; + difR2=difR<<1; + difG2=difG<<1; + difB2=difB<<1; + + if(xmin<drawX) + {j=drawX-xmin;xmin=drawX;posX+=j*difX;posY+=j*difY;cR1+=j*difR;cG1+=j*difG;cB1+=j*difB;} + xmax--;if(drawW<xmax) xmax=drawW; + + for(j=xmin;j<=xmax;j++) + { + if(iDither) + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), + (cB1>>16),(cG1>>16),(cR1>>16)); + posX+=difX; + posY+=difY; + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_GT4()) return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TGD_TW(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, short tx4, short ty4, int32_t col1, int32_t col2, int32_t col3, int32_t col4) +{ + drawPoly3TGD_TW(x2,y2,x3,y3,x4,y4, + tx2,ty2,tx3,ty3,tx4,ty4, + col2,col4,col3); + drawPoly3TGD_TW(x1,y1,x2,y2,x4,y4, + tx1,ty1,tx2,ty2,tx4,ty4, + col1,col2,col3); +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + + +/* +// no real rect test, but it does its job the way I need it +__inline BOOL IsNoRect(void) +{ + if(lx0==lx1 && lx2==lx3) return FALSE; + if(lx0==lx2 && lx1==lx3) return FALSE; + if(lx0==lx3 && lx1==lx2) return FALSE; + return TRUE; +} +*/ + +// real rect test +__inline BOOL IsNoRect(void) +{ + if(!(dwActFixes&0x200)) return FALSE; + + if(ly0==ly1) + { + if(lx1==lx3 && ly3==ly2 && lx2==lx0) return FALSE; + if(lx1==lx2 && ly2==ly3 && lx3==lx0) return FALSE; + return TRUE; + } + + if(ly0==ly2) + { + if(lx2==lx3 && ly3==ly1 && lx1==lx0) return FALSE; + if(lx2==lx1 && ly1==ly3 && lx3==lx0) return FALSE; + return TRUE; + } + + if(ly0==ly3) + { + if(lx3==lx2 && ly2==ly1 && lx1==lx0) return FALSE; + if(lx3==lx1 && ly1==ly2 && lx2==lx0) return FALSE; + return TRUE; + } + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3FT(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly3TEx4_IL(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + else + drawPoly3TEx8_IL(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + } + + if(!bUsingTWin && !(dwActFixes&0x100)) + { + switch(GlobalTextTP) // depending on texture mode + { + case 0: + drawPoly3TEx4(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly3TEx8(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 2: + drawPoly3TD(lx0,ly0,lx1,ly1,lx2,ly2,(GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff)); + return; + } + return; + } + + switch(GlobalTextTP) // depending on texture mode + { + case 0: + drawPoly3TEx4_TW(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly3TEx8_TW(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 2: + drawPoly3TD_TW(lx0,ly0,lx1,ly1,lx2,ly2,(GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff)); + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4FT(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly4TEx4_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + else + drawPoly4TEx8_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + } + + if(!bUsingTWin) + { +#ifdef POLYQUAD3GT + if(IsNoRect()) + { + switch (GlobalTextTP) + { + case 0: + drawPoly4TEx4_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly4TEx8_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 2: + drawPoly4TD_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff)); + return; + } + return; + } +#endif + + switch (GlobalTextTP) + { + case 0: // grandia investigations needed + drawPoly4TEx4(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly4TEx8(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 2: + drawPoly4TD(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff)); + return; + } + return; + } + + switch (GlobalTextTP) + { + case 0: + drawPoly4TEx4_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly4TEx8_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff), ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 2: + drawPoly4TD_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),(GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6])>>8) & 0x000000ff)); + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3GT(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly3TGEx4_IL(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + else + drawPoly3TGEx8_IL(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + } + + if(!bUsingTWin) + { + switch (GlobalTextTP) + { + case 0: + drawPoly3TGEx4(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + case 1: + drawPoly3TGEx8(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + case 2: + drawPoly3TGD(lx0,ly0,lx1,ly1,lx2,ly2,(GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + } + return; + } + + switch(GlobalTextTP) + { + case 0: + drawPoly3TGEx4_TW(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + case 1: + drawPoly3TGEx8_TW(lx0,ly0,lx1,ly1,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + case 2: + drawPoly3TGD_TW(lx0,ly0,lx1,ly1,lx2,ly2,(GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4GT(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly4TGEx4_TRI_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[11]) & 0x000000ff), ((GETLE32(&gpuData[11])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0),((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + else + drawPoly4TGEx8_TRI_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[11]) & 0x000000ff), ((GETLE32(&gpuData[11])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0),((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + } + + if(!bUsingTWin) + { +#ifdef POLYQUAD3GT + if(IsNoRect()) + { + switch (GlobalTextTP) + { + case 0: + drawPoly4TGEx4_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[11]) & 0x000000ff), ((GETLE32(&gpuData[11])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0),((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + + return; + case 1: + drawPoly4TGEx8_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[11]) & 0x000000ff), ((GETLE32(&gpuData[11])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0),((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + case 2: + drawPoly4TGD_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(GETLE32(&gpuData[2]) & 0x000000ff),((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[11]) & 0x000000ff), ((GETLE32(&gpuData[11])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + } + return; + } +#endif + + switch (GlobalTextTP) + { + case 0: + drawPoly4TGEx4(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[11]) & 0x000000ff), ((GETLE32(&gpuData[11])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0),((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + + return; + case 1: + drawPoly4TGEx8(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[11]) & 0x000000ff), ((GETLE32(&gpuData[11])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0),((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + case 2: + drawPoly4TGD(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(GETLE32(&gpuData[2]) & 0x000000ff),((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[11]) & 0x000000ff), ((GETLE32(&gpuData[11])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + } + return; + } + + switch (GlobalTextTP) + { + case 0: + drawPoly4TGEx4_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[11]) & 0x000000ff), ((GETLE32(&gpuData[11])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0),((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + case 1: + drawPoly4TGEx8_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[11]) & 0x000000ff), ((GETLE32(&gpuData[11])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff), + ((GETLE32(&gpuData[2])>>12) & 0x3f0),((GETLE32(&gpuData[2])>>22) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + case 2: + drawPoly4TGD_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(GETLE32(&gpuData[2]) & 0x000000ff),((GETLE32(&gpuData[2])>>8) & 0x000000ff), (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5])>>8) & 0x000000ff),(GETLE32(&gpuData[11]) & 0x000000ff), ((GETLE32(&gpuData[11])>>8) & 0x000000ff),(GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8])>>8) & 0x000000ff),GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + } +} + +//////////////////////////////////////////////////////////////////////// +// SPRITE FUNCS +//////////////////////////////////////////////////////////////////////// + +void DrawSoftwareSpriteTWin(unsigned char * baseAddr,int32_t w,int32_t h) +{ + uint32_t *gpuData = (uint32_t *)baseAddr; + short sx0,sy0,sx1,sy1,sx2,sy2,sx3,sy3; + short tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3; + + sx0=lx0; + sy0=ly0; + + sx0=sx3=sx0+PSXDisplay.DrawOffset.x; + sx1=sx2=sx0+w; + sy0=sy1=sy0+PSXDisplay.DrawOffset.y; + sy2=sy3=sy0+h; + + tx0=tx3=GETLE32(&gpuData[2])&0xff; + tx1=tx2=tx0+w; + ty0=ty1=(GETLE32(&gpuData[2])>>8)&0xff; + ty2=ty3=ty0+h; + + switch (GlobalTextTP) + { + case 0: + drawPoly4TEx4_TW_S(sx0,sy0,sx1,sy1,sx2,sy2,sx3,sy3, + tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3, + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly4TEx8_TW_S(sx0,sy0,sx1,sy1,sx2,sy2,sx3,sy3, + tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3, + ((GETLE32(&gpuData[2])>>12) & 0x3f0), ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + return; + case 2: + drawPoly4TD_TW_S(sx0,sy0,sx1,sy1,sx2,sy2,sx3,sy3, + tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3); + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void DrawSoftwareSpriteMirror(unsigned char * baseAddr,int32_t w,int32_t h) +{ + int32_t sprtY,sprtX,sprtW,sprtH,lXDir,lYDir; + int32_t clutY0,clutX0,clutP,textX0,textY0,sprtYa,sprCY,sprCX,sprA; + short tC; + uint32_t *gpuData = (uint32_t *)baseAddr; + sprtY = ly0; + sprtX = lx0; + sprtH = h; + sprtW = w; + clutY0 = (GETLE32(&gpuData[2])>>22) & iGPUHeightMask; + clutX0 = (GETLE32(&gpuData[2])>>12) & 0x3f0; + clutP = (clutY0<<11) + (clutX0<<1); + textY0 = ((GETLE32(&gpuData[2])>>8) & 0x000000ff) + GlobalTextAddrY; + textX0 = (GETLE32(&gpuData[2]) & 0x000000ff); + + sprtX+=PSXDisplay.DrawOffset.x; + sprtY+=PSXDisplay.DrawOffset.y; + +// while (sprtX>1023) sprtX-=1024; +// while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; + + if(sprtX>drawW) + { +// if((sprtX+sprtW)>1023) sprtX-=1024; +// else return; + return; + } + + if(sprtY>drawH) + { +// if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; +// else return; + return; + } + + if(sprtY<drawY) + { + if((sprtY+sprtH)<drawY) return; + sprtH-=(drawY-sprtY); + textY0+=(drawY-sprtY); + sprtY=drawY; + } + + if(sprtX<drawX) + { + if((sprtX+sprtW)<drawX) return; + sprtW-=(drawX-sprtX); + textX0+=(drawX-sprtX); + sprtX=drawX; + } + + if((sprtY+sprtH)>drawH) sprtH=drawH-sprtY+1; + if((sprtX+sprtW)>drawW) sprtW=drawW-sprtX+1; + + if(usMirror&0x1000) lXDir=-1; else lXDir=1; + if(usMirror&0x2000) lYDir=-1; else lYDir=1; + + switch (GlobalTextTP) + { + case 0: // texture is 4-bit + + sprtW=sprtW/2; + textX0=(GlobalTextAddrX<<1)+(textX0>>1); + sprtYa=(sprtY<<10); + clutP=(clutY0<<10)+clutX0; + for (sprCY=0;sprCY<sprtH;sprCY++) + for (sprCX=0;sprCX<sprtW;sprCX++) + { + tC= psxVub[((textY0+(sprCY*lYDir))<<11) + textX0 +(sprCX*lXDir)]; + sprA=sprtYa+(sprCY<<10)+sprtX + (sprCX<<1); + GetTextureTransColG_SPR(&psxVuw[sprA],GETLE16(&psxVuw[clutP+((tC>>4)&0xf)])); + GetTextureTransColG_SPR(&psxVuw[sprA+1],GETLE16(&psxVuw[clutP+(tC&0xf)])); + } + return; + + case 1: + + clutP>>=1; + for(sprCY=0;sprCY<sprtH;sprCY++) + for(sprCX=0;sprCX<sprtW;sprCX++) + { + tC = psxVub[((textY0+(sprCY*lYDir))<<11)+(GlobalTextAddrX<<1) + textX0 + (sprCX*lXDir)] & 0xff; + GetTextureTransColG_SPR(&psxVuw[((sprtY+sprCY)<<10)+sprtX + sprCX],psxVuw[clutP+tC]); + } + return; + + case 2: + + for (sprCY=0;sprCY<sprtH;sprCY++) + for (sprCX=0;sprCX<sprtW;sprCX++) + { + GetTextureTransColG_SPR(&psxVuw[((sprtY+sprCY)<<10)+sprtX+sprCX], + GETLE16(&psxVuw[((textY0+(sprCY*lYDir))<<10)+GlobalTextAddrX + textX0 +(sprCX*lXDir)])); + } + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void DrawSoftwareSprite_IL(unsigned char * baseAddr,short w,short h,int32_t tx,int32_t ty) +{ + int32_t sprtY,sprtX,sprtW,sprtH,tdx,tdy; + uint32_t *gpuData = (uint32_t *)baseAddr; + + sprtY = ly0; + sprtX = lx0; + sprtH = h; + sprtW = w; + + sprtX+=PSXDisplay.DrawOffset.x; + sprtY+=PSXDisplay.DrawOffset.y; + + if(sprtX>drawW) return; + if(sprtY>drawH) return; + + tdx=tx+sprtW; + tdy=ty+sprtH; + + sprtW+=sprtX; + sprtH+=sprtY; + + // Pete is too lazy to make a faster version ;) + + if(GlobalTextTP==0) + drawPoly4TEx4_IL(sprtX,sprtY,sprtX,sprtH,sprtW,sprtH,sprtW,sprtY, + tx,ty, tx,tdy, tdx,tdy, tdx,ty, + (GETLE32(&gpuData[2])>>12) & 0x3f0, ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); + + + else + drawPoly4TEx8_IL(sprtX,sprtY,sprtX,sprtH,sprtW,sprtH,sprtW,sprtY, + tx,ty, tx,tdy, tdx,tdy, tdx,ty, + (GETLE32(&gpuData[2])>>12) & 0x3f0, ((GETLE32(&gpuData[2])>>22) & iGPUHeightMask)); +} + +//////////////////////////////////////////////////////////////////////// + +void DrawSoftwareSprite(unsigned char * baseAddr,short w,short h,int32_t tx,int32_t ty) +{ + int32_t sprtY,sprtX,sprtW,sprtH; + int32_t clutY0,clutX0,clutP,textX0,textY0,sprtYa,sprCY,sprCX,sprA; + short tC,tC2; + uint32_t *gpuData = (uint32_t *)baseAddr; + unsigned char * pV; + BOOL bWT,bWS; + + if(GlobalTextIL && GlobalTextTP<2) + {DrawSoftwareSprite_IL(baseAddr,w,h,tx,ty);return;} + + sprtY = ly0; + sprtX = lx0; + sprtH = h; + sprtW = w; + clutY0 = (GETLE32(&gpuData[2])>>22) & iGPUHeightMask; + clutX0 = (GETLE32(&gpuData[2])>>12) & 0x3f0; + + clutP = (clutY0<<11) + (clutX0<<1); + + textY0 =ty+ GlobalTextAddrY; + textX0 =tx; + + sprtX+=PSXDisplay.DrawOffset.x; + sprtY+=PSXDisplay.DrawOffset.y; + + //while (sprtX>1023) sprtX-=1024; + //while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; + + if(sprtX>drawW) + { +// if((sprtX+sprtW)>1023) sprtX-=1024; +// else return; + return; + } + + if(sprtY>drawH) + { +// if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; +// else return; + return; + } + + if(sprtY<drawY) + { + if((sprtY+sprtH)<drawY) return; + sprtH-=(drawY-sprtY); + textY0+=(drawY-sprtY); + sprtY=drawY; + } + + if(sprtX<drawX) + { + if((sprtX+sprtW)<drawX) return; + + sprtW-=(drawX-sprtX); + textX0+=(drawX-sprtX); + sprtX=drawX; + } + + if((sprtY+sprtH)>drawH) sprtH=drawH-sprtY+1; + if((sprtX+sprtW)>drawW) sprtW=drawW-sprtX+1; + + + bWT=FALSE; + bWS=FALSE; + + switch (GlobalTextTP) + { + case 0: + + if(textX0&1) {bWS=TRUE;sprtW--;} + if(sprtW&1) bWT=TRUE; + + sprtW=sprtW>>1; + textX0=(GlobalTextAddrX<<1)+(textX0>>1)+(textY0<<11); + sprtYa=(sprtY<<10)+sprtX; + clutP=(clutY0<<10)+clutX0; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (sprCY=0;sprCY<sprtH;sprCY++) + { + sprA=sprtYa+(sprCY<<10); + pV=&psxVub[(sprCY<<11)+textX0]; + + if(bWS) + { + tC=*pV++; + GetTextureTransColG_S(&psxVuw[sprA++],GETLE16(&psxVuw[clutP+((tC>>4)&0xf)])); + } + + for (sprCX=0;sprCX<sprtW;sprCX++,sprA+=2) + { + tC=*pV++; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[sprA], + (((int32_t)GETLE16(&psxVuw[clutP+((tC>>4)&0xf)]))<<16)| + GETLE16(&psxVuw[clutP+(tC&0x0f)])); + } + + if(bWT) + { + tC=*pV; + GetTextureTransColG_S(&psxVuw[sprA],GETLE16(&psxVuw[clutP+(tC&0x0f)])); + } + } + return; + } + +#endif + + for (sprCY=0;sprCY<sprtH;sprCY++) + { + sprA=sprtYa+(sprCY<<10); + pV=&psxVub[(sprCY<<11)+textX0]; + + if(bWS) + { + tC=*pV++; + GetTextureTransColG_SPR(&psxVuw[sprA++],GETLE16(&psxVuw[clutP+((tC>>4)&0xf)])); + } + + for (sprCX=0;sprCX<sprtW;sprCX++,sprA+=2) + { + tC=*pV++; + + GetTextureTransColG32_SPR((uint32_t *)&psxVuw[sprA], + (((int32_t)GETLE16(&psxVuw[clutP+((tC>>4)&0xf)])<<16))| + GETLE16(&psxVuw[clutP+(tC&0x0f)])); + } + + if(bWT) + { + tC=*pV; + GetTextureTransColG_SPR(&psxVuw[sprA],GETLE16(&psxVuw[clutP+(tC&0x0f)])); + } + } + return; + + case 1: + clutP>>=1;sprtW--; + textX0+=(GlobalTextAddrX<<1) + (textY0<<11); + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for(sprCY=0;sprCY<sprtH;sprCY++) + { + sprA=((sprtY+sprCY)<<10)+sprtX; + pV=&psxVub[(sprCY<<11)+textX0]; + for(sprCX=0;sprCX<sprtW;sprCX+=2,sprA+=2) + { + tC = *pV++;tC2 = *pV++; + GetTextureTransColG32_S((uint32_t *)&psxVuw[sprA], + (((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16)| + GETLE16(&psxVuw[clutP+tC])); + } + if(sprCX==sprtW) + GetTextureTransColG_S(&psxVuw[sprA],GETLE16(&psxVuw[clutP+(*pV)])); + } + return; + } + +#endif + + for(sprCY=0;sprCY<sprtH;sprCY++) + { + sprA=((sprtY+sprCY)<<10)+sprtX; + pV=&psxVub[(sprCY<<11)+textX0]; + for(sprCX=0;sprCX<sprtW;sprCX+=2,sprA+=2) + { + tC = *pV++;tC2 = *pV++; + GetTextureTransColG32_SPR((uint32_t *)&psxVuw[sprA], + (((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16)| + GETLE16(&psxVuw[clutP+tC])); + } + if(sprCX==sprtW) + GetTextureTransColG_SPR(&psxVuw[sprA],GETLE16(&psxVuw[clutP+(*pV)])); + } + return; + + case 2: + + textX0+=(GlobalTextAddrX) + (textY0<<10); + sprtW--; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (sprCY=0;sprCY<sprtH;sprCY++) + { + sprA=((sprtY+sprCY)<<10)+sprtX; + + for (sprCX=0;sprCX<sprtW;sprCX+=2,sprA+=2) + { + GetTextureTransColG32_S((uint32_t *)&psxVuw[sprA], + (((int32_t)GETLE16(&psxVuw[(sprCY<<10) + textX0 + sprCX +1]))<<16)| + GETLE16(&psxVuw[(sprCY<<10) + textX0 + sprCX])); + } + if(sprCX==sprtW) + GetTextureTransColG_S(&psxVuw[sprA], + GETLE16(&psxVuw[(sprCY<<10) + textX0 + sprCX])); + + } + return; + } + +#endif + + for (sprCY=0;sprCY<sprtH;sprCY++) + { + sprA=((sprtY+sprCY)<<10)+sprtX; + + for (sprCX=0;sprCX<sprtW;sprCX+=2,sprA+=2) + { + GetTextureTransColG32_SPR((uint32_t *)&psxVuw[sprA], + (((int32_t)GETLE16(&psxVuw[(sprCY<<10) + textX0 + sprCX +1]))<<16)| + GETLE16(&psxVuw[(sprCY<<10) + textX0 + sprCX])); + } + if(sprCX==sprtW) + GetTextureTransColG_SPR(&psxVuw[sprA], + GETLE16(&psxVuw[(sprCY<<10) + textX0 + sprCX])); + + } + return; + } +} + +/////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +// LINE FUNCS +//////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////// + +void Line_E_SE_Shade(int x0, int y0, int x1, int y1, uint32_t rgb0, uint32_t rgb1) +{ + int dx, dy, incrE, incrSE, d; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dx = x1 - x0; + dy = y1 - y0; + + if (dx > 0) + { + dr = ((int32_t)r1 - (int32_t)r0) / dx; + dg = ((int32_t)g1 - (int32_t)g0) / dx; + db = ((int32_t)b1 - (int32_t)b0) / dx; + } + else + { + dr = ((int32_t)r1 - (int32_t)r0); + dg = ((int32_t)g1 - (int32_t)g0); + db = ((int32_t)b1 - (int32_t)b0); + } + + d = 2*dy - dx; /* Initial value of d */ + incrE = 2*dy; /* incr. used for move to E */ + incrSE = 2*(dy - dx); /* incr. used for move to SE */ + + if ((x0>=drawX)&&(x0<drawW)&&(y0>=drawY)&&(y0<drawH)) + GetShadeTransCol(&psxVuw[(y0<<10)+x0],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); + while(x0 < x1) + { + if (d <= 0) + { + d = d + incrE; /* Choose E */ + } + else + { + d = d + incrSE; /* Choose SE */ + y0++; + } + x0++; + + r0+=dr; + g0+=dg; + b0+=db; + + if ((x0>=drawX)&&(x0<drawW)&&(y0>=drawY)&&(y0<drawH)) + GetShadeTransCol(&psxVuw[(y0<<10)+x0],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_S_SE_Shade(int x0, int y0, int x1, int y1, uint32_t rgb0, uint32_t rgb1) +{ + int dx, dy, incrS, incrSE, d; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dx = x1 - x0; + dy = y1 - y0; + + if (dy > 0) + { + dr = ((int32_t)r1 - (int32_t)r0) / dy; + dg = ((int32_t)g1 - (int32_t)g0) / dy; + db = ((int32_t)b1 - (int32_t)b0) / dy; + } + else + { + dr = ((int32_t)r1 - (int32_t)r0); + dg = ((int32_t)g1 - (int32_t)g0); + db = ((int32_t)b1 - (int32_t)b0); + } + + d = 2*dx - dy; /* Initial value of d */ + incrS = 2*dx; /* incr. used for move to S */ + incrSE = 2*(dx - dy); /* incr. used for move to SE */ + + if ((x0>=drawX)&&(x0<drawW)&&(y0>=drawY)&&(y0<drawH)) + GetShadeTransCol(&psxVuw[(y0<<10)+x0],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); + while(y0 < y1) + { + if (d <= 0) + { + d = d + incrS; /* Choose S */ + } + else + { + d = d + incrSE; /* Choose SE */ + x0++; + } + y0++; + + r0+=dr; + g0+=dg; + b0+=db; + + if ((x0>=drawX)&&(x0<drawW)&&(y0>=drawY)&&(y0<drawH)) + GetShadeTransCol(&psxVuw[(y0<<10)+x0],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_N_NE_Shade(int x0, int y0, int x1, int y1, uint32_t rgb0, uint32_t rgb1) +{ + int dx, dy, incrN, incrNE, d; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dx = x1 - x0; + dy = -(y1 - y0); + + if (dy > 0) + { + dr = ((int32_t)r1 - (int32_t)r0) / dy; + dg = ((int32_t)g1 - (int32_t)g0) / dy; + db = ((int32_t)b1 - (int32_t)b0) / dy; + } + else + { + dr = ((int32_t)r1 - (int32_t)r0); + dg = ((int32_t)g1 - (int32_t)g0); + db = ((int32_t)b1 - (int32_t)b0); + } + + d = 2*dx - dy; /* Initial value of d */ + incrN = 2*dx; /* incr. used for move to N */ + incrNE = 2*(dx - dy); /* incr. used for move to NE */ + + if ((x0>=drawX)&&(x0<drawW)&&(y0>=drawY)&&(y0<drawH)) + GetShadeTransCol(&psxVuw[(y0<<10)+x0],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); + while(y0 > y1) + { + if (d <= 0) + { + d = d + incrN; /* Choose N */ + } + else + { + d = d + incrNE; /* Choose NE */ + x0++; + } + y0--; + + r0+=dr; + g0+=dg; + b0+=db; + + if ((x0>=drawX)&&(x0<drawW)&&(y0>=drawY)&&(y0<drawH)) + GetShadeTransCol(&psxVuw[(y0<<10)+x0],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_E_NE_Shade(int x0, int y0, int x1, int y1, uint32_t rgb0, uint32_t rgb1) +{ + int dx, dy, incrE, incrNE, d; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dx = x1 - x0; + dy = -(y1 - y0); + + if (dx > 0) + { + dr = ((int32_t)r1 - (int32_t)r0) / dx; + dg = ((int32_t)g1 - (int32_t)g0) / dx; + db = ((int32_t)b1 - (int32_t)b0) / dx; + } + else + { + dr = ((int32_t)r1 - (int32_t)r0); + dg = ((int32_t)g1 - (int32_t)g0); + db = ((int32_t)b1 - (int32_t)b0); + } + + d = 2*dy - dx; /* Initial value of d */ + incrE = 2*dy; /* incr. used for move to E */ + incrNE = 2*(dy - dx); /* incr. used for move to NE */ + + if ((x0>=drawX)&&(x0<drawW)&&(y0>=drawY)&&(y0<drawH)) + GetShadeTransCol(&psxVuw[(y0<<10)+x0],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); + while(x0 < x1) + { + if (d <= 0) + { + d = d + incrE; /* Choose E */ + } + else + { + d = d + incrNE; /* Choose NE */ + y0--; + } + x0++; + + r0+=dr; + g0+=dg; + b0+=db; + + if ((x0>=drawX)&&(x0<drawW)&&(y0>=drawY)&&(y0<drawH)) + GetShadeTransCol(&psxVuw[(y0<<10)+x0],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); + } +} + +/////////////////////////////////////////////////////////////////////// + +void VertLineShade(int x, int y0, int y1, uint32_t rgb0, uint32_t rgb1) +{ + int y, dy; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dy = (y1 - y0); + + if (dy > 0) + { + dr = ((int32_t)r1 - (int32_t)r0) / dy; + dg = ((int32_t)g1 - (int32_t)g0) / dy; + db = ((int32_t)b1 - (int32_t)b0) / dy; + } + else + { + dr = ((int32_t)r1 - (int32_t)r0); + dg = ((int32_t)g1 - (int32_t)g0); + db = ((int32_t)b1 - (int32_t)b0); + } + + if (y0 < drawY) + { + r0+=dr*(drawY - y0); + g0+=dg*(drawY - y0); + b0+=db*(drawY - y0); + y0 = drawY; + } + + if (y1 > drawH) + y1 = drawH; + + for (y = y0; y <= y1; y++) + { + GetShadeTransCol(&psxVuw[(y<<10)+x],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); + r0+=dr; + g0+=dg; + b0+=db; + } +} + +/////////////////////////////////////////////////////////////////////// + +void HorzLineShade(int y, int x0, int x1, uint32_t rgb0, uint32_t rgb1) +{ + int x, dx; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dx = (x1 - x0); + + if (dx > 0) + { + dr = ((int32_t)r1 - (int32_t)r0) / dx; + dg = ((int32_t)g1 - (int32_t)g0) / dx; + db = ((int32_t)b1 - (int32_t)b0) / dx; + } + else + { + dr = ((int32_t)r1 - (int32_t)r0); + dg = ((int32_t)g1 - (int32_t)g0); + db = ((int32_t)b1 - (int32_t)b0); + } + + if (x0 < drawX) + { + r0+=dr*(drawX - x0); + g0+=dg*(drawX - x0); + b0+=db*(drawX - x0); + x0 = drawX; + } + + if (x1 > drawW) + x1 = drawW; + + for (x = x0; x <= x1; x++) + { + GetShadeTransCol(&psxVuw[(y<<10)+x],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); + r0+=dr; + g0+=dg; + b0+=db; + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_E_SE_Flat(int x0, int y0, int x1, int y1, unsigned short colour) +{ + int dx, dy, incrE, incrSE, d, x, y; + + dx = x1 - x0; + dy = y1 - y0; + d = 2*dy - dx; /* Initial value of d */ + incrE = 2*dy; /* incr. used for move to E */ + incrSE = 2*(dy - dx); /* incr. used for move to SE */ + x = x0; + y = y0; + if ((x>=drawX)&&(x<drawW)&&(y>=drawY)&&(y<drawH)) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); + while(x < x1) + { + if (d <= 0) + { + d = d + incrE; /* Choose E */ + x++; + } + else + { + d = d + incrSE; /* Choose SE */ + x++; + y++; + } + if ((x>=drawX)&&(x<drawW)&&(y>=drawY)&&(y<drawH)) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_S_SE_Flat(int x0, int y0, int x1, int y1, unsigned short colour) +{ + int dx, dy, incrS, incrSE, d, x, y; + + dx = x1 - x0; + dy = y1 - y0; + d = 2*dx - dy; /* Initial value of d */ + incrS = 2*dx; /* incr. used for move to S */ + incrSE = 2*(dx - dy); /* incr. used for move to SE */ + x = x0; + y = y0; + if ((x>=drawX)&&(x<drawW)&&(y>=drawY)&&(y<drawH)) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); + while(y < y1) + { + if (d <= 0) + { + d = d + incrS; /* Choose S */ + y++; + } + else + { + d = d + incrSE; /* Choose SE */ + x++; + y++; + } + if ((x>=drawX)&&(x<drawW)&&(y>=drawY)&&(y<drawH)) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_N_NE_Flat(int x0, int y0, int x1, int y1, unsigned short colour) +{ + int dx, dy, incrN, incrNE, d, x, y; + + dx = x1 - x0; + dy = -(y1 - y0); + d = 2*dx - dy; /* Initial value of d */ + incrN = 2*dx; /* incr. used for move to N */ + incrNE = 2*(dx - dy); /* incr. used for move to NE */ + x = x0; + y = y0; + if ((x>=drawX)&&(x<drawW)&&(y>=drawY)&&(y<drawH)) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); + while(y > y1) + { + if (d <= 0) + { + d = d + incrN; /* Choose N */ + y--; + } + else + { + d = d + incrNE; /* Choose NE */ + x++; + y--; + } + if ((x>=drawX)&&(x<drawW)&&(y>=drawY)&&(y<drawH)) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_E_NE_Flat(int x0, int y0, int x1, int y1, unsigned short colour) +{ + int dx, dy, incrE, incrNE, d, x, y; + + dx = x1 - x0; + dy = -(y1 - y0); + d = 2*dy - dx; /* Initial value of d */ + incrE = 2*dy; /* incr. used for move to E */ + incrNE = 2*(dy - dx); /* incr. used for move to NE */ + x = x0; + y = y0; + if ((x>=drawX)&&(x<drawW)&&(y>=drawY)&&(y<drawH)) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); + while(x < x1) + { + if (d <= 0) + { + d = d + incrE; /* Choose E */ + x++; + } + else + { + d = d + incrNE; /* Choose NE */ + x++; + y--; + } + if ((x>=drawX)&&(x<drawW)&&(y>=drawY)&&(y<drawH)) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); + } +} + +/////////////////////////////////////////////////////////////////////// + +void VertLineFlat(int x, int y0, int y1, unsigned short colour) +{ + int y; + + if (y0 < drawY) + y0 = drawY; + + if (y1 > drawH) + y1 = drawH; + + for (y = y0; y <= y1; y++) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); +} + +/////////////////////////////////////////////////////////////////////// + +void HorzLineFlat(int y, int x0, int x1, unsigned short colour) +{ + int x; + + if (x0 < drawX) + x0 = drawX; + + if (x1 > drawW) + x1 = drawW; + + for (x = x0; x <= x1; x++) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); +} + +/////////////////////////////////////////////////////////////////////// + +/* Bresenham Line drawing function */ +void DrawSoftwareLineShade(int32_t rgb0, int32_t rgb1) +{ + short x0, y0, x1, y1, xt, yt; + int32_t rgbt; + double m, dy, dx; + + if(lx0>drawW && lx1>drawW) return; + if(ly0>drawH && ly1>drawH) return; + if(lx0<drawX && lx1<drawX) return; + if(ly0<drawY && ly1<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + x0 = lx0; + y0 = ly0; + x1 = lx1; + y1 = ly1; + + dx = x1 - x0; + dy = y1 - y0; + + if (dx == 0) + { + if (dy > 0) + VertLineShade(x0, y0, y1, rgb0, rgb1); + else + VertLineShade(x0, y1, y0, rgb1, rgb0); + } + else + if (dy == 0) + { + if (dx > 0) + HorzLineShade(y0, x0, x1, rgb0, rgb1); + else + HorzLineShade(y0, x1, x0, rgb1, rgb0); + } + else + { + if (dx < 0) + { + xt = x0; + yt = y0; + rgbt = rgb0; + x0 = x1; + y0 = y1; + rgb0 = rgb1; + x1 = xt; + y1 = yt; + rgb1 = rgb0; + + dx = x1 - x0; + dy = y1 - y0; + } + + m = dy/dx; + + if (m >= 0) + { + if (m > 1) + Line_S_SE_Shade(x0, y0, x1, y1, rgb0, rgb1); + else + Line_E_SE_Shade(x0, y0, x1, y1, rgb0, rgb1); + } + else + if (m < -1) + Line_N_NE_Shade(x0, y0, x1, y1, rgb0, rgb1); + else + Line_E_NE_Shade(x0, y0, x1, y1, rgb0, rgb1); + } +} + +/////////////////////////////////////////////////////////////////////// + +void DrawSoftwareLineFlat(int32_t rgb) +{ + short x0, y0, x1, y1, xt, yt; + double m, dy, dx; + unsigned short colour = 0; + + if(lx0>drawW && lx1>drawW) return; + if(ly0>drawH && ly1>drawH) return; + if(lx0<drawX && lx1<drawX) return; + if(ly0<drawY && ly1<drawY) return; + if(drawY>=drawH) return; + if(drawX>=drawW) return; + + colour = ((rgb & 0x00f80000)>>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); + + x0 = lx0; + y0 = ly0; + x1 = lx1; + y1 = ly1; + + dx = x1 - x0; + dy = y1 - y0; + + if (dx == 0) + { + if (dy == 0) + return; // Nothing to draw + else if (dy > 0) + VertLineFlat(x0, y0, y1, colour); + else + VertLineFlat(x0, y1, y0, colour); + } + else + if (dy == 0) + { + if (dx > 0) + HorzLineFlat(y0, x0, x1, colour); + else + HorzLineFlat(y0, x1, x0, colour); + } + else + { + if (dx < 0) + { + xt = x0; + yt = y0; + x0 = x1; + y0 = y1; + x1 = xt; + y1 = yt; + + dx = x1 - x0; + dy = y1 - y0; + } + + m = dy/dx; + + if (m >= 0) + { + if (m > 1) + Line_S_SE_Flat(x0, y0, x1, y1, colour); + else + Line_E_SE_Flat(x0, y0, x1, y1, colour); + } + else + if (m < -1) + Line_N_NE_Flat(x0, y0, x1, y1, colour); + else + Line_E_NE_Flat(x0, y0, x1, y1, colour); + } +} + +/////////////////////////////////////////////////////////////////////// diff --git a/plugins/dfxvideo/soft.h b/plugins/dfxvideo/soft.h new file mode 100644 index 00000000..f52d5c03 --- /dev/null +++ b/plugins/dfxvideo/soft.h @@ -0,0 +1,42 @@ +/***************************************************************************
+ soft.h - description
+ -------------------
+ begin : Sun Oct 28 2001
+ copyright : (C) 2001 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#ifndef _GPU_SOFT_H_
+#define _GPU_SOFT_H_
+
+void offsetPSXLine(void);
+void offsetPSX2(void);
+void offsetPSX3(void);
+void offsetPSX4(void);
+
+void FillSoftwareAreaTrans(short x0,short y0,short x1,short y1,unsigned short col);
+void FillSoftwareArea(short x0,short y0,short x1,short y1,unsigned short col);
+void drawPoly3G(int32_t rgb1, int32_t rgb2, int32_t rgb3);
+void drawPoly4G(int32_t rgb1, int32_t rgb2, int32_t rgb3, int32_t rgb4);
+void drawPoly3F(int32_t rgb);
+void drawPoly4F(int32_t rgb);
+void drawPoly4FT(unsigned char * baseAddr);
+void drawPoly4GT(unsigned char * baseAddr);
+void drawPoly3FT(unsigned char * baseAddr);
+void drawPoly3GT(unsigned char * baseAddr);
+void DrawSoftwareSprite(unsigned char * baseAddr,short w,short h,int32_t tx,int32_t ty);
+void DrawSoftwareSpriteTWin(unsigned char * baseAddr,int32_t w,int32_t h);
+void DrawSoftwareSpriteMirror(unsigned char * baseAddr,int32_t w,int32_t h);
+void DrawSoftwareLineShade(int32_t rgb0, int32_t rgb1);
+void DrawSoftwareLineFlat(int32_t rgb);
+
+#endif // _GPU_SOFT_H_
diff --git a/plugins/dfxvideo/swap.h b/plugins/dfxvideo/swap.h new file mode 100644 index 00000000..3f7ac21d --- /dev/null +++ b/plugins/dfxvideo/swap.h @@ -0,0 +1,71 @@ +#include <stdint.h> + +// byteswappings + +#define SWAP16(x) ({ uint16_t y=(x); (((y)>>8 & 0xff) | ((y)<<8 & 0xff00)); }) +#define SWAP32(x) ({ uint32_t y=(x); (((y)>>24 & 0xfful) | ((y)>>8 & 0xff00ul) | ((y)<<8 & 0xff0000ul) | ((y)<<24 & 0xff000000ul)); }) + +#ifdef __BIG_ENDIAN__ + +// big endian config +#define HOST2LE32(x) SWAP32(x) +#define HOST2BE32(x) (x) +#define LE2HOST32(x) SWAP32(x) +#define BE2HOST32(x) (x) + +#define HOST2LE16(x) SWAP16(x) +#define HOST2BE16(x) (x) +#define LE2HOST16(x) SWAP16(x) +#define BE2HOST16(x) (x) + +#else + +// little endian config +#define HOST2LE32(x) (x) +#define HOST2BE32(x) SWAP32(x) +#define LE2HOST32(x) (x) +#define BE2HOST32(x) SWAP32(x) + +#define HOST2LE16(x) (x) +#define HOST2BE16(x) SWAP16(x) +#define LE2HOST16(x) (x) +#define BE2HOST16(x) SWAP16(x) + +#endif + +#define GETLEs16(X) ((int16_t)GETLE16((uint16_t *)X)) +#define GETLEs32(X) ((int16_t)GETLE32((uint16_t *)X)) + +#if defined(__PPC__) && defined(__BIG_ENDIAN__) + +// GCC style +static __inline__ uint16_t GETLE16(uint16_t *ptr) { + uint16_t ret; __asm__ ("lhbrx %0, 0, %1" : "=r" (ret) : "r" (ptr)); + return ret; +} +static __inline__ uint32_t GETLE32(uint32_t *ptr) { + uint32_t ret; + __asm__ ("lwbrx %0, 0, %1" : "=r" (ret) : "r" (ptr)); + return ret; +} +static __inline__ uint32_t GETLE16D(uint32_t *ptr) { + uint32_t ret; + __asm__ ("lwbrx %0, 0, %1\n" + "rlwinm %0, %0, 16, 0, 31" : "=r" (ret) : "r" (ptr)); + return ret; +} + +static __inline__ void PUTLE16(uint16_t *ptr, uint16_t val) { + __asm__ ("sthbrx %0, 0, %1" : : "r" (val), "r" (ptr) : "memory"); +} +static __inline__ void PUTLE32(uint32_t *ptr, uint32_t val) { + __asm__ ("stwbrx %0, 0, %1" : : "r" (val), "r" (ptr) : "memory"); +} + +#else +#define GETLE16(X) LE2HOST16(*(uint16_t *)X) +#define GETLE32(X) LE2HOST32(*(uint32_t *)X) +#define GETLE16D(X) ({uint32_t val = GETLE32(X); (val<<16 | val >> 16);}) +#define PUTLE16(X, Y) do{*((uint16_t *)X)=HOST2LE16((uint16_t)Y);}while(0) +#define PUTLE32(X, Y) do{*((uint32_t *)X)=HOST2LE16((uint32_t)Y);}while(0) +#endif diff --git a/plugins/dfxvideo/zn.c b/plugins/dfxvideo/zn.c new file mode 100644 index 00000000..6233642b --- /dev/null +++ b/plugins/dfxvideo/zn.c @@ -0,0 +1,255 @@ +/*************************************************************************** + zn.c - description + ------------------- + begin : Sat Jan 31 2004 + copyright : (C) 2004 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define _IN_ZN + +#include "externals.h" + +// --------------------------------------------------- // +// - psx gpu plugin interface prototypes-------------- // +// --------------------------------------------------- // + +long GPUopen(unsigned long * disp,const char * CapText,const char * CfgFile); + +void CALLBACK GPUdisplayText(char * pText); +void CALLBACK GPUdisplayFlags(uint32_t dwFlags); +void CALLBACK GPUmakeSnapshot(void); +long CALLBACK GPUinit(); +long CALLBACK GPUclose(); +long CALLBACK GPUshutdown(); +void CALLBACK GPUcursor(int iPlayer,int x,int y); +void CALLBACK GPUupdateLace(void); +uint32_t CALLBACK GPUreadStatus(void); +void CALLBACK GPUwriteStatus(uint32_t gdata); +void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize); +uint32_t CALLBACK GPUreadData(void); +void CALLBACK GPUwriteDataMem(uint32_t * pMem, int iSize); +void CALLBACK GPUwriteData(uint32_t gdata); +void CALLBACK GPUsetMode(uint32_t gdata); +long CALLBACK GPUgetMode(void); +long CALLBACK GPUdmaChain(uint32_t * baseAddrL, uint32_t addr); +long CALLBACK GPUconfigure(void); +void CALLBACK GPUabout(void); +long CALLBACK GPUtest(void); +long CALLBACK GPUfreeze(uint32_t ulGetFreezeData,void * pF); +void CALLBACK GPUgetScreenPic(unsigned char * pMem); +void CALLBACK GPUshowScreenPic(unsigned char * pMem); + +void CALLBACK GPUkeypressed(int keycode); + + +// --------------------------------------------------- // +// - zn gpu interface -------------------------------- // +// --------------------------------------------------- // + +uint32_t dwGPUVersion=0; +int iGPUHeight=512; +int iGPUHeightMask=511; +int GlobalTextIL=0; +int iTileCheat=0; + +// --------------------------------------------------- // +// --------------------------------------------------- // +// --------------------------------------------------- // + +typedef struct GPUOTAG + { + uint32_t Version; // Version of structure - currently 1 + long hWnd; // Window handle + uint32_t ScreenRotation; // 0 = 0CW, 1 = 90CW, 2 = 180CW, 3 = 270CW = 90CCW + uint32_t GPUVersion; // 0 = a, 1 = b, 2 = c + const char* GameName; // NULL terminated string + const char* CfgFile; // NULL terminated string + } GPUConfiguration_t; + +// --------------------------------------------------- // +// --------------------------------------------------- // +// --------------------------------------------------- // + +void CALLBACK ZN_GPUdisplayFlags(uint32_t dwFlags) +{ + GPUdisplayFlags(dwFlags); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUmakeSnapshot(void) +{ + GPUmakeSnapshot(); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUinit() +{ // we always set the vram size to 2MB, if the ZN interface is used + iGPUHeight=1024; + iGPUHeightMask=1023; + + return GPUinit(); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUopen(void * vcfg) +{ + GPUConfiguration_t * cfg=(GPUConfiguration_t *)vcfg; + long lret; + + if(!cfg) return -1; + if(cfg->Version!=1) return -1; + + lret = GPUopen(&cfg->hWnd, cfg->GameName, cfg->CfgFile); + + +/* + if(!lstrcmp(cfg->GameName,"kikaioh") || + !lstrcmp(cfg->GameName,"sr2j") || + !lstrcmp(cfg->GameName,"rvschool_a")) + iTileCheat=1; +*/ + + // some ZN games seem to erase the cluts with a 'white' TileS... strange.. + // I've added a cheat to avoid this issue. We can set it globally (for + // all ZiNc games) without much risk + + iTileCheat=1; + + dwGPUVersion=cfg->GPUVersion; + + return lret; +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUclose() +{ + return GPUclose(); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUshutdown() +{ + return GPUshutdown(); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUupdateLace(void) +{ + GPUupdateLace(); +} + +// --------------------------------------------------- // + +uint32_t CALLBACK ZN_GPUreadStatus(void) +{ + return GPUreadStatus(); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUwriteStatus(uint32_t gdata) +{ + GPUwriteStatus(gdata); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUdmaSliceOut(uint32_t *baseAddrL, uint32_t addr, uint32_t iSize) +{ + GPUreadDataMem(baseAddrL+addr,iSize); + return 0; +} + +// --------------------------------------------------- // + +uint32_t CALLBACK ZN_GPUreadData(void) +{ + return GPUreadData(); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUsetMode(uint32_t gdata) +{ + GPUsetMode(gdata); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUgetMode(void) +{ + return GPUgetMode(); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUdmaSliceIn(uint32_t *baseAddrL, uint32_t addr, uint32_t iSize) +{ + GPUwriteDataMem(baseAddrL+addr,iSize); + return 0; +} +// --------------------------------------------------- // + +void CALLBACK ZN_GPUwriteData(uint32_t gdata) +{ + GPUwriteDataMem(&gdata,1); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUdmaChain(uint32_t * baseAddrL, uint32_t addr) +{ + return GPUdmaChain(baseAddrL,addr); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUtest(void) +{ + return GPUtest(); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUfreeze(uint32_t ulGetFreezeData,void * pF) +{ + return GPUfreeze(ulGetFreezeData,pF); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUgetScreenPic(unsigned char * pMem) +{ + GPUgetScreenPic(pMem); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUshowScreenPic(unsigned char * pMem) +{ + GPUshowScreenPic(pMem); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUkeypressed(int keycode) +{ + GPUkeypressed(keycode); +} + |
