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