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