1 /*
2 Copyright (C) 2002 Rice1964
3 Copyright (C) 2009-2011 Richard Goedeken
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21 #include <vector>
22
23 #include <stdarg.h>
24 #include <stdlib.h>
25
26 #include "osal_opengl.h"
27
28 #define M64P_PLUGIN_PROTOTYPES 1
29 #include "m64p_types.h"
30 #include "m64p_common.h"
31 #include "m64p_plugin.h"
32
33 #include "Config.h"
34 #include "Debugger.h"
35 #include "DeviceBuilder.h"
36 #include "FrameBuffer.h"
37 #include "GraphicsContext.h"
38 #include "Render.h"
39 #include "RSP_Parser.h"
40 #include "TextureManager.h"
41 #include "Video.h"
42 #include "version.h"
43
44 //=======================================================
45 // local variables
46
47 static void (*l_DebugCallback)(void *, int, const char *) = NULL;
48 static void *l_DebugCallContext = NULL;
49 static int l_PluginInit = 0;
50
51 //=======================================================
52 // global variables
53
54 PluginStatus status;
55
56 unsigned int g_dwRamSize = 0x400000;
57
58 M64P_RECT frameWriteByCPURect;
59 std::vector<M64P_RECT> frameWriteByCPURects;
60 M64P_RECT frameWriteByCPURectArray[20][20];
61 bool frameWriteByCPURectFlag[20][20];
62 std::vector<uint32_t> frameWriteRecord;
63
64 void (*renderCallback)(int) = NULL;
65
66 // Forward function declarations
67
68 extern "C" void riceRomClosed(void);
69
StartVideo(void)70 static bool StartVideo(void)
71 {
72 windowSetting.dps = windowSetting.fps = -1;
73 windowSetting.lastSecDlistCount = windowSetting.lastSecFrameCount = 0xFFFFFFFF;
74
75 memcpy(&g_curRomInfo.romheader, gfx_info.HEADER, sizeof(ROMHeader));
76 unsigned char *puc = (unsigned char *) &g_curRomInfo.romheader;
77 unsigned int i;
78 unsigned char temp;
79 for (i = 0; i < sizeof(ROMHeader); i += 4) /* byte-swap the ROM header */
80 {
81 temp = puc[i];
82 puc[i] = puc[i+3];
83 puc[i+3] = temp;
84 temp = puc[i+1];
85 puc[i+1] = puc[i+2];
86 puc[i+2] = temp;
87 }
88
89 ROM_GetRomNameFromHeader(g_curRomInfo.szGameName, &g_curRomInfo.romheader);
90 Ini_GetRomOptions(&g_curRomInfo);
91 char *p = (char *) g_curRomInfo.szGameName + (strlen((char *) g_curRomInfo.szGameName) -1); // -1 to skip null
92 while (p >= (char *) g_curRomInfo.szGameName)
93 {
94 if( *p == ':' || *p == '\\' || *p == '/' )
95 *p = '-';
96 p--;
97 }
98
99 GenerateCurrentRomOptions();
100 status.dwTvSystem = CountryCodeToTVSystem(g_curRomInfo.romheader.nCountryID);
101 if( status.dwTvSystem == TV_SYSTEM_NTSC )
102 status.fRatio = 0.75f;
103 else
104 status.fRatio = 9/11.0f;;
105
106 CDeviceBuilder::GetBuilder()->CreateGraphicsContext();
107 CGraphicsContext::InitWindowInfo();
108
109 bool res = CGraphicsContext::Get()->Initialize(windowSetting.uDisplayWidth, windowSetting.uDisplayHeight);
110 if (!res)
111 {
112 return false;
113 }
114 CDeviceBuilder::GetBuilder()->CreateRender();
115 CRender::GetRender()->Initialize();
116 DLParser_Init();
117 status.bGameIsRunning = true;
118
119 return true;
120 }
121
122 //---------------------------------------------------------------------------------------
123 // Global functions, for use by other source files in this plugin
124
SetVIScales()125 void SetVIScales()
126 {
127 if( g_curRomInfo.VIHeight>0 && g_curRomInfo.VIWidth>0 )
128 {
129 windowSetting.fViWidth = windowSetting.uViWidth = g_curRomInfo.VIWidth;
130 windowSetting.fViHeight = windowSetting.uViHeight = g_curRomInfo.VIHeight;
131 }
132 else if( g_curRomInfo.UseCIWidthAndRatio && g_CI.dwWidth )
133 {
134 windowSetting.fViWidth = windowSetting.uViWidth = g_CI.dwWidth;
135 windowSetting.fViHeight = windowSetting.uViHeight =
136 g_curRomInfo.UseCIWidthAndRatio == USE_CI_WIDTH_AND_RATIO_FOR_NTSC ? g_CI.dwWidth/4*3 : g_CI.dwWidth/11*9;
137 }
138 else
139 {
140 float xscale, yscale;
141 uint32_t val = *gfx_info.VI_X_SCALE_REG & 0xFFF;
142 xscale = (float)val / (1<<10);
143 uint32_t start = *gfx_info.VI_H_START_REG >> 16;
144 uint32_t end = *gfx_info.VI_H_START_REG&0xFFFF;
145 uint32_t width = *gfx_info.VI_WIDTH_REG;
146 windowSetting.fViWidth = (end-start)*xscale;
147 if( abs((int)(windowSetting.fViWidth - width) ) < 8 )
148 {
149 windowSetting.fViWidth = (float)width;
150 }
151 else
152 {
153 DebuggerAppendMsg("fViWidth = %f, Width Reg=%d", windowSetting.fViWidth, width);
154 }
155
156 val = (*gfx_info.VI_Y_SCALE_REG & 0xFFF);// - ((*gfx_info.VI_Y_SCALE_REG>>16) & 0xFFF);
157 if( val == 0x3FF ) val = 0x400;
158 yscale = (float)val / (1<<10);
159 start = *gfx_info.VI_V_START_REG >> 16;
160 end = *gfx_info.VI_V_START_REG&0xFFFF;
161 windowSetting.fViHeight = (end-start)/2*yscale;
162
163 if( yscale == 0 )
164 {
165 windowSetting.fViHeight = windowSetting.fViWidth*status.fRatio;
166 }
167 else
168 {
169 if( *gfx_info.VI_WIDTH_REG > 0x300 )
170 windowSetting.fViHeight *= 2;
171
172 if( windowSetting.fViWidth*status.fRatio > windowSetting.fViHeight && (*gfx_info.VI_X_SCALE_REG & 0xFF) != 0 )
173 {
174 if( abs(int(windowSetting.fViWidth*status.fRatio - windowSetting.fViHeight)) < 8 )
175 {
176 windowSetting.fViHeight = windowSetting.fViWidth*status.fRatio;
177 }
178 /*
179 else
180 {
181 if( abs(windowSetting.fViWidth*status.fRatio-windowSetting.fViHeight) > windowSetting.fViWidth*0.1f )
182 {
183 if( status.fRatio > 0.8 )
184 windowSetting.fViHeight = windowSetting.fViWidth*3/4;
185 //windowSetting.fViHeight = (*gfx_info.VI_V_SYNC_REG - 0x2C)/2;
186 }
187 }
188 */
189 }
190
191 if( windowSetting.fViHeight<100 || windowSetting.fViWidth<100 )
192 {
193 //At sometime, value in VI_H_START_REG or VI_V_START_REG are 0
194 windowSetting.fViWidth = (float)*gfx_info.VI_WIDTH_REG;
195 windowSetting.fViHeight = windowSetting.fViWidth*status.fRatio;
196 }
197 }
198
199 windowSetting.uViWidth = (unsigned short)(windowSetting.fViWidth/4);
200 windowSetting.fViWidth = windowSetting.uViWidth *= 4;
201
202 windowSetting.uViHeight = (unsigned short)(windowSetting.fViHeight/4);
203 windowSetting.fViHeight = windowSetting.uViHeight *= 4;
204 uint16_t optimizeHeight = (uint16_t)(windowSetting.uViWidth*status.fRatio);
205 optimizeHeight &= ~3;
206
207 uint16_t optimizeHeight2 = (uint16_t)(windowSetting.uViWidth*3/4);
208 optimizeHeight2 &= ~3;
209
210 if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 )
211 {
212 if( abs(windowSetting.uViHeight-optimizeHeight) <= 8 )
213 windowSetting.fViHeight = windowSetting.uViHeight = optimizeHeight;
214 else if( abs(windowSetting.uViHeight-optimizeHeight2) <= 8 )
215 windowSetting.fViHeight = windowSetting.uViHeight = optimizeHeight2;
216 }
217
218
219 if( gRDP.scissor.left == 0 && gRDP.scissor.top == 0 && gRDP.scissor.right != 0 )
220 {
221 if( (*gfx_info.VI_X_SCALE_REG & 0xFF) != 0x0 && gRDP.scissor.right == windowSetting.uViWidth )
222 {
223 // Mario Tennis
224 if( abs(int( windowSetting.fViHeight - gRDP.scissor.bottom )) < 8 )
225 {
226 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom;
227 }
228 else if( windowSetting.fViHeight < gRDP.scissor.bottom )
229 {
230 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom;
231 }
232 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom;
233 }
234 else if( gRDP.scissor.right == windowSetting.uViWidth - 1 && gRDP.scissor.bottom != 0 )
235 {
236 if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 )
237 {
238 if( status.fRatio != 0.75 && windowSetting.fViHeight > optimizeHeight/2 )
239 {
240 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom + gRDP.scissor.top + 1;
241 }
242 }
243 }
244 else if( gRDP.scissor.right == windowSetting.uViWidth && gRDP.scissor.bottom != 0 && status.fRatio != 0.75 )
245 {
246 if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 )
247 {
248 if( status.fRatio != 0.75 && windowSetting.fViHeight > optimizeHeight/2 )
249 {
250 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom + gRDP.scissor.top + 1;
251 }
252 }
253 }
254 }
255 }
256 SetScreenMult(windowSetting.uDisplayWidth/windowSetting.fViWidth, windowSetting.uDisplayHeight/windowSetting.fViHeight);
257 }
258
TriggerDPInterrupt(void)259 void TriggerDPInterrupt(void)
260 {
261 *(gfx_info.MI_INTR_REG) |= MI_INTR_DP;
262 gfx_info.CheckInterrupts();
263 }
264
TriggerSPInterrupt(void)265 void TriggerSPInterrupt(void)
266 {
267 *(gfx_info.MI_INTR_REG) |= MI_INTR_SP;
268 gfx_info.CheckInterrupts();
269 }
270
_VIDEO_DisplayTemporaryMessage(const char * Message)271 void _VIDEO_DisplayTemporaryMessage(const char *Message)
272 {
273 }
274
DebugMessage(int level,const char * message,...)275 void DebugMessage(int level, const char *message, ...)
276 {
277 char msgbuf[1024];
278 va_list args;
279
280 if (l_DebugCallback == NULL)
281 return;
282
283 va_start(args, message);
284 vsprintf(msgbuf, message, args);
285
286 (*l_DebugCallback)(l_DebugCallContext, level, msgbuf);
287
288 va_end(args);
289 }
290
291 //---------------------------------------------------------------------------------------
292 // Global functions, exported for use by the core library
293
294 // since these functions are exported, they need to have C-style names
295 #ifdef __cplusplus
296 extern "C" {
297 #endif
298
299 /* Mupen64Plus plugin functions */
ricePluginStartup(m64p_dynlib_handle CoreLibHandle,void * Context,void (* DebugCallback)(void *,int,const char *))300 m64p_error ricePluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
301 void (*DebugCallback)(void *, int, const char *))
302 {
303 if (l_PluginInit)
304 return M64ERR_ALREADY_INIT;
305
306 /* first thing is to set the callback function for debug info */
307 l_DebugCallback = DebugCallback;
308 l_DebugCallContext = Context;
309
310 /* open config section handles and set parameter default values */
311 if (!InitConfiguration())
312 return M64ERR_INTERNAL;
313
314 l_PluginInit = 1;
315 return M64ERR_SUCCESS;
316 }
317
ricePluginShutdown(void)318 m64p_error ricePluginShutdown(void)
319 {
320 if (!l_PluginInit)
321 return M64ERR_NOT_INIT;
322
323 if( status.bGameIsRunning )
324 {
325 riceRomClosed();
326 }
327 #if 0
328 if (bIniIsChanged)
329 {
330 WriteIniFile();
331 TRACE0("Write back INI file");
332 }
333 #endif
334
335 /* reset some local variables */
336 l_DebugCallback = NULL;
337 l_DebugCallContext = NULL;
338
339 l_PluginInit = 0;
340 return M64ERR_SUCCESS;
341 }
342
ricePluginGetVersion(m64p_plugin_type * PluginType,int * PluginVersion,int * APIVersion,const char ** PluginNamePtr,int * Capabilities)343 m64p_error ricePluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
344 {
345 /* set version info */
346 if (PluginType != NULL)
347 *PluginType = M64PLUGIN_GFX;
348
349 if (PluginVersion != NULL)
350 *PluginVersion = PLUGIN_VERSION;
351
352 if (APIVersion != NULL)
353 *APIVersion = VIDEO_PLUGIN_API_VERSION;
354
355 if (PluginNamePtr != NULL)
356 *PluginNamePtr = PLUGIN_NAME;
357
358 if (Capabilities != NULL)
359 {
360 *Capabilities = 0;
361 }
362
363 return M64ERR_SUCCESS;
364 }
365
riceChangeWindow(void)366 void riceChangeWindow (void)
367 {
368 }
369
riceMoveScreen(int xpos,int ypos)370 void riceMoveScreen (int xpos, int ypos)
371 {
372 }
373
riceRomClosed(void)374 void riceRomClosed(void)
375 {
376 TRACE0("To stop video");
377 Ini_StoreRomOptions(&g_curRomInfo);
378
379 status.bGameIsRunning = false;
380
381 // Kill all textures?
382 gTextureManager.RecycleAllTextures();
383 gTextureManager.CleanUp();
384 RDP_Cleanup();
385
386 CDeviceBuilder::GetBuilder()->DeleteRender();
387 CGraphicsContext::Get()->CleanUp();
388 CDeviceBuilder::GetBuilder()->DeleteGraphicsContext();
389
390 windowSetting.dps = windowSetting.fps = -1;
391 windowSetting.lastSecDlistCount = windowSetting.lastSecFrameCount = 0xFFFFFFFF;
392 status.gDlistCount = status.gFrameCount = 0;
393
394 TRACE0("Video is stopped");
395 }
396
riceRomOpen(void)397 int riceRomOpen(void)
398 {
399 /* Read RiceVideoLinux.ini file, set up internal variables by reading values from core configuration API */
400 LoadConfiguration();
401
402 status.bDisableFPS=false;
403
404 g_dwRamSize = 0x800000;
405
406 #ifdef DEBUGGER
407 if( debuggerPause )
408 {
409 debuggerPause = false;
410 usleep(100 * 1000);
411 }
412 #endif
413
414 if (!StartVideo())
415 return 0;
416
417 return 1;
418 }
419
riceUpdateScreen(void)420 void riceUpdateScreen(void)
421 {
422 status.bVIOriginIsUpdated = false;
423
424 if (status.ToResize && status.gDlistCount > 0)
425 {
426 // Delete all OpenGL textures
427 gTextureManager.CleanUp();
428 RDP_Cleanup();
429 // delete our opengl renderer
430 CDeviceBuilder::GetBuilder()->DeleteRender();
431
432 // call video extension function with updated width, height (this creates a new OpenGL context)
433 windowSetting.uDisplayWidth = status.gNewResizeWidth;
434 windowSetting.uDisplayHeight = status.gNewResizeHeight;
435 //CoreVideo_ResizeWindow(windowSetting.uDisplayWidth, windowSetting.uDisplayHeight);
436
437 // re-initialize our OpenGL graphics context state
438 bool res = CGraphicsContext::Get()->ResizeInitialize(windowSetting.uDisplayWidth, windowSetting.uDisplayHeight);
439 if (res)
440 {
441 // re-create the OpenGL renderer
442 CDeviceBuilder::GetBuilder()->CreateRender();
443 CRender::GetRender()->Initialize();
444 DLParser_Init();
445 }
446
447 status.ToResize = false;
448 return;
449 }
450
451 if( status.bHandleN64RenderTexture )
452 g_pFrameBufferManager->CloseRenderTexture(true);
453
454 g_pFrameBufferManager->SetAddrBeDisplayed(*gfx_info.VI_ORIGIN_REG);
455
456 if( status.gDlistCount == 0 )
457 {
458 // CPU frame buffer update
459 uint32_t width = *gfx_info.VI_WIDTH_REG;
460 if( (*gfx_info.VI_ORIGIN_REG & (g_dwRamSize-1) ) > width*2 && *gfx_info.VI_H_START_REG != 0 && width != 0 )
461 {
462 SetVIScales();
463 CRender::GetRender()->DrawFrameBuffer(true, 0, 0, 0, 0);
464 CGraphicsContext::Get()->UpdateFrame(false);
465 }
466 return;
467 }
468
469 TXTRBUF_DETAIL_DUMP(TRACE1("VI ORIG is updated to %08X", *gfx_info.VI_ORIGIN_REG));
470
471 if( currentRomOptions.screenUpdateSetting == SCREEN_UPDATE_AT_VI_UPDATE )
472 {
473 CGraphicsContext::Get()->UpdateFrame(false);
474 return;
475 }
476
477 TXTRBUF_DETAIL_DUMP(TRACE1("VI ORIG is updated to %08X", *gfx_info.VI_ORIGIN_REG));
478
479 if( currentRomOptions.screenUpdateSetting == SCREEN_UPDATE_AT_VI_UPDATE_AND_DRAWN )
480 {
481 if( status.bScreenIsDrawn )
482 CGraphicsContext::Get()->UpdateFrame(false);
483
484 return;
485 }
486
487 if( currentRomOptions.screenUpdateSetting==SCREEN_UPDATE_AT_VI_CHANGE )
488 {
489
490 if( *gfx_info.VI_ORIGIN_REG != status.curVIOriginReg )
491 {
492 if( *gfx_info.VI_ORIGIN_REG < status.curDisplayBuffer || *gfx_info.VI_ORIGIN_REG > status.curDisplayBuffer+0x2000 )
493 {
494 status.curDisplayBuffer = *gfx_info.VI_ORIGIN_REG;
495 status.curVIOriginReg = status.curDisplayBuffer;
496 //status.curRenderBuffer = NULL;
497
498 CGraphicsContext::Get()->UpdateFrame(false);
499 }
500 else
501 {
502 status.curDisplayBuffer = *gfx_info.VI_ORIGIN_REG;
503 status.curVIOriginReg = status.curDisplayBuffer;
504 }
505 }
506
507 return;
508 }
509
510 if( currentRomOptions.screenUpdateSetting >= SCREEN_UPDATE_AT_1ST_CI_CHANGE )
511 {
512 status.bVIOriginIsUpdated=true;
513 return;
514 }
515 }
516
riceViStatusChanged(void)517 void riceViStatusChanged(void)
518 {
519 SetVIScales();
520 CRender::g_pRender->UpdateClipRectangle();
521 }
522
riceViWidthChanged(void)523 void riceViWidthChanged(void)
524 {
525 SetVIScales();
526 CRender::g_pRender->UpdateClipRectangle();
527 }
528
riceInitiateGFX(GFX_INFO Gfx_Info)529 int riceInitiateGFX(GFX_INFO Gfx_Info)
530 {
531 memset(&status, 0, sizeof(status));
532
533 windowSetting.fViWidth = 320;
534 windowSetting.fViHeight = 240;
535 status.ToResize = false;
536 status.bDisableFPS=false;
537
538 if (!InitConfiguration())
539 {
540 DebugMessage(M64MSG_ERROR, "Failed to read configuration data");
541 return false;
542 }
543
544 CGraphicsContext::InitWindowInfo();
545 CGraphicsContext::InitDeviceParameters();
546
547 return true;
548 }
549
riceResizeVideoOutput(int width,int height)550 void riceResizeVideoOutput(int width, int height)
551 {
552 // save the new window resolution. actual resizing operation is asynchronous (it happens later)
553 status.gNewResizeWidth = width;
554 status.gNewResizeHeight = height;
555 status.ToResize = true;
556 }
557
riceProcessRDPList(void)558 void riceProcessRDPList(void)
559 {
560 RDP_DLParser_Process();
561 }
562
riceProcessDList(void)563 void riceProcessDList(void)
564 {
565 if( status.toShowCFB )
566 {
567 CRender::GetRender()->DrawFrameBuffer(true, 0, 0, 0, 0);
568 status.toShowCFB = false;
569 }
570
571 DLParser_Process((OSTask *)(gfx_info.DMEM + 0x0FC0));
572 }
573
574 //---------------------------------------------------------------------------------------
575
576 /******************************************************************
577 Function: FrameBufferRead
578 Purpose: This function is called to notify the dll that the
579 frame buffer memory is beening read at the given address.
580 DLL should copy content from its render buffer to the frame buffer
581 in N64 RDRAM
582 DLL is responsible to maintain its own frame buffer memory addr list
583 DLL should copy 4KB block content back to RDRAM frame buffer.
584 Emulator should not call this function again if other memory
585 is read within the same 4KB range
586
587 Since depth buffer is also being watched, the reported addr
588 may belong to depth buffer
589 input: addr rdram address
590 val val
591 size 1 = uint8_t, 2 = uint16_t, 4 = uint32_t
592 output: none
593 *******************************************************************/
594
riceFBRead(uint32_t addr)595 void riceFBRead(uint32_t addr)
596 {
597 g_pFrameBufferManager->FrameBufferReadByCPU(addr);
598 }
599
600
601 /******************************************************************
602 Function: FrameBufferWrite
603 Purpose: This function is called to notify the dll that the
604 frame buffer has been modified by CPU at the given address.
605
606 Since depth buffer is also being watched, the reported addr
607 may belong to depth buffer
608
609 input: addr rdram address
610 val val
611 size 1 = uint8_t, 2 = uint16_t, 4 = uint32_t
612 output: none
613 *******************************************************************/
614
riceFBWrite(uint32_t addr,uint32_t size)615 void riceFBWrite(uint32_t addr, uint32_t size)
616 {
617 g_pFrameBufferManager->FrameBufferWriteByCPU(addr, size);
618 }
619
620 /************************************************************************
621 Function: FBGetFrameBufferInfo
622 Purpose: This function is called by the emulator core to retrieve frame
623 buffer information from the video plugin in order to be able
624 to notify the video plugin about CPU frame buffer read/write
625 operations
626
627 size:
628 = 1 byte
629 = 2 word (16 bit) <-- this is N64 default depth buffer format
630 = 4 dword (32 bit)
631
632 when frame buffer information is not available yet, set all values
633 in the FrameBufferInfo structure to 0
634
635 input: FrameBufferInfo pinfo[6]
636 pinfo is pointed to a FrameBufferInfo structure which to be
637 filled in by this function
638 output: Values are return in the FrameBufferInfo structure
639 Plugin can return up to 6 frame buffer info
640 ************************************************************************/
641
riceFBGetFrameBufferInfo(void * p)642 void riceFBGetFrameBufferInfo(void *p)
643 {
644 FrameBufferInfo * pinfo = (FrameBufferInfo *)p;
645 memset(pinfo,0,sizeof(FrameBufferInfo)*6);
646
647 //if( g_ZI.dwAddr == 0 )
648 //{
649 // memset(pinfo,0,sizeof(FrameBufferInfo)*6);
650 //}
651 //else
652 {
653 for (int i=0; i<5; i++ )
654 {
655 if( status.gDlistCount-g_RecentCIInfo[i].lastUsedFrame > 30 || g_RecentCIInfo[i].lastUsedFrame == 0 )
656 {
657 //memset(&pinfo[i],0,sizeof(FrameBufferInfo));
658 }
659 else
660 {
661 pinfo[i].addr = g_RecentCIInfo[i].dwAddr;
662 pinfo[i].size = 2;
663 pinfo[i].width = g_RecentCIInfo[i].dwWidth;
664 pinfo[i].height = g_RecentCIInfo[i].dwHeight;
665 TXTRBUF_DETAIL_DUMP(TRACE3("Protect 0x%08X (%d,%d)", g_RecentCIInfo[i].dwAddr, g_RecentCIInfo[i].dwWidth, g_RecentCIInfo[i].dwHeight));
666 pinfo[5].width = g_RecentCIInfo[i].dwWidth;
667 pinfo[5].height = g_RecentCIInfo[i].dwHeight;
668 }
669 }
670
671 pinfo[5].addr = g_ZI.dwAddr;
672 //pinfo->size = g_RecentCIInfo[5].dwSize;
673 pinfo[5].size = 2;
674 TXTRBUF_DETAIL_DUMP(TRACE3("Protect 0x%08X (%d,%d)", pinfo[5].addr, pinfo[5].width, pinfo[5].height));
675 }
676 }
677
678 // Plugin spec 1.3 functions
riceShowCFB(void)679 void riceShowCFB(void)
680 {
681 status.toShowCFB = true;
682 }
683
riceReadScreen2(void * dest,int * width,int * height,int bFront)684 void riceReadScreen2(void *dest, int *width, int *height, int bFront)
685 {
686 if (width == NULL || height == NULL)
687 return;
688
689 *width = windowSetting.uDisplayWidth;
690 *height = windowSetting.uDisplayHeight;
691
692 if (dest == NULL)
693 return;
694 }
695
696
riceSetRenderingCallback(void (* callback)(int))697 void riceSetRenderingCallback(void (*callback)(int))
698 {
699 renderCallback = callback;
700 }
701
702 #ifdef __cplusplus
703 }
704 #endif
705
706