basic profiling
[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 {
497 DoBufferSwap(); // -> swap
498 }
499}
500
501////////////////////////////////////////////////////////////////////////
502// roughly emulated screen centering bits... not complete !!!
503////////////////////////////////////////////////////////////////////////
504
505void ChangeDispOffsetsX(void) // X CENTER
506{
507 long lx,l;
508
509 if(!PSXDisplay.Range.x1) return;
510
511 l=PreviousPSXDisplay.DisplayMode.x;
512
513 l*=(long)PSXDisplay.Range.x1;
514 l/=2560;lx=l;l&=0xfffffff8;
515
516 if(l==PreviousPSXDisplay.Range.y1) return; // abusing range.y1 for
517 PreviousPSXDisplay.Range.y1=(short)l; // storing last x range and test
518
519 if(lx>=PreviousPSXDisplay.DisplayMode.x)
520 {
521 PreviousPSXDisplay.Range.x1=
522 (short)PreviousPSXDisplay.DisplayMode.x;
523 PreviousPSXDisplay.Range.x0=0;
524 }
525 else
526 {
527 PreviousPSXDisplay.Range.x1=(short)l;
528
529 PreviousPSXDisplay.Range.x0=
530 (PSXDisplay.Range.x0-500)/8;
531
532 if(PreviousPSXDisplay.Range.x0<0)
533 PreviousPSXDisplay.Range.x0=0;
534
535 if((PreviousPSXDisplay.Range.x0+lx)>
536 PreviousPSXDisplay.DisplayMode.x)
537 {
538 PreviousPSXDisplay.Range.x0=
539 (short)(PreviousPSXDisplay.DisplayMode.x-lx);
540 PreviousPSXDisplay.Range.x0+=2; //???
541
542 PreviousPSXDisplay.Range.x1+=(short)(lx-l);
543
544 PreviousPSXDisplay.Range.x1-=2; // makes linux stretching easier
545
546 }
547
548
549 // some linux alignment security
550 PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0>>1;
551 PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0<<1;
552 PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1>>1;
553 PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1<<1;
554
555
556 DoClearScreenBuffer();
557 }
558
559 bDoVSyncUpdate=TRUE;
560}
561
562////////////////////////////////////////////////////////////////////////
563
564void ChangeDispOffsetsY(void) // Y CENTER
565{
566 int iT,iO=PreviousPSXDisplay.Range.y0;
567 int iOldYOffset=PreviousPSXDisplay.DisplayModeNew.y;
568
569// new
570
571 if((PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)>iGPUHeight)
572 {
573 int dy1=iGPUHeight-PreviousPSXDisplay.DisplayModeNew.x;
574 int dy2=(PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)-iGPUHeight;
575
576 if(dy1>=dy2)
577 {
578 PreviousPSXDisplay.DisplayModeNew.y=-dy2;
579 }
580 else
581 {
582 PSXDisplay.DisplayPosition.y=0;
583 PreviousPSXDisplay.DisplayModeNew.y=-dy1;
584 }
585 }
586 else PreviousPSXDisplay.DisplayModeNew.y=0;
587
588// eon
589
590 if(PreviousPSXDisplay.DisplayModeNew.y!=iOldYOffset) // if old offset!=new offset: recalc height
591 {
592 PSXDisplay.Height = PSXDisplay.Range.y1 -
593 PSXDisplay.Range.y0 +
594 PreviousPSXDisplay.DisplayModeNew.y;
595 PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;
596 }
597
598//
599
600 if(PSXDisplay.PAL) iT=48; else iT=28;
601
602 if(PSXDisplay.Range.y0>=iT)
603 {
604 PreviousPSXDisplay.Range.y0=
605 (short)((PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double);
606 if(PreviousPSXDisplay.Range.y0<0)
607 PreviousPSXDisplay.Range.y0=0;
608 PSXDisplay.DisplayModeNew.y+=
609 PreviousPSXDisplay.Range.y0;
610 }
611 else
612 PreviousPSXDisplay.Range.y0=0;
613
614 if(iO!=PreviousPSXDisplay.Range.y0)
615 {
616 DoClearScreenBuffer();
617 }
618}
619
620////////////////////////////////////////////////////////////////////////
621// check if update needed
622////////////////////////////////////////////////////////////////////////
623
624void updateDisplayIfChanged(void) // UPDATE DISPLAY IF CHANGED
625{
626 if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) &&
627 (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))
628 {
629 if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) &&
630 (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew)) return;
631 }
632
633 PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos
634
635 PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;
636 PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;
637 PreviousPSXDisplay.DisplayMode.x= // previous will hold
638 min(640,PSXDisplay.DisplayMode.x); // max 640x512... that's
639 PreviousPSXDisplay.DisplayMode.y= // the size of my
640 min(512,PSXDisplay.DisplayMode.y); // back buffer surface
641 PSXDisplay.Interlaced = PSXDisplay.InterlacedNew;
642
643 PSXDisplay.DisplayEnd.x= // calc end of display
644 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
645 PSXDisplay.DisplayEnd.y=
646 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
647 PreviousPSXDisplay.DisplayEnd.x=
648 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
649 PreviousPSXDisplay.DisplayEnd.y=
650 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
651
652 ChangeDispOffsetsX();
653
654 if(iFrameLimit==2) SetAutoFrameCap(); // -> set it
655
656 if(UseFrameSkip) updateDisplay(); // stupid stuff when frame skipping enabled
657}
658
659////////////////////////////////////////////////////////////////////////
660
661#ifndef _MACGL
662
663#include "draw.h"
664
665void ChangeWindowMode(void) // TOGGLE FULLSCREEN - WINDOW
666{
667 extern Display *display;
668 extern Window window;
669 extern int root_window_id;
670 Screen *screen;
671 XSizeHints hints;
672 MotifWmHints mwmhints;
673 Atom mwmatom;
674
675 screen=DefaultScreenOfDisplay(display);
676 iWindowMode=!iWindowMode;
677
678 if(!iWindowMode) // fullscreen
679 {
680 mwmhints.flags=MWM_HINTS_DECORATIONS;
681 mwmhints.functions=0;
682 mwmhints.decorations=0;
683 mwmhints.input_mode=0;
684 mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0);
685 XChangeProperty(display,window,mwmatom,mwmatom,32,
686 PropModeReplace,(unsigned char *)&mwmhints,5);
687
688 XResizeWindow(display,window,screen->width,screen->height);
689
690 hints.min_width = hints.max_width = hints.base_width = screen->width;
691 hints.min_height= hints.max_height = hints.base_height = screen->height;
692
693 XSetWMNormalHints(display,window,&hints);
694
695 {
696 XEvent xev;
697
698 memset(&xev, 0, sizeof(xev));
699 xev.xclient.type = ClientMessage;
700 xev.xclient.serial = 0;
701 xev.xclient.send_event = 1;
702 xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0);
703 xev.xclient.window = window;
704 xev.xclient.format = 32;
705 xev.xclient.data.l[0] = 1;
706 xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", 0);
707 xev.xclient.data.l[2] = 0;
708 xev.xclient.data.l[3] = 0;
709 xev.xclient.data.l[4] = 0;
710
711 XSendEvent(display, root_window_id, 0,
712 SubstructureRedirectMask | SubstructureNotifyMask, &xev);
713 }
714 } else {
715 {
716 XEvent xev;
717
718 memset(&xev, 0, sizeof(xev));
719 xev.xclient.type = ClientMessage;
720 xev.xclient.serial = 0;
721 xev.xclient.send_event = 1;
722 xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0);
723 xev.xclient.window = window;
724 xev.xclient.format = 32;
725 xev.xclient.data.l[0] = 0;
726 xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", 0);
727 xev.xclient.data.l[2] = 0;
728 xev.xclient.data.l[3] = 0;
729 xev.xclient.data.l[4] = 0;
730
731 XSendEvent(display, root_window_id, 0,
732 SubstructureRedirectMask | SubstructureNotifyMask, &xev);
733 }
734
735 mwmhints.flags=MWM_HINTS_DECORATIONS;
736 mwmhints.functions=0;
737 mwmhints.decorations=1;
738 mwmhints.input_mode=0;
739 mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0);
740
741 //This shouldn't work on 64 bit longs, but it does...in fact, it breaks when I change all the mwmhints to int.
742 //I don't pretend to understand it.
743 XChangeProperty(display,window,mwmatom,mwmatom,32,
744 PropModeReplace,(unsigned char *)&mwmhints,5);
745
746 hints.flags=USPosition|USSize;
747 hints.base_width = iResX;
748 hints.base_height = iResY;
749 XSetWMNormalHints(display,window,&hints);
750
751 XResizeWindow(display,window,iResX,iResY);
752}
753
754 DoClearScreenBuffer();
755
756 bChangeWinMode=FALSE;
757 bDoVSyncUpdate=TRUE;
758}
759
760#endif
761
762////////////////////////////////////////////////////////////////////////
763// gun cursor func: player=0-7, x=0-511, y=0-255
764////////////////////////////////////////////////////////////////////////
765
766void CALLBACK GPUcursor(int iPlayer,int x,int y)
767{
768 if(iPlayer<0) return;
769 if(iPlayer>7) return;
770
771 usCursorActive|=(1<<iPlayer);
772
773 if(x<0) x=0;
774 if(x>511) x=511;
775 if(y<0) y=0;
776 if(y>255) y=255;
777
778 ptCursorPoint[iPlayer].x=x;
779 ptCursorPoint[iPlayer].y=y;
780}
781
782////////////////////////////////////////////////////////////////////////
783// update lace is called evry VSync
784////////////////////////////////////////////////////////////////////////
785
786void CALLBACK GPUupdateLace(void) // VSYNC
787{
788 if(!(dwActFixes&1))
789 lGPUstatusRet^=0x80000000; // odd/even bit
790
791 if(!(dwActFixes&32)) // std fps limitation?
792 CheckFrameRate();
793
794 if(PSXDisplay.Interlaced) // interlaced mode?
795 {
796 if(bDoVSyncUpdate && PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)
797 {
798 updateDisplay();
799 }
800 }
801 else // non-interlaced?
802 {
803 if(dwActFixes&64) // lazy screen update fix
804 {
805 if(bDoLazyUpdate && !UseFrameSkip)
806 updateDisplay();
807 bDoLazyUpdate=FALSE;
808 }
809 else
810 {
811 if(bDoVSyncUpdate && !UseFrameSkip) // some primitives drawn?
812 updateDisplay(); // -> update display
813 }
814 }
815#ifndef _MACGL
816 if(bChangeWinMode) ChangeWindowMode(); // toggle full - window mode
817#endif
818 bDoVSyncUpdate=FALSE; // vsync done
819}
820
821////////////////////////////////////////////////////////////////////////
822// process read request from GPU status register
823////////////////////////////////////////////////////////////////////////
824
825
826uint32_t CALLBACK GPUreadStatus(void) // READ STATUS
827{
828 if(dwActFixes&1)
829 {
830 static int iNumRead=0; // odd/even hack
831 if((iNumRead++)==2)
832 {
833 iNumRead=0;
834 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)
835 }
836 }
837
838 if(iFakePrimBusy) // 27.10.2007 - PETE : emulating some 'busy' while drawing... pfff
839 {
840 iFakePrimBusy--;
841
842 if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims
843 {
844 GPUIsBusy;
845 GPUIsNotReadyForCommands;
846 }
847 else
848 {
849 GPUIsIdle;
850 GPUIsReadyForCommands;
851 }
852 }
853 return lGPUstatusRet;
854}
855
856////////////////////////////////////////////////////////////////////////
857// processes data send to GPU status register
858// these are always single packet commands.
859////////////////////////////////////////////////////////////////////////
860
861void CALLBACK GPUwriteStatus(uint32_t gdata) // WRITE STATUS
862{
863 uint32_t lCommand=(gdata>>24)&0xff;
864
865 ulStatusControl[lCommand]=gdata; // store command for freezing
866
867 switch(lCommand)
868 {
869 //--------------------------------------------------//
870 // reset gpu
871 case 0x00:
872 memset(lGPUInfoVals,0x00,16*sizeof(uint32_t));
873 lGPUstatusRet=0x14802000;
874 PSXDisplay.Disabled=1;
875 DataWriteMode=DataReadMode=DR_NORMAL;
876 PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0;
877 drawX=drawY=0;drawW=drawH=0;
878 sSetMask=0;lSetMask=0;bCheckMask=FALSE;
879 usMirror=0;
880 GlobalTextAddrX=0;GlobalTextAddrY=0;
881 GlobalTextTP=0;GlobalTextABR=0;
882 PSXDisplay.RGB24=FALSE;
883 PSXDisplay.Interlaced=FALSE;
884 bUsingTWin = FALSE;
885 return;
886 //--------------------------------------------------//
887 // dis/enable display
888 case 0x03:
889
890 PreviousPSXDisplay.Disabled = PSXDisplay.Disabled;
891 PSXDisplay.Disabled = (gdata & 1);
892
893 if(PSXDisplay.Disabled)
894 lGPUstatusRet|=GPUSTATUS_DISPLAYDISABLED;
895 else lGPUstatusRet&=~GPUSTATUS_DISPLAYDISABLED;
896 return;
897
898 //--------------------------------------------------//
899 // setting transfer mode
900 case 0x04:
901 gdata &= 0x03; // Only want the lower two bits
902
903 DataWriteMode=DataReadMode=DR_NORMAL;
904 if(gdata==0x02) DataWriteMode=DR_VRAMTRANSFER;
905 if(gdata==0x03) DataReadMode =DR_VRAMTRANSFER;
906 lGPUstatusRet&=~GPUSTATUS_DMABITS; // Clear the current settings of the DMA bits
907 lGPUstatusRet|=(gdata << 29); // Set the DMA bits according to the received data
908
909 return;
910 //--------------------------------------------------//
911 // setting display position
912 case 0x05:
913 {
914 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
915 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
916
917////////
918/*
919 PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff);
920 if (PSXDisplay.DisplayPosition.y & 0x200)
921 PSXDisplay.DisplayPosition.y |= 0xfffffc00;
922 if(PSXDisplay.DisplayPosition.y<0)
923 {
924 PreviousPSXDisplay.DisplayModeNew.y=PSXDisplay.DisplayPosition.y/PSXDisplay.Double;
925 PSXDisplay.DisplayPosition.y=0;
926 }
927 else PreviousPSXDisplay.DisplayModeNew.y=0;
928*/
929
930// new
931 if(iGPUHeight==1024)
932 {
933 if(dwGPUVersion==2)
934 PSXDisplay.DisplayPosition.y = (short)((gdata>>12)&0x3ff);
935 else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff);
936 }
937 else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x1ff);
938
939 // store the same val in some helper var, we need it on later compares
940 PreviousPSXDisplay.DisplayModeNew.x=PSXDisplay.DisplayPosition.y;
941
942 if((PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)>iGPUHeight)
943 {
944 int dy1=iGPUHeight-PSXDisplay.DisplayPosition.y;
945 int dy2=(PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)-iGPUHeight;
946
947 if(dy1>=dy2)
948 {
949 PreviousPSXDisplay.DisplayModeNew.y=-dy2;
950 }
951 else
952 {
953 PSXDisplay.DisplayPosition.y=0;
954 PreviousPSXDisplay.DisplayModeNew.y=-dy1;
955 }
956 }
957 else PreviousPSXDisplay.DisplayModeNew.y=0;
958// eon
959
960 PSXDisplay.DisplayPosition.x = (short)(gdata & 0x3ff);
961 PSXDisplay.DisplayEnd.x=
962 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
963 PSXDisplay.DisplayEnd.y=
964 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y + PreviousPSXDisplay.DisplayModeNew.y;
965 PreviousPSXDisplay.DisplayEnd.x=
966 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
967 PreviousPSXDisplay.DisplayEnd.y=
968 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y + PreviousPSXDisplay.DisplayModeNew.y;
969
970 bDoVSyncUpdate=TRUE;
971
972 if (!(PSXDisplay.Interlaced)) // stupid frame skipping option
973 {
974 if(UseFrameSkip) updateDisplay();
975 if(dwActFixes&64) bDoLazyUpdate=TRUE;
976 }
977 }return;
978 //--------------------------------------------------//
979 // setting width
980 case 0x06:
981
982 PSXDisplay.Range.x0=(short)(gdata & 0x7ff);
983 PSXDisplay.Range.x1=(short)((gdata>>12) & 0xfff);
984
985 PSXDisplay.Range.x1-=PSXDisplay.Range.x0;
986
987 ChangeDispOffsetsX();
988
989 return;
990 //--------------------------------------------------//
991 // setting height
992 case 0x07:
993 {
994
995 PSXDisplay.Range.y0=(short)(gdata & 0x3ff);
996 PSXDisplay.Range.y1=(short)((gdata>>10) & 0x3ff);
997
998 PreviousPSXDisplay.Height = PSXDisplay.Height;
999
1000 PSXDisplay.Height = PSXDisplay.Range.y1 -
1001 PSXDisplay.Range.y0 +
1002 PreviousPSXDisplay.DisplayModeNew.y;
1003
1004 if(PreviousPSXDisplay.Height!=PSXDisplay.Height)
1005 {
1006 PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;
1007
1008 ChangeDispOffsetsY();
1009
1010 updateDisplayIfChanged();
1011 }
1012 return;
1013 }
1014 //--------------------------------------------------//
1015 // setting display infos
1016 case 0x08:
1017
1018 PSXDisplay.DisplayModeNew.x =
1019 sDispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)];
1020
1021 if (gdata&0x04) PSXDisplay.Double=2;
1022 else PSXDisplay.Double=1;
1023
1024 PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double;
1025
1026 ChangeDispOffsetsY();
1027
1028 PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC
1029 PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor
1030 PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace
1031
1032 lGPUstatusRet&=~GPUSTATUS_WIDTHBITS; // Clear the width bits
1033 lGPUstatusRet|=
1034 (((gdata & 0x03) << 17) |
1035 ((gdata & 0x40) << 10)); // Set the width bits
1036
1037 if(PSXDisplay.InterlacedNew)
1038 {
1039 if(!PSXDisplay.Interlaced)
1040 {
1041 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
1042 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
1043 }
1044 lGPUstatusRet|=GPUSTATUS_INTERLACED;
1045 }
1046 else lGPUstatusRet&=~GPUSTATUS_INTERLACED;
1047
1048 if (PSXDisplay.PAL)
1049 lGPUstatusRet|=GPUSTATUS_PAL;
1050 else lGPUstatusRet&=~GPUSTATUS_PAL;
1051
1052 if (PSXDisplay.Double==2)
1053 lGPUstatusRet|=GPUSTATUS_DOUBLEHEIGHT;
1054 else lGPUstatusRet&=~GPUSTATUS_DOUBLEHEIGHT;
1055
1056 if (PSXDisplay.RGB24New)
1057 lGPUstatusRet|=GPUSTATUS_RGB24;
1058 else lGPUstatusRet&=~GPUSTATUS_RGB24;
1059
1060 updateDisplayIfChanged();
1061
1062 return;
1063 //--------------------------------------------------//
1064 // ask about GPU version and other stuff
1065 case 0x10:
1066
1067 gdata&=0xff;
1068
1069 switch(gdata)
1070 {
1071 case 0x02:
1072 lGPUdataRet=lGPUInfoVals[INFO_TW]; // tw infos
1073 return;
1074 case 0x03:
1075 lGPUdataRet=lGPUInfoVals[INFO_DRAWSTART]; // draw start
1076 return;
1077 case 0x04:
1078 lGPUdataRet=lGPUInfoVals[INFO_DRAWEND]; // draw end
1079 return;
1080 case 0x05:
1081 case 0x06:
1082 lGPUdataRet=lGPUInfoVals[INFO_DRAWOFF]; // draw offset
1083 return;
1084 case 0x07:
1085 if(dwGPUVersion==2)
1086 lGPUdataRet=0x01;
1087 else lGPUdataRet=0x02; // gpu type
1088 return;
1089 case 0x08:
1090 case 0x0F: // some bios addr?
1091 lGPUdataRet=0xBFC03720;
1092 return;
1093 }
1094 return;
1095 //--------------------------------------------------//
1096 }
1097}
1098
1099////////////////////////////////////////////////////////////////////////
1100// vram read/write helpers, needed by LEWPY's optimized vram read/write :)
1101////////////////////////////////////////////////////////////////////////
1102
1103__inline void FinishedVRAMWrite(void)
1104{
1105/*
1106// NEWX
1107 if(!PSXDisplay.Interlaced && UseFrameSkip) // stupid frame skipping
1108 {
1109 VRAMWrite.Width +=VRAMWrite.x;
1110 VRAMWrite.Height+=VRAMWrite.y;
1111 if(VRAMWrite.x<PSXDisplay.DisplayEnd.x &&
1112 VRAMWrite.Width >=PSXDisplay.DisplayPosition.x &&
1113 VRAMWrite.y<PSXDisplay.DisplayEnd.y &&
1114 VRAMWrite.Height>=PSXDisplay.DisplayPosition.y)
1115 updateDisplay();
1116 }
1117*/
1118
1119 // Set register to NORMAL operation
1120 DataWriteMode = DR_NORMAL;
1121 // Reset transfer values, to prevent mis-transfer of data
1122 VRAMWrite.x = 0;
1123 VRAMWrite.y = 0;
1124 VRAMWrite.Width = 0;
1125 VRAMWrite.Height = 0;
1126 VRAMWrite.ColsRemaining = 0;
1127 VRAMWrite.RowsRemaining = 0;
1128}
1129
1130__inline void FinishedVRAMRead(void)
1131{
1132 // Set register to NORMAL operation
1133 DataReadMode = DR_NORMAL;
1134 // Reset transfer values, to prevent mis-transfer of data
1135 VRAMRead.x = 0;
1136 VRAMRead.y = 0;
1137 VRAMRead.Width = 0;
1138 VRAMRead.Height = 0;
1139 VRAMRead.ColsRemaining = 0;
1140 VRAMRead.RowsRemaining = 0;
1141
1142 // Indicate GPU is no longer ready for VRAM data in the STATUS REGISTER
1143 lGPUstatusRet&=~GPUSTATUS_READYFORVRAM;
1144}
1145
1146////////////////////////////////////////////////////////////////////////
1147// core read from vram
1148////////////////////////////////////////////////////////////////////////
1149
1150void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize)
1151{
1152 int i;
1153
1154 if(DataReadMode!=DR_VRAMTRANSFER) return;
1155
1156 GPUIsBusy;
1157
1158 // adjust read ptr, if necessary
1159 while(VRAMRead.ImagePtr>=psxVuw_eom)
1160 VRAMRead.ImagePtr-=iGPUHeight*1024;
1161 while(VRAMRead.ImagePtr<psxVuw)
1162 VRAMRead.ImagePtr+=iGPUHeight*1024;
1163
1164 for(i=0;i<iSize;i++)
1165 {
1166 // do 2 seperate 16bit reads for compatibility (wrap issues)
1167 if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))
1168 {
1169 // lower 16 bit
1170 lGPUdataRet=(uint32_t)GETLE16(VRAMRead.ImagePtr);
1171
1172 VRAMRead.ImagePtr++;
1173 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
1174 VRAMRead.RowsRemaining --;
1175
1176 if(VRAMRead.RowsRemaining<=0)
1177 {
1178 VRAMRead.RowsRemaining = VRAMRead.Width;
1179 VRAMRead.ColsRemaining--;
1180 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
1181 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
1182 }
1183
1184 // higher 16 bit (always, even if it's an odd width)
1185 lGPUdataRet|=(uint32_t)GETLE16(VRAMRead.ImagePtr)<<16;
1186 PUTLE32(pMem, lGPUdataRet); pMem++;
1187
1188 if(VRAMRead.ColsRemaining <= 0)
1189 {FinishedVRAMRead();goto ENDREAD;}
1190
1191 VRAMRead.ImagePtr++;
1192 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
1193 VRAMRead.RowsRemaining--;
1194 if(VRAMRead.RowsRemaining<=0)
1195 {
1196 VRAMRead.RowsRemaining = VRAMRead.Width;
1197 VRAMRead.ColsRemaining--;
1198 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
1199 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
1200 }
1201 if(VRAMRead.ColsRemaining <= 0)
1202 {FinishedVRAMRead();goto ENDREAD;}
1203 }
1204 else {FinishedVRAMRead();goto ENDREAD;}
1205 }
1206
1207ENDREAD:
1208 GPUIsIdle;
1209}
1210
1211
1212////////////////////////////////////////////////////////////////////////
1213
1214uint32_t CALLBACK GPUreadData(void)
1215{
1216 uint32_t l;
1217 GPUreadDataMem(&l,1);
1218 return lGPUdataRet;
1219}
1220
1221////////////////////////////////////////////////////////////////////////
1222// processes data send to GPU data register
1223// extra table entries for fixing polyline troubles
1224////////////////////////////////////////////////////////////////////////
1225
1226const unsigned char primTableCX[256] =
1227{
1228 // 00
1229 0,0,3,0,0,0,0,0,
1230 // 08
1231 0,0,0,0,0,0,0,0,
1232 // 10
1233 0,0,0,0,0,0,0,0,
1234 // 18
1235 0,0,0,0,0,0,0,0,
1236 // 20
1237 4,4,4,4,7,7,7,7,
1238 // 28
1239 5,5,5,5,9,9,9,9,
1240 // 30
1241 6,6,6,6,9,9,9,9,
1242 // 38
1243 8,8,8,8,12,12,12,12,
1244 // 40
1245 3,3,3,3,0,0,0,0,
1246 // 48
1247// 5,5,5,5,6,6,6,6, // FLINE
1248 254,254,254,254,254,254,254,254,
1249 // 50
1250 4,4,4,4,0,0,0,0,
1251 // 58
1252// 7,7,7,7,9,9,9,9, // GLINE
1253 255,255,255,255,255,255,255,255,
1254 // 60
1255 3,3,3,3,4,4,4,4,
1256 // 68
1257 2,2,2,2,3,3,3,3, // 3=SPRITE1???
1258 // 70
1259 2,2,2,2,3,3,3,3,
1260 // 78
1261 2,2,2,2,3,3,3,3,
1262 // 80
1263 4,0,0,0,0,0,0,0,
1264 // 88
1265 0,0,0,0,0,0,0,0,
1266 // 90
1267 0,0,0,0,0,0,0,0,
1268 // 98
1269 0,0,0,0,0,0,0,0,
1270 // a0
1271 3,0,0,0,0,0,0,0,
1272 // a8
1273 0,0,0,0,0,0,0,0,
1274 // b0
1275 0,0,0,0,0,0,0,0,
1276 // b8
1277 0,0,0,0,0,0,0,0,
1278 // c0
1279 3,0,0,0,0,0,0,0,
1280 // c8
1281 0,0,0,0,0,0,0,0,
1282 // d0
1283 0,0,0,0,0,0,0,0,
1284 // d8
1285 0,0,0,0,0,0,0,0,
1286 // e0
1287 0,1,1,1,1,1,1,0,
1288 // e8
1289 0,0,0,0,0,0,0,0,
1290 // f0
1291 0,0,0,0,0,0,0,0,
1292 // f8
1293 0,0,0,0,0,0,0,0
1294};
1295
1296void CALLBACK GPUwriteDataMem(uint32_t * pMem, int iSize)
1297{
1298 unsigned char command;
1299 uint32_t gdata=0;
1300 int i=0;
1301 GPUIsBusy;
1302 GPUIsNotReadyForCommands;
1303
1304STARTVRAM:
1305
1306 if(DataWriteMode==DR_VRAMTRANSFER)
1307 {
1308 BOOL bFinished=FALSE;
1309
1310 // make sure we are in vram
1311 while(VRAMWrite.ImagePtr>=psxVuw_eom)
1312 VRAMWrite.ImagePtr-=iGPUHeight*1024;
1313 while(VRAMWrite.ImagePtr<psxVuw)
1314 VRAMWrite.ImagePtr+=iGPUHeight*1024;
1315
1316 // now do the loop
1317 while(VRAMWrite.ColsRemaining>0)
1318 {
1319 while(VRAMWrite.RowsRemaining>0)
1320 {
1321 if(i>=iSize) {goto ENDVRAM;}
1322 i++;
1323
1324 gdata=GETLE32(pMem); pMem++;
1325
1326 PUTLE16(VRAMWrite.ImagePtr, (unsigned short)gdata); VRAMWrite.ImagePtr++;
1327 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
1328 VRAMWrite.RowsRemaining --;
1329
1330 if(VRAMWrite.RowsRemaining <= 0)
1331 {
1332 VRAMWrite.ColsRemaining--;
1333 if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width
1334 {
1335 gdata=(gdata&0xFFFF)|(((uint32_t)GETLE16(VRAMWrite.ImagePtr))<<16);
1336 FinishedVRAMWrite();
1337 bDoVSyncUpdate=TRUE;
1338 goto ENDVRAM;
1339 }
1340 VRAMWrite.RowsRemaining = VRAMWrite.Width;
1341 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
1342 }
1343
1344 PUTLE16(VRAMWrite.ImagePtr, (unsigned short)(gdata>>16)); VRAMWrite.ImagePtr++;
1345 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
1346 VRAMWrite.RowsRemaining --;
1347 }
1348
1349 VRAMWrite.RowsRemaining = VRAMWrite.Width;
1350 VRAMWrite.ColsRemaining--;
1351 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
1352 bFinished=TRUE;
1353 }
1354
1355 FinishedVRAMWrite();
1356 if(bFinished) bDoVSyncUpdate=TRUE;
1357 }
1358
1359ENDVRAM:
1360
1361 if(DataWriteMode==DR_NORMAL)
1362 {
1363 void (* *primFunc)(unsigned char *);
1364 if(bSkipNextFrame) primFunc=primTableSkip;
1365 else primFunc=primTableJ;
1366
1367 for(;i<iSize;)
1368 {
1369 if(DataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;
1370
1371 gdata=GETLE32(pMem); pMem++; i++;
1372
1373 if(gpuDataC == 0)
1374 {
1375 command = (unsigned char)((gdata>>24) & 0xff);
1376
1377//if(command>=0xb0 && command<0xc0) auxprintf("b0 %x!!!!!!!!!\n",command);
1378
1379 if(primTableCX[command])
1380 {
1381 gpuDataC = primTableCX[command];
1382 gpuCommand = command;
1383 PUTLE32(&gpuDataM[0], gdata);
1384 gpuDataP = 1;
1385 }
1386 else continue;
1387 }
1388 else
1389 {
1390 PUTLE32(&gpuDataM[gpuDataP], gdata);
1391 if(gpuDataC>128)
1392 {
1393 if((gpuDataC==254 && gpuDataP>=3) ||
1394 (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1)))
1395 {
1396 if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000)
1397 gpuDataP=gpuDataC-1;
1398 }
1399 }
1400 gpuDataP++;
1401 }
1402
1403 if(gpuDataP == gpuDataC)
1404 {
1405 gpuDataC=gpuDataP=0;
1406 primFunc[gpuCommand]((unsigned char *)gpuDataM);
1407 if(dwEmuFixes&0x0001 || dwActFixes&0x0400) // hack for emulating "gpu busy" in some games
1408 iFakePrimBusy=4;\r }
1409 }
1410 }
1411
1412 lGPUdataRet=gdata;
1413
1414 GPUIsReadyForCommands;
1415 GPUIsIdle;
1416}
1417
1418////////////////////////////////////////////////////////////////////////
1419
1420void CALLBACK GPUwriteData(uint32_t gdata)
1421{
1422 PUTLE32(&gdata, gdata);
1423 GPUwriteDataMem(&gdata,1);
1424}
1425
1426////////////////////////////////////////////////////////////////////////
1427// this functions will be removed soon (or 'soonish')... not really needed, but some emus want them
1428////////////////////////////////////////////////////////////////////////
1429
1430void CALLBACK GPUsetMode(unsigned long gdata)
1431{
1432// Peops does nothing here...
1433// DataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL;
1434// DataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL;
1435}
1436
1437long CALLBACK GPUgetMode(void)
1438{
1439 long iT=0;
1440
1441 if(DataWriteMode==DR_VRAMTRANSFER) iT|=0x1;
1442 if(DataReadMode ==DR_VRAMTRANSFER) iT|=0x2;
1443 return iT;
1444}
1445
1446////////////////////////////////////////////////////////////////////////
1447// call config dlg
1448////////////////////////////////////////////////////////////////////////
1449
1450long CALLBACK GPUconfigure(void)
1451{
1452 SoftDlgProc();
1453
1454 return 0;
1455}
1456
1457////////////////////////////////////////////////////////////////////////
1458// sets all kind of act fixes
1459////////////////////////////////////////////////////////////////////////
1460
1461void SetFixes(void)
1462 {
1463 if(dwActFixes&0x02) sDispWidths[4]=384;
1464 else sDispWidths[4]=368;
1465 }
1466
1467////////////////////////////////////////////////////////////////////////
1468// process gpu commands
1469////////////////////////////////////////////////////////////////////////
1470
1471unsigned long lUsedAddr[3];
1472
1473__inline BOOL CheckForEndlessLoop(unsigned long laddr)
1474{
1475 if(laddr==lUsedAddr[1]) return TRUE;
1476 if(laddr==lUsedAddr[2]) return TRUE;
1477
1478 if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
1479 else lUsedAddr[2]=laddr;
1480 lUsedAddr[0]=laddr;
1481 return FALSE;
1482}
1483
1484long CALLBACK GPUdmaChain(uint32_t * baseAddrL, uint32_t addr)
1485{
1486 uint32_t dmaMem;
1487 unsigned char * baseAddrB;
1488 short count;unsigned int DMACommandCounter = 0;
1489
1490 GPUIsBusy;
1491
1492 lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;
1493
1494 baseAddrB = (unsigned char*) baseAddrL;
1495
1496 do
1497 {
1498 if(iGPUHeight==512) addr&=0x1FFFFC;
1499 if(DMACommandCounter++ > 2000000) break;
1500 if(CheckForEndlessLoop(addr)) break;
1501
1502 count = baseAddrB[addr+3];
1503
1504 dmaMem=addr+4;
1505
1506 if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
1507
1508 addr = GETLE32(&baseAddrL[addr>>2])&0xffffff;
1509 }
1510 while (addr != 0xffffff);
1511
1512 GPUIsIdle;
1513
1514 return 0;
1515}
1516
1517////////////////////////////////////////////////////////////////////////
1518// show about dlg
1519////////////////////////////////////////////////////////////////////////
1520
1521
1522void CALLBACK GPUabout(void) // ABOUT
1523{
1524 AboutDlgProc();
1525 return;
1526}
1527
1528////////////////////////////////////////////////////////////////////////
1529// We are ever fine ;)
1530////////////////////////////////////////////////////////////////////////
1531
1532long CALLBACK GPUtest(void)
1533{
1534 // if test fails this function should return negative value for error (unable to continue)
1535 // and positive value for warning (can continue but output might be crappy)
1536 return 0;
1537}
1538
1539////////////////////////////////////////////////////////////////////////
1540// Freeze
1541////////////////////////////////////////////////////////////////////////
1542
1543typedef struct GPUFREEZETAG
1544{
1545 uint32_t ulFreezeVersion; // should be always 1 for now (set by main emu)
1546 uint32_t ulStatus; // current gpu status
1547 uint32_t ulControl[256]; // latest control register values
1548 unsigned char psxVRam[1024*1024*2]; // current VRam image (full 2 MB for ZN)
1549} GPUFreeze_t;
1550
1551////////////////////////////////////////////////////////////////////////
1552
1553long CALLBACK GPUfreeze(uint32_t ulGetFreezeData,GPUFreeze_t * pF)
1554{
1555 //----------------------------------------------------//
1556 if(ulGetFreezeData==2) // 2: info, which save slot is selected? (just for display)
1557 {
1558 long lSlotNum=*((long *)pF);
1559 if(lSlotNum<0) return 0;
1560 if(lSlotNum>8) return 0;
1561 lSelectedSlot=lSlotNum+1;
1562 BuildDispMenu(0);
1563 return 1;
1564 }
1565 //----------------------------------------------------//
1566 if(!pF) return 0; // some checks
1567 if(pF->ulFreezeVersion!=1) return 0;
1568
1569 if(ulGetFreezeData==1) // 1: get data
1570 {
1571 pF->ulStatus=lGPUstatusRet;
1572 memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t));
1573 memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2);
1574
1575 return 1;
1576 }
1577
1578 if(ulGetFreezeData!=0) return 0; // 0: set data
1579
1580 lGPUstatusRet=pF->ulStatus;
1581 memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t));
1582 memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2);
1583
1584// RESET TEXTURE STORE HERE, IF YOU USE SOMETHING LIKE THAT
1585
1586 GPUwriteStatus(ulStatusControl[0]);
1587 GPUwriteStatus(ulStatusControl[1]);
1588 GPUwriteStatus(ulStatusControl[2]);
1589 GPUwriteStatus(ulStatusControl[3]);
1590 GPUwriteStatus(ulStatusControl[8]); // try to repair things
1591 GPUwriteStatus(ulStatusControl[6]);
1592 GPUwriteStatus(ulStatusControl[7]);
1593 GPUwriteStatus(ulStatusControl[5]);
1594 GPUwriteStatus(ulStatusControl[4]);
1595
1596 return 1;
1597}
1598
1599////////////////////////////////////////////////////////////////////////
1600////////////////////////////////////////////////////////////////////////
1601////////////////////////////////////////////////////////////////////////
1602////////////////////////////////////////////////////////////////////////
1603////////////////////////////////////////////////////////////////////////
1604////////////////////////////////////////////////////////////////////////
1605
1606////////////////////////////////////////////////////////////////////////
1607// SAVE STATE DISPLAY STUFF
1608////////////////////////////////////////////////////////////////////////
1609
1610// font 0-9, 24x20 pixels, 1 byte = 4 dots
1611// 00 = black
1612// 01 = white
1613// 10 = red
1614// 11 = transparent
1615
1616unsigned char cFont[10][120]=
1617{
1618// 0
1619{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1620 0x80,0x00,0x00,0x00,0x00,0x00,
1621 0x80,0x00,0x00,0x00,0x00,0x00,
1622 0x80,0x00,0x00,0x00,0x00,0x00,
1623 0x80,0x00,0x00,0x00,0x00,0x00,
1624 0x80,0x00,0x05,0x54,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,0x14,0x05,0x00,0x00,
1632 0x80,0x00,0x14,0x05,0x00,0x00,
1633 0x80,0x00,0x05,0x54,0x00,0x00,
1634 0x80,0x00,0x00,0x00,0x00,0x00,
1635 0x80,0x00,0x00,0x00,0x00,0x00,
1636 0x80,0x00,0x00,0x00,0x00,0x00,
1637 0x80,0x00,0x00,0x00,0x00,0x00,
1638 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1639},
1640// 1
1641{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1642 0x80,0x00,0x00,0x00,0x00,0x00,
1643 0x80,0x00,0x00,0x00,0x00,0x00,
1644 0x80,0x00,0x00,0x00,0x00,0x00,
1645 0x80,0x00,0x00,0x00,0x00,0x00,
1646 0x80,0x00,0x00,0x50,0x00,0x00,
1647 0x80,0x00,0x05,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,0x00,0x50,0x00,0x00,
1654 0x80,0x00,0x00,0x50,0x00,0x00,
1655 0x80,0x00,0x05,0x55,0x00,0x00,
1656 0x80,0x00,0x00,0x00,0x00,0x00,
1657 0x80,0x00,0x00,0x00,0x00,0x00,
1658 0x80,0x00,0x00,0x00,0x00,0x00,
1659 0x80,0x00,0x00,0x00,0x00,0x00,
1660 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1661},
1662// 2
1663{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1664 0x80,0x00,0x00,0x00,0x00,0x00,
1665 0x80,0x00,0x00,0x00,0x00,0x00,
1666 0x80,0x00,0x00,0x00,0x00,0x00,
1667 0x80,0x00,0x00,0x00,0x00,0x00,
1668 0x80,0x00,0x05,0x54,0x00,0x00,
1669 0x80,0x00,0x14,0x05,0x00,0x00,
1670 0x80,0x00,0x00,0x05,0x00,0x00,
1671 0x80,0x00,0x00,0x05,0x00,0x00,
1672 0x80,0x00,0x00,0x14,0x00,0x00,
1673 0x80,0x00,0x00,0x50,0x00,0x00,
1674 0x80,0x00,0x01,0x40,0x00,0x00,
1675 0x80,0x00,0x05,0x00,0x00,0x00,
1676 0x80,0x00,0x14,0x00,0x00,0x00,
1677 0x80,0x00,0x15,0x55,0x00,0x00,
1678 0x80,0x00,0x00,0x00,0x00,0x00,
1679 0x80,0x00,0x00,0x00,0x00,0x00,
1680 0x80,0x00,0x00,0x00,0x00,0x00,
1681 0x80,0x00,0x00,0x00,0x00,0x00,
1682 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1683},
1684// 3
1685{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1686 0x80,0x00,0x00,0x00,0x00,0x00,
1687 0x80,0x00,0x00,0x00,0x00,0x00,
1688 0x80,0x00,0x00,0x00,0x00,0x00,
1689 0x80,0x00,0x00,0x00,0x00,0x00,
1690 0x80,0x00,0x05,0x54,0x00,0x00,
1691 0x80,0x00,0x14,0x05,0x00,0x00,
1692 0x80,0x00,0x00,0x05,0x00,0x00,
1693 0x80,0x00,0x00,0x05,0x00,0x00,
1694 0x80,0x00,0x01,0x54,0x00,0x00,
1695 0x80,0x00,0x00,0x05,0x00,0x00,
1696 0x80,0x00,0x00,0x05,0x00,0x00,
1697 0x80,0x00,0x00,0x05,0x00,0x00,
1698 0x80,0x00,0x14,0x05,0x00,0x00,
1699 0x80,0x00,0x05,0x54,0x00,0x00,
1700 0x80,0x00,0x00,0x00,0x00,0x00,
1701 0x80,0x00,0x00,0x00,0x00,0x00,
1702 0x80,0x00,0x00,0x00,0x00,0x00,
1703 0x80,0x00,0x00,0x00,0x00,0x00,
1704 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1705},
1706// 4
1707{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1708 0x80,0x00,0x00,0x00,0x00,0x00,
1709 0x80,0x00,0x00,0x00,0x00,0x00,
1710 0x80,0x00,0x00,0x00,0x00,0x00,
1711 0x80,0x00,0x00,0x00,0x00,0x00,
1712 0x80,0x00,0x00,0x14,0x00,0x00,
1713 0x80,0x00,0x00,0x54,0x00,0x00,
1714 0x80,0x00,0x01,0x54,0x00,0x00,
1715 0x80,0x00,0x01,0x54,0x00,0x00,
1716 0x80,0x00,0x05,0x14,0x00,0x00,
1717 0x80,0x00,0x14,0x14,0x00,0x00,
1718 0x80,0x00,0x15,0x55,0x00,0x00,
1719 0x80,0x00,0x00,0x14,0x00,0x00,
1720 0x80,0x00,0x00,0x14,0x00,0x00,
1721 0x80,0x00,0x00,0x55,0x00,0x00,
1722 0x80,0x00,0x00,0x00,0x00,0x00,
1723 0x80,0x00,0x00,0x00,0x00,0x00,
1724 0x80,0x00,0x00,0x00,0x00,0x00,
1725 0x80,0x00,0x00,0x00,0x00,0x00,
1726 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1727},
1728// 5
1729{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1730 0x80,0x00,0x00,0x00,0x00,0x00,
1731 0x80,0x00,0x00,0x00,0x00,0x00,
1732 0x80,0x00,0x00,0x00,0x00,0x00,
1733 0x80,0x00,0x00,0x00,0x00,0x00,
1734 0x80,0x00,0x15,0x55,0x00,0x00,
1735 0x80,0x00,0x14,0x00,0x00,0x00,
1736 0x80,0x00,0x14,0x00,0x00,0x00,
1737 0x80,0x00,0x14,0x00,0x00,0x00,
1738 0x80,0x00,0x15,0x54,0x00,0x00,
1739 0x80,0x00,0x00,0x05,0x00,0x00,
1740 0x80,0x00,0x00,0x05,0x00,0x00,
1741 0x80,0x00,0x00,0x05,0x00,0x00,
1742 0x80,0x00,0x14,0x05,0x00,0x00,
1743 0x80,0x00,0x05,0x54,0x00,0x00,
1744 0x80,0x00,0x00,0x00,0x00,0x00,
1745 0x80,0x00,0x00,0x00,0x00,0x00,
1746 0x80,0x00,0x00,0x00,0x00,0x00,
1747 0x80,0x00,0x00,0x00,0x00,0x00,
1748 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1749},
1750// 6
1751{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1752 0x80,0x00,0x00,0x00,0x00,0x00,
1753 0x80,0x00,0x00,0x00,0x00,0x00,
1754 0x80,0x00,0x00,0x00,0x00,0x00,
1755 0x80,0x00,0x00,0x00,0x00,0x00,
1756 0x80,0x00,0x01,0x54,0x00,0x00,
1757 0x80,0x00,0x05,0x00,0x00,0x00,
1758 0x80,0x00,0x14,0x00,0x00,0x00,
1759 0x80,0x00,0x14,0x00,0x00,0x00,
1760 0x80,0x00,0x15,0x54,0x00,0x00,
1761 0x80,0x00,0x15,0x05,0x00,0x00,
1762 0x80,0x00,0x14,0x05,0x00,0x00,
1763 0x80,0x00,0x14,0x05,0x00,0x00,
1764 0x80,0x00,0x14,0x05,0x00,0x00,
1765 0x80,0x00,0x05,0x54,0x00,0x00,
1766 0x80,0x00,0x00,0x00,0x00,0x00,
1767 0x80,0x00,0x00,0x00,0x00,0x00,
1768 0x80,0x00,0x00,0x00,0x00,0x00,
1769 0x80,0x00,0x00,0x00,0x00,0x00,
1770 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1771},
1772// 7
1773{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1774 0x80,0x00,0x00,0x00,0x00,0x00,
1775 0x80,0x00,0x00,0x00,0x00,0x00,
1776 0x80,0x00,0x00,0x00,0x00,0x00,
1777 0x80,0x00,0x00,0x00,0x00,0x00,
1778 0x80,0x00,0x15,0x55,0x00,0x00,
1779 0x80,0x00,0x14,0x05,0x00,0x00,
1780 0x80,0x00,0x00,0x14,0x00,0x00,
1781 0x80,0x00,0x00,0x14,0x00,0x00,
1782 0x80,0x00,0x00,0x50,0x00,0x00,
1783 0x80,0x00,0x00,0x50,0x00,0x00,
1784 0x80,0x00,0x01,0x40,0x00,0x00,
1785 0x80,0x00,0x01,0x40,0x00,0x00,
1786 0x80,0x00,0x05,0x00,0x00,0x00,
1787 0x80,0x00,0x05,0x00,0x00,0x00,
1788 0x80,0x00,0x00,0x00,0x00,0x00,
1789 0x80,0x00,0x00,0x00,0x00,0x00,
1790 0x80,0x00,0x00,0x00,0x00,0x00,
1791 0x80,0x00,0x00,0x00,0x00,0x00,
1792 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1793},
1794// 8
1795{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1796 0x80,0x00,0x00,0x00,0x00,0x00,
1797 0x80,0x00,0x00,0x00,0x00,0x00,
1798 0x80,0x00,0x00,0x00,0x00,0x00,
1799 0x80,0x00,0x00,0x00,0x00,0x00,
1800 0x80,0x00,0x05,0x54,0x00,0x00,
1801 0x80,0x00,0x14,0x05,0x00,0x00,
1802 0x80,0x00,0x14,0x05,0x00,0x00,
1803 0x80,0x00,0x14,0x05,0x00,0x00,
1804 0x80,0x00,0x05,0x54,0x00,0x00,
1805 0x80,0x00,0x14,0x05,0x00,0x00,
1806 0x80,0x00,0x14,0x05,0x00,0x00,
1807 0x80,0x00,0x14,0x05,0x00,0x00,
1808 0x80,0x00,0x14,0x05,0x00,0x00,
1809 0x80,0x00,0x05,0x54,0x00,0x00,
1810 0x80,0x00,0x00,0x00,0x00,0x00,
1811 0x80,0x00,0x00,0x00,0x00,0x00,
1812 0x80,0x00,0x00,0x00,0x00,0x00,
1813 0x80,0x00,0x00,0x00,0x00,0x00,
1814 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1815},
1816// 9
1817{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
1818 0x80,0x00,0x00,0x00,0x00,0x00,
1819 0x80,0x00,0x00,0x00,0x00,0x00,
1820 0x80,0x00,0x00,0x00,0x00,0x00,
1821 0x80,0x00,0x00,0x00,0x00,0x00,
1822 0x80,0x00,0x05,0x54,0x00,0x00,
1823 0x80,0x00,0x14,0x05,0x00,0x00,
1824 0x80,0x00,0x14,0x05,0x00,0x00,
1825 0x80,0x00,0x14,0x05,0x00,0x00,
1826 0x80,0x00,0x14,0x15,0x00,0x00,
1827 0x80,0x00,0x05,0x55,0x00,0x00,
1828 0x80,0x00,0x00,0x05,0x00,0x00,
1829 0x80,0x00,0x00,0x05,0x00,0x00,
1830 0x80,0x00,0x00,0x14,0x00,0x00,
1831 0x80,0x00,0x05,0x50,0x00,0x00,
1832 0x80,0x00,0x00,0x00,0x00,0x00,
1833 0x80,0x00,0x00,0x00,0x00,0x00,
1834 0x80,0x00,0x00,0x00,0x00,0x00,
1835 0x80,0x00,0x00,0x00,0x00,0x00,
1836 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
1837}
1838};
1839
1840////////////////////////////////////////////////////////////////////////
1841
1842void PaintPicDot(unsigned char * p,unsigned char c)
1843{
1844
1845 if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;} // black
1846 if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;} // white
1847 if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;} // red
1848 // transparent
1849}
1850
1851////////////////////////////////////////////////////////////////////////
1852// the main emu allocs 128x96x3 bytes, and passes a ptr
1853// to it in pMem... the plugin has to fill it with
1854// 8-8-8 bit BGR screen data (Win 24 bit BMP format
1855// without header).
1856// Beware: the func can be called at any time,
1857// so you have to use the frontbuffer to get a fully
1858// rendered picture
1859
1860// LINUX version:
1861
1862extern char * Xpixels;
1863
1864void GPUgetScreenPic(unsigned char * pMem)
1865{
1866/*
1867 unsigned short c;unsigned char * pf;int x,y;
1868
1869 float XS=(float)iResX/128;
1870 float YS=(float)iResY/96;
1871
1872 pf=pMem;
1873 memset(pMem, 0, 128*96*3);
1874
1875 if(Xpixels)
1876 {
1877 unsigned char * ps=(unsigned char *)Xpixels;
1878 {
1879 long lPitch=iResX<<2;
1880 uint32_t sx;
1881
1882 for(y=0;y<96;y++)
1883 {
1884 for(x=0;x<128;x++)
1885 {
1886 sx=*((uint32_t *)((ps)+
1887 (((int)((float)y*YS))*lPitch)+
1888 ((int)((float)x*XS))*4));
1889 *(pf+0)=(sx&0xff);
1890 *(pf+1)=(sx&0xff00)>>8;
1891 *(pf+2)=(sx&0xff0000)>>16;
1892 pf+=3;
1893 }
1894 }
1895 }
1896 }
1897
1898
1899 /////////////////////////////////////////////////////////////////////
1900 // generic number/border painter
1901
1902 pf=pMem+(103*3); // offset to number rect
1903
1904 for(y=0;y<20;y++) // loop the number rect pixel
1905 {
1906 for(x=0;x<6;x++)
1907 {
1908 c=cFont[lSelectedSlot][x+y*6]; // get 4 char dot infos at once (number depends on selected slot)
1909 PaintPicDot(pf,(c&0xc0)>>6);pf+=3; // paint the dots into the rect
1910 PaintPicDot(pf,(c&0x30)>>4);pf+=3;
1911 PaintPicDot(pf,(c&0x0c)>>2);pf+=3;
1912 PaintPicDot(pf,(c&0x03)); pf+=3;
1913 }
1914 pf+=104*3; // next rect y line
1915 }
1916
1917 pf=pMem; // ptr to first pos in 128x96 pic
1918 for(x=0;x<128;x++) // loop top/bottom line
1919 {
1920 *(pf+(95*128*3))=0x00;*pf++=0x00;
1921 *(pf+(95*128*3))=0x00;*pf++=0x00; // paint it red
1922 *(pf+(95*128*3))=0xff;*pf++=0xff;
1923 }
1924 pf=pMem; // ptr to first pos
1925 for(y=0;y<96;y++) // loop left/right line
1926 {
1927 *(pf+(127*3))=0x00;*pf++=0x00;
1928 *(pf+(127*3))=0x00;*pf++=0x00; // paint it red
1929 *(pf+(127*3))=0xff;*pf++=0xff;
1930 pf+=127*3; // offset to next line
1931 }
1932*/
1933}
1934
1935
1936////////////////////////////////////////////////////////////////////////
1937// func will be called with 128x96x3 BGR data.
1938// the plugin has to store the data and display
1939// it in the upper right corner.
1940// If the func is called with a NULL ptr, you can
1941// release your picture data and stop displaying
1942// the screen pic
1943
1944void CALLBACK GPUshowScreenPic(unsigned char * pMem)
1945{
1946 DestroyPic(); // destroy old pic data
1947 if(pMem==0) return; // done
1948 CreatePic(pMem); // create new pic... don't free pMem or something like that... just read from it
1949}
1950
1951void CALLBACK GPUsetfix(uint32_t dwFixBits)
1952{
1953 dwEmuFixes=dwFixBits;
1954}