mirror of
https://github.com/dolphin-emu/fifoplayer.git
synced 2026-01-31 01:05:16 +01:00
312 lines
8.1 KiB
C++
312 lines
8.1 KiB
C++
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
typedef unsigned int u32;
|
|
typedef unsigned char u8;
|
|
|
|
std::map<u32, std::vector<u8> > memory_map; // map of memory chunks (indexed by starting address)
|
|
|
|
bool IntersectsMemoryRange(u32 start1, u32 size1, u32 start2, u32 size2)
|
|
{
|
|
return size1 && size2 && ((start1 >= start2 && start1 < start2 + size2) ||
|
|
(start2 >= start1 && start2 < start1 + size1));
|
|
}
|
|
|
|
void PrepareMemoryLoad(u32 start_addr, u32 size)
|
|
{
|
|
std::vector<u32> affected_elements;
|
|
u32 new_start_addr = start_addr;
|
|
u32 new_end_addr = start_addr + size - 1;
|
|
|
|
// Find overlaps with existing memory chunks
|
|
for (auto it = memory_map.begin(); it != memory_map.end(); ++it)
|
|
{
|
|
if (IntersectsMemoryRange(it->first, it->second.size(), start_addr, size))
|
|
{
|
|
affected_elements.push_back(it->first);
|
|
if (it->first < new_start_addr)
|
|
new_start_addr = it->first;
|
|
if (it->first + it->second.size() > new_end_addr + 1)
|
|
new_end_addr = it->first + it->second.size() - 1;
|
|
}
|
|
}
|
|
|
|
std::vector<u8>& new_memchunk = memory_map[new_start_addr]; // creates a new vector or uses the existing one
|
|
u32 new_size = new_end_addr - new_start_addr + 1;
|
|
|
|
// if the new memory range is inside an existing chunk, there's nothing to do
|
|
if (new_memchunk.size() == new_size)
|
|
return;
|
|
|
|
// resize chunk to required size, move old content to it, replace old arrays with new one
|
|
// NOTE: can't do reserve here because not the whole memory might be covered by existing memory chunks
|
|
new_memchunk.resize(new_size);
|
|
while (!affected_elements.empty())
|
|
{
|
|
u32 addr = affected_elements.back();
|
|
|
|
// first chunk is already in new_memchunk
|
|
if (addr != new_start_addr)
|
|
{
|
|
std::vector<u8>& src = memory_map[addr];
|
|
memcpy(&new_memchunk[addr - new_start_addr], &src[0], src.size());
|
|
memory_map.erase(addr);
|
|
}
|
|
affected_elements.pop_back();
|
|
}
|
|
|
|
// TODO: Handle critical case where memory allocation fails!
|
|
}
|
|
|
|
// Must have been reserved via PrepareMemoryLoad first
|
|
u8* GetPointer(u32 addr)
|
|
{
|
|
for (auto it = memory_map.begin(); it != memory_map.end(); ++it)
|
|
if (addr >= it->first && addr < it->first + it->second.size())
|
|
return &it->second[addr - it->first];
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#include <malloc.h>
|
|
#include <gccore.h>
|
|
#include <wiiuse/wpad.h>
|
|
|
|
#define DEFAULT_FIFO_SIZE (256*1024)
|
|
|
|
static void *frameBuffer[2] = { NULL, NULL};
|
|
GXRModeObj *rmode;
|
|
|
|
u32 fb = 0;
|
|
u32 first_frame = 1;
|
|
Mtx view;
|
|
Mtx model, modelview;
|
|
void Init()
|
|
{
|
|
f32 yscale;
|
|
|
|
u32 xfbHeight;
|
|
|
|
Mtx44 perspective;
|
|
|
|
GXColor background = { 0, 0, 0, 0xff };
|
|
|
|
VIDEO_Init();
|
|
|
|
rmode = VIDEO_GetPreferredMode(NULL);
|
|
first_frame = 1;
|
|
fb = 0;
|
|
frameBuffer[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); // TODO: Shouldn't require manual framebuffer management!
|
|
frameBuffer[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
|
|
|
VIDEO_Configure(rmode);
|
|
VIDEO_SetNextFramebuffer(frameBuffer[fb]);
|
|
VIDEO_SetBlack(FALSE);
|
|
VIDEO_Flush();
|
|
VIDEO_WaitVSync();
|
|
if(rmode->viTVMode & VI_NON_INTERLACE)
|
|
VIDEO_WaitVSync();
|
|
fb ^= 1;
|
|
|
|
void *gp_fifo = NULL;
|
|
gp_fifo = memalign(32,DEFAULT_FIFO_SIZE);
|
|
memset(gp_fifo,0,DEFAULT_FIFO_SIZE);
|
|
|
|
GX_Init(gp_fifo,DEFAULT_FIFO_SIZE);
|
|
|
|
// clears the bg to color and clears the z buffer
|
|
GX_SetCopyClear(background, 0x00ffffff);
|
|
|
|
// other gx setup
|
|
GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
|
|
yscale = GX_GetYScaleFactor(rmode->efbHeight,rmode->xfbHeight);
|
|
xfbHeight = GX_SetDispCopyYScale(yscale);
|
|
GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
|
|
GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight);
|
|
GX_SetDispCopyDst(rmode->fbWidth,xfbHeight);
|
|
GX_SetCopyFilter(rmode->aa,rmode->sample_pattern,GX_TRUE,rmode->vfilter);
|
|
GX_SetFieldMode(rmode->field_rendering,((rmode->viHeight==2*rmode->xfbHeight)?GX_ENABLE:GX_DISABLE));
|
|
|
|
if (rmode->aa)
|
|
GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR);
|
|
else
|
|
GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
|
|
|
|
GX_SetCullMode(GX_CULL_NONE);
|
|
GX_CopyDisp(frameBuffer[fb],GX_TRUE);
|
|
GX_SetDispCopyGamma(GX_GM_1_0);
|
|
|
|
GX_ClearVtxDesc();
|
|
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
|
|
|
|
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
|
|
|
GX_SetNumChans(1);
|
|
GX_SetNumTexGens(0);
|
|
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0);
|
|
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
|
|
|
|
guVector cam = {0.0F, 0.0F, 0.0F},
|
|
up = {0.0F, 1.0F, 0.0F},
|
|
look = {0.0F, 0.0F, -1.0F};
|
|
|
|
guLookAt(view, &cam, &up, &look);
|
|
|
|
f32 w = rmode->viWidth;
|
|
f32 h = rmode->viHeight;
|
|
guPerspective(perspective, 45, (f32)w/h, 0.1F, 300.0F);
|
|
GX_LoadProjectionMtx(perspective, GX_PERSPECTIVE);
|
|
|
|
WPAD_Init();
|
|
}
|
|
|
|
#include "mygx.h"
|
|
|
|
int main()
|
|
{
|
|
Init();
|
|
|
|
GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 3); // Apply dirty state
|
|
wgPipe->F32 = 0.0f; wgPipe->F32 = 1.0f; wgPipe->F32 = 0.0f; // Top
|
|
wgPipe->F32 = -1.0f; wgPipe->F32 = -1.0f; wgPipe->F32 = 0.0f; // Bottom left
|
|
wgPipe->F32 = 1.0f; wgPipe->F32 = -1.0f; wgPipe->F32 = 0.0f; // Bottom right
|
|
GX_End();
|
|
|
|
bool processing = true;
|
|
int first_frame = 0;
|
|
int last_frame = 0;
|
|
int cur_frame = first_frame;
|
|
while (processing)
|
|
{
|
|
// for (element = frame_elements[cur_frame])
|
|
{
|
|
// switch (element.type)
|
|
{
|
|
// case LOAD_REG:
|
|
// if (is_bp_reg)
|
|
{
|
|
// if (teximage3)
|
|
{
|
|
// TODO: Decode addr
|
|
// GetPointer(addr);
|
|
// TODO: Encode addr
|
|
}
|
|
// if (trigger_efbcopy)
|
|
{
|
|
// PrepareMemoryLoad(dest_addr, dest_size);
|
|
// TODO: Decode addr
|
|
// GetPointer(addr);
|
|
// TODO: Encode addr
|
|
}
|
|
}
|
|
// break;
|
|
// case LOAD_MEM:
|
|
// PrepareMemoryLoad(start_addr, size);
|
|
// memcpy (GetPointer(element.start_addr), element.data, element.size);
|
|
// break;
|
|
}
|
|
}
|
|
|
|
// Simple testing code
|
|
// GX_SetViewport
|
|
wgPipe->U8 = 0x10;
|
|
wgPipe->U32 = (u32)((5<<16)|0x101a);
|
|
wgPipe->F32 = rmode->fbWidth * 0.5;
|
|
wgPipe->F32 = (-rmode->efbHeight) * 0.5;
|
|
wgPipe->F32 = 1*16777215.0;
|
|
wgPipe->F32 = rmode->fbWidth * 0.5 + 342.0;
|
|
wgPipe->F32 = rmode->efbHeight * 0.5 + 342.0;
|
|
wgPipe->F32 = 1*16777215.0;
|
|
|
|
// InvVtxCache
|
|
wgPipe->U8 = 0x48;
|
|
|
|
guMtxIdentity(model);
|
|
guMtxTransApply(model, model, -1.5f,0.0f,-6.0f);
|
|
guMtxConcat(view,model,modelview);
|
|
wgPipe->U8 = 0x10;
|
|
wgPipe->U32 = (u32)((11<<16)|(_SHIFTL(GX_PNMTX0,2,8)));
|
|
for (unsigned int i = 0;i < 12; ++i)
|
|
{
|
|
wgPipe->F32 = ((f32*)modelview)[i];
|
|
}
|
|
|
|
// Setup vtx desc
|
|
wgPipe->U8 = 0x08;
|
|
wgPipe->U8 = 0x50;
|
|
wgPipe->U32 = _SHIFTL(GX_DIRECT,9,2);
|
|
|
|
wgPipe->U8 = 0x08;
|
|
wgPipe->U8 = 0x60;
|
|
wgPipe->U32 = 0;
|
|
|
|
wgPipe->U8 = 0x10;
|
|
wgPipe->U32 = 0x1008;
|
|
wgPipe->U32 = 0;
|
|
|
|
// Draw a triangle
|
|
wgPipe->U8 = GX_TRIANGLES|(GX_VTXFMT0&7);
|
|
wgPipe->U16 = 3;
|
|
wgPipe->F32 = 0.0f; wgPipe->F32 = 1.0f; wgPipe->F32 = 0.0f; // Top
|
|
wgPipe->F32 = -1.0f; wgPipe->F32 = -1.0f; wgPipe->F32 = 0.0f; // Bottom left
|
|
wgPipe->F32 = 1.0f; wgPipe->F32 = -1.0f; wgPipe->F32 = 0.0f; // Bottom right
|
|
|
|
guMtxTransApply(model, model, 3.0f,0.0f,0.0f);
|
|
guMtxConcat(view,model,modelview);
|
|
wgPipe->U8 = 0x10;
|
|
wgPipe->U32 = (u32)((11<<16)|(_SHIFTL(GX_PNMTX0,2,8)));
|
|
for (unsigned int i = 0;i < 12; ++i)
|
|
{
|
|
wgPipe->F32 = ((f32*)modelview)[i];
|
|
}
|
|
|
|
// Draw a quad
|
|
wgPipe->U8 = GX_QUADS|(GX_VTXFMT0&7);
|
|
wgPipe->U16 = 4;
|
|
wgPipe->F32 = -1.0f; wgPipe->F32 = 1.0f; wgPipe->F32 = 0.0f; // Top left
|
|
wgPipe->F32 = 1.0f; wgPipe->F32 = 1.0f; wgPipe->F32 = 0.0f; // Top right
|
|
wgPipe->F32 = 1.0f; wgPipe->F32 = -1.0f; wgPipe->F32 = 0.0f; // Bottom right
|
|
wgPipe->F32 = -1.0f; wgPipe->F32 = -1.0f; wgPipe->F32 = 0.0f; // Bottom left
|
|
|
|
// finish frame...
|
|
GX_DrawDone();
|
|
GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
|
|
GX_SetColorUpdate(GX_TRUE);
|
|
GX_CopyDisp(frameBuffer[fb],GX_TRUE);
|
|
|
|
VIDEO_SetNextFramebuffer(frameBuffer[fb]);
|
|
if (first_frame)
|
|
{
|
|
VIDEO_SetBlack(FALSE);
|
|
first_frame = 0;
|
|
}
|
|
|
|
VIDEO_Flush();
|
|
VIDEO_WaitVSync();
|
|
fb ^= 1;
|
|
|
|
// TODO: Menu stuff
|
|
// reset GX state
|
|
// draw menu
|
|
// restore GX state
|
|
|
|
// input checking
|
|
// A = select menu point
|
|
// B = menu back
|
|
// plus = pause
|
|
// minus = hide menu
|
|
// home = stop
|
|
WPAD_ScanPads();
|
|
|
|
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)
|
|
processing = false;
|
|
|
|
++cur_frame;
|
|
cur_frame = first_frame + ((cur_frame-first_frame) % (last_frame-first_frame+1));
|
|
}
|
|
|
|
return 0;
|
|
}
|