summaryrefslogtreecommitdiff
path: root/plugins/gxvideo/gpu.c
diff options
context:
space:
mode:
authorSND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2011-03-13 08:26:16 +0000
committerSND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2011-03-13 08:26:16 +0000
commit379a8879f7dae1a9074317c0270e12dd203b32c0 (patch)
tree348efb7ecd4f7cbc030f4b5db6683a857f2ae6cf /plugins/gxvideo/gpu.c
parentd34b4220bde29d7937d927e9d17a50470a36c500 (diff)
downloadpcsxr-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.c3104
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;
+}