diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2011-03-13 08:26:16 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2011-03-13 08:26:16 +0000 |
| commit | 379a8879f7dae1a9074317c0270e12dd203b32c0 (patch) | |
| tree | 348efb7ecd4f7cbc030f4b5db6683a857f2ae6cf /plugins/gxvideo/gpu.c | |
| parent | d34b4220bde29d7937d927e9d17a50470a36c500 (diff) | |
| download | pcsxr-379a8879f7dae1a9074317c0270e12dd203b32c0.tar.gz | |
Temporarily reverted r64524 until I (or someone else) find the time to sort out the stuff.
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@64536 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'plugins/gxvideo/gpu.c')
| -rw-r--r-- | plugins/gxvideo/gpu.c | 3104 |
1 files changed, 1555 insertions, 1549 deletions
diff --git a/plugins/gxvideo/gpu.c b/plugins/gxvideo/gpu.c index 85b003bd..22544950 100644 --- a/plugins/gxvideo/gpu.c +++ b/plugins/gxvideo/gpu.c @@ -1,1549 +1,1555 @@ -/* - * Copyright (C) 2010 Benoit Gschwind - * Inspired by original author : Pete Bernert - * - * 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 3 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 "config.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "globals.h" -#include "gpu.h" -#include "swap.h" -#include "psemu_plugin_defs.h" - -#define CALLBACK - -#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 MIN(a,b) ((a) > (b) ? (b) : (a)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) - -//////////////////////////////////////////////////////////////////////// -// PPDK developer must change libraryName field and can change revision and build -//////////////////////////////////////////////////////////////////////// - -unsigned char const version = 1; // do not touch - library for PSEmu 1.x -unsigned char const revision = 0; -unsigned char const build = 0; // increase that with each version - -static char const * libraryName = N_("GXVideo Driver"); -#if 0 -static char const * libraryInfo = N_("GXvideo Driver v1.00"); -#endif -//static char const * PluginAuthor = -// N_("gschwind (rewrite from Pete Bernert and the P.E.Op.S. team)"); - -//////////////////////////////////////////////////////////////////////// -// some misc external display funcs -//////////////////////////////////////////////////////////////////////// - -#include <time.h> - -//void CALLBACK GPUdisplayText(char * 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; - return 2; /* GPU plugin */ -} - -unsigned long CALLBACK PSEgetLibVersion(void) { - return version << 16 | revision << 8 | build; -} - -#if 0 -char * GPUgetLibInfos(void) { - return _(libraryInfo); -} -#endif - -//////////////////////////////////////////////////////////////////////// -// Snapshot func -//////////////////////////////////////////////////////////////////////// - -//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); -// //----------------------------------------------------// -// -// sprintf(szTxt, "Resolution/Color:\r\n- %dx%d ", g_cfg.ResX, g_cfg.ResY); -// -// 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); -// //----------------------------------------------------// -//#if !defined (_MACGL) && !defined (_WINDOWS) -// 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); -//#endif -// sprintf(szTxt, "- Game fixes: %s [%08x]\r\n", szO[iUseFixes], dwCfgFixes); -// strcat(pB, szTxt); -// //----------------------------------------------------// -// return pB; -// return 0; -//} - -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 = gpu_ctx.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] = gpu_ctx.PreviousPSXDisplay.Range.x1 % 256; - // header[0x13] = gpu_ctx.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++; - //#ifdef _WINDOWS - // sprintf(filename,"snap\\pcsx%04ld.bmp",snapshotnr); - //#else - // sprintf(filename, "%s/pcsx%04ld.bmp", getenv("HOME"), snapshotnr); - //#endif - // - // 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] = (unsigned char) RED(lu); - // line[j * 3 + 1] = (unsigned char) GREEN(lu); - // line[j * 3 + 0] = (unsigned char) 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() { - fprintf(stderr, "%s\n", __FUNCTION__); - memset(g_gpu.ulStatusControl, 0, 256 * sizeof(uint32_t)); // init save state scontrol field - g_gpu.psxVSecure.u8 = (uint8_t *) malloc((512 * 2) * 1024 + (1024 * 1024)); // always alloc one extra MB for soft drawing funcs security - if (!g_gpu.psxVSecure.u8) - return -1; - - //!!! ATTENTION !!! - g_gpu.psx_vram.u8 = g_gpu.psxVSecure.u8 + 512 * 1024; // security offset into double sized psx vram! - - g_gpu.psxVuw_eom.u16 = g_gpu.psx_vram.u16 + 1024 * 512; // pre-calc of end of vram - - memset(g_gpu.psxVSecure.s8, 0x00, (512 * 2) * 1024 + (1024 * 1024)); - memset(g_gpu.lGPUInfoVals, 0x00, 16 * sizeof(uint32_t)); - - g_gpu.dsp.range.x0 = 0; - g_gpu.dsp.range.x1 = 0; - g_gpu.lGPUdataRet = 0x400; - - g_gpu.DataWriteMode = DR_NORMAL; - - // Reset transfer values, to prevent mis-transfer of data - memset(&g_gpu.VRAMWrite, 0, sizeof(gxv_vram_load_t)); - memset(&g_gpu.VRAMRead, 0, sizeof(gxv_vram_load_t)); - - // device initialised already ! - g_gpu.status_reg = 0x14802000; - return 0; -} - -/* Here starts all... */ -long GPUopen(unsigned long * disp, char * CapText, char * CfgFile) { - unsigned long d; - - ReadConfig(); - - g_draw.bIsFirstFrame = 1; - - d = init_display(); // setup x - - if (disp) - *disp = d; // wanna x pointer? ok - - if (d) - return 0; - return -1; -} - -//////////////////////////////////////////////////////////////////////// -// time to leave... -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUclose() { - fprintf(stderr, "%s\n", __FUNCTION__); - //ReleaseKeyHandler(); // de-subclass window - CloseDisplay(); // shutdown direct draw - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// I shot the sheriff -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUshutdown() { - free(g_gpu.psxVSecure.s8); - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// roughly emulated screen centering bits... not complete !!! -//////////////////////////////////////////////////////////////////////// -// -//void ChangeDispOffsetsX(void) // X CENTER -//{ -// long lx, l; -// -// if (!g_gpu.dsp.range.x1) -// return; -// -// l = g_gpu.prev_dsp.DisplayMode.x; -// -// l *= (long) g_gpu.dsp.range.x1; -// l /= 2560; -// lx = l; -// l &= 0xfffffff8; -// -// if (l == g_gpu.prev_dsp.range.y1) -// return; // abusing range.y1 for -// g_gpu.prev_dsp.range.y1 = (short) l; // storing last x range and test -// -// if (lx >= g_gpu.prev_dsp.DisplayMode.x) { -// g_gpu.prev_dsp.range.x1 = (short) g_gpu.prev_dsp.DisplayMode.x; -// g_gpu.prev_dsp.range.x0 = 0; -// } else { -// g_gpu.prev_dsp.range.x1 = (short) l; -// -// g_gpu.prev_dsp.range.x0 = (g_gpu.dsp.range.x0 - 500) / 8; -// -// if (g_gpu.prev_dsp.range.x0 < 0) -// g_gpu.prev_dsp.range.x0 = 0; -// -// if ((g_gpu.prev_dsp.range.x0 + lx) > g_gpu.prev_dsp.DisplayMode.x) { -// g_gpu.prev_dsp.range.x0 = (short) (g_gpu.prev_dsp.DisplayMode.x -// - lx); -// g_gpu.prev_dsp.range.x0 += 2; //??? -// -// g_gpu.prev_dsp.range.x1 += (short) (lx - l); -// -// g_gpu.prev_dsp.range.x1 -= 2; // makes linux stretching easier -// } -// -// // some linux alignment security -// g_gpu.prev_dsp.range.x0 = g_gpu.prev_dsp.range.x0 >> 1; -// g_gpu.prev_dsp.range.x0 = g_gpu.prev_dsp.range.x0 << 1; -// g_gpu.prev_dsp.range.x1 = g_gpu.prev_dsp.range.x1 >> 1; -// g_gpu.prev_dsp.range.x1 = g_gpu.prev_dsp.range.x1 << 1; -// -// DoClearScreenBuffer(); -// } -// -// g_prim.bDoVSyncUpdate = 1; -//} - -//////////////////////////////////////////////////////////////////////// - -//void ChangeDispOffsetsY(void) // Y CENTER -//{ -// int iT, iO = g_gpu.prev_dsp.range.y0; -// int iOldYOffset = g_gpu.prev_dsp.DisplayModeNew.y; -// -// // new -// -// if ((g_gpu.prev_dsp.DisplayModeNew.x + g_gpu.dsp.DisplayModeNew.y) > 512) { -// int dy1 = 512 - g_gpu.prev_dsp.DisplayModeNew.x; -// int dy2 = -// (g_gpu.prev_dsp.DisplayModeNew.x + g_gpu.dsp.DisplayModeNew.y) -// - 512; -// -// if (dy1 >= dy2) { -// g_gpu.prev_dsp.DisplayModeNew.y = -dy2; -// } else { -// g_gpu.dsp.position.y = 0; -// g_gpu.prev_dsp.DisplayModeNew.y = -dy1; -// } -// } else -// g_gpu.prev_dsp.DisplayModeNew.y = 0; -// -// // eon -// -// if (g_gpu.prev_dsp.DisplayModeNew.y != iOldYOffset) // if old offset!=new offset: recalc height -// { -// g_gpu.dsp.Height = g_gpu.dsp.range.y1 - g_gpu.dsp.range.y0 -// + g_gpu.prev_dsp.DisplayModeNew.y; -// g_gpu.dsp.DisplayModeNew.y = g_gpu.dsp.Height * g_gpu.dsp.Double; -// } -// -// // -// -// if (g_gpu.dsp.PAL) -// iT = 48; -// else -// iT = 28; -// -// if (g_gpu.dsp.range.y0 >= iT) { -// g_gpu.prev_dsp.range.y0 = (short) ((g_gpu.dsp.range.y0 - iT - 4) -// * g_gpu.dsp.Double); -// if (g_gpu.prev_dsp.range.y0 < 0) -// g_gpu.prev_dsp.range.y0 = 0; -// g_gpu.dsp.DisplayModeNew.y += g_gpu.prev_dsp.range.y0; -// } else -// g_gpu.prev_dsp.range.y0 = 0; -// -// if (iO != g_gpu.prev_dsp.range.y0) { -// DoClearScreenBuffer(); -// } -//} - -//////////////////////////////////////////////////////////////////////// -// check if update needed -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// - -// TOGGLE FULLSCREEN - WINDOW DISABLED -//void ChangeWindowMode(void) { -// 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 = 0; -// bDoVSyncUpdate = 1; -//} - -//////////////////////////////////////////////////////////////////////// -// gun cursor func: player=0-7, x=0-511, y=0-255 -//////////////////////////////////////////////////////////////////////// - -/* disabled */ -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 -{ - - g_gpu.status_reg ^= STATUS_ODDLINES; - - if (g_gpu.status_reg & STATUS_DISPLAYDISABLED) { - do_clear_screen_buffer(); - return; - } - - /* I do not roughly emulate interlace, I just draw 1/2 frame - * to save CPU, and improve render */ - if (!(g_gpu.status_reg & STATUS_INTERLACED) || (g_gpu.status_reg - & STATUS_ODDLINES)) - do_buffer_swap(); - - frame_cap(g_gpu.fps); -} - -//////////////////////////////////////////////////////////////////////// -// process read request from GPU status register -//////////////////////////////////////////////////////////////////////// - - -uint32_t CALLBACK GPUreadStatus(void) // READ STATUS -{ - return g_gpu.status_reg; -} - -//////////////////////////////////////////////////////////////////////// -// processes data send to GPU status register -// these are always single packet commands. -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUwriteStatus(uint32_t gdata) { - uint32_t lCommand = (gdata >> 24) & 0xff; - g_gpu.ulStatusControl[lCommand] = gdata; // store command for freezing - switch (lCommand) { - case 0x00: - /* reset GPU */ - memset(g_gpu.lGPUInfoVals, 0x00, 16 * sizeof(uint32_t)); - /* STATUS_READYFORCOMMANDS | STATUS_IDLE | STATUS_DISPLAYDISABLED | UNKNOW13 */ - g_gpu.status_reg = 0x14802000; - g_gpu.DataWriteMode = DR_NORMAL; - g_gpu.DataReadMode = DR_NORMAL; - g_prim.drawX = 0; - g_prim.drawY = 0; - g_prim.drawW = 0; - g_prim.drawH = 0; - g_draw.sSetMask = 0; - g_draw.lSetMask = 0; - g_draw.bCheckMask = 0; - g_prim.usMirror = 0; - g_soft.GlobalTextAddrX = 0; - g_soft.GlobalTextAddrY = 0; - g_soft.GlobalTextTP = 0; - g_soft.GlobalTextABR = 0; - g_prim.bUsingTWin = 0; - return; - case 0x01: - /* reset command buffer */ - //fprintf(stderr, "Reset command buffer not implemented\n"); - return; - case 0x02: - /* reset IRQ */ - //fprintf(stderr, "Reset IRQ not implemented\n"); - return; - case 0x03: - /* Enable or disable the display */ - if (gdata & 0x01) - g_gpu.status_reg |= STATUS_DISPLAYDISABLED; - else - g_gpu.status_reg &= ~STATUS_DISPLAYDISABLED; - return; - case 0x04: - /* Set the transfering mode */ - gdata &= 0x03; // Only want the lower two bits - g_gpu.DataWriteMode = DR_NORMAL; - g_gpu.DataReadMode = DR_NORMAL; - if (gdata == 0x02) - g_gpu.DataWriteMode = DR_VRAMTRANSFER; - if (gdata == 0x03) - g_gpu.DataReadMode = DR_VRAMTRANSFER; - g_gpu.status_reg &= ~STATUS_DMABITS; // Clear the current settings of the DMA bits - g_gpu.status_reg |= (gdata << 29); // Set the DMA bits according to the received data - return; - case 0x05: - /* setting display position */ - g_gpu.dsp.position.y = (short) ((gdata >> 10) & 0x1ff); - g_gpu.dsp.position.x = (short) (gdata & 0x3ff); - //fprintf(stderr, "Update display position X=%d,Y=%d\n", - // g_gpu.dsp.position.x, g_gpu.dsp.position.y); - return; - case 0x06: - /* Set width */ - g_gpu.dsp.range.x0 = (short) (gdata & 0x03ff); - g_gpu.dsp.range.x1 = (short) ((gdata >> 12) & 0x0fff); - //fprintf(stderr, "Setrange x0 : %d, x1 : %d\n", g_gpu.dsp.range.x0, - // g_gpu.dsp.range.x1); - return; - case 0x07: - /* Set height */ - g_gpu.dsp.range.y0 = (short) (gdata & 0x3ff); - g_gpu.dsp.range.y1 = (short) ((gdata >> 10) & 0x3ff); - //fprintf(stderr, "Setrange y0 : %d, y1 : %d\n", g_gpu.dsp.range.y0, - // g_gpu.dsp.range.y1); - return; - case 0x08: - /* setting display infos */ - //fprintf(stderr, "command %x\n", gdata&0x000043); - switch (gdata & 0x000043) { - case 0x00: - g_gpu.dsp.mode.x = 10; - break; - case 0x01: - g_gpu.dsp.mode.x = 8; - break; - case 0x02: - g_gpu.dsp.mode.x = 5; - break; - case 0x03: - g_gpu.dsp.mode.x = 4; - break; - case 0x40: - g_gpu.dsp.mode.x = 7; - break; - default: - g_gpu.dsp.mode.x = 0; - } - - /* clear width status */ - g_gpu.status_reg &= ~STATUS_WIDTHBITS; - /* update status reg */ - g_gpu.status_reg |= ((gdata & 0x00000003) << 17) - | ((gdata & 0x00000040) << 10); - - switch (gdata & 0x000004) { - case 0x00: - g_gpu.status_reg &= ~STATUS_DOUBLEHEIGHT; - g_gpu.dsp.mode.y = 1; - break; - case 0x04: - g_gpu.status_reg |= STATUS_DOUBLEHEIGHT; - g_gpu.dsp.mode.y = 2; - break; - } - - switch (gdata & 0x08) { - case 0x00: - g_gpu.status_reg &= ~STATUS_PAL; - g_gpu.fps = 60; - break; - case 0x08: - g_gpu.status_reg |= STATUS_PAL; - g_gpu.fps = 50; - break; - } - //fprintf(stderr, "video mode %dx%d\n", g_gpu.dsp.mode.x, g_gpu.dsp.mode.y); - - if ((gdata & 0x10)) { - g_gpu.status_reg |= STATUS_RGB24; - } else { - g_gpu.status_reg &= ~STATUS_RGB24; - } - - if ((gdata & 0x20)) { - g_gpu.status_reg |= STATUS_INTERLACED; - } else { - g_gpu.status_reg &= ~STATUS_INTERLACED; - } - return; - case 0x10: - /* ask about GPU version and other stuff */ - gdata &= 0xff; - switch (gdata) { - case 0x02: - g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_TW]; // tw infos - return; - case 0x03: - g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_DRAWSTART]; // draw start - return; - case 0x04: - g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_DRAWEND]; // draw end - return; - case 0x05: - case 0x06: - g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_DRAWOFF]; // draw offset - return; - case 0x07: - if (0) - g_gpu.lGPUdataRet = 0x01; - else - g_gpu.lGPUdataRet = 0x02; // gpu type - return; - case 0x08: - case 0x0F: // some bios addr? - g_gpu.lGPUdataRet = 0xBFC03720; - return; - } - return; - default: - fprintf(stderr, "Unknow command %02x\n", lCommand); - } -} - -//////////////////////////////////////////////////////////////////////// -// vram read/write helpers, needed by LEWPY's optimized vram read/write :) -//////////////////////////////////////////////////////////////////////// - -static inline void FinishedVRAMWrite(void) { - // Set register to NORMAL operation - g_gpu.DataWriteMode = DR_NORMAL; - // Reset transfer values, to prevent mis-transfer of data - g_gpu.VRAMWrite.x = 0; - g_gpu.VRAMWrite.y = 0; - g_gpu.VRAMWrite.Width = 0; - g_gpu.VRAMWrite.Height = 0; - g_gpu.VRAMWrite.ColsRemaining = 0; - g_gpu.VRAMWrite.RowsRemaining = 0; -} - -static inline void FinishedVRAMRead(void) { - // Set register to NORMAL operation - g_gpu.DataReadMode = DR_NORMAL; - // Reset transfer values, to prevent mis-transfer of data - g_gpu.VRAMRead.x = 0; - g_gpu.VRAMRead.y = 0; - g_gpu.VRAMRead.Width = 0; - g_gpu.VRAMRead.Height = 0; - g_gpu.VRAMRead.ColsRemaining = 0; - g_gpu.VRAMRead.RowsRemaining = 0; - - // Indicate GPU is no longer ready for VRAM data in the STATUS REGISTER - g_gpu.status_reg &= ~STATUS_READYFORVRAM; -} - -//////////////////////////////////////////////////////////////////////// -// core read from vram -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize) { - int i; - - if (g_gpu.DataReadMode != DR_VRAMTRANSFER) - return; - - g_gpu.status_reg &= ~STATUS_IDLE; - - // adjust read ptr, if necessary - - while (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16) - g_gpu.VRAMRead.ImagePtr -= 512 * 1024; - while (g_gpu.VRAMRead.ImagePtr < g_gpu.psx_vram.u16) - g_gpu.VRAMRead.ImagePtr += 512 * 1024; - - for (i = 0; i < iSize; i++) { - // do 2 seperate 16bit reads for compatibility (wrap issues) - if ((g_gpu.VRAMRead.ColsRemaining > 0) && (g_gpu.VRAMRead.RowsRemaining - > 0)) { - // lower 16 bit - g_gpu.lGPUdataRet = (uint32_t) GETLE16(g_gpu.VRAMRead.ImagePtr); - - g_gpu.VRAMRead.ImagePtr++; - if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16) - g_gpu.VRAMRead.ImagePtr -= 512 * 1024; - g_gpu.VRAMRead.RowsRemaining--; - - if (g_gpu.VRAMRead.RowsRemaining <= 0) { - g_gpu.VRAMRead.RowsRemaining = g_gpu.VRAMRead.Width; - g_gpu.VRAMRead.ColsRemaining--; - g_gpu.VRAMRead.ImagePtr += 1024 - g_gpu.VRAMRead.Width; - if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16) - g_gpu.VRAMRead.ImagePtr -= 512 * 1024; - } - - // higher 16 bit (always, even if it's an odd width) - g_gpu.lGPUdataRet |= (uint32_t) GETLE16(g_gpu.VRAMRead.ImagePtr) - << 16; - PUTLE32(pMem, g_gpu.lGPUdataRet); - pMem++; - - if (g_gpu.VRAMRead.ColsRemaining <= 0) { - FinishedVRAMRead(); - goto ENDREAD; - } - - g_gpu.VRAMRead.ImagePtr++; - if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16) - g_gpu.VRAMRead.ImagePtr -= 512 * 1024; - g_gpu.VRAMRead.RowsRemaining--; - if (g_gpu.VRAMRead.RowsRemaining <= 0) { - g_gpu.VRAMRead.RowsRemaining = g_gpu.VRAMRead.Width; - g_gpu.VRAMRead.ColsRemaining--; - g_gpu.VRAMRead.ImagePtr += 1024 - g_gpu.VRAMRead.Width; - if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16) - g_gpu.VRAMRead.ImagePtr -= 512 * 1024; - } - if (g_gpu.VRAMRead.ColsRemaining <= 0) { - FinishedVRAMRead(); - goto ENDREAD; - } - } else { - FinishedVRAMRead(); - goto ENDREAD; - } - } - - ENDREAD: g_gpu.status_reg |= STATUS_IDLE; -} - -//////////////////////////////////////////////////////////////////////// - -uint32_t CALLBACK GPUreadData(void) { - uint32_t l; - GPUreadDataMem(&l, 1); - return g_gpu.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; - - g_gpu.status_reg &= ~STATUS_IDLE; - g_gpu.status_reg &= ~STATUS_READYFORCOMMANDS; - - STARTVRAM: - - if (g_gpu.DataWriteMode == DR_VRAMTRANSFER) { - char bFinished = 0; - - // make sure we are in vram - while (g_gpu.VRAMWrite.ImagePtr >= g_gpu.psxVuw_eom.u16) - g_gpu.VRAMWrite.ImagePtr -= 512 * 1024; - while (g_gpu.VRAMWrite.ImagePtr < g_gpu.psx_vram.u16) - g_gpu.VRAMWrite.ImagePtr += 512 * 1024; - - // now do the loop - while (g_gpu.VRAMWrite.ColsRemaining > 0) { - while (g_gpu.VRAMWrite.RowsRemaining > 0) { - if (i >= iSize) { - goto ENDVRAM; - } - i++; - - gdata = GETLE32(pMem); - pMem++; - - PUTLE16(g_gpu.VRAMWrite.ImagePtr, (unsigned short)gdata); - g_gpu.VRAMWrite.ImagePtr++; - if (g_gpu.VRAMWrite.ImagePtr >= g_gpu.psxVuw_eom.u16) - g_gpu.VRAMWrite.ImagePtr -= 512 * 1024; - g_gpu.VRAMWrite.RowsRemaining--; - - if (g_gpu.VRAMWrite.RowsRemaining <= 0) { - g_gpu.VRAMWrite.ColsRemaining--; - if (g_gpu.VRAMWrite.ColsRemaining <= 0) // last pixel is odd width - { - gdata - = (gdata & 0xFFFF) - | (((uint32_t) GETLE16(g_gpu.VRAMWrite.ImagePtr)) - << 16); - FinishedVRAMWrite(); - goto ENDVRAM; - } - g_gpu.VRAMWrite.RowsRemaining = g_gpu.VRAMWrite.Width; - g_gpu.VRAMWrite.ImagePtr += 1024 - g_gpu.VRAMWrite.Width; - } - - PUTLE16(g_gpu.VRAMWrite.ImagePtr, (unsigned short)(gdata>>16)); - g_gpu.VRAMWrite.ImagePtr++; - if (g_gpu.VRAMWrite.ImagePtr >= g_gpu.psxVuw_eom.u16) - g_gpu.VRAMWrite.ImagePtr -= 512 * 1024; - g_gpu.VRAMWrite.RowsRemaining--; - } - - g_gpu.VRAMWrite.RowsRemaining = g_gpu.VRAMWrite.Width; - g_gpu.VRAMWrite.ColsRemaining--; - g_gpu.VRAMWrite.ImagePtr += 1024 - g_gpu.VRAMWrite.Width; - bFinished = 1; - } - - FinishedVRAMWrite(); - } - - ENDVRAM: - - if (g_gpu.DataWriteMode == DR_NORMAL) { - void (* *primFunc)(unsigned char *); - primFunc = primTableJ; - - for (; i < iSize;) { - if (g_gpu.DataWriteMode == DR_VRAMTRANSFER) - goto STARTVRAM; - - gdata = GETLE32(pMem); - pMem++; - i++; - - if (g_gpu.gpuDataC == 0) { - command = (unsigned char) ((gdata >> 24) & 0xff); - - //if(command>=0xb0 && command<0xc0) auxprintf("b0 %x!!!!!!!!!\n",command); - - if (primTableCX[command]) { - g_gpu.gpuDataC = primTableCX[command]; - g_gpu.gpuCommand = command; - PUTLE32(&g_gpu.gpuDataM[0], gdata); - g_gpu.gpuDataP = 1; - } else { - //fprintf(stderr, "unknow command %02x \n", command); - continue; - } - } else { - PUTLE32(&g_gpu.gpuDataM[g_gpu.gpuDataP], gdata); - if (g_gpu.gpuDataC > 128) { - if ((g_gpu.gpuDataC == 254 && g_gpu.gpuDataP >= 3) - || (g_gpu.gpuDataC == 255 && g_gpu.gpuDataP >= 4 - && !(g_gpu.gpuDataP & 1))) { - if ((g_gpu.gpuDataM[g_gpu.gpuDataP] & 0xF000F000) - == 0x50005000) - g_gpu.gpuDataP = g_gpu.gpuDataC - 1; - } - } - g_gpu.gpuDataP++; - } - - if (g_gpu.gpuDataP == g_gpu.gpuDataC) { - g_gpu.gpuDataC = g_gpu.gpuDataP = 0; - primFunc[g_gpu.gpuCommand]((unsigned char *) g_gpu.gpuDataM); - } - } - } - - g_gpu.lGPUdataRet = gdata; - - g_gpu.status_reg |= STATUS_READYFORCOMMANDS; - g_gpu.status_reg |= STATUS_IDLE; -} - -//////////////////////////////////////////////////////////////////////// - -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 -//////////////////////////////////////////////////////////////////////// - -#if 0 -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 (g_gpu.DataWriteMode == DR_VRAMTRANSFER) - iT |= 0x1; - if (g_gpu.DataReadMode == DR_VRAMTRANSFER) - iT |= 0x2; - return iT; -} -#endif - -//////////////////////////////////////////////////////////////////////// -// call config dlg -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUconfigure(void) { - SoftDlgProc(); - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// sets all kind of act fixes -//////////////////////////////////////////////////////////////////////// - -#if 0 -void SetFixes(void) { - -} -#endif - -//////////////////////////////////////////////////////////////////////// -// process gpu commands -//////////////////////////////////////////////////////////////////////// - -unsigned long lUsedAddr[3]; - -static inline char CheckForEndlessLoop(unsigned long laddr) { - if (laddr == lUsedAddr[1]) - return 1; - if (laddr == lUsedAddr[2]) - return 1; - - if (laddr < lUsedAddr[0]) - lUsedAddr[1] = laddr; - else - lUsedAddr[2] = laddr; - lUsedAddr[0] = laddr; - return 0; -} - -long CALLBACK GPUdmaChain(uint32_t * baseAddrL, uint32_t addr) { - uint32_t dmaMem; - unsigned char * baseAddrB; - short count; - unsigned int DMACommandCounter = 0; - - g_gpu.status_reg &= ~STATUS_IDLE; - - lUsedAddr[0] = lUsedAddr[1] = lUsedAddr[2] = 0xffffff; - - baseAddrB = (unsigned char*) baseAddrL; - - do { - if (1) - 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); - - g_gpu.status_reg |= STATUS_IDLE; - 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 -//////////////////////////////////////////////////////////////////////// - -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; - //g_gpu.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 = g_gpu.status_reg; - memcpy(pF->ulControl, g_gpu.ulStatusControl, 256 * sizeof(uint32_t)); - memcpy(pF->psxVRam, g_gpu.psx_vram.u8, 1024 * 512 * 2); - - return 1; - } - - if (ulGetFreezeData != 0) - return 0; // 0: set data - - g_gpu.status_reg = pF->ulStatus; - memcpy(g_gpu.ulStatusControl, pF->ulControl, 256 * sizeof(uint32_t)); - memcpy(g_gpu.psx_vram.u8, pF->psxVRam, 1024 * 512 * 2); - - // RESET TEXTURE STORE HERE, IF YOU USE SOMETHING LIKE THAT - - GPUwriteStatus(g_gpu.ulStatusControl[0]); - GPUwriteStatus(g_gpu.ulStatusControl[1]); - GPUwriteStatus(g_gpu.ulStatusControl[2]); - GPUwriteStatus(g_gpu.ulStatusControl[3]); - GPUwriteStatus(g_gpu.ulStatusControl[8]); // try to repair things - GPUwriteStatus(g_gpu.ulStatusControl[6]); - GPUwriteStatus(g_gpu.ulStatusControl[7]); - GPUwriteStatus(g_gpu.ulStatusControl[5]); - GPUwriteStatus(g_gpu.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 } }; - -//////////////////////////////////////////////////////////////////////// - -#if 0 -static 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 -} -#endif - -//////////////////////////////////////////////////////////////////////// -// 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: - -long 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 - } - */ - return -1; -} - -//////////////////////////////////////////////////////////////////////// -// 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 - -long CALLBACK GPUshowScreenPic(unsigned char * pMem) { - DestroyPic(); // destroy old pic data - if (pMem == 0) - return 0; // done - CreatePic(pMem); // create new pic... don't free pMem or something like that... just read from it - return 0; -} - -#if 0 -void CALLBACK GPUsetfix(uint32_t dwFixBits) { - g_prim.dwEmuFixes = dwFixBits; -} -#endif - -void CALLBACK GPUvBlank(int val) { - //fprintf(stderr, "Vblanc %d\n", val); - //if(val) - // g_gpu.status_reg |= STATUS_ODDLINES; - //else - // g_gpu.status_reg &= ~STATUS_ODDLINES; -} +/*
+ * Copyright (C) 2010 Benoit Gschwind
+ * Inspired by original author : Pete Bernert
+ *
+ * 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 3 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 "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "globals.h"
+#include "gpu.h"
+#include "swap.h"
+
+#define CALLBACK
+
+#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 MIN(a,b) ((a) > (b) ? (b) : (a))
+#define MAX(a,b) ((a) < (b) ? (b) : (a))
+
+#ifdef ENABLE_NLS
+#include <libintl.h>
+#include <locale.h>
+#define _(x) gettext(x)
+#define N_(x) (x)
+#else
+#define _(x) (x)
+#define N_(x) (x)
+#endif
+
+////////////////////////////////////////////////////////////////////////
+// PPDK developer must change libraryName field and can change revision and build
+////////////////////////////////////////////////////////////////////////
+
+unsigned char const version = 1; // do not touch - library for PSEmu 1.x
+unsigned char const revision = 0;
+unsigned char const build = 0; // increase that with each version
+
+static char const * libraryName = N_("GXVideo Driver");
+static char const * libraryInfo = N_("GXvideo Driver v1.00");
+//static char const * PluginAuthor =
+// N_("gschwind (rewrite from Pete Bernert and the P.E.Op.S. team)");
+
+////////////////////////////////////////////////////////////////////////
+// some misc external display funcs
+////////////////////////////////////////////////////////////////////////
+
+#include <time.h>
+
+//void CALLBACK GPUdisplayText(char * 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;
+ return 2; /* GPU plugin */
+}
+
+unsigned long CALLBACK PSEgetLibVersion(void) {
+ return version << 16 | revision << 8 | build;
+}
+
+char * GPUgetLibInfos(void) {
+ return _(libraryInfo);
+}
+
+////////////////////////////////////////////////////////////////////////
+// Snapshot func
+////////////////////////////////////////////////////////////////////////
+
+//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);
+// //----------------------------------------------------//
+//
+// sprintf(szTxt, "Resolution/Color:\r\n- %dx%d ", g_cfg.ResX, g_cfg.ResY);
+//
+// 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);
+// //----------------------------------------------------//
+//#if !defined (_MACGL) && !defined (_WINDOWS)
+// 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);
+//#endif
+// sprintf(szTxt, "- Game fixes: %s [%08x]\r\n", szO[iUseFixes], dwCfgFixes);
+// strcat(pB, szTxt);
+// //----------------------------------------------------//
+// return pB;
+// return 0;
+//}
+
+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 = gpu_ctx.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] = gpu_ctx.PreviousPSXDisplay.Range.x1 % 256;
+ // header[0x13] = gpu_ctx.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++;
+ //#ifdef _WINDOWS
+ // sprintf(filename,"snap\\pcsx%04ld.bmp",snapshotnr);
+ //#else
+ // sprintf(filename, "%s/pcsx%04ld.bmp", getenv("HOME"), snapshotnr);
+ //#endif
+ //
+ // 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] = (unsigned char) RED(lu);
+ // line[j * 3 + 1] = (unsigned char) GREEN(lu);
+ // line[j * 3 + 0] = (unsigned char) 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() {
+ fprintf(stderr, "%s\n", __FUNCTION__);
+ memset(g_gpu.ulStatusControl, 0, 256 * sizeof(uint32_t)); // init save state scontrol field
+ g_gpu.psxVSecure.u8 = (uint8_t *) malloc((512 * 2) * 1024 + (1024 * 1024)); // always alloc one extra MB for soft drawing funcs security
+ if (!g_gpu.psxVSecure.u8)
+ return -1;
+
+ //!!! ATTENTION !!!
+ g_gpu.psx_vram.u8 = g_gpu.psxVSecure.u8 + 512 * 1024; // security offset into double sized psx vram!
+
+ g_gpu.psxVuw_eom.u16 = g_gpu.psx_vram.u16 + 1024 * 512; // pre-calc of end of vram
+
+ memset(g_gpu.psxVSecure.s8, 0x00, (512 * 2) * 1024 + (1024 * 1024));
+ memset(g_gpu.lGPUInfoVals, 0x00, 16 * sizeof(uint32_t));
+
+ g_gpu.dsp.range.x0 = 0;
+ g_gpu.dsp.range.x1 = 0;
+ g_gpu.lGPUdataRet = 0x400;
+
+ g_gpu.DataWriteMode = DR_NORMAL;
+
+ // Reset transfer values, to prevent mis-transfer of data
+ memset(&g_gpu.VRAMWrite, 0, sizeof(gxv_vram_load_t));
+ memset(&g_gpu.VRAMRead, 0, sizeof(gxv_vram_load_t));
+
+ // device initialised already !
+ g_gpu.status_reg = 0x14802000;
+ return 0;
+}
+
+/* Here starts all... */
+long GPUopen(unsigned long * disp, char * CapText, char * CfgFile) {
+ unsigned long d;
+
+ ReadConfig();
+
+ g_draw.bIsFirstFrame = 1;
+
+ d = init_display(); // setup x
+
+ if (disp)
+ *disp = d; // wanna x pointer? ok
+
+ if (d)
+ return 0;
+ return -1;
+}
+
+////////////////////////////////////////////////////////////////////////
+// time to leave...
+////////////////////////////////////////////////////////////////////////
+
+long CALLBACK GPUclose() {
+ fprintf(stderr, "%s\n", __FUNCTION__);
+ //ReleaseKeyHandler(); // de-subclass window
+ CloseDisplay(); // shutdown direct draw
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+// I shot the sheriff
+////////////////////////////////////////////////////////////////////////
+
+long CALLBACK GPUshutdown() {
+ free(g_gpu.psxVSecure.s8);
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+// roughly emulated screen centering bits... not complete !!!
+////////////////////////////////////////////////////////////////////////
+//
+//void ChangeDispOffsetsX(void) // X CENTER
+//{
+// long lx, l;
+//
+// if (!g_gpu.dsp.range.x1)
+// return;
+//
+// l = g_gpu.prev_dsp.DisplayMode.x;
+//
+// l *= (long) g_gpu.dsp.range.x1;
+// l /= 2560;
+// lx = l;
+// l &= 0xfffffff8;
+//
+// if (l == g_gpu.prev_dsp.range.y1)
+// return; // abusing range.y1 for
+// g_gpu.prev_dsp.range.y1 = (short) l; // storing last x range and test
+//
+// if (lx >= g_gpu.prev_dsp.DisplayMode.x) {
+// g_gpu.prev_dsp.range.x1 = (short) g_gpu.prev_dsp.DisplayMode.x;
+// g_gpu.prev_dsp.range.x0 = 0;
+// } else {
+// g_gpu.prev_dsp.range.x1 = (short) l;
+//
+// g_gpu.prev_dsp.range.x0 = (g_gpu.dsp.range.x0 - 500) / 8;
+//
+// if (g_gpu.prev_dsp.range.x0 < 0)
+// g_gpu.prev_dsp.range.x0 = 0;
+//
+// if ((g_gpu.prev_dsp.range.x0 + lx) > g_gpu.prev_dsp.DisplayMode.x) {
+// g_gpu.prev_dsp.range.x0 = (short) (g_gpu.prev_dsp.DisplayMode.x
+// - lx);
+// g_gpu.prev_dsp.range.x0 += 2; //???
+//
+// g_gpu.prev_dsp.range.x1 += (short) (lx - l);
+//
+// g_gpu.prev_dsp.range.x1 -= 2; // makes linux stretching easier
+// }
+//
+// // some linux alignment security
+// g_gpu.prev_dsp.range.x0 = g_gpu.prev_dsp.range.x0 >> 1;
+// g_gpu.prev_dsp.range.x0 = g_gpu.prev_dsp.range.x0 << 1;
+// g_gpu.prev_dsp.range.x1 = g_gpu.prev_dsp.range.x1 >> 1;
+// g_gpu.prev_dsp.range.x1 = g_gpu.prev_dsp.range.x1 << 1;
+//
+// DoClearScreenBuffer();
+// }
+//
+// g_prim.bDoVSyncUpdate = 1;
+//}
+
+////////////////////////////////////////////////////////////////////////
+
+//void ChangeDispOffsetsY(void) // Y CENTER
+//{
+// int iT, iO = g_gpu.prev_dsp.range.y0;
+// int iOldYOffset = g_gpu.prev_dsp.DisplayModeNew.y;
+//
+// // new
+//
+// if ((g_gpu.prev_dsp.DisplayModeNew.x + g_gpu.dsp.DisplayModeNew.y) > 512) {
+// int dy1 = 512 - g_gpu.prev_dsp.DisplayModeNew.x;
+// int dy2 =
+// (g_gpu.prev_dsp.DisplayModeNew.x + g_gpu.dsp.DisplayModeNew.y)
+// - 512;
+//
+// if (dy1 >= dy2) {
+// g_gpu.prev_dsp.DisplayModeNew.y = -dy2;
+// } else {
+// g_gpu.dsp.position.y = 0;
+// g_gpu.prev_dsp.DisplayModeNew.y = -dy1;
+// }
+// } else
+// g_gpu.prev_dsp.DisplayModeNew.y = 0;
+//
+// // eon
+//
+// if (g_gpu.prev_dsp.DisplayModeNew.y != iOldYOffset) // if old offset!=new offset: recalc height
+// {
+// g_gpu.dsp.Height = g_gpu.dsp.range.y1 - g_gpu.dsp.range.y0
+// + g_gpu.prev_dsp.DisplayModeNew.y;
+// g_gpu.dsp.DisplayModeNew.y = g_gpu.dsp.Height * g_gpu.dsp.Double;
+// }
+//
+// //
+//
+// if (g_gpu.dsp.PAL)
+// iT = 48;
+// else
+// iT = 28;
+//
+// if (g_gpu.dsp.range.y0 >= iT) {
+// g_gpu.prev_dsp.range.y0 = (short) ((g_gpu.dsp.range.y0 - iT - 4)
+// * g_gpu.dsp.Double);
+// if (g_gpu.prev_dsp.range.y0 < 0)
+// g_gpu.prev_dsp.range.y0 = 0;
+// g_gpu.dsp.DisplayModeNew.y += g_gpu.prev_dsp.range.y0;
+// } else
+// g_gpu.prev_dsp.range.y0 = 0;
+//
+// if (iO != g_gpu.prev_dsp.range.y0) {
+// DoClearScreenBuffer();
+// }
+//}
+
+////////////////////////////////////////////////////////////////////////
+// check if update needed
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+
+// TOGGLE FULLSCREEN - WINDOW DISABLED
+//void ChangeWindowMode(void) {
+// 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 = 0;
+// bDoVSyncUpdate = 1;
+//}
+
+////////////////////////////////////////////////////////////////////////
+// gun cursor func: player=0-7, x=0-511, y=0-255
+////////////////////////////////////////////////////////////////////////
+
+/* disabled */
+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
+{
+
+ g_gpu.status_reg ^= STATUS_ODDLINES;
+
+ if (g_gpu.status_reg & STATUS_DISPLAYDISABLED) {
+ do_clear_screen_buffer();
+ return;
+ }
+
+ /* I do not roughly emulate interlace, I just draw 1/2 frame
+ * to save CPU, and improve render */
+ if (!(g_gpu.status_reg & STATUS_INTERLACED) || (g_gpu.status_reg
+ & STATUS_ODDLINES))
+ do_buffer_swap();
+
+ frame_cap(g_gpu.fps);
+}
+
+////////////////////////////////////////////////////////////////////////
+// process read request from GPU status register
+////////////////////////////////////////////////////////////////////////
+
+
+uint32_t CALLBACK GPUreadStatus(void) // READ STATUS
+{
+ return g_gpu.status_reg;
+}
+
+////////////////////////////////////////////////////////////////////////
+// processes data send to GPU status register
+// these are always single packet commands.
+////////////////////////////////////////////////////////////////////////
+
+void CALLBACK GPUwriteStatus(uint32_t gdata) {
+ uint32_t lCommand = (gdata >> 24) & 0xff;
+ g_gpu.ulStatusControl[lCommand] = gdata; // store command for freezing
+ switch (lCommand) {
+ case 0x00:
+ /* reset GPU */
+ memset(g_gpu.lGPUInfoVals, 0x00, 16 * sizeof(uint32_t));
+ /* STATUS_READYFORCOMMANDS | STATUS_IDLE | STATUS_DISPLAYDISABLED | UNKNOW13 */
+ g_gpu.status_reg = 0x14802000;
+ g_gpu.DataWriteMode = DR_NORMAL;
+ g_gpu.DataReadMode = DR_NORMAL;
+ g_prim.drawX = 0;
+ g_prim.drawY = 0;
+ g_prim.drawW = 0;
+ g_prim.drawH = 0;
+ g_draw.sSetMask = 0;
+ g_draw.lSetMask = 0;
+ g_draw.bCheckMask = 0;
+ g_prim.usMirror = 0;
+ g_soft.GlobalTextAddrX = 0;
+ g_soft.GlobalTextAddrY = 0;
+ g_soft.GlobalTextTP = 0;
+ g_soft.GlobalTextABR = 0;
+ g_prim.bUsingTWin = 0;
+ return;
+ case 0x01:
+ /* reset command buffer */
+ //fprintf(stderr, "Reset command buffer not implemented\n");
+ return;
+ case 0x02:
+ /* reset IRQ */
+ //fprintf(stderr, "Reset IRQ not implemented\n");
+ return;
+ case 0x03:
+ /* Enable or disable the display */
+ if (gdata & 0x01)
+ g_gpu.status_reg |= STATUS_DISPLAYDISABLED;
+ else
+ g_gpu.status_reg &= ~STATUS_DISPLAYDISABLED;
+ return;
+ case 0x04:
+ /* Set the transfering mode */
+ gdata &= 0x03; // Only want the lower two bits
+ g_gpu.DataWriteMode = DR_NORMAL;
+ g_gpu.DataReadMode = DR_NORMAL;
+ if (gdata == 0x02)
+ g_gpu.DataWriteMode = DR_VRAMTRANSFER;
+ if (gdata == 0x03)
+ g_gpu.DataReadMode = DR_VRAMTRANSFER;
+ g_gpu.status_reg &= ~STATUS_DMABITS; // Clear the current settings of the DMA bits
+ g_gpu.status_reg |= (gdata << 29); // Set the DMA bits according to the received data
+ return;
+ case 0x05:
+ /* setting display position */
+ g_gpu.dsp.position.y = (short) ((gdata >> 10) & 0x1ff);
+ g_gpu.dsp.position.x = (short) (gdata & 0x3ff);
+ //fprintf(stderr, "Update display position X=%d,Y=%d\n",
+ // g_gpu.dsp.position.x, g_gpu.dsp.position.y);
+ return;
+ case 0x06:
+ /* Set width */
+ g_gpu.dsp.range.x0 = (short) (gdata & 0x03ff);
+ g_gpu.dsp.range.x1 = (short) ((gdata >> 12) & 0x0fff);
+ //fprintf(stderr, "Setrange x0 : %d, x1 : %d\n", g_gpu.dsp.range.x0,
+ // g_gpu.dsp.range.x1);
+ return;
+ case 0x07:
+ /* Set height */
+ g_gpu.dsp.range.y0 = (short) (gdata & 0x3ff);
+ g_gpu.dsp.range.y1 = (short) ((gdata >> 10) & 0x3ff);
+ //fprintf(stderr, "Setrange y0 : %d, y1 : %d\n", g_gpu.dsp.range.y0,
+ // g_gpu.dsp.range.y1);
+ return;
+ case 0x08:
+ /* setting display infos */
+ //fprintf(stderr, "command %x\n", gdata&0x000043);
+ switch (gdata & 0x000043) {
+ case 0x00:
+ g_gpu.dsp.mode.x = 10;
+ break;
+ case 0x01:
+ g_gpu.dsp.mode.x = 8;
+ break;
+ case 0x02:
+ g_gpu.dsp.mode.x = 5;
+ break;
+ case 0x03:
+ g_gpu.dsp.mode.x = 4;
+ break;
+ case 0x40:
+ g_gpu.dsp.mode.x = 7;
+ break;
+ default:
+ g_gpu.dsp.mode.x = 0;
+ }
+
+ /* clear width status */
+ g_gpu.status_reg &= ~STATUS_WIDTHBITS;
+ /* update status reg */
+ g_gpu.status_reg |= ((gdata & 0x00000003) << 17)
+ | ((gdata & 0x00000040) << 10);
+
+ switch (gdata & 0x000004) {
+ case 0x00:
+ g_gpu.status_reg &= ~STATUS_DOUBLEHEIGHT;
+ g_gpu.dsp.mode.y = 1;
+ break;
+ case 0x04:
+ g_gpu.status_reg |= STATUS_DOUBLEHEIGHT;
+ g_gpu.dsp.mode.y = 2;
+ break;
+ }
+
+ switch (gdata & 0x08) {
+ case 0x00:
+ g_gpu.status_reg &= ~STATUS_PAL;
+ g_gpu.fps = 60;
+ break;
+ case 0x08:
+ g_gpu.status_reg |= STATUS_PAL;
+ g_gpu.fps = 50;
+ break;
+ }
+ //fprintf(stderr, "video mode %dx%d\n", g_gpu.dsp.mode.x, g_gpu.dsp.mode.y);
+
+ if ((gdata & 0x10)) {
+ g_gpu.status_reg |= STATUS_RGB24;
+ } else {
+ g_gpu.status_reg &= ~STATUS_RGB24;
+ }
+
+ if ((gdata & 0x20)) {
+ g_gpu.status_reg |= STATUS_INTERLACED;
+ } else {
+ g_gpu.status_reg &= ~STATUS_INTERLACED;
+ }
+ return;
+ case 0x10:
+ /* ask about GPU version and other stuff */
+ gdata &= 0xff;
+ switch (gdata) {
+ case 0x02:
+ g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_TW]; // tw infos
+ return;
+ case 0x03:
+ g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_DRAWSTART]; // draw start
+ return;
+ case 0x04:
+ g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_DRAWEND]; // draw end
+ return;
+ case 0x05:
+ case 0x06:
+ g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_DRAWOFF]; // draw offset
+ return;
+ case 0x07:
+ if (0)
+ g_gpu.lGPUdataRet = 0x01;
+ else
+ g_gpu.lGPUdataRet = 0x02; // gpu type
+ return;
+ case 0x08:
+ case 0x0F: // some bios addr?
+ g_gpu.lGPUdataRet = 0xBFC03720;
+ return;
+ }
+ return;
+ default:
+ fprintf(stderr, "Unknow command %02x\n", lCommand);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+// vram read/write helpers, needed by LEWPY's optimized vram read/write :)
+////////////////////////////////////////////////////////////////////////
+
+inline void FinishedVRAMWrite(void) {
+ // Set register to NORMAL operation
+ g_gpu.DataWriteMode = DR_NORMAL;
+ // Reset transfer values, to prevent mis-transfer of data
+ g_gpu.VRAMWrite.x = 0;
+ g_gpu.VRAMWrite.y = 0;
+ g_gpu.VRAMWrite.Width = 0;
+ g_gpu.VRAMWrite.Height = 0;
+ g_gpu.VRAMWrite.ColsRemaining = 0;
+ g_gpu.VRAMWrite.RowsRemaining = 0;
+}
+
+inline void FinishedVRAMRead(void) {
+ // Set register to NORMAL operation
+ g_gpu.DataReadMode = DR_NORMAL;
+ // Reset transfer values, to prevent mis-transfer of data
+ g_gpu.VRAMRead.x = 0;
+ g_gpu.VRAMRead.y = 0;
+ g_gpu.VRAMRead.Width = 0;
+ g_gpu.VRAMRead.Height = 0;
+ g_gpu.VRAMRead.ColsRemaining = 0;
+ g_gpu.VRAMRead.RowsRemaining = 0;
+
+ // Indicate GPU is no longer ready for VRAM data in the STATUS REGISTER
+ g_gpu.status_reg &= ~STATUS_READYFORVRAM;
+}
+
+////////////////////////////////////////////////////////////////////////
+// core read from vram
+////////////////////////////////////////////////////////////////////////
+
+void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize) {
+ int i;
+
+ if (g_gpu.DataReadMode != DR_VRAMTRANSFER)
+ return;
+
+ g_gpu.status_reg &= ~STATUS_IDLE;
+
+ // adjust read ptr, if necessary
+
+ while (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16)
+ g_gpu.VRAMRead.ImagePtr -= 512 * 1024;
+ while (g_gpu.VRAMRead.ImagePtr < g_gpu.psx_vram.u16)
+ g_gpu.VRAMRead.ImagePtr += 512 * 1024;
+
+ for (i = 0; i < iSize; i++) {
+ // do 2 seperate 16bit reads for compatibility (wrap issues)
+ if ((g_gpu.VRAMRead.ColsRemaining > 0) && (g_gpu.VRAMRead.RowsRemaining
+ > 0)) {
+ // lower 16 bit
+ g_gpu.lGPUdataRet = (uint32_t) GETLE16(g_gpu.VRAMRead.ImagePtr);
+
+ g_gpu.VRAMRead.ImagePtr++;
+ if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16)
+ g_gpu.VRAMRead.ImagePtr -= 512 * 1024;
+ g_gpu.VRAMRead.RowsRemaining--;
+
+ if (g_gpu.VRAMRead.RowsRemaining <= 0) {
+ g_gpu.VRAMRead.RowsRemaining = g_gpu.VRAMRead.Width;
+ g_gpu.VRAMRead.ColsRemaining--;
+ g_gpu.VRAMRead.ImagePtr += 1024 - g_gpu.VRAMRead.Width;
+ if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16)
+ g_gpu.VRAMRead.ImagePtr -= 512 * 1024;
+ }
+
+ // higher 16 bit (always, even if it's an odd width)
+ g_gpu.lGPUdataRet |= (uint32_t) GETLE16(g_gpu.VRAMRead.ImagePtr)
+ << 16;
+ PUTLE32(pMem, g_gpu.lGPUdataRet);
+ pMem++;
+
+ if (g_gpu.VRAMRead.ColsRemaining <= 0) {
+ FinishedVRAMRead();
+ goto ENDREAD;
+ }
+
+ g_gpu.VRAMRead.ImagePtr++;
+ if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16)
+ g_gpu.VRAMRead.ImagePtr -= 512 * 1024;
+ g_gpu.VRAMRead.RowsRemaining--;
+ if (g_gpu.VRAMRead.RowsRemaining <= 0) {
+ g_gpu.VRAMRead.RowsRemaining = g_gpu.VRAMRead.Width;
+ g_gpu.VRAMRead.ColsRemaining--;
+ g_gpu.VRAMRead.ImagePtr += 1024 - g_gpu.VRAMRead.Width;
+ if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16)
+ g_gpu.VRAMRead.ImagePtr -= 512 * 1024;
+ }
+ if (g_gpu.VRAMRead.ColsRemaining <= 0) {
+ FinishedVRAMRead();
+ goto ENDREAD;
+ }
+ } else {
+ FinishedVRAMRead();
+ goto ENDREAD;
+ }
+ }
+
+ ENDREAD: g_gpu.status_reg |= STATUS_IDLE;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+uint32_t CALLBACK GPUreadData(void) {
+ uint32_t l;
+ GPUreadDataMem(&l, 1);
+ return g_gpu.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;
+
+ g_gpu.status_reg &= ~STATUS_IDLE;
+ g_gpu.status_reg &= ~STATUS_READYFORCOMMANDS;
+
+ STARTVRAM:
+
+ if (g_gpu.DataWriteMode == DR_VRAMTRANSFER) {
+ char bFinished = 0;
+
+ // make sure we are in vram
+ while (g_gpu.VRAMWrite.ImagePtr >= g_gpu.psxVuw_eom.u16)
+ g_gpu.VRAMWrite.ImagePtr -= 512 * 1024;
+ while (g_gpu.VRAMWrite.ImagePtr < g_gpu.psx_vram.u16)
+ g_gpu.VRAMWrite.ImagePtr += 512 * 1024;
+
+ // now do the loop
+ while (g_gpu.VRAMWrite.ColsRemaining > 0) {
+ while (g_gpu.VRAMWrite.RowsRemaining > 0) {
+ if (i >= iSize) {
+ goto ENDVRAM;
+ }
+ i++;
+
+ gdata = GETLE32(pMem);
+ pMem++;
+
+ PUTLE16(g_gpu.VRAMWrite.ImagePtr, (unsigned short)gdata);
+ g_gpu.VRAMWrite.ImagePtr++;
+ if (g_gpu.VRAMWrite.ImagePtr >= g_gpu.psxVuw_eom.u16)
+ g_gpu.VRAMWrite.ImagePtr -= 512 * 1024;
+ g_gpu.VRAMWrite.RowsRemaining--;
+
+ if (g_gpu.VRAMWrite.RowsRemaining <= 0) {
+ g_gpu.VRAMWrite.ColsRemaining--;
+ if (g_gpu.VRAMWrite.ColsRemaining <= 0) // last pixel is odd width
+ {
+ gdata
+ = (gdata & 0xFFFF)
+ | (((uint32_t) GETLE16(g_gpu.VRAMWrite.ImagePtr))
+ << 16);
+ FinishedVRAMWrite();
+ goto ENDVRAM;
+ }
+ g_gpu.VRAMWrite.RowsRemaining = g_gpu.VRAMWrite.Width;
+ g_gpu.VRAMWrite.ImagePtr += 1024 - g_gpu.VRAMWrite.Width;
+ }
+
+ PUTLE16(g_gpu.VRAMWrite.ImagePtr, (unsigned short)(gdata>>16));
+ g_gpu.VRAMWrite.ImagePtr++;
+ if (g_gpu.VRAMWrite.ImagePtr >= g_gpu.psxVuw_eom.u16)
+ g_gpu.VRAMWrite.ImagePtr -= 512 * 1024;
+ g_gpu.VRAMWrite.RowsRemaining--;
+ }
+
+ g_gpu.VRAMWrite.RowsRemaining = g_gpu.VRAMWrite.Width;
+ g_gpu.VRAMWrite.ColsRemaining--;
+ g_gpu.VRAMWrite.ImagePtr += 1024 - g_gpu.VRAMWrite.Width;
+ bFinished = 1;
+ }
+
+ FinishedVRAMWrite();
+ }
+
+ ENDVRAM:
+
+ if (g_gpu.DataWriteMode == DR_NORMAL) {
+ void (* *primFunc)(unsigned char *);
+ primFunc = primTableJ;
+
+ for (; i < iSize;) {
+ if (g_gpu.DataWriteMode == DR_VRAMTRANSFER)
+ goto STARTVRAM;
+
+ gdata = GETLE32(pMem);
+ pMem++;
+ i++;
+
+ if (g_gpu.gpuDataC == 0) {
+ command = (unsigned char) ((gdata >> 24) & 0xff);
+
+ //if(command>=0xb0 && command<0xc0) auxprintf("b0 %x!!!!!!!!!\n",command);
+
+ if (primTableCX[command]) {
+ g_gpu.gpuDataC = primTableCX[command];
+ g_gpu.gpuCommand = command;
+ PUTLE32(&g_gpu.gpuDataM[0], gdata);
+ g_gpu.gpuDataP = 1;
+ } else {
+ //fprintf(stderr, "unknow command %02x \n", command);
+ continue;
+ }
+ } else {
+ PUTLE32(&g_gpu.gpuDataM[g_gpu.gpuDataP], gdata);
+ if (g_gpu.gpuDataC > 128) {
+ if ((g_gpu.gpuDataC == 254 && g_gpu.gpuDataP >= 3)
+ || (g_gpu.gpuDataC == 255 && g_gpu.gpuDataP >= 4
+ && !(g_gpu.gpuDataP & 1))) {
+ if ((g_gpu.gpuDataM[g_gpu.gpuDataP] & 0xF000F000)
+ == 0x50005000)
+ g_gpu.gpuDataP = g_gpu.gpuDataC - 1;
+ }
+ }
+ g_gpu.gpuDataP++;
+ }
+
+ if (g_gpu.gpuDataP == g_gpu.gpuDataC) {
+ g_gpu.gpuDataC = g_gpu.gpuDataP = 0;
+ primFunc[g_gpu.gpuCommand]((unsigned char *) g_gpu.gpuDataM);
+ }
+ }
+ }
+
+ g_gpu.lGPUdataRet = gdata;
+
+ g_gpu.status_reg |= STATUS_READYFORCOMMANDS;
+ g_gpu.status_reg |= STATUS_IDLE;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+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 (g_gpu.DataWriteMode == DR_VRAMTRANSFER)
+ iT |= 0x1;
+ if (g_gpu.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) {
+
+}
+
+////////////////////////////////////////////////////////////////////////
+// process gpu commands
+////////////////////////////////////////////////////////////////////////
+
+unsigned long lUsedAddr[3];
+
+inline char CheckForEndlessLoop(unsigned long laddr) {
+ if (laddr == lUsedAddr[1])
+ return 1;
+ if (laddr == lUsedAddr[2])
+ return 1;
+
+ if (laddr < lUsedAddr[0])
+ lUsedAddr[1] = laddr;
+ else
+ lUsedAddr[2] = laddr;
+ lUsedAddr[0] = laddr;
+ return 0;
+}
+
+long CALLBACK GPUdmaChain(uint32_t * baseAddrL, uint32_t addr) {
+ uint32_t dmaMem;
+ unsigned char * baseAddrB;
+ short count;
+ unsigned int DMACommandCounter = 0;
+
+ g_gpu.status_reg &= ~STATUS_IDLE;
+
+ lUsedAddr[0] = lUsedAddr[1] = lUsedAddr[2] = 0xffffff;
+
+ baseAddrB = (unsigned char*) baseAddrL;
+
+ do {
+ if (1)
+ 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);
+
+ g_gpu.status_reg |= STATUS_IDLE;
+ 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;
+ //g_gpu.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 = g_gpu.status_reg;
+ memcpy(pF->ulControl, g_gpu.ulStatusControl, 256 * sizeof(uint32_t));
+ memcpy(pF->psxVRam, g_gpu.psx_vram.u8, 1024 * 512 * 2);
+
+ return 1;
+ }
+
+ if (ulGetFreezeData != 0)
+ return 0; // 0: set data
+
+ g_gpu.status_reg = pF->ulStatus;
+ memcpy(g_gpu.ulStatusControl, pF->ulControl, 256 * sizeof(uint32_t));
+ memcpy(g_gpu.psx_vram.u8, pF->psxVRam, 1024 * 512 * 2);
+
+ // RESET TEXTURE STORE HERE, IF YOU USE SOMETHING LIKE THAT
+
+ GPUwriteStatus(g_gpu.ulStatusControl[0]);
+ GPUwriteStatus(g_gpu.ulStatusControl[1]);
+ GPUwriteStatus(g_gpu.ulStatusControl[2]);
+ GPUwriteStatus(g_gpu.ulStatusControl[3]);
+ GPUwriteStatus(g_gpu.ulStatusControl[8]); // try to repair things
+ GPUwriteStatus(g_gpu.ulStatusControl[6]);
+ GPUwriteStatus(g_gpu.ulStatusControl[7]);
+ GPUwriteStatus(g_gpu.ulStatusControl[5]);
+ GPUwriteStatus(g_gpu.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
+}
+
+void CALLBACK GPUsetfix(uint32_t dwFixBits) {
+ g_prim.dwEmuFixes = dwFixBits;
+}
+
+void CALLBACK GPUvBlank(int val) {
+ //fprintf(stderr, "Vblanc %d\n", val);
+ //if(val)
+ // g_gpu.status_reg |= STATUS_ODDLINES;
+ //else
+ // g_gpu.status_reg &= ~STATUS_ODDLINES;
+}
|
