remove stuff we won't need
[pcsx_rearmed.git] / plugins / dfxvideo / gpu.c
CommitLineData
ef79bbde
P
1/***************************************************************************
2 gpu.c - description
3 -------------------
4 begin : Sun Oct 28 2001
5 copyright : (C) 2001 by Pete Bernert
6 email : BlackDove@addcom.de
7 ***************************************************************************/
8/***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. See also the license.txt file for *
14 * additional informations. *
15 * *
16 ***************************************************************************/
17
18#ifndef _MACGL
19#include "config.h"
20#endif
21
22#define _IN_GPU
23
24#include "externals.h"
25#include "gpu.h"
26#include "draw.h"
27#include "cfg.h"
28#include "prim.h"
29#include "stdint.h"
30#include "psemu_plugin_defs.h"
31#include "menu.h"
32#include "key.h"
33#include "fps.h"
34#include "swap.h"
35
36#ifdef ENABLE_NLS
37#include <libintl.h>
38#include <locale.h>
39#define _(x) gettext(x)
40#define N_(x) (x)
41#else
42#define _(x) (x)
43#define N_(x) (x)
44#endif
45
46////////////////////////////////////////////////////////////////////////
47// PPDK developer must change libraryName field and can change revision and build
48////////////////////////////////////////////////////////////////////////
49
50const unsigned char version = 1; // do not touch - library for PSEmu 1.x
51const unsigned char revision = 1;
52const unsigned char build = 17; // increase that with each version
53
54#ifdef _MACGL
55static char *libraryName = N_("SoftGL Driver");
56static char *libraryInfo = N_("P.E.Op.S. SoftGL Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n");
57#else
58static char *libraryName = N_("XVideo Driver");
59static char *libraryInfo = N_("P.E.Op.S. Xvideo Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n");
60#endif
61
62static char *PluginAuthor = N_("Pete Bernert and the P.E.Op.S. team");
63
64////////////////////////////////////////////////////////////////////////
65// memory image of the PSX vram
66////////////////////////////////////////////////////////////////////////
67
68unsigned char *psxVSecure;
69unsigned char *psxVub;
70signed char *psxVsb;
71unsigned short *psxVuw;
72unsigned short *psxVuw_eom;
73signed short *psxVsw;
74uint32_t *psxVul;
75int32_t *psxVsl;
76
77////////////////////////////////////////////////////////////////////////
78// GPU globals
79////////////////////////////////////////////////////////////////////////
80
81static long lGPUdataRet;
82long lGPUstatusRet;
83char szDispBuf[64];
84char szMenuBuf[36];
85char szDebugText[512];
86uint32_t ulStatusControl[256];
87
88static uint32_t gpuDataM[256];
89static unsigned char gpuCommand = 0;
90static long gpuDataC = 0;
91static long gpuDataP = 0;
92
93VRAMLoad_t VRAMWrite;
94VRAMLoad_t VRAMRead;
95DATAREGISTERMODES DataWriteMode;
96DATAREGISTERMODES DataReadMode;
97
98BOOL bSkipNextFrame = FALSE;
99DWORD dwLaceCnt=0;
100int iColDepth;
101int iWindowMode;
102short sDispWidths[8] = {256,320,512,640,368,384,512,640};
103PSXDisplay_t PSXDisplay;
104PSXDisplay_t PreviousPSXDisplay;
105long lSelectedSlot=0;
106BOOL bChangeWinMode=FALSE;
107BOOL bDoLazyUpdate=FALSE;
108uint32_t lGPUInfoVals[16];
109static int iFakePrimBusy=0;
110
111////////////////////////////////////////////////////////////////////////
112// some misc external display funcs
113////////////////////////////////////////////////////////////////////////
114
115#include <time.h>
116time_t tStart;
117
118void CALLBACK GPUdisplayText(char * pText) // some debug func
119{
120 if(!pText) {szDebugText[0]=0;return;}
121 if(strlen(pText)>511) return;
122 time(&tStart);
123 strcpy(szDebugText,pText);
124}
125
126////////////////////////////////////////////////////////////////////////
127
128void CALLBACK GPUdisplayFlags(unsigned long dwFlags) // some info func
129{
130 dwCoreFlags=dwFlags;
131 BuildDispMenu(0);
132}
133
134////////////////////////////////////////////////////////////////////////
135// stuff to make this a true PDK module
136////////////////////////////////////////////////////////////////////////
137
138char * CALLBACK PSEgetLibName(void)
139{
140 return _(libraryName);
141}
142
143unsigned long CALLBACK PSEgetLibType(void)
144{
145 return PSE_LT_GPU;
146}
147
148unsigned long CALLBACK PSEgetLibVersion(void)
149{
150 return version<<16|revision<<8|build;
151}
152
153char * GPUgetLibInfos(void)
154{
155 return _(libraryInfo);
156}
157
158////////////////////////////////////////////////////////////////////////
159// Snapshot func
160////////////////////////////////////////////////////////////////////////
161
162static char * pGetConfigInfos(int iCfg)
163{
164 char szO[2][4]={"off","on "};
165 char szTxt[256];
166 char * pB = (char *)malloc(32767);
167
168 if (!pB) return NULL;
169 *pB = 0;
170 //----------------------------------------------------//
171 sprintf(szTxt,"Plugin: %s %d.%d.%d\r\n",libraryName,version,revision,build);
172 strcat(pB,szTxt);
173 sprintf(szTxt,"Author: %s\r\n\r\n",PluginAuthor);
174 strcat(pB,szTxt);
175 //----------------------------------------------------//
176 if(iCfg && iWindowMode)
177 sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize));
178 else
179 sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY);
180 strcat(pB,szTxt);
181 if(iWindowMode && iCfg)
182 strcpy(szTxt,"Window mode\r\n");
183 else
184 if(iWindowMode)
185 sprintf(szTxt,"Window mode - [%d Bit]\r\n",iDesktopCol);
186 else
187 sprintf(szTxt,"Fullscreen - [%d Bit]\r\n",iColDepth);
188 strcat(pB,szTxt);
189
190 sprintf(szTxt,"Stretch mode: %d\r\n",iUseNoStretchBlt);
191 strcat(pB,szTxt);
192 sprintf(szTxt,"Dither mode: %d\r\n\r\n",iUseDither);
193 strcat(pB,szTxt);
194 //----------------------------------------------------//
195 sprintf(szTxt,"Framerate:\r\n- FPS limit: %s\r\n",szO[UseFrameLimit]);
196 strcat(pB,szTxt);
197 sprintf(szTxt,"- Frame skipping: %s",szO[UseFrameSkip]);
198 strcat(pB,szTxt);
199 if(iFastFwd) strcat(pB," (fast forward)");
200 strcat(pB,"\r\n");
201 if(iFrameLimit==2)
202 strcpy(szTxt,"- FPS limit: Auto\r\n\r\n");
203 else sprintf(szTxt,"- FPS limit: %.1f\r\n\r\n",fFrameRate);
204 strcat(pB,szTxt);
205 //----------------------------------------------------//
206#ifndef _MACGL
207 strcpy(szTxt,"Misc:\r\n- MaintainAspect: ");
208 if(iMaintainAspect == 0) strcat(szTxt,"disabled");
209 else
210 if(iMaintainAspect == 1) strcat(szTxt,"enabled");
211 strcat(szTxt,"\r\n");
212 strcat(pB,szTxt);
213#endif
214 sprintf(szTxt,"- Game fixes: %s [%08x]\r\n",szO[iUseFixes],dwCfgFixes);
215 strcat(pB,szTxt);
216 //----------------------------------------------------//
217 return pB;
218}
219
220static void DoTextSnapShot(int iNum)
221{
222 FILE *txtfile;
223 char szTxt[256];
224 char *pB;
225
226 sprintf(szTxt,"%s/pcsx%04d.txt",getenv("HOME"),iNum);
227
228 if ((txtfile = fopen(szTxt, "wb")) == NULL)
229 return;
230
231 pB = pGetConfigInfos(0);
232 if (pB)
233 {
234 fwrite(pB, strlen(pB), 1, txtfile);
235 free(pB);
236 }
237 fclose(txtfile);
238}
239
240void CALLBACK GPUmakeSnapshot(void)
241{
242 FILE *bmpfile;
243 char filename[256];
244 unsigned char header[0x36];
245 long size, height;
246 unsigned char line[1024 * 3];
247 short i, j;
248 unsigned char empty[2] = {0,0};
249 unsigned short color;
250 unsigned long snapshotnr = 0;
251 unsigned char *pD;
252
253 height = PreviousPSXDisplay.DisplayMode.y;
254
255 size = height * PreviousPSXDisplay.Range.x1 * 3 + 0x38;
256
257 // fill in proper values for BMP
258
259 // hardcoded BMP header
260 memset(header, 0, 0x36);
261 header[0] = 'B';
262 header[1] = 'M';
263 header[2] = size & 0xff;
264 header[3] = (size >> 8) & 0xff;
265 header[4] = (size >> 16) & 0xff;
266 header[5] = (size >> 24) & 0xff;
267 header[0x0a] = 0x36;
268 header[0x0e] = 0x28;
269 header[0x12] = PreviousPSXDisplay.Range.x1 % 256;
270 header[0x13] = PreviousPSXDisplay.Range.x1 / 256;
271 header[0x16] = height % 256;
272 header[0x17] = height / 256;
273 header[0x1a] = 0x01;
274 header[0x1c] = 0x18;
275 header[0x26] = 0x12;
276 header[0x27] = 0x0B;
277 header[0x2A] = 0x12;
278 header[0x2B] = 0x0B;
279
280 // increment snapshot value & try to get filename
281 do
282 {
283 snapshotnr++;
284 sprintf(filename, "%s/pcsx%04ld.bmp", getenv("HOME"), snapshotnr);
285
286 bmpfile = fopen(filename,"rb");
287 if (bmpfile == NULL)
288 break;
289
290 fclose(bmpfile);
291 }
292 while(TRUE);
293
294 // try opening new snapshot file
295 if ((bmpfile = fopen(filename,"wb")) == NULL)
296 return;
297
298 fwrite(header, 0x36, 1, bmpfile);
299 for (i = height + PSXDisplay.DisplayPosition.y - 1; i >= PSXDisplay.DisplayPosition.y; i--)
300 {
301 pD = (unsigned char *)&psxVuw[i * 1024 + PSXDisplay.DisplayPosition.x];
302 for (j = 0; j < PreviousPSXDisplay.Range.x1; j++)
303 {
304 if (PSXDisplay.RGB24)
305 {
306 uint32_t lu = *(uint32_t *)pD;
307 line[j * 3 + 2] = RED(lu);
308 line[j * 3 + 1] = GREEN(lu);
309 line[j * 3 + 0] = BLUE(lu);
310 pD += 3;
311 }
312 else
313 {
314 color = GETLE16(pD);
315 line[j * 3 + 2] = (color << 3) & 0xf1;
316 line[j * 3 + 1] = (color >> 2) & 0xf1;
317 line[j * 3 + 0] = (color >> 7) & 0xf1;
318 pD += 2;
319 }
320 }
321 fwrite(line, PreviousPSXDisplay.Range.x1 * 3, 1, bmpfile);
322 }
323 fwrite(empty, 0x2, 1, bmpfile);
324 fclose(bmpfile);
325
326 DoTextSnapShot(snapshotnr);
327}
328
329////////////////////////////////////////////////////////////////////////
330// INIT, will be called after lib load... well, just do some var init...
331////////////////////////////////////////////////////////////////////////
332
333long CALLBACK GPUinit() // GPU INIT
334{
335 memset(ulStatusControl,0,256*sizeof(uint32_t)); // init save state scontrol field
336
337 szDebugText[0] = 0; // init debug text buffer
338
339 psxVSecure = (unsigned char *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security
340 if (!psxVSecure)
341 return -1;
342
343 //!!! ATTENTION !!!
344 psxVub=psxVSecure + 512 * 1024; // security offset into double sized psx vram!
345
346 psxVsb=(signed char *)psxVub; // different ways of accessing PSX VRAM
347 psxVsw=(signed short *)psxVub;
348 psxVsl=(int32_t *)psxVub;
349 psxVuw=(unsigned short *)psxVub;
350 psxVul=(uint32_t *)psxVub;
351
352 psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram
353
354 memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024));
355 memset(lGPUInfoVals,0x00,16*sizeof(uint32_t));
356
357 SetFPSHandler();
358
359 PSXDisplay.RGB24 = FALSE; // init some stuff
360 PSXDisplay.Interlaced = FALSE;
361 PSXDisplay.DrawOffset.x = 0;
362 PSXDisplay.DrawOffset.y = 0;
363 PSXDisplay.DisplayMode.x= 320;
364 PSXDisplay.DisplayMode.y= 240;
365 PreviousPSXDisplay.DisplayMode.x= 320;
366 PreviousPSXDisplay.DisplayMode.y= 240;
367 PSXDisplay.Disabled = FALSE;
368 PreviousPSXDisplay.Range.x0 =0;
369 PreviousPSXDisplay.Range.y0 =0;
370 PSXDisplay.Range.x0=0;
371 PSXDisplay.Range.x1=0;
372 PreviousPSXDisplay.DisplayModeNew.y=0;
373 PSXDisplay.Double = 1;
374 lGPUdataRet = 0x400;
375
376 DataWriteMode = DR_NORMAL;
377
378 // Reset transfer values, to prevent mis-transfer of data
379 memset(&VRAMWrite, 0, sizeof(VRAMLoad_t));
380 memset(&VRAMRead, 0, sizeof(VRAMLoad_t));
381
382 // device initialised already !
383 lGPUstatusRet = 0x14802000;
384 GPUIsIdle;
385 GPUIsReadyForCommands;
386 bDoVSyncUpdate = TRUE;
387
388 return 0;
389}
390
391////////////////////////////////////////////////////////////////////////
392// Here starts all...
393////////////////////////////////////////////////////////////////////////
394
395
396long GPUopen(unsigned long * disp,char * CapText,char * CfgFile)
397{
398 unsigned long d;
399
400 pCaptionText=CapText;
401
402
403 ReadConfig(); // read registry
404
405 InitFPS();
406
407 bIsFirstFrame = TRUE; // we have to init later
408 bDoVSyncUpdate = TRUE;
409
410 d=ulInitDisplay(); // setup x
411
412 if(disp)
413 *disp=d; // wanna x pointer? ok
414
415 if(d) return 0;
416 return -1;
417}
418
419
420////////////////////////////////////////////////////////////////////////
421// time to leave...
422////////////////////////////////////////////////////////////////////////
423
424long CALLBACK GPUclose() // GPU CLOSE
425{
426
427 ReleaseKeyHandler(); // de-subclass window
428
429 CloseDisplay(); // shutdown direct draw
430
431 return 0;
432}
433
434////////////////////////////////////////////////////////////////////////
435// I shot the sheriff
436////////////////////////////////////////////////////////////////////////
437
438long CALLBACK GPUshutdown() // GPU SHUTDOWN
439{
440 free(psxVSecure);
441
442 return 0; // nothinh to do
443}
444
445////////////////////////////////////////////////////////////////////////
446// Update display (swap buffers)
447////////////////////////////////////////////////////////////////////////
448
449void updateDisplay(void) // UPDATE DISPLAY
450{
451 if(PSXDisplay.Disabled) // disable?
452 {
453 DoClearFrontBuffer(); // -> clear frontbuffer
454 return; // -> and bye
455 }
456
457 if(dwActFixes&32) // pc fps calculation fix
458 {
459 if(UseFrameLimit) PCFrameCap(); // -> brake
460 if(UseFrameSkip || ulKeybits&KEY_SHOWFPS)
461 PCcalcfps();
462 }
463
464 if(ulKeybits&KEY_SHOWFPS) // make fps display buf
465 {
466 sprintf(szDispBuf,"FPS %06.1f",fps_cur);
467 }
468
469 if(iFastFwd) // fastfwd ?
470 {
471 static int fpscount; UseFrameSkip=1;
472
473 if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip
474 if(fpscount%6) // -> skip 6/7 frames
475 bSkipNextFrame = TRUE;
476 else bSkipNextFrame = FALSE;
477 fpscount++;
478 if(fpscount >= (int)fFrameRateHz) fpscount = 0;
479 return;
480 }
481
482 if(UseFrameSkip) // skip ?
483 {
484 if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip
485 if(dwActFixes&0xa0) // -> pc fps calculation fix/old skipping fix
486 {
487 if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) // -> skip max one in a row
488 {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;}
489 else bSkipNextFrame = FALSE;
490 }
491 else FrameSkip();
492 }
493 else // no skip ?
494 {
495 DoBufferSwap(); // -> swap
496 }
497}
498
499////////////////////////////////////////////////////////////////////////
500// roughly emulated screen centering bits... not complete !!!
501////////////////////////////////////////////////////////////////////////
502
503void ChangeDispOffsetsX(void) // X CENTER
504{
505 long lx,l;
506
507 if(!PSXDisplay.Range.x1) return;
508
509 l=PreviousPSXDisplay.DisplayMode.x;
510
511 l*=(long)PSXDisplay.Range.x1;
512 l/=2560;lx=l;l&=0xfffffff8;
513
514 if(l==PreviousPSXDisplay.Range.y1) return; // abusing range.y1 for
515 PreviousPSXDisplay.Range.y1=(short)l; // storing last x range and test
516
517 if(lx>=PreviousPSXDisplay.DisplayMode.x)
518 {
519 PreviousPSXDisplay.Range.x1=
520 (short)PreviousPSXDisplay.DisplayMode.x;
521 PreviousPSXDisplay.Range.x0=0;
522 }
523 else
524 {
525 PreviousPSXDisplay.Range.x1=(short)l;
526
527 PreviousPSXDisplay.Range.x0=
528 (PSXDisplay.Range.x0-500)/8;
529
530 if(PreviousPSXDisplay.Range.x0<0)
531 PreviousPSXDisplay.Range.x0=0;
532
533 if((PreviousPSXDisplay.Range.x0+lx)>
534 PreviousPSXDisplay.DisplayMode.x)
535 {
536 PreviousPSXDisplay.Range.x0=
537 (short)(PreviousPSXDisplay.DisplayMode.x-lx);
538 PreviousPSXDisplay.Range.x0+=2; //???
539
540 PreviousPSXDisplay.Range.x1+=(short)(lx-l);
541
542 PreviousPSXDisplay.Range.x1-=2; // makes linux stretching easier
543
544 }
545
546
547 // some linux alignment security
548 PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0>>1;
549 PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0<<1;
550 PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1>>1;
551 PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1<<1;
552
553
554 DoClearScreenBuffer();
555 }
556
557 bDoVSyncUpdate=TRUE;
558}
559
560////////////////////////////////////////////////////////////////////////
561
562void ChangeDispOffsetsY(void) // Y CENTER
563{
564 int iT,iO=PreviousPSXDisplay.Range.y0;
565 int iOldYOffset=PreviousPSXDisplay.DisplayModeNew.y;
566
567// new
568
569 if((PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)>iGPUHeight)
570 {
571 int dy1=iGPUHeight-PreviousPSXDisplay.DisplayModeNew.x;
572 int dy2=(PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)-iGPUHeight;
573
574 if(dy1>=dy2)
575 {
576 PreviousPSXDisplay.DisplayModeNew.y=-dy2;
577 }
578 else
579 {
580 PSXDisplay.DisplayPosition.y=0;
581 PreviousPSXDisplay.DisplayModeNew.y=-dy1;
582 }
583 }
584 else PreviousPSXDisplay.DisplayModeNew.y=0;
585
586// eon
587
588 if(PreviousPSXDisplay.DisplayModeNew.y!=iOldYOffset) // if old offset!=new offset: recalc height
589 {
590 PSXDisplay.Height = PSXDisplay.Range.y1 -
591 PSXDisplay.Range.y0 +
592 PreviousPSXDisplay.DisplayModeNew.y;
593 PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;
594 }
595
596//
597
598 if(PSXDisplay.PAL) iT=48; else iT=28;
599
600 if(PSXDisplay.Range.y0>=iT)
601 {
602 PreviousPSXDisplay.Range.y0=
603 (short)((PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double);
604 if(PreviousPSXDisplay.Range.y0<0)
605 PreviousPSXDisplay.Range.y0=0;
606 PSXDisplay.DisplayModeNew.y+=
607 PreviousPSXDisplay.Range.y0;
608 }
609 else
610 PreviousPSXDisplay.Range.y0=0;
611
612 if(iO!=PreviousPSXDisplay.Range.y0)
613 {
614 DoClearScreenBuffer();
615 }
616}
617
618////////////////////////////////////////////////////////////////////////
619// check if update needed
620////////////////////////////////////////////////////////////////////////
621
622void updateDisplayIfChanged(void) // UPDATE DISPLAY IF CHANGED
623{
624 if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) &&
625 (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))
626 {
627 if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) &&
628 (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew)) return;
629 }
630
631 PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos
632
633 PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;
634 PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;
635 PreviousPSXDisplay.DisplayMode.x= // previous will hold
636 min(640,PSXDisplay.DisplayMode.x); // max 640x512... that's
637 PreviousPSXDisplay.DisplayMode.y= // the size of my
638 min(512,PSXDisplay.DisplayMode.y); // back buffer surface
639 PSXDisplay.Interlaced = PSXDisplay.InterlacedNew;
640
641 PSXDisplay.DisplayEnd.x= // calc end of display
642 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
643 PSXDisplay.DisplayEnd.y=
644 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
645 PreviousPSXDisplay.DisplayEnd.x=
646 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
647 PreviousPSXDisplay.DisplayEnd.y=
648 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
649
650 ChangeDispOffsetsX();
651
652 if(iFrameLimit==2) SetAutoFrameCap(); // -> set it
653
654 if(UseFrameSkip) updateDisplay(); // stupid stuff when frame skipping enabled
655}
656
657////////////////////////////////////////////////////////////////////////
658
659#ifndef _MACGL
660
661#include "draw.h"
662
663void ChangeWindowMode(void) // TOGGLE FULLSCREEN - WINDOW
664{
665 extern Display *display;
666 extern Window window;
667 extern int root_window_id;
668 Screen *screen;
669 XSizeHints hints;
670 MotifWmHints mwmhints;
671 Atom mwmatom;
672
673 screen=DefaultScreenOfDisplay(display);
674 iWindowMode=!iWindowMode;
675
676 if(!iWindowMode) // fullscreen
677 {
678 mwmhints.flags=MWM_HINTS_DECORATIONS;
679 mwmhints.functions=0;
680 mwmhints.decorations=0;
681 mwmhints.input_mode=0;
682 mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0);
683 XChangeProperty(display,window,mwmatom,mwmatom,32,
684 PropModeReplace,(unsigned char *)&mwmhints,5);
685
686 XResizeWindow(display,window,screen->width,screen->height);
687
688 hints.min_width = hints.max_width = hints.base_width = screen->width;
689 hints.min_height= hints.max_height = hints.base_height = screen->height;
690
691 XSetWMNormalHints(display,window,&hints);
692
693 {
694 XEvent xev;
695
696 memset(&xev, 0, sizeof(xev));
697 xev.xclient.type = ClientMessage;
698 xev.xclient.serial = 0;
699 xev.xclient.send_event = 1;
700 xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0);
701 xev.xclient.window = window;
702 xev.xclient.format = 32;
703 xev.xclient.data.l[0] = 1;
704 xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", 0);
705 xev.xclient.data.l[2] = 0;
706 xev.xclient.data.l[3] = 0;
707 xev.xclient.data.l[4] = 0;
708
709 XSendEvent(display, root_window_id, 0,
710 SubstructureRedirectMask | SubstructureNotifyMask, &xev);
711 }
712 } else {
713 {
714 XEvent xev;
715
716 memset(&xev, 0, sizeof(xev));
717 xev.xclient.type = ClientMessage;
718 xev.xclient.serial = 0;
719 xev.xclient.send_event = 1;
720 xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0);
721 xev.xclient.window = window;
722 xev.xclient.format = 32;
723 xev.xclient.data.l[0] = 0;
724 xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", 0);
725 xev.xclient.data.l[2] = 0;
726 xev.xclient.data.l[3] = 0;
727 xev.xclient.data.l[4] = 0;
728
729 XSendEvent(display, root_window_id, 0,
730 SubstructureRedirectMask | SubstructureNotifyMask, &xev);
731 }
732
733 mwmhints.flags=MWM_HINTS_DECORATIONS;
734 mwmhints.functions=0;
735 mwmhints.decorations=1;
736 mwmhints.input_mode=0;
737 mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0);
738
739 //This shouldn't work on 64 bit longs, but it does...in fact, it breaks when I change all the mwmhints to int.
740 //I don't pretend to understand it.
741 XChangeProperty(display,window,mwmatom,mwmatom,32,
742 PropModeReplace,(unsigned char *)&mwmhints,5);
743
744 hints.flags=USPosition|USSize;
745 hints.base_width = iResX;
746 hints.base_height = iResY;
747 XSetWMNormalHints(display,window,&hints);
748
749 XResizeWindow(display,window,iResX,iResY);
750}
751
752 DoClearScreenBuffer();
753
754 bChangeWinMode=FALSE;
755 bDoVSyncUpdate=TRUE;
756}
757
758#endif
759
760////////////////////////////////////////////////////////////////////////
761// gun cursor func: player=0-7, x=0-511, y=0-255
762////////////////////////////////////////////////////////////////////////
763
764void CALLBACK GPUcursor(int iPlayer,int x,int y)
765{
766 if(iPlayer<0) return;
767 if(iPlayer>7) return;
768
769 usCursorActive|=(1<<iPlayer);
770
771 if(x<0) x=0;
772 if(x>511) x=511;
773 if(y<0) y=0;
774 if(y>255) y=255;
775
776 ptCursorPoint[iPlayer].x=x;
777 ptCursorPoint[iPlayer].y=y;
778}
779
780////////////////////////////////////////////////////////////////////////
781// update lace is called evry VSync
782////////////////////////////////////////////////////////////////////////
783
784void CALLBACK GPUupdateLace(void) // VSYNC
785{
786 if(!(dwActFixes&1))
787 lGPUstatusRet^=0x80000000; // odd/even bit
788
789 if(!(dwActFixes&32)) // std fps limitation?
790 CheckFrameRate();
791
792 if(PSXDisplay.Interlaced) // interlaced mode?
793 {
794 if(bDoVSyncUpdate && PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)
795 {
796 updateDisplay();
797 }
798 }
799 else // non-interlaced?
800 {
801 if(dwActFixes&64) // lazy screen update fix
802 {
803 if(bDoLazyUpdate && !UseFrameSkip)
804 updateDisplay();
805 bDoLazyUpdate=FALSE;
806 }
807 else
808 {
809 if(bDoVSyncUpdate && !UseFrameSkip) // some primitives drawn?
810 updateDisplay(); // -> update display
811 }
812 }
813#ifndef _MACGL
814 if(bChangeWinMode) ChangeWindowMode(); // toggle full - window mode
815#endif
816 bDoVSyncUpdate=FALSE; // vsync done
817}
818
819////////////////////////////////////////////////////////////////////////
820// process read request from GPU status register
821////////////////////////////////////////////////////////////////////////
822
823
824uint32_t CALLBACK GPUreadStatus(void) // READ STATUS
825{
826 if(dwActFixes&1)
827 {
828 static int iNumRead=0; // odd/even hack
829 if((iNumRead++)==2)
830 {
831 iNumRead=0;
832 lGPUstatusRet^=0x80000000; // interlaced bit toggle... we do it on every 3 read status... needed by some games (like ChronoCross) with old epsxe versions (1.5.2 and older)
833 }
834 }
835
836 if(iFakePrimBusy) // 27.10.2007 - PETE : emulating some 'busy' while drawing... pfff
837 {
838 iFakePrimBusy--;
839
840 if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims
841 {
842 GPUIsBusy;
843 GPUIsNotReadyForCommands;
844 }
845 else
846 {
847 GPUIsIdle;
848 GPUIsReadyForCommands;
849 }
850 }
851 return lGPUstatusRet;
852}
853
854////////////////////////////////////////////////////////////////////////
855// processes data send to GPU status register
856// these are always single packet commands.
857////////////////////////////////////////////////////////////////////////
858
859void CALLBACK GPUwriteStatus(uint32_t gdata) // WRITE STATUS
860{
861 uint32_t lCommand=(gdata>>24)&0xff;
862
863 ulStatusControl[lCommand]=gdata; // store command for freezing
864
865 switch(lCommand)
866 {
867 //--------------------------------------------------//
868 // reset gpu
869 case 0x00:
870 memset(lGPUInfoVals,0x00,16*sizeof(uint32_t));
871 lGPUstatusRet=0x14802000;
872 PSXDisplay.Disabled=1;
873 DataWriteMode=DataReadMode=DR_NORMAL;
874 PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0;
875 drawX=drawY=0;drawW=drawH=0;
876 sSetMask=0;lSetMask=0;bCheckMask=FALSE;
877 usMirror=0;
878 GlobalTextAddrX=0;GlobalTextAddrY=0;
879 GlobalTextTP=0;GlobalTextABR=0;
880 PSXDisplay.RGB24=FALSE;
881 PSXDisplay.Interlaced=FALSE;
882 bUsingTWin = FALSE;
883 return;
884 //--------------------------------------------------//
885 // dis/enable display
886 case 0x03:
887
888 PreviousPSXDisplay.Disabled = PSXDisplay.Disabled;
889 PSXDisplay.Disabled = (gdata & 1);
890
891 if(PSXDisplay.Disabled)
892 lGPUstatusRet|=GPUSTATUS_DISPLAYDISABLED;
893 else lGPUstatusRet&=~GPUSTATUS_DISPLAYDISABLED;
894 return;
895
896 //--------------------------------------------------//
897 // setting transfer mode
898 case 0x04:
899 gdata &= 0x03; // Only want the lower two bits
900
901 DataWriteMode=DataReadMode=DR_NORMAL;
902 if(gdata==0x02) DataWriteMode=DR_VRAMTRANSFER;
903 if(gdata==0x03) DataReadMode =DR_VRAMTRANSFER;
904 lGPUstatusRet&=~GPUSTATUS_DMABITS; // Clear the current settings of the DMA bits
905 lGPUstatusRet|=(gdata << 29); // Set the DMA bits according to the received data
906
907 return;
908 //--------------------------------------------------//
909 // setting display position
910 case 0x05:
911 {
912 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
913 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
914
915////////
916/*
917 PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff);
918 if (PSXDisplay.DisplayPosition.y & 0x200)
919 PSXDisplay.DisplayPosition.y |= 0xfffffc00;
920 if(PSXDisplay.DisplayPosition.y<0)
921 {
922 PreviousPSXDisplay.DisplayModeNew.y=PSXDisplay.DisplayPosition.y/PSXDisplay.Double;
923 PSXDisplay.DisplayPosition.y=0;
924 }
925 else PreviousPSXDisplay.DisplayModeNew.y=0;
926*/
927
928// new
929 if(iGPUHeight==1024)
930 {
931 if(dwGPUVersion==2)
932 PSXDisplay.DisplayPosition.y = (short)((gdata>>12)&0x3ff);
933 else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff);
934 }
935 else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x1ff);
936
937 // store the same val in some helper var, we need it on later compares
938 PreviousPSXDisplay.DisplayModeNew.x=PSXDisplay.DisplayPosition.y;
939
940 if((PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)>iGPUHeight)
941 {
942 int dy1=iGPUHeight-PSXDisplay.DisplayPosition.y;
943 int dy2=(PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)-iGPUHeight;
944
945 if(dy1>=dy2)
946 {
947 PreviousPSXDisplay.DisplayModeNew.y=-dy2;
948 }
949 else
950 {
951 PSXDisplay.DisplayPosition.y=0;
952 PreviousPSXDisplay.DisplayModeNew.y=-dy1;
953 }
954 }
955 else PreviousPSXDisplay.DisplayModeNew.y=0;
956// eon
957
958 PSXDisplay.DisplayPosition.x = (short)(gdata & 0x3ff);
959 PSXDisplay.DisplayEnd.x=
960 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
961 PSXDisplay.DisplayEnd.y=
962 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y + PreviousPSXDisplay.DisplayModeNew.y;
963 PreviousPSXDisplay.DisplayEnd.x=
964 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
965 PreviousPSXDisplay.DisplayEnd.y=
966 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y + PreviousPSXDisplay.DisplayModeNew.y;
967
968 bDoVSyncUpdate=TRUE;
969
970 if (!(PSXDisplay.Interlaced)) // stupid frame skipping option
971 {
972 if(UseFrameSkip) updateDisplay();
973 if(dwActFixes&64) bDoLazyUpdate=TRUE;
974 }
975 }return;
976 //--------------------------------------------------//
977 // setting width
978 case 0x06:
979
980 PSXDisplay.Range.x0=(short)(gdata & 0x7ff);
981 PSXDisplay.Range.x1=(short)((gdata>>12) & 0xfff);
982
983 PSXDisplay.Range.x1-=PSXDisplay.Range.x0;
984
985 ChangeDispOffsetsX();
986
987 return;
988 //--------------------------------------------------//
989 // setting height
990 case 0x07:
991 {
992
993 PSXDisplay.Range.y0=(short)(gdata & 0x3ff);
994 PSXDisplay.Range.y1=(short)((gdata>>10) & 0x3ff);
995
996 PreviousPSXDisplay.Height = PSXDisplay.Height;
997
998 PSXDisplay.Height = PSXDisplay.Range.y1 -
999 PSXDisplay.Range.y0 +
1000 PreviousPSXDisplay.DisplayModeNew.y;
1001
1002 if(PreviousPSXDisplay.Height!=PSXDisplay.Height)
1003 {
1004 PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;
1005
1006 ChangeDispOffsetsY();
1007
1008 updateDisplayIfChanged();
1009 }
1010 return;
1011 }
1012 //--------------------------------------------------//
1013 // setting display infos
1014 case 0x08:
1015
1016 PSXDisplay.DisplayModeNew.x =
1017 sDispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)];
1018
1019 if (gdata&0x04) PSXDisplay.Double=2;
1020 else PSXDisplay.Double=1;
1021
1022 PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double;
1023
1024 ChangeDispOffsetsY();
1025
1026 PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC
1027 PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor
1028 PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace
1029
1030 lGPUstatusRet&=~GPUSTATUS_WIDTHBITS; // Clear the width bits
1031 lGPUstatusRet|=
1032 (((gdata & 0x03) << 17) |
1033 ((gdata & 0x40) << 10)); // Set the width bits
1034
1035 if(PSXDisplay.InterlacedNew)
1036 {
1037 if(!PSXDisplay.Interlaced)
1038 {
1039 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
1040 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
1041 }
1042 lGPUstatusRet|=GPUSTATUS_INTERLACED;
1043 }
1044 else lGPUstatusRet&=~GPUSTATUS_INTERLACED;
1045
1046 if (PSXDisplay.PAL)
1047 lGPUstatusRet|=GPUSTATUS_PAL;
1048 else lGPUstatusRet&=~GPUSTATUS_PAL;
1049
1050 if (PSXDisplay.Double==2)
1051 lGPUstatusRet|=GPUSTATUS_DOUBLEHEIGHT;
1052 else lGPUstatusRet&=~GPUSTATUS_DOUBLEHEIGHT;
1053
1054 if (PSXDisplay.RGB24New)
1055 lGPUstatusRet|=GPUSTATUS_RGB24;
1056 else lGPUstatusRet&=~GPUSTATUS_RGB24;
1057
1058 updateDisplayIfChanged();
1059
1060 return;
1061 //--------------------------------------------------//
1062 // ask about GPU version and other stuff
1063 case 0x10:
1064
1065 gdata&=0xff;
1066
1067 switch(gdata)
1068 {
1069 case 0x02:
1070 lGPUdataRet=lGPUInfoVals[INFO_TW]; // tw infos
1071 return;
1072 case 0x03:
1073 lGPUdataRet=lGPUInfoVals[INFO_DRAWSTART]; // draw start
1074 return;
1075 case 0x04:
1076 lGPUdataRet=lGPUInfoVals[INFO_DRAWEND]; // draw end
1077 return;
1078 case 0x05:
1079 case 0x06:
1080 lGPUdataRet=lGPUInfoVals[INFO_DRAWOFF]; // draw offset
1081 return;
1082 case 0x07:
1083 if(dwGPUVersion==2)
1084 lGPUdataRet=0x01;
1085 else lGPUdataRet=0x02; // gpu type
1086 return;
1087 case 0x08:
1088 case 0x0F: // some bios addr?
1089 lGPUdataRet=0xBFC03720;
1090 return;
1091 }
1092 return;
1093 //--------------------------------------------------//
1094 }
1095}
1096
1097////////////////////////////////////////////////////////////////////////
1098// vram read/write helpers, needed by LEWPY's optimized vram read/write :)
1099////////////////////////////////////////////////////////////////////////
1100
1101__inline void FinishedVRAMWrite(void)
1102{
1103/*
1104// NEWX
1105 if(!PSXDisplay.Interlaced && UseFrameSkip) // stupid frame skipping
1106 {
1107 VRAMWrite.Width +=VRAMWrite.x;
1108 VRAMWrite.Height+=VRAMWrite.y;
1109 if(VRAMWrite.x<PSXDisplay.DisplayEnd.x &&
1110 VRAMWrite.Width >=PSXDisplay.DisplayPosition.x &&
1111 VRAMWrite.y<PSXDisplay.DisplayEnd.y &&
1112 VRAMWrite.Height>=PSXDisplay.DisplayPosition.y)
1113 updateDisplay();
1114 }
1115*/
1116
1117 // Set register to NORMAL operation
1118 DataWriteMode = DR_NORMAL;
1119 // Reset transfer values, to prevent mis-transfer of data
1120 VRAMWrite.x = 0;
1121 VRAMWrite.y = 0;
1122 VRAMWrite.Width = 0;
1123 VRAMWrite.Height = 0;
1124 VRAMWrite.ColsRemaining = 0;
1125 VRAMWrite.RowsRemaining = 0;
1126}
1127
1128__inline void FinishedVRAMRead(void)
1129{
1130 // Set register to NORMAL operation
1131 DataReadMode = DR_NORMAL;
1132 // Reset transfer values, to prevent mis-transfer of data
1133 VRAMRead.x = 0;
1134 VRAMRead.y = 0;
1135 VRAMRead.Width = 0;
1136 VRAMRead.Height = 0;
1137 VRAMRead.ColsRemaining = 0;
1138 VRAMRead.RowsRemaining = 0;
1139
1140 // Indicate GPU is no longer ready for VRAM data in the STATUS REGISTER
1141 lGPUstatusRet&=~GPUSTATUS_READYFORVRAM;
1142}
1143
1144////////////////////////////////////////////////////////////////////////
1145// core read from vram
1146////////////////////////////////////////////////////////////////////////
1147
1148void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize)
1149{
1150 int i;
1151
1152 if(DataReadMode!=DR_VRAMTRANSFER) return;
1153
1154 GPUIsBusy;
1155
1156 // adjust read ptr, if necessary
1157 while(VRAMRead.ImagePtr>=psxVuw_eom)
1158 VRAMRead.ImagePtr-=iGPUHeight*1024;
1159 while(VRAMRead.ImagePtr<psxVuw)
1160 VRAMRead.ImagePtr+=iGPUHeight*1024;
1161
1162 for(i=0;i<iSize;i++)
1163 {
1164 // do 2 seperate 16bit reads for compatibility (wrap issues)
1165 if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))
1166 {
1167 // lower 16 bit
1168 lGPUdataRet=(uint32_t)GETLE16(VRAMRead.ImagePtr);
1169
1170 VRAMRead.ImagePtr++;
1171 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
1172 VRAMRead.RowsRemaining --;
1173
1174 if(VRAMRead.RowsRemaining<=0)
1175 {
1176 VRAMRead.RowsRemaining = VRAMRead.Width;
1177 VRAMRead.ColsRemaining--;
1178 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
1179 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
1180 }
1181
1182 // higher 16 bit (always, even if it's an odd width)
1183 lGPUdataRet|=(uint32_t)GETLE16(VRAMRead.ImagePtr)<<16;
1184 PUTLE32(pMem, lGPUdataRet); pMem++;
1185
1186 if(VRAMRead.ColsRemaining <= 0)
1187 {FinishedVRAMRead();goto ENDREAD;}
1188
1189 VRAMRead.ImagePtr++;
1190 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
1191 VRAMRead.RowsRemaining--;
1192 if(VRAMRead.RowsRemaining<=0)
1193 {
1194 VRAMRead.RowsRemaining = VRAMRead.Width;
1195 VRAMRead.ColsRemaining--;
1196 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
1197 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
1198 }
1199 if(VRAMRead.ColsRemaining <= 0)
1200 {FinishedVRAMRead();goto ENDREAD;}
1201 }
1202 else {FinishedVRAMRead();goto ENDREAD;}
1203 }
1204
1205ENDREAD:
1206 GPUIsIdle;
1207}
1208
1209
1210////////////////////////////////////////////////////////////////////////
1211
1212uint32_t CALLBACK GPUreadData(void)
1213{
1214 uint32_t l;
1215 GPUreadDataMem(&l,1);
1216 return lGPUdataRet;
1217}
1218
1219////////////////////////////////////////////////////////////////////////
1220// processes data send to GPU data register
1221// extra table entries for fixing polyline troubles
1222////////////////////////////////////////////////////////////////////////
1223
1224const unsigned char primTableCX[256] =
1225{
1226 // 00
1227 0,0,3,0,0,0,0,0,
1228 // 08
1229 0,0,0,0,0,0,0,0,
1230 // 10
1231 0,0,0,0,0,0,0,0,
1232 // 18
1233 0,0,0,0,0,0,0,0,
1234 // 20
1235 4,4,4,4,7,7,7,7,
1236 // 28
1237 5,5,5,5,9,9,9,9,
1238 // 30
1239 6,6,6,6,9,9,9,9,
1240 // 38
1241 8,8,8,8,12,12,12,12,
1242 // 40
1243 3,3,3,3,0,0,0,0,
1244 // 48
1245// 5,5,5,5,6,6,6,6, // FLINE
1246 254,254,254,254,254,254,254,254,
1247 // 50
1248 4,4,4,4,0,0,0,0,
1249 // 58
1250// 7,7,7,7,9,9,9,9, // GLINE
1251 255,255,255,255,255,255,255,255,
1252 // 60
1253 3,3,3,3,4,4,4,4,
1254 // 68
1255 2,2,2,2,3,3,3,3, // 3=SPRITE1???
1256 // 70
1257 2,2,2,2,3,3,3,3,
1258 // 78
1259 2,2,2,2,3,3,3,3,
1260 // 80
1261 4,0,0,0,0,0,0,0,
1262 // 88
1263 0,0,0,0,0,0,0,0,
1264 // 90
1265 0,0,0,0,0,0,0,0,
1266 // 98
1267 0,0,0,0,0,0,0,0,
1268 // a0
1269 3,0,0,0,0,0,0,0,
1270 // a8
1271 0,0,0,0,0,0,0,0,
1272 // b0
1273 0,0,0,0,0,0,0,0,
1274 // b8
1275 0,0,0,0,0,0,0,0,
1276 // c0
1277 3,0,0,0,0,0,0,0,
1278 // c8
1279 0,0,0,0,0,0,0,0,
1280 // d0
1281 0,0,0,0,0,0,0,0,
1282 // d8
1283 0,0,0,0,0,0,0,0,
1284 // e0
1285 0,1,1,1,1,1,1,0,
1286 // e8
1287 0,0,0,0,0,0,0,0,
1288 // f0
1289 0,0,0,0,0,0,0,0,
1290 // f8
1291 0,0,0,0,0,0,0,0
1292};
1293
1294void CALLBACK GPUwriteDataMem(uint32_t * pMem, int iSize)
1295{
1296 unsigned char command;
1297 uint32_t gdata=0;
1298 int i=0;
1299 GPUIsBusy;
1300 GPUIsNotReadyForCommands;
1301
1302STARTVRAM:
1303
1304 if(DataWriteMode==DR_VRAMTRANSFER)
1305 {
1306 BOOL bFinished=FALSE;
1307
1308 // make sure we are in vram
1309 while(VRAMWrite.ImagePtr>=psxVuw_eom)
1310 VRAMWrite.ImagePtr-=iGPUHeight*1024;
1311 while(VRAMWrite.ImagePtr<psxVuw)
1312 VRAMWrite.ImagePtr+=iGPUHeight*1024;
1313
1314 // now do the loop
1315 while(VRAMWrite.ColsRemaining>0)
1316 {
1317 while(VRAMWrite.RowsRemaining>0)
1318 {
1319 if(i>=iSize) {goto ENDVRAM;}
1320 i++;
1321
1322 gdata=GETLE32(pMem); pMem++;
1323
1324 PUTLE16(VRAMWrite.ImagePtr, (unsigned short)gdata); VRAMWrite.ImagePtr++;
1325 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
1326 VRAMWrite.RowsRemaining --;
1327
1328 if(VRAMWrite.RowsRemaining <= 0)
1329 {
1330 VRAMWrite.ColsRemaining--;
1331 if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width
1332 {
1333 gdata=(gdata&0xFFFF)|(((uint32_t)GETLE16(VRAMWrite.ImagePtr))<<16);
1334 FinishedVRAMWrite();
1335 bDoVSyncUpdate=TRUE;
1336 goto ENDVRAM;
1337 }
1338 VRAMWrite.RowsRemaining = VRAMWrite.Width;
1339 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
1340 }
1341
1342 PUTLE16(VRAMWrite.ImagePtr, (unsigned short)(gdata>>16)); VRAMWrite.ImagePtr++;
1343 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
1344 VRAMWrite.RowsRemaining --;
1345 }
1346
1347 VRAMWrite.RowsRemaining = VRAMWrite.Width;
1348 VRAMWrite.ColsRemaining--;
1349 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
1350 bFinished=TRUE;
1351 }
1352
1353 FinishedVRAMWrite();
1354 if(bFinished) bDoVSyncUpdate=TRUE;
1355 }
1356
1357ENDVRAM:
1358
1359 if(DataWriteMode==DR_NORMAL)
1360 {
1361 void (* *primFunc)(unsigned char *);
1362 if(bSkipNextFrame) primFunc=primTableSkip;
1363 else primFunc=primTableJ;
1364
1365 for(;i<iSize;)
1366 {
1367 if(DataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;
1368
1369 gdata=GETLE32(pMem); pMem++; i++;
1370
1371 if(gpuDataC == 0)
1372 {
1373 command = (unsigned char)((gdata>>24) & 0xff);
1374
1375//if(command>=0xb0 && command<0xc0) auxprintf("b0 %x!!!!!!!!!\n",command);
1376
1377 if(primTableCX[command])
1378 {
1379 gpuDataC = primTableCX[command];
1380 gpuCommand = command;
1381 PUTLE32(&gpuDataM[0], gdata);
1382 gpuDataP = 1;
1383 }
1384 else continue;
1385 }
1386 else
1387 {
1388 PUTLE32(&gpuDataM[gpuDataP], gdata);
1389 if(gpuDataC>128)
1390 {
1391 if((gpuDataC==254 && gpuDataP>=3) ||
1392 (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1)))
1393 {
1394 if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000)
1395 gpuDataP=gpuDataC-1;
1396 }
1397 }
1398 gpuDataP++;
1399 }
1400
1401 if(gpuDataP == gpuDataC)
1402 {
1403 gpuDataC=gpuDataP=0;
1404 primFunc[gpuCommand]((unsigned char *)gpuDataM);
1405 if(dwEmuFixes&0x0001 || dwActFixes&0x0400) // hack for emulating "gpu busy" in some games
1406 iFakePrimBusy=4;\r }
1407 }
1408 }
1409
1410 lGPUdataRet=gdata;
1411
1412 GPUIsReadyForCommands;
1413 GPUIsIdle;
1414}
1415
1416////////////////////////////////////////////////////////////////////////
1417
1418void CALLBACK GPUwriteData(uint32_t gdata)
1419{
1420 PUTLE32(&gdata, gdata);
1421 GPUwriteDataMem(&gdata,1);
1422}
1423
1424////////////////////////////////////////////////////////////////////////
1425// this functions will be removed soon (or 'soonish')... not really needed, but some emus want them
1426////////////////////////////////////////////////////////////////////////
1427
1428void CALLBACK GPUsetMode(unsigned long gdata)
1429{
1430// Peops does nothing here...
1431// DataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL;
1432// DataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL;
1433}
1434
1435long CALLBACK GPUgetMode(void)
1436{
1437 long iT=0;
1438
1439 if(DataWriteMode==DR_VRAMTRANSFER) iT|=0x1;
1440 if(DataReadMode ==DR_VRAMTRANSFER) iT|=0x2;
1441 return iT;
1442}
1443
1444////////////////////////////////////////////////////////////////////////
1445// call config dlg
1446////////////////////////////////////////////////////////////////////////
1447
1448long CALLBACK GPUconfigure(void)
1449{
1450 SoftDlgProc();
1451
1452 return 0;
1453}
1454
1455////////////////////////////////////////////////////////////////////////
1456// sets all kind of act fixes
1457////////////////////////////////////////////////////////////////////////
1458
1459void SetFixes(void)
1460 {
1461 if(dwActFixes&0x02) sDispWidths[4]=384;
1462 else sDispWidths[4]=368;
1463 }
1464
1465////////////////////////////////////////////////////////////////////////
1466// process gpu commands
1467////////////////////////////////////////////////////////////////////////
1468
1469unsigned long lUsedAddr[3];
1470
1471__inline BOOL CheckForEndlessLoop(unsigned long laddr)
1472{
1473 if(laddr==lUsedAddr[1]) return TRUE;
1474 if(laddr==lUsedAddr[2]) return TRUE;
1475
1476 if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
1477 else lUsedAddr[2]=laddr;
1478 lUsedAddr[0]=laddr;
1479 return FALSE;
1480}
1481
1482long CALLBACK GPUdmaChain(uint32_t * baseAddrL, uint32_t addr)
1483{
1484 uint32_t dmaMem;
1485 unsigned char * baseAddrB;
1486 short count;unsigned int DMACommandCounter = 0;
1487
1488 GPUIsBusy;
1489
1490 lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;
1491
1492 baseAddrB = (unsigned char*) baseAddrL;
1493
1494 do
1495 {
1496 if(iGPUHeight==512) addr&=0x1FFFFC;
1497 if(DMACommandCounter++ > 2000000) break;
1498 if(CheckForEndlessLoop(addr)) break;
1499
1500 count = baseAddrB[addr+3];
1501
1502 dmaMem=addr+4;
1503
1504 if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
1505
1506 addr = GETLE32(&baseAddrL[addr>>2])&0xffffff;
1507 }
1508 while (addr != 0xffffff);
1509
1510 GPUIsIdle;
1511
1512 return 0;
1513}
1514
1515////////////////////////////////////////////////////////////////////////
1516// show about dlg
1517////////////////////////////////////////////////////////////////////////
1518
1519
1520void CALLBACK GPUabout(void) // ABOUT
1521{
1522 AboutDlgProc();
1523 return;
1524}
1525
1526////////////////////////////////////////////////////////////////////////
1527// We are ever fine ;)
1528////////////////////////////////////////////////////////////////////////
1529
1530long CALLBACK GPUtest(void)
1531{
1532 // if test fails this function should return negative value for error (unable to continue)
1533 // and positive value for warning (can continue but output might be crappy)
1534 return 0;
1535}
1536
1537////////////////////////////////////////////////////////////////////////
1538// Freeze
1539////////////////////////////////////////////////////////////////////////
1540
1541typedef struct GPUFREEZETAG
1542{
1543 uint32_t ulFreezeVersion; // should be always 1 for now (set by main emu)
1544 uint32_t ulStatus; // current gpu status
1545 uint32_t ulControl[256]; // latest control register values
1546 unsigned char psxVRam[1024*1024*2]; // current VRam image (full 2 MB for ZN)
1547} GPUFreeze_t;
1548
1549////////////////////////////////////////////////////////////////////////
1550
1551long CALLBACK GPUfreeze(uint32_t ulGetFreezeData,GPUFreeze_t * pF)
1552{
1553 //----------------------------------------------------//
1554 if(ulGetFreezeData==2) // 2: info, which save slot is selected? (just for display)
1555 {
1556 long lSlotNum=*((long *)pF);
1557 if(lSlotNum<0) return 0;
1558 if(lSlotNum>8) return 0;
1559 lSelectedSlot=lSlotNum+1;
1560 BuildDispMenu(0);
1561 return 1;
1562 }
1563 //----------------------------------------------------//
1564 if(!pF) return 0; // some checks
1565 if(pF->ulFreezeVersion!=1) return 0;
1566
1567 if(ulGetFreezeData==1) // 1: get data
1568 {
1569 pF->ulStatus=lGPUstatusRet;
1570 memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t));
1571 memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2);
1572
1573 return 1;
1574 }
1575
1576 if(ulGetFreezeData!=0) return 0; // 0: set data
1577
1578 lGPUstatusRet=pF->ulStatus;
1579 memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t));
1580 memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2);
1581
1582// RESET TEXTURE STORE HERE, IF YOU USE SOMETHING LIKE THAT
1583
1584 GPUwriteStatus(ulStatusControl[0]);
1585 GPUwriteStatus(ulStatusControl[1]);
1586 GPUwriteStatus(ulStatusControl[2]);
1587 GPUwriteStatus(ulStatusControl[3]);
1588 GPUwriteStatus(ulStatusControl[8]); // try to repair things
1589 GPUwriteStatus(ulStatusControl[6]);
1590 GPUwriteStatus(ulStatusControl[7]);
1591 GPUwriteStatus(ulStatusControl[5]);
1592 GPUwriteStatus(ulStatusControl[4]);
1593
1594 return 1;
1595}
1596
1597////////////////////////////////////////////////////////////////////////
1598////////////////////////////////////////////////////////////////////////
1599////////////////////////////////////////////////////////////////////////
1600////////////////////////////////////////////////////////////////////////
1601////////////////////////////////////////////////////////////////////////
1602////////////////////////////////////////////////////////////////////////
1603
1604////////////////////////////////////////////////////////////////////////
1605// SAVE STATE DISPLAY STUFF
1606////////////////////////////////////////////////////////////////////////
1607
1608// font 0-9, 24x20 pixels, 1 byte = 4 dots
1609// 00 = black
1610// 01 = white
1611// 10 = red
1612// 11 = transparent
1613
1614unsigned char cFont[10][120]=
1615{
1616// 0
1617{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1618 0x80,0x00,0x00,0x00,0x00,0x00,
1619 0x80,0x00,0x00,0x00,0x00,0x00,
1620 0x80,0x00,0x00,0x00,0x00,0x00,
1621 0x80,0x00,0x00,0x00,0x00,0x00,
1622 0x80,0x00,0x05,0x54,0x00,0x00,
1623 0x80,0x00,0x14,0x05,0x00,0x00,
1624 0x80,0x00,0x14,0x05,0x00,0x00,
1625 0x80,0x00,0x14,0x05,0x00,0x00,
1626 0x80,0x00,0x14,0x05,0x00,0x00,
1627 0x80,0x00,0x14,0x05,0x00,0x00,
1628 0x80,0x00,0x14,0x05,0x00,0x00,
1629 0x80,0x00,0x14,0x05,0x00,0x00,
1630 0x80,0x00,0x14,0x05,0x00,0x00,
1631 0x80,0x00,0x05,0x54,0x00,0x00,
1632 0x80,0x00,0x00,0x00,0x00,0x00,
1633 0x80,0x00,0x00,0x00,0x00,0x00,
1634 0x80,0x00,0x00,0x00,0x00,0x00,
1635 0x80,0x00,0x00,0x00,0x00,0x00,
1636 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1637},
1638// 1
1639{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1640 0x80,0x00,0x00,0x00,0x00,0x00,
1641 0x80,0x00,0x00,0x00,0x00,0x00,
1642 0x80,0x00,0x00,0x00,0x00,0x00,
1643 0x80,0x00,0x00,0x00,0x00,0x00,
1644 0x80,0x00,0x00,0x50,0x00,0x00,
1645 0x80,0x00,0x05,0x50,0x00,0x00,
1646 0x80,0x00,0x00,0x50,0x00,0x00,
1647 0x80,0x00,0x00,0x50,0x00,0x00,
1648 0x80,0x00,0x00,0x50,0x00,0x00,
1649 0x80,0x00,0x00,0x50,0x00,0x00,
1650 0x80,0x00,0x00,0x50,0x00,0x00,
1651 0x80,0x00,0x00,0x50,0x00,0x00,
1652 0x80,0x00,0x00,0x50,0x00,0x00,
1653 0x80,0x00,0x05,0x55,0x00,0x00,
1654 0x80,0x00,0x00,0x00,0x00,0x00,
1655 0x80,0x00,0x00,0x00,0x00,0x00,
1656 0x80,0x00,0x00,0x00,0x00,0x00,
1657 0x80,0x00,0x00,0x00,0x00,0x00,
1658 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1659},
1660// 2
1661{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1662 0x80,0x00,0x00,0x00,0x00,0x00,
1663 0x80,0x00,0x00,0x00,0x00,0x00,
1664 0x80,0x00,0x00,0x00,0x00,0x00,
1665 0x80,0x00,0x00,0x00,0x00,0x00,
1666 0x80,0x00,0x05,0x54,0x00,0x00,
1667 0x80,0x00,0x14,0x05,0x00,0x00,
1668 0x80,0x00,0x00,0x05,0x00,0x00,
1669 0x80,0x00,0x00,0x05,0x00,0x00,
1670 0x80,0x00,0x00,0x14,0x00,0x00,
1671 0x80,0x00,0x00,0x50,0x00,0x00,
1672 0x80,0x00,0x01,0x40,0x00,0x00,
1673 0x80,0x00,0x05,0x00,0x00,0x00,
1674 0x80,0x00,0x14,0x00,0x00,0x00,
1675 0x80,0x00,0x15,0x55,0x00,0x00,
1676 0x80,0x00,0x00,0x00,0x00,0x00,
1677 0x80,0x00,0x00,0x00,0x00,0x00,
1678 0x80,0x00,0x00,0x00,0x00,0x00,
1679 0x80,0x00,0x00,0x00,0x00,0x00,
1680 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1681},
1682// 3
1683{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1684 0x80,0x00,0x00,0x00,0x00,0x00,
1685 0x80,0x00,0x00,0x00,0x00,0x00,
1686 0x80,0x00,0x00,0x00,0x00,0x00,
1687 0x80,0x00,0x00,0x00,0x00,0x00,
1688 0x80,0x00,0x05,0x54,0x00,0x00,
1689 0x80,0x00,0x14,0x05,0x00,0x00,
1690 0x80,0x00,0x00,0x05,0x00,0x00,
1691 0x80,0x00,0x00,0x05,0x00,0x00,
1692 0x80,0x00,0x01,0x54,0x00,0x00,
1693 0x80,0x00,0x00,0x05,0x00,0x00,
1694 0x80,0x00,0x00,0x05,0x00,0x00,
1695 0x80,0x00,0x00,0x05,0x00,0x00,
1696 0x80,0x00,0x14,0x05,0x00,0x00,
1697 0x80,0x00,0x05,0x54,0x00,0x00,
1698 0x80,0x00,0x00,0x00,0x00,0x00,
1699 0x80,0x00,0x00,0x00,0x00,0x00,
1700 0x80,0x00,0x00,0x00,0x00,0x00,
1701 0x80,0x00,0x00,0x00,0x00,0x00,
1702 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1703},
1704// 4
1705{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1706 0x80,0x00,0x00,0x00,0x00,0x00,
1707 0x80,0x00,0x00,0x00,0x00,0x00,
1708 0x80,0x00,0x00,0x00,0x00,0x00,
1709 0x80,0x00,0x00,0x00,0x00,0x00,
1710 0x80,0x00,0x00,0x14,0x00,0x00,
1711 0x80,0x00,0x00,0x54,0x00,0x00,
1712 0x80,0x00,0x01,0x54,0x00,0x00,
1713 0x80,0x00,0x01,0x54,0x00,0x00,
1714 0x80,0x00,0x05,0x14,0x00,0x00,
1715 0x80,0x00,0x14,0x14,0x00,0x00,
1716 0x80,0x00,0x15,0x55,0x00,0x00,
1717 0x80,0x00,0x00,0x14,0x00,0x00,
1718 0x80,0x00,0x00,0x14,0x00,0x00,
1719 0x80,0x00,0x00,0x55,0x00,0x00,
1720 0x80,0x00,0x00,0x00,0x00,0x00,
1721 0x80,0x00,0x00,0x00,0x00,0x00,
1722 0x80,0x00,0x00,0x00,0x00,0x00,
1723 0x80,0x00,0x00,0x00,0x00,0x00,
1724 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1725},
1726// 5
1727{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1728 0x80,0x00,0x00,0x00,0x00,0x00,
1729 0x80,0x00,0x00,0x00,0x00,0x00,
1730 0x80,0x00,0x00,0x00,0x00,0x00,
1731 0x80,0x00,0x00,0x00,0x00,0x00,
1732 0x80,0x00,0x15,0x55,0x00,0x00,
1733 0x80,0x00,0x14,0x00,0x00,0x00,
1734 0x80,0x00,0x14,0x00,0x00,0x00,
1735 0x80,0x00,0x14,0x00,0x00,0x00,
1736 0x80,0x00,0x15,0x54,0x00,0x00,
1737 0x80,0x00,0x00,0x05,0x00,0x00,
1738 0x80,0x00,0x00,0x05,0x00,0x00,
1739 0x80,0x00,0x00,0x05,0x00,0x00,
1740 0x80,0x00,0x14,0x05,0x00,0x00,
1741 0x80,0x00,0x05,0x54,0x00,0x00,
1742 0x80,0x00,0x00,0x00,0x00,0x00,
1743 0x80,0x00,0x00,0x00,0x00,0x00,
1744 0x80,0x00,0x00,0x00,0x00,0x00,
1745 0x80,0x00,0x00,0x00,0x00,0x00,
1746 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1747},
1748// 6
1749{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1750 0x80,0x00,0x00,0x00,0x00,0x00,
1751 0x80,0x00,0x00,0x00,0x00,0x00,
1752 0x80,0x00,0x00,0x00,0x00,0x00,
1753 0x80,0x00,0x00,0x00,0x00,0x00,
1754 0x80,0x00,0x01,0x54,0x00,0x00,
1755 0x80,0x00,0x05,0x00,0x00,0x00,
1756 0x80,0x00,0x14,0x00,0x00,0x00,
1757 0x80,0x00,0x14,0x00,0x00,0x00,
1758 0x80,0x00,0x15,0x54,0x00,0x00,
1759 0x80,0x00,0x15,0x05,0x00,0x00,
1760 0x80,0x00,0x14,0x05,0x00,0x00,
1761 0x80,0x00,0x14,0x05,0x00,0x00,
1762 0x80,0x00,0x14,0x05,0x00,0x00,
1763 0x80,0x00,0x05,0x54,0x00,0x00,
1764 0x80,0x00,0x00,0x00,0x00,0x00,
1765 0x80,0x00,0x00,0x00,0x00,0x00,
1766 0x80,0x00,0x00,0x00,0x00,0x00,
1767 0x80,0x00,0x00,0x00,0x00,0x00,
1768 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1769},
1770// 7
1771{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1772 0x80,0x00,0x00,0x00,0x00,0x00,
1773 0x80,0x00,0x00,0x00,0x00,0x00,
1774 0x80,0x00,0x00,0x00,0x00,0x00,
1775 0x80,0x00,0x00,0x00,0x00,0x00,
1776 0x80,0x00,0x15,0x55,0x00,0x00,
1777 0x80,0x00,0x14,0x05,0x00,0x00,
1778 0x80,0x00,0x00,0x14,0x00,0x00,
1779 0x80,0x00,0x00,0x14,0x00,0x00,
1780 0x80,0x00,0x00,0x50,0x00,0x00,
1781 0x80,0x00,0x00,0x50,0x00,0x00,
1782 0x80,0x00,0x01,0x40,0x00,0x00,
1783 0x80,0x00,0x01,0x40,0x00,0x00,
1784 0x80,0x00,0x05,0x00,0x00,0x00,
1785 0x80,0x00,0x05,0x00,0x00,0x00,
1786 0x80,0x00,0x00,0x00,0x00,0x00,
1787 0x80,0x00,0x00,0x00,0x00,0x00,
1788 0x80,0x00,0x00,0x00,0x00,0x00,
1789 0x80,0x00,0x00,0x00,0x00,0x00,
1790 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1791},
1792// 8
1793{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1794 0x80,0x00,0x00,0x00,0x00,0x00,
1795 0x80,0x00,0x00,0x00,0x00,0x00,
1796 0x80,0x00,0x00,0x00,0x00,0x00,
1797 0x80,0x00,0x00,0x00,0x00,0x00,
1798 0x80,0x00,0x05,0x54,0x00,0x00,
1799 0x80,0x00,0x14,0x05,0x00,0x00,
1800 0x80,0x00,0x14,0x05,0x00,0x00,
1801 0x80,0x00,0x14,0x05,0x00,0x00,
1802 0x80,0x00,0x05,0x54,0x00,0x00,
1803 0x80,0x00,0x14,0x05,0x00,0x00,
1804 0x80,0x00,0x14,0x05,0x00,0x00,
1805 0x80,0x00,0x14,0x05,0x00,0x00,
1806 0x80,0x00,0x14,0x05,0x00,0x00,
1807 0x80,0x00,0x05,0x54,0x00,0x00,
1808 0x80,0x00,0x00,0x00,0x00,0x00,
1809 0x80,0x00,0x00,0x00,0x00,0x00,
1810 0x80,0x00,0x00,0x00,0x00,0x00,
1811 0x80,0x00,0x00,0x00,0x00,0x00,
1812 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1813},
1814// 9
1815{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1816 0x80,0x00,0x00,0x00,0x00,0x00,
1817 0x80,0x00,0x00,0x00,0x00,0x00,
1818 0x80,0x00,0x00,0x00,0x00,0x00,
1819 0x80,0x00,0x00,0x00,0x00,0x00,
1820 0x80,0x00,0x05,0x54,0x00,0x00,
1821 0x80,0x00,0x14,0x05,0x00,0x00,
1822 0x80,0x00,0x14,0x05,0x00,0x00,
1823 0x80,0x00,0x14,0x05,0x00,0x00,
1824 0x80,0x00,0x14,0x15,0x00,0x00,
1825 0x80,0x00,0x05,0x55,0x00,0x00,
1826 0x80,0x00,0x00,0x05,0x00,0x00,
1827 0x80,0x00,0x00,0x05,0x00,0x00,
1828 0x80,0x00,0x00,0x14,0x00,0x00,
1829 0x80,0x00,0x05,0x50,0x00,0x00,
1830 0x80,0x00,0x00,0x00,0x00,0x00,
1831 0x80,0x00,0x00,0x00,0x00,0x00,
1832 0x80,0x00,0x00,0x00,0x00,0x00,
1833 0x80,0x00,0x00,0x00,0x00,0x00,
1834 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1835}
1836};
1837
1838////////////////////////////////////////////////////////////////////////
1839
1840void PaintPicDot(unsigned char * p,unsigned char c)
1841{
1842
1843 if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;} // black
1844 if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;} // white
1845 if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;} // red
1846 // transparent
1847}
1848
1849////////////////////////////////////////////////////////////////////////
1850// the main emu allocs 128x96x3 bytes, and passes a ptr
1851// to it in pMem... the plugin has to fill it with
1852// 8-8-8 bit BGR screen data (Win 24 bit BMP format
1853// without header).
1854// Beware: the func can be called at any time,
1855// so you have to use the frontbuffer to get a fully
1856// rendered picture
1857
1858// LINUX version:
1859
1860extern char * Xpixels;
1861
1862void GPUgetScreenPic(unsigned char * pMem)
1863{
1864/*
1865 unsigned short c;unsigned char * pf;int x,y;
1866
1867 float XS=(float)iResX/128;
1868 float YS=(float)iResY/96;
1869
1870 pf=pMem;
1871 memset(pMem, 0, 128*96*3);
1872
1873 if(Xpixels)
1874 {
1875 unsigned char * ps=(unsigned char *)Xpixels;
1876 {
1877 long lPitch=iResX<<2;
1878 uint32_t sx;
1879
1880 for(y=0;y<96;y++)
1881 {
1882 for(x=0;x<128;x++)
1883 {
1884 sx=*((uint32_t *)((ps)+
1885 (((int)((float)y*YS))*lPitch)+
1886 ((int)((float)x*XS))*4));
1887 *(pf+0)=(sx&0xff);
1888 *(pf+1)=(sx&0xff00)>>8;
1889 *(pf+2)=(sx&0xff0000)>>16;
1890 pf+=3;
1891 }
1892 }
1893 }
1894 }
1895
1896
1897 /////////////////////////////////////////////////////////////////////
1898 // generic number/border painter
1899
1900 pf=pMem+(103*3); // offset to number rect
1901
1902 for(y=0;y<20;y++) // loop the number rect pixel
1903 {
1904 for(x=0;x<6;x++)
1905 {
1906 c=cFont[lSelectedSlot][x+y*6]; // get 4 char dot infos at once (number depends on selected slot)
1907 PaintPicDot(pf,(c&0xc0)>>6);pf+=3; // paint the dots into the rect
1908 PaintPicDot(pf,(c&0x30)>>4);pf+=3;
1909 PaintPicDot(pf,(c&0x0c)>>2);pf+=3;
1910 PaintPicDot(pf,(c&0x03)); pf+=3;
1911 }
1912 pf+=104*3; // next rect y line
1913 }
1914
1915 pf=pMem; // ptr to first pos in 128x96 pic
1916 for(x=0;x<128;x++) // loop top/bottom line
1917 {
1918 *(pf+(95*128*3))=0x00;*pf++=0x00;
1919 *(pf+(95*128*3))=0x00;*pf++=0x00; // paint it red
1920 *(pf+(95*128*3))=0xff;*pf++=0xff;
1921 }
1922 pf=pMem; // ptr to first pos
1923 for(y=0;y<96;y++) // loop left/right line
1924 {
1925 *(pf+(127*3))=0x00;*pf++=0x00;
1926 *(pf+(127*3))=0x00;*pf++=0x00; // paint it red
1927 *(pf+(127*3))=0xff;*pf++=0xff;
1928 pf+=127*3; // offset to next line
1929 }
1930*/
1931}
1932
1933
1934////////////////////////////////////////////////////////////////////////
1935// func will be called with 128x96x3 BGR data.
1936// the plugin has to store the data and display
1937// it in the upper right corner.
1938// If the func is called with a NULL ptr, you can
1939// release your picture data and stop displaying
1940// the screen pic
1941
1942void CALLBACK GPUshowScreenPic(unsigned char * pMem)
1943{
1944 DestroyPic(); // destroy old pic data
1945 if(pMem==0) return; // done
1946 CreatePic(pMem); // create new pic... don't free pMem or something like that... just read from it
1947}
1948
1949void CALLBACK GPUsetfix(uint32_t dwFixBits)
1950{
1951 dwEmuFixes=dwFixBits;
1952}