X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=plugins%2Fgpu_unai_old%2Fgpu.cpp;fp=plugins%2Fgpu_unai_old%2Fgpu.cpp;h=1552bed90af2c2a92cce7b7bb6e88e1a06649277;hb=5a920d326f0508f941d6cfc6c42500e961f82a72;hp=0000000000000000000000000000000000000000;hpb=c8d69ce8e9b4995fa43ba722d0532eb5c53225b4;p=pcsx_rearmed.git diff --git a/plugins/gpu_unai_old/gpu.cpp b/plugins/gpu_unai_old/gpu.cpp new file mode 100644 index 00000000..1552bed9 --- /dev/null +++ b/plugins/gpu_unai_old/gpu.cpp @@ -0,0 +1,915 @@ +/*************************************************************************** +* Copyright (C) 2010 PCSX4ALL Team * +* Copyright (C) 2010 Unai * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * +***************************************************************************/ + +#include "port.h" +#include "gpu.h" +#include "profiler.h" +#include "debug.h" + +int skipCount = 2; /* frame skip (0,1,2,3...) */ +int skCount = 0; /* internal frame skip */ +int linesInterlace = 0; /* internal lines interlace */ +int linesInterlace_user = 0; /* Lines interlace */ + +bool isSkip = false; /* skip frame (info coming from GPU) */ +bool wasSkip = false; +bool skipFrame = false; /* skip frame (according to frame skip) */ +bool alt_fps = false; /* Alternative FPS algorithm */ +bool show_fps = false; /* Show FPS statistics */ + +bool isPAL = false; /* PAL video timing */ +bool progressInterlace_flag = false; /* Progressive interlace flag */ +bool progressInterlace = false; /* Progressive interlace option*/ +bool frameLimit = false; /* frames to wait */ + +bool light = true; /* lighting */ +bool blend = true; /* blending */ +bool FrameToRead = false; /* load image in progress */ +bool FrameToWrite = false; /* store image in progress */ +bool fb_dirty = false; + +bool enableAbbeyHack = false; /* Abe's Odyssey hack */ + +u8 BLEND_MODE; +u8 TEXT_MODE; +u8 Masking; + +u16 PixelMSB; +u16 PixelData; + +/////////////////////////////////////////////////////////////////////////////// +// GPU Global data +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Dma Transfers info +s32 px,py; +s32 x_end,y_end; +u16* pvram; + +u32 GP0; +s32 PacketCount; +s32 PacketIndex; + +/////////////////////////////////////////////////////////////////////////////// +// Display status +u32 DisplayArea [6]; + +/////////////////////////////////////////////////////////////////////////////// +// Rasterizer status +u32 TextureWindow [4]; +u32 DrawingArea [4]; +u32 DrawingOffset [2]; + +/////////////////////////////////////////////////////////////////////////////// +// Rasterizer status + +u16* TBA; +u16* CBA; + +/////////////////////////////////////////////////////////////////////////////// +// Inner Loops +s32 u4, du4; +s32 v4, dv4; +s32 r4, dr4; +s32 g4, dg4; +s32 b4, db4; +u32 lInc; +u32 tInc, tMsk; + +GPUPacket PacketBuffer; +// FRAME_BUFFER_SIZE is defined in bytes; 512K is guard memory for out of range reads +u16 GPU_FrameBuffer[(FRAME_BUFFER_SIZE+512*1024)/2] __attribute__((aligned(2048))); +u32 GPU_GP1; + +/////////////////////////////////////////////////////////////////////////////// +// Inner loop driver instanciation file +#include "gpu_inner.h" + +/////////////////////////////////////////////////////////////////////////////// +// GPU Raster Macros +#define GPU_RGB16(rgb) ((((rgb)&0xF80000)>>9)|(((rgb)&0xF800)>>6)|(((rgb)&0xF8)>>3)) + +#define GPU_EXPANDSIGN(x) (((s32)(x)<<21)>>21) + +#define CHKMAX_X 1024 +#define CHKMAX_Y 512 + +#define GPU_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);} + +/////////////////////////////////////////////////////////////////////////////// +// GPU internal image drawing functions +#include "gpu_raster_image.h" + +/////////////////////////////////////////////////////////////////////////////// +// GPU internal line drawing functions +#include "gpu_raster_line.h" + +/////////////////////////////////////////////////////////////////////////////// +// GPU internal polygon drawing functions +#include "gpu_raster_polygon.h" + +/////////////////////////////////////////////////////////////////////////////// +// GPU internal sprite drawing functions +#include "gpu_raster_sprite.h" + +/////////////////////////////////////////////////////////////////////////////// +// GPU command buffer execution/store +#include "gpu_command.h" + +/////////////////////////////////////////////////////////////////////////////// +INLINE void gpuReset(void) +{ + GPU_GP1 = 0x14802000; + TextureWindow[0] = 0; + TextureWindow[1] = 0; + TextureWindow[2] = 255; + TextureWindow[3] = 255; + DrawingArea[2] = 256; + DrawingArea[3] = 240; + DisplayArea[2] = 256; + DisplayArea[3] = 240; + DisplayArea[5] = 240; +} + +/////////////////////////////////////////////////////////////////////////////// +bool GPU_init(void) +{ + gpuReset(); + + // s_invTable + for(int i=1;i<=(1<>1); + #else + v *= double(0x80000000); + #endif + s_invTable[i-1]=s32(v); + } + return (0); +} + +/////////////////////////////////////////////////////////////////////////////// +void GPU_shutdown(void) +{ +} + +/////////////////////////////////////////////////////////////////////////////// +long GPU_freeze(unsigned int bWrite, GPUFreeze_t* p2) +{ + if (!p2) return (0); + if (p2->Version != 1) return (0); + + if (bWrite) + { + p2->GPU_gp1 = GPU_GP1; + memset(p2->Control, 0, sizeof(p2->Control)); + // save resolution and registers for P.E.Op.S. compatibility + p2->Control[3] = (3 << 24) | ((GPU_GP1 >> 23) & 1); + p2->Control[4] = (4 << 24) | ((GPU_GP1 >> 29) & 3); + p2->Control[5] = (5 << 24) | (DisplayArea[0] | (DisplayArea[1] << 10)); + p2->Control[6] = (6 << 24) | (2560 << 12); + p2->Control[7] = (7 << 24) | (DisplayArea[4] | (DisplayArea[5] << 10)); + p2->Control[8] = (8 << 24) | ((GPU_GP1 >> 17) & 0x3f) | ((GPU_GP1 >> 10) & 0x40); + memcpy(p2->FrameBuffer, (u16*)GPU_FrameBuffer, FRAME_BUFFER_SIZE); + return (1); + } + else + { + GPU_GP1 = p2->GPU_gp1; + memcpy((u16*)GPU_FrameBuffer, p2->FrameBuffer, FRAME_BUFFER_SIZE); + GPU_writeStatus((5 << 24) | p2->Control[5]); + GPU_writeStatus((7 << 24) | p2->Control[7]); + GPU_writeStatus((8 << 24) | p2->Control[8]); + gpuSetTexture(GPU_GP1); + return (1); + } + return (0); +} + +/////////////////////////////////////////////////////////////////////////////// +// GPU DMA comunication + +/////////////////////////////////////////////////////////////////////////////// +u8 PacketSize[256] = +{ + 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 3, 3, 3, 3, 6, 6, 6, 6, 4, 4, 4, 4, 8, 8, 8, 8, // 32-47 + 5, 5, 5, 5, 8, 8, 8, 8, 7, 7, 7, 7, 11, 11, 11, 11, // 48-63 + 2, 2, 2, 2, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, // 64-79 + 3, 3, 3, 3, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, // 80-95 + 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, // 96-111 + 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, // 112-127 + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128- + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144 + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // +}; + +/////////////////////////////////////////////////////////////////////////////// +INLINE void gpuSendPacket() +{ +#ifdef DEBUG_ANALYSIS + dbg_anacnt_GPU_sendPacket++; +#endif + gpuSendPacketFunction(PacketBuffer.U4[0]>>24); +} + +/////////////////////////////////////////////////////////////////////////////// +INLINE void gpuCheckPacket(u32 uData) +{ + if (PacketCount) + { + PacketBuffer.U4[PacketIndex++] = uData; + --PacketCount; + } + else + { + PacketBuffer.U4[0] = uData; + PacketCount = PacketSize[uData >> 24]; + PacketIndex = 1; + } + if (!PacketCount) gpuSendPacket(); +} + +/////////////////////////////////////////////////////////////////////////////// +void GPU_writeDataMem(u32* dmaAddress, s32 dmaCount) +{ +#ifdef DEBUG_ANALYSIS + dbg_anacnt_GPU_writeDataMem++; +#endif + pcsx4all_prof_pause(PCSX4ALL_PROF_CPU); + pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE); + u32 data; + const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1); + GPU_GP1 &= ~0x14000000; + + while (dmaCount) + { + if (FrameToWrite) + { + while (dmaCount) + { + dmaCount--; + data = *dmaAddress++; + if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024; + pvram[px] = data; + if (++px>=x_end) + { + px = 0; + pvram += 1024; + if (++py>=y_end) + { + FrameToWrite = false; + GPU_GP1 &= ~0x08000000; + break; + } + } + if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024; + pvram[px] = data>>16; + if (++px>=x_end) + { + px = 0; + pvram += 1024; + if (++py>=y_end) + { + FrameToWrite = false; + GPU_GP1 &= ~0x08000000; + break; + } + } + } + } + else + { + data = *dmaAddress++; + dmaCount--; + gpuCheckPacket(data); + } + } + + GPU_GP1 = (GPU_GP1 | 0x14000000) & ~0x60000000; + fb_dirty = true; + pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE); + pcsx4all_prof_resume(PCSX4ALL_PROF_CPU); +} + +u32 *lUsedAddr[3]; +INLINE int CheckForEndlessLoop(u32 *laddr) +{ + if(laddr==lUsedAddr[1]) return 1; + if(laddr==lUsedAddr[2]) return 1; + + if(laddr> 2)); + if(DMACommandCounter++ > 2000000) break; + if(CheckForEndlessLoop(address)) break; + data = *address++; + count = (data >> 24); + offset = data & 0x001FFFFF; + if (dmaVAddr != offset) dmaVAddr = offset; + else dmaVAddr = 0x1FFFFF; + + if(count>0) GPU_writeDataMem(address,count); + dma_words += 1 + count; + } + GPU_GP1 = (GPU_GP1 | 0x14000000) & ~0x60000000; + pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE); + + return dma_words; +} + +/////////////////////////////////////////////////////////////////////////////// +void GPU_writeData(u32 data) +{ + const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1); +#ifdef DEBUG_ANALYSIS + dbg_anacnt_GPU_writeData++; +#endif + pcsx4all_prof_pause(PCSX4ALL_PROF_CPU); + pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE); + GPU_GP1 &= ~0x14000000; + + if (FrameToWrite) + { + if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024; + pvram[px]=(u16)data; + if (++px>=x_end) + { + px = 0; + pvram += 1024; + if (++py>=y_end) + { + FrameToWrite = false; + GPU_GP1 &= ~0x08000000; + } + } + if (FrameToWrite) + { + if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024; + pvram[px]=data>>16; + if (++px>=x_end) + { + px = 0; + pvram += 1024; + if (++py>=y_end) + { + FrameToWrite = false; + GPU_GP1 &= ~0x08000000; + } + } + } + } + else + { + gpuCheckPacket(data); + } + GPU_GP1 |= 0x14000000; + fb_dirty = true; + pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE); + pcsx4all_prof_resume(PCSX4ALL_PROF_CPU); + +} + + +/////////////////////////////////////////////////////////////////////////////// +void GPU_readDataMem(u32* dmaAddress, s32 dmaCount) +{ + const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1); +#ifdef DEBUG_ANALYSIS + dbg_anacnt_GPU_readDataMem++; +#endif + if(!FrameToRead) return; + + pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE); + GPU_GP1 &= ~0x14000000; + do + { + if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024; + // lower 16 bit + u32 data = pvram[px]; + + if (++px>=x_end) + { + px = 0; + pvram += 1024; + } + + if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024; + // higher 16 bit (always, even if it's an odd width) + data |= (u32)(pvram[px])<<16; + + *dmaAddress++ = data; + + if (++px>=x_end) + { + px = 0; + pvram += 1024; + if (++py>=y_end) + { + FrameToRead = false; + GPU_GP1 &= ~0x08000000; + break; + } + } + } while (--dmaCount); + + GPU_GP1 = (GPU_GP1 | 0x14000000) & ~0x60000000; + pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE); +} + + + +/////////////////////////////////////////////////////////////////////////////// +u32 GPU_readData(void) +{ + const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1); +#ifdef DEBUG_ANALYSIS + dbg_anacnt_GPU_readData++; +#endif + pcsx4all_prof_pause(PCSX4ALL_PROF_CPU); + pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_READ); + GPU_GP1 &= ~0x14000000; + if (FrameToRead) + { + if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024; + GP0 = pvram[px]; + if (++px>=x_end) + { + px = 0; + pvram += 1024; + if (++py>=y_end) + { + FrameToRead = false; + GPU_GP1 &= ~0x08000000; + } + } + if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024; + GP0 |= pvram[px]<<16; + if (++px>=x_end) + { + px = 0; + pvram +=1024; + if (++py>=y_end) + { + FrameToRead = false; + GPU_GP1 &= ~0x08000000; + } + } + + } + GPU_GP1 |= 0x14000000; + + pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_READ); + pcsx4all_prof_resume(PCSX4ALL_PROF_CPU); + return (GP0); +} + +/////////////////////////////////////////////////////////////////////////////// +u32 GPU_readStatus(void) +{ +#ifdef DEBUG_ANALYSIS + dbg_anacnt_GPU_readStatus++; +#endif + return GPU_GP1; +} + +/////////////////////////////////////////////////////////////////////////////// +void GPU_writeStatus(u32 data) +{ +#ifdef DEBUG_ANALYSIS + dbg_anacnt_GPU_writeStatus++; +#endif + pcsx4all_prof_pause(PCSX4ALL_PROF_CPU); + pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE); + switch (data >> 24) { + case 0x00: + gpuReset(); + break; + case 0x01: + GPU_GP1 &= ~0x08000000; + PacketCount = 0; FrameToRead = FrameToWrite = false; + break; + case 0x02: + GPU_GP1 &= ~0x08000000; + PacketCount = 0; FrameToRead = FrameToWrite = false; + break; + case 0x03: + GPU_GP1 = (GPU_GP1 & ~0x00800000) | ((data & 1) << 23); + break; + case 0x04: + if (data == 0x04000000) + PacketCount = 0; + GPU_GP1 = (GPU_GP1 & ~0x60000000) | ((data & 3) << 29); + break; + case 0x05: + DisplayArea[0] = (data & 0x000003FF); //(short)(data & 0x3ff); + DisplayArea[1] = ((data & 0x0007FC00)>>10); //(data & 0x000FFC00) >> 10; //(short)((data>>10)&0x1ff); + fb_dirty = true; + wasSkip = isSkip; + if (isSkip) + isSkip = false; + else + isSkip = skipFrame; + break; + case 0x07: + DisplayArea[4] = data & 0x000003FF; //(short)(data & 0x3ff); + DisplayArea[5] = (data & 0x000FFC00) >> 10; //(short)((data>>10) & 0x3ff); + fb_dirty = true; + break; + case 0x08: + { + GPU_GP1 = (GPU_GP1 & ~0x007F0000) | ((data & 0x3F) << 17) | ((data & 0x40) << 10); + static u32 HorizontalResolution[8] = { 256, 368, 320, 384, 512, 512, 640, 640 }; + DisplayArea[2] = HorizontalResolution[(GPU_GP1 >> 16) & 7]; + static u32 VerticalResolution[4] = { 240, 480, 256, 480 }; + DisplayArea[3] = VerticalResolution[(GPU_GP1 >> 19) & 3]; + isPAL = (data & 0x08) ? true : false; // if 1 - PAL mode, else NTSC + } + fb_dirty = true; + break; + case 0x10: + switch (data & 0xffff) { + case 0: + case 1: + case 3: + GP0 = (DrawingArea[1] << 10) | DrawingArea[0]; + break; + case 4: + GP0 = ((DrawingArea[3]-1) << 10) | (DrawingArea[2]-1); + break; + case 6: + case 5: + GP0 = (DrawingOffset[1] << 11) | DrawingOffset[0]; + break; + case 7: + GP0 = 2; + break; + default: + GP0 = 0; + } + break; + } + pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE); + pcsx4all_prof_resume(PCSX4ALL_PROF_CPU); +} + +#ifndef REARMED + +// Blitting functions +#include "gpu_blit.h" + +INLINE void gpuVideoOutput(void) +{ + static s16 old_res_horz, old_res_vert, old_rgb24; + s16 h0, x0, y0, w0, h1; + + x0 = DisplayArea[0]; + y0 = DisplayArea[1]; + + w0 = DisplayArea[2]; + h0 = DisplayArea[3]; // video mode + + h1 = DisplayArea[5] - DisplayArea[4]; // display needed + if (h0 == 480) h1 = Min2(h1*2,480); + + u16* dest_screen16 = SCREEN; + u16* src_screen16 = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(x0,y0)]; + u32 isRGB24 = (GPU_GP1 & 0x00200000 ? 32 : 0); + + /* Clear the screen if resolution changed to prevent interlacing and clipping to clash */ + if( (w0 != old_res_horz || h1 != old_res_vert || (s16)isRGB24 != old_rgb24) ) + { + // Update old resolution + old_res_horz = w0; + old_res_vert = h1; + old_rgb24 = (s16)isRGB24; + // Finally, clear the screen for this special case + video_clear(); + } + + // Height centering + int sizeShift = 1; + if(h0==256) h0 = 240; else if(h0==480) sizeShift = 2; + if(h1>h0) { src_screen16 += ((h1-h0)>>sizeShift)*1024; h1 = h0; } + else if(h1>sizeShift)*VIDEO_WIDTH; + + /* Main blitter */ + int incY = (h0==480) ? 2 : 1; + h0=(h0==480 ? 2048 : 1024); + + { + const int li=linesInterlace; + bool pi=progressInterlace; + bool pif=progressInterlace_flag; + switch ( w0 ) + { + case 256: + for(int y1=y0+h1; y0=1000000) + { + u32 expected_fps=(isPAL?50:60); + sprintf(msg,"FPS=%3d/%2d SPD=%3d%%",((real_fps*(12-skipCount))/12),((expected_fps*(12-skipCount))/12),((real_fps*100)/expected_fps)); + prev=now; + real_fps=0; + } + port_printf(5,5,msg); + } + + // Update frame-skip + if (!alt_fps) + { + // Video frame-skip + skipFrame=skipTable[skipCount][skCount]; + skCount--; if (skCount<0) skCount=11; + isSkip=skipFrame; + } + else + { + // Game frame-skip + if (!isSkip) + { + skipFrame=skipTable[skipCount][skCount]; + skCount--; if (skCount<0) skCount=11; + isSkip=true; + } + } + fb_dirty=false; + + pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_COUNTERS); +} + +#else + +#include "../../frontend/plugin_lib.h" + +extern "C" { + +static const struct rearmed_cbs *cbs; +static s16 old_res_horz, old_res_vert, old_rgb24; + +static void blit(void) +{ + u16 *base = (u16 *)GPU_FrameBuffer; + s16 isRGB24 = (GPU_GP1 & 0x00200000) ? 1 : 0; + s16 h0, x0, y0, w0, h1; + + x0 = DisplayArea[0] & ~1; // alignment needed by blitter + y0 = DisplayArea[1]; + base += FRAME_OFFSET(x0, y0); + + w0 = DisplayArea[2]; + h0 = DisplayArea[3]; // video mode + + h1 = DisplayArea[5] - DisplayArea[4]; // display needed + if (h0 == 480) h1 = Min2(h1*2,480); + + if (h1 <= 0) + return; + + if (w0 != old_res_horz || h1 != old_res_vert || isRGB24 != old_rgb24) + { + old_res_horz = w0; + old_res_vert = h1; + old_rgb24 = (s16)isRGB24; + cbs->pl_vout_set_mode(w0, h1, w0, h1, isRGB24 ? 24 : 16); + } + + cbs->pl_vout_flip(base, 1024, isRGB24, w0, h1); +} + +void GPU_updateLace(void) +{ + // Interlace bit toggle + GPU_GP1 ^= 0x80000000; + + if (!fb_dirty || (GPU_GP1&0x08800000)) + return; + + if (!wasSkip) { + blit(); + fb_dirty = false; + skCount = 0; + } + else { + skCount++; + if (skCount >= 8) + wasSkip = isSkip = 0; + } + + skipFrame = cbs->fskip_advice || cbs->frameskip == 1; +} + +long GPUopen(unsigned long *, char *, char *) +{ + cbs->pl_vout_open(); + return 0; +} + +long GPUclose(void) +{ + cbs->pl_vout_close(); + return 0; +} + +long GPUfreeze(unsigned int ulGetFreezeData, GPUFreeze_t* p2) +{ + if (ulGetFreezeData > 1) + return 0; + + return GPU_freeze(ulGetFreezeData, p2); +} + +void GPUrearmedCallbacks(const struct rearmed_cbs *cbs_) +{ + enableAbbeyHack = cbs_->gpu_unai.abe_hack; + light = !cbs_->gpu_unai.no_light; + blend = !cbs_->gpu_unai.no_blend; + if (cbs_->pl_vout_set_raw_vram) + cbs_->pl_vout_set_raw_vram((void *)GPU_FrameBuffer); + + cbs = cbs_; + if (cbs->pl_set_gpu_caps) + cbs->pl_set_gpu_caps(0); +} + +} /* extern "C" */ + +#endif