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