Basic IGGY renderer implementation, do not PR.

This commit is contained in:
JuiceyDev 2026-03-05 16:54:56 +01:00
parent 299564be0a
commit cb4e0e82b7
6 changed files with 157 additions and 24 deletions

View file

@ -160,6 +160,14 @@ static GLenum mapPrimType(int pt)
}
}
// clientside awawawa
static bool isCompilingDisplayList()
{
GLint listMode = 0;
::glGetIntegerv(GL_LIST_MODE, &listMode);
return (listMode == GL_COMPILE || listMode == GL_COMPILE_AND_EXECUTE);
}
void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count,
void *dataIn, eVertexType vType,
C4JRender::ePixelShaderType psType)
@ -169,19 +177,39 @@ void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count,
GLenum mode = mapPrimType((int)PrimitiveType);
unsigned char *data = (unsigned char *)dataIn;
// Vertex layout: 3 floats pos, 2 floats tex, 4 bytes color, 4 bytes normal, 4 bytes padding = 32 bytes
const int stride = 32;
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
::glEnableClientState(GL_COLOR_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
if (isCompilingDisplayList()) {
// run.
::glBegin(mode);
for (int i = 0; i < count; i++) {
unsigned char *v = data + i * stride;
float *pos = (float *)(v);
float *tex = (float *)(v + 12);
unsigned char *col = v + 20;
signed char *nrm = (signed char *)(v + 24);
::glVertexPointer(3, GL_FLOAT, stride, data);
::glTexCoordPointer(2, GL_FLOAT, stride, data + 12);
::glColorPointer(4, GL_UNSIGNED_BYTE, stride, data + 20);
::glNormalPointer(GL_BYTE, stride, data + 24);
::glNormal3f(nrm[0] / 127.0f, nrm[1] / 127.0f, nrm[2] / 127.0f);
::glColor4ub(col[0], col[1], col[2], col[3]);
::glTexCoord2f(tex[0], tex[1]);
::glVertex3f(pos[0], pos[1], pos[2]);
}
::glEnd();
} else {
// waiter ! fast vertex pls !
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
::glEnableClientState(GL_COLOR_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
::glDrawArrays(mode, 0, count);
::glVertexPointer(3, GL_FLOAT, stride, data);
::glTexCoordPointer(2, GL_FLOAT, stride, data + 12);
::glColorPointer(4, GL_UNSIGNED_BYTE, stride, data + 20);
::glNormalPointer(GL_BYTE, stride, data + 24);
::glDrawArrays(mode, 0, count);
}
}

View file

@ -2,6 +2,10 @@
#include "UI.h"
#include "UIScene_Intro.h"
#ifdef __linux__
static int s_introTickCount = 0;
#endif
#include <Linux_UIController.h>
UIScene_Intro::UIScene_Intro(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
@ -9,6 +13,9 @@ UIScene_Intro::UIScene_Intro(int iPad, void *initData, UILayer *parentLayer) : U
initialiseMovie();
m_bIgnoreNavigate = false;
m_bAnimationEnded = false;
#ifdef __linux__
s_introTickCount = 0;
#endif
bool bSkipESRB = false;
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
@ -166,3 +173,22 @@ void UIScene_Intro::handleGainFocus(bool navBack)
ui.NavigateToScene(0,eUIScene_MainMenu);
}
}
#ifdef __linux__
void UIScene_Intro::tick()
{
// Call base tick first (processes Iggy ticking)
UIScene::tick();
// Auto-skip the intro after 60 ticks (~2 seconds at 30fps)
// since we have no SWF renderer to play the intro animation
s_introTickCount++;
if(s_introTickCount == 60 && !m_bIgnoreNavigate)
{
fprintf(stderr, "[Linux] Auto-skipping intro -> MainMenu after %d ticks\n", s_introTickCount);
m_bIgnoreNavigate = true;
// Skip straight to MainMenu, bypassing SaveMessage (no SWF interaction possible)
ui.NavigateToScene(0, eUIScene_MainMenu);
}
}
#endif

