1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-06-30 08:24:05 +00:00

Merge pull request #2 from DaMarkov/oot-framebuffer-emulation

OOT framebuffer emulation
This commit is contained in:
Blake Warner 2022-02-08 12:19:07 -05:00 committed by GitHub
commit 88f7de3e2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 196 additions and 20 deletions

View File

@ -677,7 +677,11 @@ void FrameBufferList::setBufferChanged(f32 _maxY)
void FrameBufferList::clearBuffersChanged()
{
gDP.colorImage.changed = FALSE;
#ifndef NATIVE
FrameBuffer * pBuffer = frameBufferList().findBuffer(*REG.VI_ORIGIN & 0xffffff);
#else
FrameBuffer* pBuffer = frameBufferList().findBuffer(*REG.VI_ORIGIN);
#endif
if (pBuffer != nullptr)
pBuffer->m_changed = false;
}
@ -1229,7 +1233,11 @@ bool FrameBufferList::RdpUpdate::update(RdpUpdateResult & _result)
if ((vitype & 2) == 0) {
prevwasblank = true;
return false;
#ifdef NATIVE
//return false;//HACK, REG.VI_STATUS might be set up incorrectly
#else
return false
#endif
}
prevwasblank = false;
@ -1247,7 +1255,11 @@ bool FrameBufferList::RdpUpdate::update(RdpUpdateResult & _result)
_result.vi_maxhpass = hres_clamped ? 0 : 7;
_result.vi_width = _SHIFTR(*REG.VI_WIDTH, 0, 12);
_result.vi_lowerfield = lowerfield;
#ifndef NATIVE
_result.vi_origin = _SHIFTR(*REG.VI_ORIGIN, 0, 24);
#else
_result.vi_origin = *REG.VI_ORIGIN;//This is incorrect REG.VI_ORIGIN should contain only 24 bits of the frame buffer address
#endif
_result.vi_fsaa = (*REG.VI_STATUS & 512) == 0;
_result.vi_divot = (*REG.VI_STATUS & VI_STATUS_DIVOT_ENABLED) != 0;
return true;

View File

@ -684,7 +684,11 @@ namespace glsl {
void activate() override {
FXAAShaderBase::activate();
#ifndef NATIVE
FrameBuffer * pBuffer = frameBufferList().findBuffer(*REG.VI_ORIGIN & 0xffffff);
#else
FrameBuffer* pBuffer = frameBufferList().findBuffer(*REG.VI_ORIGIN);
#endif
if (pBuffer != nullptr && pBuffer->m_pTexture != nullptr &&
(m_width != pBuffer->m_pTexture->width || m_height != pBuffer->m_pTexture->height)) {
m_width = pBuffer->m_pTexture->width;

View File

@ -253,8 +253,11 @@ void VI_UpdateScreen()
}
if (config.frameBufferEmulation.enable) {
#ifndef NATIVE
FrameBuffer * pBuffer = frameBufferList().findBuffer(*REG.VI_ORIGIN & 0xffffff);
#else
FrameBuffer* pBuffer = frameBufferList().findBuffer(*REG.VI_ORIGIN);
#endif
if (pBuffer == nullptr) {
gDP.changed |= CHANGED_CPU_FB_WRITE;
} else if (!FBInfo::fbInfo.isSupported() &&
@ -288,8 +291,14 @@ void VI_UpdateScreen()
bVIUpdated = true;
}
const u32 size = *REG.VI_STATUS & VI_STATUS_TYPE_32;
if (VI.height > 0 && size > G_IM_SIZ_8b && VI.width > 0)
if (VI.height > 0 && size > G_IM_SIZ_8b && VI.width > 0)
{
#ifndef NATIVE
frameBufferList().saveBuffer(*REG.VI_ORIGIN & 0xffffff, G_IM_FMT_RGBA, size, VI.width, true);
#else
frameBufferList().saveBuffer(*REG.VI_ORIGIN, G_IM_FMT_RGBA, size, VI.width, true);
#endif
}
}
}
// if ((((*REG.VI_STATUS) & 3) > 0) && (gDP.colorImage.changed || bCFB)) { // Does not work in release build!!!
@ -298,7 +307,11 @@ void VI_UpdateScreen()
VI_UpdateSize();
bVIUpdated = true;
}
#ifndef NATIVE
FrameBuffer_CopyFromRDRAM(*REG.VI_ORIGIN & 0xffffff, bCFB);
#else
FrameBuffer_CopyFromRDRAM(*REG.VI_ORIGIN, bCFB);
#endif
}
frameBufferList().renderBuffer();
frameBufferList().clearBuffersChanged();

View File

