Implement config option for interlaced video.

This commit is contained in:
hackgrid 2023-10-18 22:41:23 +02:00
parent 2227af6a9e
commit 2b3dda58e4
7 changed files with 90 additions and 44 deletions

View file

@ -9,7 +9,6 @@
#define MAX_FRAME_BUFFER_MESGS 8
#define HIGH_RES 0
#define INTERLACED 0
#define INIT_PRIORITY 10
#define GAME_PRIORITY 10

View file

@ -1,2 +1,7 @@
#ifndef __LOCALES_H__
#define __LOCALES_H__
int getAudioLanguage();
int mapLocaleSound(int soundId);
#endif

View file

@ -1,4 +1,3 @@
#include <ultra64.h>
#include <sched.h>
@ -26,6 +25,7 @@
#include "levels/levels.h"
#include "savefile/checkpoint.h"
#include "main.h"
#ifdef PORTAL64_WITH_DEBUGGER
#include "../debugger/debugger.h"
@ -52,8 +52,7 @@ static OSScClient gfxClient;
OSSched scheduler;
u64 scheduleStack[OS_SC_STACKSIZE/8];
OSMesgQueue *schedulerCommandQueue;
u8 schedulerMode = OS_VI_NTSC_LPF1;
u8 schedulerMode;
OSPiHandle *gPiHandle;
void boot(void *arg) {
@ -143,26 +142,36 @@ void levelLoadWithCallbacks(int levelIndex) {
int updateSchedulerModeAndGetFPS() {
int fps = 60;
schedulerMode = INTERLACED ? OS_VI_NTSC_LPF1 : OS_VI_NTSC_LPN1;
int interlacedMode = (gSaveData.controls.flags & ControlSaveInterlacedMode) != 0 ? 1 : 0;
schedulerMode = interlacedMode ? OS_VI_NTSC_LPF1 : OS_VI_NTSC_LPN1;
switch (osTvType) {
case 0: // PAL
schedulerMode = HIGH_RES ? (INTERLACED ? OS_VI_PAL_HPF1 : OS_VI_PAL_HPN1) : (INTERLACED ? OS_VI_PAL_LPF1 : OS_VI_PAL_LPN1);
schedulerMode = HIGH_RES ? (interlacedMode ? OS_VI_PAL_HPF1 : OS_VI_PAL_HPN1) : (interlacedMode ? OS_VI_PAL_LPF1 : OS_VI_PAL_LPN1);
fps = 50;
break;
case 1: // NTSC
schedulerMode = HIGH_RES ? (INTERLACED ? OS_VI_NTSC_HPF1 : OS_VI_NTSC_HPN1) : (INTERLACED ? OS_VI_NTSC_LPF1 : OS_VI_NTSC_LPN1);
schedulerMode = HIGH_RES ? (interlacedMode ? OS_VI_NTSC_HPF1 : OS_VI_NTSC_HPN1) : (interlacedMode ? OS_VI_NTSC_LPF1 : OS_VI_NTSC_LPN1);
break;
case 2: // MPAL
schedulerMode = HIGH_RES ? (INTERLACED ? OS_VI_MPAL_HPF1 : OS_VI_MPAL_HPN1) : (INTERLACED ? OS_VI_MPAL_LPF1 : OS_VI_MPAL_LPN1);
schedulerMode = HIGH_RES ? (interlacedMode ? OS_VI_MPAL_HPF1 : OS_VI_MPAL_HPN1) : (interlacedMode ? OS_VI_MPAL_LPF1 : OS_VI_MPAL_LPN1);
break;
}
return fps;
}
void setViMode(int reload) {
if (reload)
updateSchedulerModeAndGetFPS();
osViSetMode(&osViModeTable[schedulerMode]);
}
static void gameProc(void* arg) {
int fps = updateSchedulerModeAndGetFPS();
schedulerMode = OS_VI_NTSC_LPF1;
int fps = 60;
osCreateScheduler(
&scheduler,
@ -208,7 +217,11 @@ static void gameProc(void* arg) {
dynamicSceneInit();
contactSolverInit(&gContactSolver);
portalSurfaceCleanupQueueInit();
savefileLoad();
fps = updateSchedulerModeAndGetFPS();
setViMode(0);
levelLoadWithCallbacks(MAIN_MENU);
gCurrentTestSubject = 0;
cutsceneRunnerReset();

View file

@ -8,6 +8,8 @@
#include "../build/assets/materials/ui.h"
#include "../build/src/audio/clips.h"
#include "../main.h"
#define GAMEPLAY_Y 54
#define GAMEPLAY_WIDTH 252
#define GAMEPLAY_HEIGHT 124
@ -53,17 +55,20 @@ void gameplayOptionsHandleSlider(unsigned short* settingValue, float* sliderValu
}
void gameplayOptionsInit(struct GameplayOptions* gameplayOptions) {
gameplayOptions->selectedItem = GameplayOptionMovingPortals;
gameplayOptions->selectedItem = GameplayOptionWideScreen;
gameplayOptions->wideScreen = menuBuildCheckbox(&gDejaVuSansFont, "Wide Screen", GAMEPLAY_X + 8, GAMEPLAY_Y + 8);
gameplayOptions->interlacedMode = menuBuildCheckbox(&gDejaVuSansFont, "Interlaced Video", GAMEPLAY_X + 8, GAMEPLAY_Y + 28);
gameplayOptions->movingPortals = menuBuildCheckbox(&gDejaVuSansFont, "Movable Portals", GAMEPLAY_X + 8, GAMEPLAY_Y + 48);
gameplayOptions->portalFunnel = menuBuildCheckbox(&gDejaVuSansFont, "Portal Funneling", GAMEPLAY_X + 8, GAMEPLAY_Y + 68);
gameplayOptions->movingPortals = menuBuildCheckbox(&gDejaVuSansFont, "Movable Portals", GAMEPLAY_X + 8, GAMEPLAY_Y + 8);
gameplayOptions->wideScreen = menuBuildCheckbox(&gDejaVuSansFont, "Wide Screen", GAMEPLAY_X + 8, GAMEPLAY_Y + 28);
gameplayOptions->portalFunnel = menuBuildCheckbox(&gDejaVuSansFont, "Portal Funneling", GAMEPLAY_X + 8, GAMEPLAY_Y + 48);
gameplayOptions->portalRenderDepthText = menuBuildText(&gDejaVuSansFont, "Portal Render Depth", GAMEPLAY_X + 8, GAMEPLAY_Y + 68);
gameplayOptions->portalRenderDepth = menuBuildSlider(GAMEPLAY_X + 126, GAMEPLAY_Y + 68, 126, SCROLL_TICKS);
gameplayOptions->movingPortals.checked = (gSaveData.controls.flags & ControlSaveMoveablePortals) != 0;
gameplayOptions->portalRenderDepthText = menuBuildText(&gDejaVuSansFont, "Portal Render Depth", GAMEPLAY_X + 8, GAMEPLAY_Y + 88);
gameplayOptions->portalRenderDepth = menuBuildSlider(GAMEPLAY_X + 126, GAMEPLAY_Y + 88, 126, SCROLL_TICKS);
gameplayOptions->wideScreen.checked = (gSaveData.controls.flags & ControlSaveWideScreen) != 0;
gameplayOptions->interlacedMode.checked = (gSaveData.controls.flags & ControlSaveInterlacedMode) != 0;
gameplayOptions->movingPortals.checked = (gSaveData.controls.flags & ControlSaveMoveablePortals) != 0;
gameplayOptions->portalFunnel.checked = (gSaveData.controls.flags & ControlSavePortalFunneling) != 0;
gameplayOptions->portalRenderDepth.value = (float)(gSaveData.controls.portalRenderDepth / PORTAL_RENDER_DEPTH_MAX);
gameplayOptions->render_depth = (0xFFFF/PORTAL_RENDER_DEPTH_MAX)* gSaveData.controls.portalRenderDepth;
@ -94,18 +99,6 @@ enum MenuDirection gameplayOptionsUpdate(struct GameplayOptions* gameplayOptions
}
switch (gameplayOptions->selectedItem) {
case GameplayOptionMovingPortals:
if (controllerGetButtonDown(0, A_BUTTON)) {
gameplayOptions->movingPortals.checked = !gameplayOptions->movingPortals.checked;
soundPlayerPlay(SOUNDS_BUTTONCLICKRELEASE, 1.0f, 0.5f, NULL, NULL, SoundTypeAll);
if (gameplayOptions->movingPortals.checked) {
gSaveData.controls.flags |= ControlSaveMoveablePortals;
} else {
gSaveData.controls.flags &= ~ControlSaveMoveablePortals;
}
}
break;
case GameplayOptionWideScreen:
if (controllerGetButtonDown(0, A_BUTTON)) {
gameplayOptions->wideScreen.checked = !gameplayOptions->wideScreen.checked;
@ -118,6 +111,32 @@ enum MenuDirection gameplayOptionsUpdate(struct GameplayOptions* gameplayOptions
}
}
break;
case GameplayOptionInterlacedMode:
if (controllerGetButtonDown(0, A_BUTTON)) {
gameplayOptions->interlacedMode.checked = !gameplayOptions->interlacedMode.checked;
soundPlayerPlay(SOUNDS_BUTTONCLICKRELEASE, 1.0f, 0.5f, NULL, NULL, SoundTypeAll);
if (gameplayOptions->interlacedMode.checked) {
gSaveData.controls.flags |= ControlSaveInterlacedMode;
} else {
gSaveData.controls.flags &= ~ControlSaveInterlacedMode;
}
setViMode(1);
}
break;
case GameplayOptionMovingPortals:
if (controllerGetButtonDown(0, A_BUTTON)) {
gameplayOptions->movingPortals.checked = !gameplayOptions->movingPortals.checked;
soundPlayerPlay(SOUNDS_BUTTONCLICKRELEASE, 1.0f, 0.5f, NULL, NULL, SoundTypeAll);
if (gameplayOptions->movingPortals.checked) {
gSaveData.controls.flags |= ControlSaveMoveablePortals;
} else {
gSaveData.controls.flags &= ~ControlSaveMoveablePortals;
}
}
break;
case GameplayOptionPortalFunneling:
if (controllerGetButtonDown(0, A_BUTTON)) {
gameplayOptions->portalFunnel.checked = !gameplayOptions->portalFunnel.checked;
@ -160,13 +179,16 @@ enum MenuDirection gameplayOptionsUpdate(struct GameplayOptions* gameplayOptions
void gameplayOptionsRender(struct GameplayOptions* gameplayOptions, struct RenderState* renderState, struct GraphicsTask* task) {
gSPDisplayList(renderState->dl++, ui_material_list[SOLID_ENV_INDEX]);
gSPDisplayList(renderState->dl++, gameplayOptions->movingPortals.outline);
renderState->dl = menuCheckboxRender(&gameplayOptions->movingPortals, renderState->dl);
gSPDisplayList(renderState->dl++, gameplayOptions->wideScreen.outline);
renderState->dl = menuCheckboxRender(&gameplayOptions->wideScreen, renderState->dl);
gSPDisplayList(renderState->dl++, gameplayOptions->interlacedMode.outline);
renderState->dl = menuCheckboxRender(&gameplayOptions->interlacedMode, renderState->dl);
gSPDisplayList(renderState->dl++, gameplayOptions->movingPortals.outline);
renderState->dl = menuCheckboxRender(&gameplayOptions->movingPortals, renderState->dl);
gSPDisplayList(renderState->dl++, gameplayOptions->portalFunnel.outline);
renderState->dl = menuCheckboxRender(&gameplayOptions->portalFunnel, renderState->dl);
@ -184,6 +206,9 @@ void gameplayOptionsRender(struct GameplayOptions* gameplayOptions, struct Rende
menuSetRenderColor(renderState, gameplayOptions->selectedItem == GameplayOptionWideScreen, &gSelectionGray, &gColorWhite);
gSPDisplayList(renderState->dl++, gameplayOptions->wideScreen.text);
menuSetRenderColor(renderState, gameplayOptions->selectedItem == GameplayOptionInterlacedMode, &gSelectionGray, &gColorWhite);
gSPDisplayList(renderState->dl++, gameplayOptions->interlacedMode.text);
menuSetRenderColor(renderState, gameplayOptions->selectedItem == GameplayOptionPortalFunneling, &gSelectionGray, &gColorWhite);
gSPDisplayList(renderState->dl++, gameplayOptions->portalFunnel.text);
@ -192,4 +217,4 @@ void gameplayOptionsRender(struct GameplayOptions* gameplayOptions, struct Rende
gSPDisplayList(renderState->dl++, gameplayOptions->portalRenderDepthText);
gSPDisplayList(renderState->dl++, ui_material_revert_list[DEJAVU_SANS_INDEX]);
}
}

View file

@ -5,8 +5,9 @@
#include "../graphics/graphics.h"
enum GameplayOption {
GameplayOptionMovingPortals,
GameplayOptionWideScreen,
GameplayOptionInterlacedMode,
GameplayOptionMovingPortals,
GameplayOptionPortalFunneling,
GameplayOptionPortalRenderDepth,
@ -14,8 +15,9 @@ enum GameplayOption {
};
struct GameplayOptions {
struct MenuCheckbox movingPortals;
struct MenuCheckbox wideScreen;
struct MenuCheckbox interlacedMode;
struct MenuCheckbox movingPortals;
struct MenuCheckbox portalFunnel;
struct MenuSlider portalRenderDepth;
Gfx* portalRenderDepthText;
@ -27,4 +29,4 @@ void gameplayOptionsInit(struct GameplayOptions* gameplayOptions);
enum MenuDirection gameplayOptionsUpdate(struct GameplayOptions* gameplayOptions);
void gameplayOptionsRender(struct GameplayOptions* gameplayOptions, struct RenderState* renderState, struct GraphicsTask* task);
#endif
#endif

View file

@ -34,7 +34,7 @@ void savefileSramSave(void* dst, void* src, int size) {
OSIoMesg dmaIoMesgBuf;
// save chechpoint
// save checkpoint
dmaIoMesgBuf.hdr.pri = OS_MESG_PRI_HIGH;
dmaIoMesgBuf.hdr.retQueue = &dmaMessageQ;
dmaIoMesgBuf.dramAddr = src;
@ -92,6 +92,7 @@ void savefileNew() {
controllerSetDefaultSource();
gSaveData.controls.flags = 0;
gSaveData.controls.flags |= ControlSavePortalFunneling;
gSaveData.controls.flags |= ControlSaveInterlacedMode;
gSaveData.controls.sensitivity = 0x4000;
gSaveData.controls.acceleration = 0x4000;
gSaveData.controls.deadzone = 0x4000;
@ -334,4 +335,4 @@ void savefileGrabScreenshot() {
++dst;
}
}
}
}

View file

@ -20,7 +20,7 @@
#define SCREEN_SHOT_SRAM(slotIndex) (((slotIndex) + 1) * SAVE_SLOT_SIZE + MAX_CHECKPOINT_SIZE + SRAM_START_ADDR)
#define SAVEFILE_HEADER 0xDEF3
#define SAVEFILE_HEADER 0xDEF4
// first save slot is always reserved for auto save
#define MAX_SAVE_SLOTS ((int)(SRAM_SIZE / SAVE_SLOT_SIZE) - 1)
@ -44,6 +44,7 @@ enum ControlSaveFlags {
ControlSavePortalFunneling = (1 << 7),
ControlSaveMoveablePortals = (1 << 8),
ControlSaveWideScreen = (1 << 9),
ControlSaveInterlacedMode = (1 << 10),
};
struct ControlSaveState {
@ -106,4 +107,4 @@ extern u16 gScreenGrabBuffer[SAVE_SLOT_IMAGE_W * SAVE_SLOT_IMAGE_H];
void savefileGrabScreenshot();
#endif
#endif