View file

@ -45,6 +45,10 @@ public:
virtual void handleAnimationEnd();
virtual void handleGainFocus(bool navBack);
#ifdef __linux__
virtual void tick();
#endif
#ifdef __PSVITA__
virtual void handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased);
#endif

View file

@ -1802,6 +1802,19 @@ void UIScene_MainMenu::tick()
{
UIScene::tick();
#ifdef __linux__
{
static int s_mainMenuTickCount = 0;
s_mainMenuTickCount++;
if(s_mainMenuTickCount == 90) // ~3 seconds at 30fps
{
fprintf(stderr, "[Linux] Auto-starting trial world from MainMenu after %d ticks\n", s_mainMenuTickCount);
LoadTrial();
return;
}
}
#endif
#if defined(__PS3__) || defined (__ORBIS__) || defined(__PSVITA__)
if(m_bLaunchFullVersionPurchase)
{

View file

@ -36,29 +36,55 @@ RADEXPFUNC inline void RADEXPLINK IggyPlayerDrawTilesEnd(Iggy *f) {
STUBBED;
}
static int thing = 0;
// Each fake Iggy player gets its own state block
struct FakeIggyPlayer {
int tickCount;
bool needsTick;
IggyProperties props;
void *userdata;
};
// Simple player pool
static FakeIggyPlayer s_fakePlayers[64];
static int s_fakePlayerCount = 0;
RADEXPFUNC inline Iggy * RADEXPLINK IggyPlayerCreateFromMemory(
void const * data,
U32 data_size_in_bytes,
IggyPlayerConfig *config) {
STUBBED;
return (Iggy*)&thing;
if(s_fakePlayerCount >= 64) return nullptr;
FakeIggyPlayer *fp = &s_fakePlayers[s_fakePlayerCount++];
fp->tickCount = 0;
fp->needsTick = true;
fp->userdata = nullptr;
// Default to 1920x1080 at 30fps
memset(&fp->props, 0, sizeof(fp->props));
fp->props.movie_width_in_pixels = 1920;
fp->props.movie_height_in_pixels = 1080;
fp->props.movie_frame_rate_from_file_in_fps = 30.0f;
fp->props.movie_frame_rate_current_in_fps = 30.0f;
fprintf(stderr, "[Iggy Stub] Created fake player %d (data=%p, size=%u)\n", s_fakePlayerCount-1, data, data_size_in_bytes);
return (Iggy*)fp;
}
static FakeIggyPlayer* getFakePlayer(Iggy *player) {
return (FakeIggyPlayer*)player;
}
RADEXPFUNC inline void RADEXPLINK IggyPlayerInitializeAndTickRS(Iggy *player) {
STUBBED;
FakeIggyPlayer *fp = getFakePlayer(player);
if(fp) { fp->tickCount = 0; fp->needsTick = true; }
}
static IggyProperties properties;
RADEXPFUNC inline IggyProperties * RADEXPLINK IggyPlayerProperties(Iggy *player) {
STUBBED;
return &properties;
FakeIggyPlayer *fp = getFakePlayer(player);
if(fp) return &fp->props;
static IggyProperties defaultProps = {};
return &defaultProps;
}
RADEXPFUNC inline void RADEXPLINK IggyPlayerSetUserdata(Iggy *player, void *userdata) {
STUBBED;
FakeIggyPlayer *fp = getFakePlayer(player);
if(fp) fp->userdata = userdata;
}
RADEXPFUNC inline IggyName RADEXPLINK IggyPlayerCreateFastName(Iggy *f, IggyUTF16 const *name, S32 len) {
STUBBED;
@ -69,14 +95,22 @@ RADEXPFUNC inline rrbool RADEXPLINK IggyDebugGetMemoryUseInfo(Iggy *player, Iggy
return false;
}
RADEXPFUNC inline rrbool RADEXPLINK IggyPlayerReadyToTick(Iggy *player) {
STUBBED;
FakeIggyPlayer *fp = getFakePlayer(player);
if(fp && fp->needsTick) return true;
return false;
}
RADEXPFUNC inline void RADEXPLINK IggyPlayerTickRS(Iggy *player) {
STUBBED;
FakeIggyPlayer *fp = getFakePlayer(player);
if(fp) {
fp->tickCount++;
// Allow one tick per frame cycle
fp->needsTick = false;
}
}
RADEXPFUNC inline void RADEXPLINK IggyPlayerDraw(Iggy *f) {
STUBBED;
// Re-arm tick for next frame
FakeIggyPlayer *fp = getFakePlayer(f);
if(fp) fp->needsTick = true;
}
RADEXPFUNC inline void RADEXPLINK IggyMakeEventKey(IggyEvent *event, IggyKeyevent event_type, IggyKeycode keycode, IggyKeyloc keyloc) {
STUBBED;
@ -144,7 +178,8 @@ RADEXPFUNC inline void RADEXPLINK IggySetTextureSubstitutionCallbacks(Iggy_Textu
STUBBED;
}
RADEXPFUNC inline void * RADEXPLINK IggyPlayerGetUserdata(Iggy *player) {
STUBBED;
FakeIggyPlayer *fp = getFakePlayer(player);
if(fp) return fp->userdata;
return 0;
}
RADEXPFUNC inline IggyLibrary RADEXPLINK IggyLibraryCreateFromMemoryUTF16(
@ -186,4 +221,7 @@ RADEXPFUNC inline void RADEXPLINK IggyInstallPerfmon(void *perfmon) {
STUBBED;
}
// GDraw memory/warning functions are defined in gdraw_glfw.c (C linkage)
// Juicey you stupid idiot do NOT define them here
#endif // IGGYSTUBS_H

View file

@ -5,6 +5,7 @@
#include <cassert>
#include <cstdarg>
#include <sys/mman.h>
#define TRUE true
#define FALSE false
@ -967,11 +968,34 @@ static inline int swprintf_s(wchar_t* buf, size_t sz, const wchar_t* fmt, ...) {
static inline HMODULE GetModuleHandle(LPCSTR lpModuleName) { return 0; }
static inline LPVOID VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) {
assert(0 && "FIXME: implement VirtualAlloc");
// MEM_COMMIT | MEM_RESERVE → mmap anonymous
int prot = 0;
if (flProtect == 0x04 /*PAGE_READWRITE*/) prot = PROT_READ | PROT_WRITE;
else if (flProtect == 0x40 /*PAGE_EXECUTE_READWRITE*/) prot = PROT_READ | PROT_WRITE | PROT_EXEC;
else if (flProtect == 0x02 /*PAGE_READONLY*/) prot = PROT_READ;
else prot = PROT_READ | PROT_WRITE; // default
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
if (lpAddress != NULL) flags |= MAP_FIXED;
void *p = mmap(lpAddress, dwSize, prot, flags, -1, 0);
if (p == MAP_FAILED) return NULL;
return p;
}
static inline BOOL VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) {
assert(0 && "FIXME: implement VirtualFree");
if (lpAddress == NULL) return FALSE;
// MEM_RELEASE (0x8000) frees the whole region
if (dwFreeType == 0x8000 /*MEM_RELEASE*/) {
// dwSize should be 0 for MEM_RELEASE per Win32 API, but we don't track allocation sizes
// Use dwSize if provided, otherwise this is a best-effort
if (dwSize == 0) dwSize = 4096; // minimum page
munmap(lpAddress, dwSize);
} else {
// MEM_DECOMMIT (0x4000) - just decommit (make inaccessible)
madvise(lpAddress, dwSize, MADV_DONTNEED);
}
return TRUE;
}
#define swscanf_s swscanf