@ -7,13 +7,15 @@
#include "DebugDump.h"
#include "Config.h"
#include "DisplayWindow.h"
#include "FrameBuffer.h"
#include "FrameBufferInfo.h"
#include <wchar.h>
#include "settings.h"
#define START_WIDTH 1280
#define START_HEIGHT 720
static u64 g_width = START_WIDTH;
static u64 g_width = START_WIDTH;
static u64 g_height = START_HEIGHT;
extern "C" {
@ -94,35 +96,32 @@ extern "C"
{
g_width = width;
g_height = height;
config.video.windowedWidth = g_width;
config.video.windowedWidth = g_width;
config.video.windowedHeight = g_height;
dwnd().setWindowSize(g_width, g_height);
(*REG.VI_ORIGIN)++;
}
}
void _CheckInterrupts() {
}
extern "C" {
void gfx_init(const char* romName, OSViMode* viMode) {
REG.VI_STATUS = &viMode->comRegs.ctrl;
REG.VI_WIDTH = &viMode->comRegs.width;
REG.VI_TIMING = &viMode->comRegs.burst;
REG.VI_V_SYNC = &viMode->comRegs.vSync;
REG.VI_H_SYNC = &viMode->comRegs.hSync;
REG.VI_LEAP = &viMode->comRegs.leap;
REG.VI_STATUS = &viMode->comRegs.ctrl;
REG.VI_WIDTH = &viMode->comRegs.width;
REG.VI_TIMING = &viMode->comRegs.burst;
REG.VI_V_SYNC = &viMode->comRegs.vSync;
REG.VI_H_SYNC = &viMode->comRegs.hSync;
REG.VI_LEAP = &viMode->comRegs.leap;
REG.VI_H_START = &viMode->comRegs.hStart;
REG.VI_X_SCALE = &viMode->comRegs.xScale;
REG.VI_V_CURRENT_LINE = &viMode->comRegs.vCurrent;
REG.VI_ORIGIN = &viMode->fldRegs->origin;
REG.VI_ORIGIN = &viMode->fldRegs->origin;
REG.VI_Y_SCALE = &viMode->fldRegs->yScale;
REG.VI_V_START = &viMode->fldRegs->vStart;
REG.VI_V_BURST = &viMode->fldRegs->vBurst;
REG.VI_INTR = &viMode->fldRegs->vIntr;
REG.VI_INTR = &viMode->fldRegs->vIntr;
CheckInterrupts = _CheckInterrupts;
@ -132,10 +131,6 @@ extern "C" {
RDRAMSize = (word)-1;
api().RomOpen(romName);
config.frameBufferEmulation.enable = 0;
config.frameBufferEmulation.aspect = Config::aAdjust;
}
void gfx_shutdown() {
@ -152,6 +147,55 @@ extern "C" {
api().UpdateScreen();
//Sleep(30);
}
int gfx_fbe_is_enabled() {
return config.frameBufferEmulation.enable;
}
void gfx_fbe_enable(int enable) {
config.frameBufferEmulation.enable = enable;
}
void gfx_fbe_sync(GraphicsContext* gfxCtx, GameInfo* GameInfo) {
if (!config.frameBufferEmulation.enable)
return;
CfbInfo* cfb = gfxCtx->task.framebuffer;//Current frame buffer (according the the game)
FrameBufferList& frameBuffers = FrameBufferList::get();//GLideN64's frame buffer list
if (!frameBuffers.getCurrent())
return;
gfxCtx->curFrameBuffer = &frameBuffers.getCurrent()->m_startAddress;
gfxCtx->viMode->fldRegs->origin = frameBuffers.getCurrent()->m_startAddress;
cfb->fb1 = gfxCtx->curFrameBuffer;
cfb->swapBuffer = gfxCtx->curFrameBuffer;
cfb->viMode = gfxCtx->viMode;
cfb->features = gfxCtx->viFeatures;
cfb->xScale = gfxCtx->xScale;
cfb->xScale = gfxCtx->yScale;
cfb->unk_10 = 0;
cfb->updateRate = (s8)R_UPDATE_RATE;
REG.VI_STATUS = &cfb->viMode->comRegs.ctrl;
REG.VI_WIDTH = &cfb->viMode->comRegs.width;
REG.VI_TIMING = &cfb->viMode->comRegs.burst;
REG.VI_V_SYNC = &cfb->viMode->comRegs.vSync;
REG.VI_H_SYNC = &cfb->viMode->comRegs.hSync;
REG.VI_LEAP = &cfb->viMode->comRegs.leap;
REG.VI_H_START = &cfb->viMode->comRegs.hStart;
REG.VI_X_SCALE = &cfb->viMode->comRegs.xScale;
REG.VI_V_CURRENT_LINE = &cfb->viMode->comRegs.vCurrent;
REG.VI_ORIGIN = &cfb->viMode->fldRegs->origin;//This is incorrect REG.VI_ORIGIN should contain only 24 bits of the frame buffer address
REG.VI_Y_SCALE = &cfb->viMode->fldRegs->yScale;
REG.VI_V_START = &cfb->viMode->fldRegs->vStart;
REG.VI_V_BURST = &cfb->viMode->fldRegs->vBurst;
REG.VI_INTR = &cfb->viMode->fldRegs->vIntr;
}
}
Config config;

View File

@ -52,6 +52,109 @@ typedef struct {
/* 0x3C */ u32 yield_data_size;
} OSTask_t; // size = 0x40
//Copied over from OOT - needs cleanup
struct Gfx;
struct OSThread;
typedef void* OSMesg;
typedef struct OSMesgQueue {
/* 0x00 */ OSThread* mtqueue;
/* 0x04 */ OSThread* fullqueue;
/* 0x08 */ s32 validCount;
/* 0x0C */ s32 first;
/* 0x10 */ s32 msgCount;
/* 0x14 */ OSMesg* msg;
} OSMesgQueue; // size = 0x18
typedef struct {
/* 0x0000 */ u32 size;
/* 0x0004 */ Gfx* bufp;
/* 0x0008 */ Gfx* p;
/* 0x000C */ Gfx* d;
} TwoHeadGfxArena; // size = 0x10
typedef struct CfbInfo {
/* 0x00 */ u32* fb1;//Address to the frame buffer
/* 0x04 */ u32* swapBuffer;
/* 0x08 */ OSViMode* viMode;
/* 0x0C */ u32 features;
/* 0x10 */ u8 unk_10;
/* 0x11 */ s8 updateRate;
/* 0x12 */ s8 updateRate2;
/* 0x13 */ u8 unk_13;
/* 0x14 */ f32 xScale;
/* 0x18 */ f32 yScale;
} CfbInfo; // size = 0x1C
typedef union {
OSTask_t t;
long long int force_structure_alignment;
} OSTask;
typedef struct OSScTask {
/* 0x00 */ struct OSScTask* next;
/* 0x04 */ u32 state;
/* 0x08 */ u32 flags;
/* 0x0C */ CfbInfo* framebuffer;
/* 0x10 */ OSTask list;
/* 0x50 */ OSMesgQueue* msgQ;
/* 0x54 */ OSMesg msg;
} OSScTask;
typedef struct GraphicsContext {
/* 0x0000 */ Gfx* polyOpaBuffer; // Pointer to "Zelda 0"
/* 0x0004 */ Gfx* polyXluBuffer; // Pointer to "Zelda 1"
/* 0x0008 */ char unk_008[0x08]; // Unused, could this be pointers to "Zelda 2" / "Zelda 3"
/* 0x0010 */ Gfx* overlayBuffer; // Pointer to "Zelda 4"
/* 0x0014 */ u32 unk_014;
/* 0x0018 */ char unk_018[0x20];
/* 0x0038 */ OSMesg msgBuff[0x08];
/* 0x0058 */ OSMesgQueue* schedMsgQ;
/* 0x005C */ OSMesgQueue queue;
/* 0x0074 */ char unk_074[0x04];
/* 0x0078 */ OSScTask task; // size of OSScTask might be wrong
/* 0x00D0 */ char unk_0D0[0xE0];
/* 0x01B0 */ Gfx* workBuffer;
/* 0x01B4 */ TwoHeadGfxArena work;
/* 0x01C4 */ char unk_01C4[0xC0];
/* 0x0284 */ OSViMode* viMode;
/* 0x0288 */ char unk_0288[0x20]; // Unused, could this be Zelda 2/3 ?
/* 0x02A8 */ TwoHeadGfxArena overlay; // "Zelda 4"
/* 0x02B8 */ TwoHeadGfxArena polyOpa; // "Zelda 0"
/* 0x02C8 */ TwoHeadGfxArena polyXlu; // "Zelda 1"
/* 0x02D8 */ u32 gfxPoolIdx;
/* 0x02DC */ u32* curFrameBuffer;
/* 0x02E0 */ char unk_2E0[0x04];
/* 0x02E4 */ u32 viFeatures;
/* 0x02E8 */ s32 fbIdx;
/* 0x02EC */ void (*callback)(struct GraphicsContext*, void*);
/* 0x02F0 */ void* callbackParam;
/* 0x02F4 */ f32 xScale;
/* 0x02F8 */ f32 yScale;
/* 0x02FC */ char unk_2FC[0x04];
} GraphicsContext; // size = 0x300
#define REG_GROUPS 29 // number of REG groups, i.e. REG, SREG, OREG, etc.
#define REG_PAGES 6
#define REG_PER_PAGE 16
#define REG_PER_GROUP REG_PAGES * REG_PER_PAGE
typedef struct {
/* 0x00 */ s32 regPage; // 1 is first page
/* 0x04 */ s32 regGroup; // "register" group (R, RS, RO, RP etc.)
/* 0x08 */ s32 regCur; // selected register within page
/* 0x0C */ s32 dpadLast;
/* 0x10 */ s32 repeat;
/* 0x14 */ s16 data[REG_GROUPS * REG_PER_GROUP]; // 0xAE0 entries
} GameInfo; // size = 0x15D4
#define BASE_REG(n, r) GameInfo->data[n * REG_PER_GROUP + r]
#define SREG(r) BASE_REG(1, r)
#define R_UPDATE_RATE SREG(30)
extern "C" {
void gfx_init(const char* romName, OSViMode* viMode);
void gfx_shutdown();