diff --git a/config/sym_extern.us.txt b/config/sym_extern.us.txt index 73e3f8b7..f15f22ae 100644 --- a/config/sym_extern.us.txt +++ b/config/sym_extern.us.txt @@ -8,6 +8,7 @@ g_RewardMenuTable = 0x800697EC; g_EntityToLine = 0x8007078C; g_BattleMode = 0x800707BE; g_FieldScriptSyncWaitEntity = 0x80071A88; +g_PosCursorDisabled = 0x80071C1C; g_FieldMusicLock = 0x800716D4; g_FieldWaitCounter = 0x800716DC; g_SavedFieldScriptPC = 0x80071748; @@ -17,25 +18,27 @@ g_CurrentEntity = 0x800722C4; D_800730CC = 0x800730CC; g_MateriaData = 0x800730D0; g_FieldMapVars = 0x80075E24; +g_FieldModelAnimStatus = 0x800756E8; g_FieldText = 0x8007E7A8; g_FieldLines = 0x8007E7AC; g_EntityToModel = 0x8007EB98; g_EntitySplitJoinState = 0x80081D90; g_CharacterLock = 0x80081DC4; +g_FieldModelEffAnimSpeed = 0x80082248; g_FieldScriptPC = 0x800831FC; + +g_FieldModelAnimId = 0x8008325C; g_WindowToEntity = 0x8008326C; g_WindowData = 0x80083274; g_FieldScriptSyncState = 0x800833F8; g_FieldLineCount = 0x80095D84; +g_FieldPaletteBuffer = 0x80095DE0; D_80099788 = 0x80099788; D_8009A000 = 0x8009A000; D_8009A004 = 0x8009A004; D_8009A008 = 0x8009A008; D_8009A00C = 0x8009A00C; g_PartyMenuTables = 0x8009A0C8; -g_ActiveCharacters = 0x8009D84C; -g_CharacterLevelData = 0x8009D7E4; -g_BattleItemsEarned = 0x8009D808; g_FieldScriptPriority = 0x8009A1C4; g_FieldState = 0x8009ABF4; g_CharIdToEntity = 0x8009AD30; @@ -44,7 +47,11 @@ g_FieldModelCount = 0x8009C6C4; g_FieldScripts = 0x8009C6DC; g_pFieldState = 0x8009C6E0; Savemap = 0x8009C6E4; +g_CharacterLevelData = 0x8009D7E4; +g_BattleItemsEarned = 0x8009D808; g_DebugLevel = 0x8009D820; +g_FieldModelBaseAnimSpeed = 0x8009D828; +g_ActiveCharacters = 0x8009D84C; func_800A0000 = 0x800A0000; func_800A0030 = 0x800A0030; func_800A00BC = 0x800A00BC; @@ -94,10 +101,10 @@ D_800708C4 = 0x800708C4; D_80082268 = 0x80082268; D_80082460 = 0x80082460; D_80082484 = 0x80082484; +D_8009D58A = 0x8009D58A; D_8009D7D8 = 0x8009D7D8; D_8009D7DC = 0x8009D7DC; D_8009D7E0 = 0x8009D7E0; D_8009D7ED = 0x8009D7ED; D_8009D7EE = 0x8009D7EE; -D_8009D58A = 0x8009D58A; D_80167938 = 0x80167938; diff --git a/config/sym_ovl_export.us.txt b/config/sym_ovl_export.us.txt index ddf91d64..8aee2c33 100644 --- a/config/sym_ovl_export.us.txt +++ b/config/sym_ovl_export.us.txt @@ -1512,9 +1512,9 @@ FieldEnablePartyModels = 0x800bb1b4; FieldEventOpcodeCycle = 0x800bb3a8; FieldUpdateAnimationState = 0x800bbbcc; FieldEventRequestRun = 0x800bbf74; -ResetFieldRenderState = 0x800bc338; -UpdateFieldExitArrows = 0x800bc438; -DrawFieldExitArrow = 0x800bc4d4; +ResetPositionCursorPrimitives = 0x800bc338; +UpdatePositionCursor = 0x800bc438; +DrawPositionCursor = 0x800bc4d4; DebugUpdateActor = 0x800bc9fc; DebugPrintOpcode = 0x800bead4; FieldDebugAddParseValueToPage2 = 0x800beca4; diff --git a/config/symbols.field.us.txt b/config/symbols.field.us.txt index 6620af0f..dcc31213 100644 --- a/config/symbols.field.us.txt +++ b/config/symbols.field.us.txt @@ -189,9 +189,9 @@ FieldEnablePartyModels = 0x800BB1B4; FieldEventOpcodeCycle = 0x800BB3A8; FieldUpdateAnimationState = 0x800BBBCC; FieldEventRequestRun = 0x800BBF74; -ResetFieldRenderState = 0x800BC338; -UpdateFieldExitArrows = 0x800BC438; -DrawFieldExitArrow = 0x800BC4D4; +ResetPositionCursorPrimitives = 0x800BC338; +UpdatePositionCursor = 0x800BC438; +DrawPositionCursor = 0x800BC4D4; DebugUpdateActor = 0x800BC9FC; DebugPrintOpcode = 0x800BEAD4; FieldDebugAddParseValueToPage2 = 0x800BECA4; @@ -545,6 +545,7 @@ g_DebugMessageBuffer = 0x800E4288; g_FieldRain = 0x800E42D8; // size:0x600 g_RainForce = 0x800E48D8; g_EntityForSplitJoin = 0x800E48F0; +g_PosCursorPrims = 0x800E48F4; // size:0x50 g_WindowString = 0x800E4944; // size:0x400 g_FieldMoviePlayed = 0x800E4D44; g_WindowReplaceBankAddr = 0x800E4D48; @@ -553,7 +554,10 @@ g_WindowExtraRows = 0x801142CC; // size:0x8 SavedScriptIds = 0x801142D4; // size:0x180 g_FieldKeyState = 0x80114454; //size:0x4 g_WindowWaitTime = 0x8011445C; +g_PosCursorX = 0x80114464; +g_PosCursorY = 0x80114468; g_WindowTextBudget = 0x80114470; // size:0x8 g_WindowFastForwardLevel = 0x80114480; // size:0x8 +g_PosCursorPrimId = 0x80114490; g_WindowBuffer = 0x801144DC; // size:0x40 g_WindowBufferPos = 0x8011451C; // size:0x8 diff --git a/include/game.h b/include/game.h index 01c646a0..bd10e447 100644 --- a/include/game.h +++ b/include/game.h @@ -177,6 +177,20 @@ typedef enum { WSTATE_WAIT_NEXT_WINDOW, } WindowState; +typedef enum { + ANIMSTATUS_DEFAULT_LOOP, // Loop and track animId/effAnimSpeed. + ANIMSTATUS_SCRIPTED_LOOP, // Loop current requested animation without + // re-tracking defaults. + ANIMSTATUS_PLAY_ONCE_SYNC, // Blocking one-shot. + ANIMSTATUS_HOLD_FRAME, // Freeze on last frame. + ANIMSTATUS_PLAY_ONCE_SYNC_DONE, // Blocking one-shot finished, waiting for + // script-side consumption. + ANIMSTATUS_PLAY_ONCE_THEN_RESET, // Non-blocking one-shot, return to + // DEFAULT_LOOP when done. + ANIMSTATUS_PLAY_ONCE_THEN_HOLD, // Non-blocking one-shot, go to HOLD_FRAME + // when done. +} ModelAnimationStatus; + typedef struct { s16 x1; s16 y1; @@ -840,14 +854,14 @@ typedef struct { u8 unk67; // Uses PADx macros in libetc.h // Raw states ignore custom key mapping set by player. - u32 activeKeysRaw; // Currently active keys. - u32 activeKeysPrevRaw; // activeKeysRaw from last frame. - u32 pressedKeysRaw; // Was inactive last frame. - u32 releasedKeysRaw; // Was active last frame. - u32 activeKeys; - u32 activeKeysPrev; - u32 pressedKeys; - u32 releasedKeys; + s32 activeKeysRaw; // Currently active keys. + s32 activeKeysPrevRaw; // activeKeysRaw from last frame. + s32 pressedKeysRaw; // Was inactive last frame. + s32 releasedKeysRaw; // Was active last frame. + s32 activeKeys; + s32 activeKeysPrev; + s32 pressedKeys; + s32 releasedKeys; s16 currentMovieFrame; // Set by SHAKE to enable a randomized camera shake effect. FieldShakeData shakeX; @@ -975,7 +989,7 @@ extern u8 D_800708D0[][0x1C]; // kernel-region table, by attack/effect id extern AttackData D_800722CC[]; // magic/summon/skill table extern WeaponRecord g_WeaponTable[]; // 0x800738A0, by weapon id extern FieldEntity g_FieldEntity[]; -extern u8 D_800756E8[]; // per-model flags, indexed by field model id +extern u8 g_FieldModelAnimStatus[16]; // per-model flags, indexed by field model id extern s32 D_800756F8[]; extern Unk80075D00* D_80075D00; extern int D_80075DEC; // buffer index, either 0 or 1 @@ -988,22 +1002,25 @@ extern DISPENV D_8007EB68[2]; extern u8 g_EntityToModel[48]; // entity id -> model id (0xFF: none) extern s8 D_8007EBCC; extern s8 D_8007EBDC; -extern u8 D_8007EBE0; // field debug mode -extern u8 g_CharacterLock; // mirror of the UC opcode's control-lock flag -extern u8 g_EntitySplitJoinState[48]; // states for SPLIT and JOIN opcodes -extern s16 D_80082248[]; // per-model current animation playback speed +extern u8 D_8007EBE0; // field debug mode +extern u8 g_CharacterLock; // mirror of the UC opcode's control-lock flag +extern u8 g_EntitySplitJoinState[48]; // states for SPLIT and JOIN opcodes +extern s16 g_FieldModelEffAnimSpeed[16]; // per-model current animation playback speed extern u8 D_80083184[0x40]; -extern u8 D_800831C4[]; // Magic Order table from kernel.bin section 3. -extern u16 g_FieldScriptPC[48]; // program counters for active entity scripts -extern u8 D_8008325C[]; // per-model default animation id (DFANM) +extern u8 D_800831C4[]; // Magic Order table from kernel.bin section 3. +extern u16 g_FieldScriptPC[48]; // program counters for active entity scripts +extern u8 g_FieldModelAnimId[16]; // per-model default animation id (DFANM) extern u8 g_WindowToEntity[4]; extern WindowData g_WindowData[4]; +extern u8 D_8008325C[16]; extern u8 D_8008326C[4]; extern s32 D_80083338; + extern u8 g_FieldScriptSyncState[48][8]; // sync states of entity scripts per // priority level extern FieldModelLoaderData* g_FieldModelLoaderData; extern s16 g_FieldLineCount; +extern u16 g_FieldPaletteBuffer[64][16]; extern s8 D_80095DCC; extern volatile u16 D_80095DD4; extern s16 g_PlayerModelId; @@ -1041,8 +1058,8 @@ extern u8 D_8009D60E; extern u8 g_DebugLevel; // field debug related extern CharacterLevelData g_CharacterLevelData[3]; extern u8 D_8009D824; -extern s16 D_8009D828[]; // per-model base animation speed -extern s16 D_8009D85C[]; // record fields, stride 0x440 +extern s16 g_FieldModelBaseAnimSpeed[16]; // per-model base animation speed +extern s16 D_8009D85C[]; // record fields, stride 0x440 extern BattleItemReward g_BattleItemsEarned[4]; extern u8 D_8009D8F8[]; extern u32 D_8009D260; diff --git a/include/psxsdk/libgpu.h b/include/psxsdk/libgpu.h index 23746c2d..892baa59 100644 --- a/include/psxsdk/libgpu.h +++ b/include/psxsdk/libgpu.h @@ -134,8 +134,10 @@ extern int (*GPU_printf)(); /* printf() object */ ((tge) ? setcode(p, getcode(p) | 0x01) : setcode(p, getcode(p) & ~0x01)) #define getTPage(tp, abr, x, y) \ - ((((tp) & 0x3) << 7) | (((abr) & 0x3) << 5) | (((y) & 0x100) >> 4) | \ - (((x) & 0x3ff) >> 6) | (((y) & 0x200) << 2)) + ((GetGraphType()==1||GetGraphType()==2)? \ + ((((tp)&0x3)<<9)|(((abr)&0x3)<<7)|(((y)&0x300)>>3)|(((x)&0x3ff)>>6)): \ + ((((tp)&0x3)<<7)|(((abr)&0x3)<<5)|(((y)&0x100)>>4)|(((x)&0x3ff)>>6)| \ + (((y)&0x200)<<2))) #define getClut(x, y) ((y << 6) | ((x >> 4) & 0x3f)) @@ -644,4 +646,5 @@ extern DISPENV* SetDefDispEnv(DISPENV* env, int x, int y, int w, int h); extern DRAWENV* SetDefDrawEnv(DRAWENV* env, int x, int y, int w, int h); extern TIM_IMAGE* ReadTIM(TIM_IMAGE* timimg); +extern int GetGraphType(void); #endif diff --git a/src/field/field.c b/src/field/field.c index bb8d699d..8cd91a21 100644 --- a/src/field/field.c +++ b/src/field/field.c @@ -38,8 +38,6 @@ extern s32 (*g_FieldOpcodes[256])(void); extern u8 g_EntityForSplitJoin; extern s16 D_800DF120[][2]; extern char g_DebugMessageBuffer[]; // debug value transformed into text - -extern u8 D_80114498[]; extern u32 g_FieldKeyState; void AddBackgroundToRender(struct FieldRenderData* buf); diff --git a/src/field/field2.c b/src/field/field2.c index 50fdf145..ca8f5f88 100644 --- a/src/field/field2.c +++ b/src/field/field2.c @@ -3,6 +3,8 @@ #include extern u8 D_800E08C0[]; +extern char D_800E0628[]; +extern char D_800E0630[]; extern u8 g_DialogDigitCharacters[16]; extern u8 g_WindowReplaceBank[4][8]; extern u16 g_WindowReplaceBankAddr[4][8]; @@ -19,8 +21,6 @@ extern s16 g_WindowBufferPos[4]; extern u8 g_WindowBuffer[4][16]; extern s16 g_WindowTotalRowsHeight[4]; extern char g_FieldDebugDigits[16]; -extern s8 D_800E0628; -extern s8 D_800E0630; extern u16 g_FieldDebugRb; extern s16 g_FieldDebugRChars; extern s16 g_FieldDebugRLines; @@ -1212,13 +1212,13 @@ void InitFieldDebugPages(void) { SetStrToDebugRow(5, 6, " Info OFF"); FieldDebugPageHide(5); FieldDebugPageInit(4, 0x6C, 0x52, 0x6C, 0x52); - AddStrNextDebugRow(4, &D_800E0628); + AddStrNextDebugRow(4, D_800E0628); FieldDebugPageHide(4); FieldDebugPageInit(3, 0x6C, 0xA4, 0x6C, 0x5C); - AddStrNextDebugRow(3, &D_800E0630); + AddStrNextDebugRow(3, D_800E0630); FieldDebugPageHide(3); FieldDebugPageInit(1, 0, 0, 0x6C, 0xCA); - AddStrNextDebugRow(1, &D_800E0628); + AddStrNextDebugRow(1, D_800E0628); FieldDebugPageHide(1); D_80099FFC = 3; D_8007EBCC = 4; diff --git a/src/field/field_event.c b/src/field/field_event.c index 6b916c0e..54752c2a 100644 --- a/src/field/field_event.c +++ b/src/field/field_event.c @@ -6,8 +6,17 @@ extern s32 (*g_FieldOpcodes[256])(void); extern u8 g_EntityForSplitJoin; extern char g_DebugMessageBuffer[]; -extern u8 D_80114498[]; - +extern u8 D_80114498[48]; +extern u8 g_PosCursorDisabled; +extern POLY_FT4 g_PosCursorPrims[2]; +extern s16 g_PosCursorX; +extern s16 g_PosCursorY; +extern u8 g_PosCursorPrimId; +extern char D_800E0628[]; // "Actor:" +extern char g_DebugText[]; +extern u8 D_800716D4; + +void DebugPrintToFieldWindow(const char* str); void FieldEventOpcodeCycle(void); void FieldUpdateAnimationState(void); u8 FieldEventRequestRun(s16 entityId, s16 priority, s16 scriptId); @@ -18,13 +27,48 @@ void SetStrToDebugRow(s32 page, s16 row, const char* str); void FieldDebugStringCopy(char* dst, const char* src); void FieldDebugStringConcat(char* dest, char* src); void InitFieldDebugPages(void); +void FieldEventClearAkaoStruct(void); +void FieldWindowResetAll(void); +void FieldInitDefaultValues(void); +void FieldEventRunInit(void); +void ResetPositionCursorPrimitives(void); +void UpdatePositionCursor(OT_TYPE* ot); +void DrawPositionCursor(OT_TYPE* ot); + +void FieldEventInit(FieldState* fieldState, FieldEntity* fieldModels, FieldScriptHeader* fieldScripts) { + g_pFieldState = fieldState; + g_FieldModels = fieldModels; + g_FieldScripts = fieldScripts; + D_80095DCC = 0; + D_8007EBE0 = 1; + D_8009FE8C = 0; + if ((fieldState->activeKeysRaw >> 16) & PADselect) { + D_80095DCC = 1; + D_80099FFC = 4; + } + if (fieldScripts->eventDataVersion < 2) { + SystemError('K', 10); + } + if (fieldScripts->eventDataVersion > 2 || fieldScripts->eventVersion > 5) { + SystemError('K', 12); + } + if (fieldScripts->eventVersion < 5) { + SystemError('K', 11); + } + FieldWindowResetAll(); + FieldInitDefaultValues(); + FieldEventRunInit(); + if (!D_800716D4) { + FieldEventClearAkaoStruct(); + D_8009A000[0] = 242; + SystemAkaoExecute(); + } +} -INCLUDE_ASM("asm/us/field/nonmatchings/field_event", FieldEventInit); - -void FieldEventUpdate(s32 arg0) { +void FieldEventUpdate(OT_TYPE* ot) { if (D_8007EBE0) { FieldWindowResetTextAll(); - ResetFieldRenderState(); + ResetPositionCursorPrimitives(); FieldDebugInitBuffers(); InitFieldDebugPages(); D_80095DCC = 0; @@ -46,14 +90,195 @@ void FieldEventUpdate(s32 arg0) { } } if (g_WindowCount) { - SystemMenuDrawDialog(g_WindowData, 4, arg0, g_pFieldState->renderBuffer ^ 1); + SystemMenuDrawDialog(g_WindowData, 4, ot, g_pFieldState->renderBuffer ^ 1); } - UpdateFieldExitArrows(arg0); + UpdatePositionCursor(ot); } -INCLUDE_ASM("asm/us/field/nonmatchings/field_event", FieldInitDefaultValues); +void FieldInitDefaultValues(void) { + s32 i, j; + + g_pFieldState->eventCmd = EVTCMD_NONE; + g_pFieldState->eventCmdParam = 0; + g_pFieldState->movieCommandState = MOVCMD_IDLE; + g_pFieldState->modelCount = g_FieldScripts->numModels; + g_pFieldState->pcModelId = 0; + g_pFieldState->idleAnimId = 0; + g_pFieldState->walkAnimId = 1; + g_pFieldState->runAnimId = 2; + g_pFieldState->characterLock = 0; + g_CharacterLock = 0; + g_pFieldState->suspendWalkAndAnim = 0; + g_pFieldState->menuDisabled = 0; + g_pFieldState->unk35 = 0; + g_pFieldState->battlesDisabled = 0; + g_pFieldState->mapJumpDisabled = 0; + g_pFieldState->scrloSet = 0; + g_pFieldState->nextFieldMusic = 0; + g_pFieldState->nextBattleMusic = 0; + g_pFieldState->unk40 = 0; + g_pFieldState->battleMode2 = 0; + g_pFieldState->battleMode1 = 0; + g_pFieldState->encounterTableId = 0; + g_pFieldState->viewOffsetNumSteps = 0; + g_pFieldState->viewOffsetCurrentStep = 0; + g_pFieldState->viewOffsetMode = OMODE_INSTANT; + g_pFieldState->viewOffsetStart = 0; + g_pFieldState->viewOffsetTarget = 0; + g_pFieldState->shakeX.enabled = 0; + g_pFieldState->shakeY.enabled = 0; + g_pFieldState->shakeX.segmentActive = 0; + g_pFieldState->shakeY.segmentActive = 0; + g_pFieldState->shakeX.amplitude = 0; + g_pFieldState->shakeY.amplitude = 0; + g_pFieldState->shakeX.numStepsPerSegment = 0; + g_pFieldState->shakeY.numStepsPerSegment = 0; + g_pFieldState->shakeX.currentStep = 0; + g_pFieldState->shakeY.currentStep = 0; + g_pFieldState->backgroundMovieEnabled = 0; + g_pFieldState->cameraScrollMode = SCRL_OFF; + g_pFieldState->currentFieldScale = g_FieldScripts->scale; + + for (i = 0; i < 256; i++) { + g_FieldMapVars[i] = 0; + } + for (i = 0; i < 8; i++) { + for (j = 0; j < g_FieldScripts->numEntities; j++) { + g_SavedFieldScriptPC[j][i] = 0; + g_FieldScriptSyncState[j][i] = SYNC_NONE; + g_FieldScriptSyncWaitEntity[j][i] = 0xFF; + SavedScriptIds[j][i] = 0; + } + } + for (i = 0; i < g_FieldScripts->numEntities; i++) { + g_FieldScriptPriority[i] = 7; + g_EntityToModel[i] = 0xFF; + g_FieldWaitCounter[i] = 0; + g_EntitySplitJoinState[i] = 0; + g_EntityToLine[i] = 0xFF; + D_80114498[i] = 0; + } + for (i = 0; i < g_FieldScripts->numModels; i++) { + g_FieldModels[i].charId = 0; + g_FieldModels[i].PosX = 0; + g_FieldModels[i].PosY = 0; + g_FieldModels[i].PosZ = 0; + g_FieldModels[i].PosI = 0; + g_FieldModels[i].MoveEndI = 0; + g_FieldModels[i].MoveDir = 0; + g_FieldModels[i].Dir = 0; + g_FieldModels[i].TurnType = 0; + g_FieldModels[i].TurnSteps = 0; + g_FieldModels[i].TurnStep = 0; + g_FieldModels[i].TurnStart = 0; + g_FieldModels[i].TurnEnd = 0; + g_FieldModels[i].OffsetX = 0; + g_FieldModels[i].OffsetY = 0; + g_FieldModels[i].OffsetZ = 0; + g_FieldModels[i].OffsetStartX = 0; + g_FieldModels[i].OffsetStartY = 0; + g_FieldModels[i].OffsetStartZ = 0; + g_FieldModels[i].OffsetEndX = 0; + g_FieldModels[i].OffsetEndY = 0; + g_FieldModels[i].OffsetEndZ = 0; + g_FieldModels[i].OffsetSteps = 0; + g_FieldModels[i].OffsetStep = 0; + g_FieldModels[i].OfsType = OMODE_INSTANT; + g_FieldModels[i].activeAnimId = 0; + g_FieldModels[i].animSpeed = 16; + g_FieldModels[i].MoveEndX = 0; + g_FieldModels[i].MoveEndY = 0; + g_FieldModels[i].MoveEndZ = 0; + g_FieldModels[i].animCurrentFrame = 0; + g_FieldModels[i].animLastFrame = 0; + g_FieldModels[i].visible = 0; + g_FieldModels[i].MoveSpeed = 1024 * g_pFieldState->currentFieldScale / 512; + g_FieldModels[i].scriptedMoveMode = SMODE_NONE; + g_FieldModels[i].ActionArg = 0; + g_FieldModels[i].ActionState = 0; + g_FieldModels[i].requestTalkScript = 0; + g_FieldModels[i].requestPushScript = 0; + g_FieldModels[i].SolidOff = 0; + g_FieldModels[i].TalkOff = 0; + g_FieldModels[i].DirLock = 0; + g_FieldModels[i].SolidRange = 30 * g_pFieldState->currentFieldScale / 512; + g_FieldModels[i].TalkRange = 80 * g_pFieldState->currentFieldScale / 512; + g_FieldModelAnimId[i] = 0; + g_FieldModelAnimStatus[i] = ANIMSTATUS_DEFAULT_LOOP; + g_FieldModelBaseAnimSpeed[i] = 16; + g_FieldModelEffAnimSpeed[i] = 16; + g_FieldModels[i].KawaiOp1 = 0; + g_FieldModels[i].KawaiOp0 = 0; + g_FieldModels[i].KawaiDataOffset = 0; + g_FieldModels[i].BlinkOn = 0; + g_FieldModels[i].KawaiA = 0; + } + for (i = 0; i < 64; i++) { + g_pFieldState->backgroundLayerVisibility[i] = 0; + } + for (i = 0; i < 64; i++) { + g_pFieldState->blockedAccesses[i] = 0; + } + for (i = 0; i < 64; i++) { + for (j = 0; j < 16; j++) { + g_FieldPaletteBuffer[i][j] = 0; + } + } + for (i = 0; i < 32; i++) { + g_FieldLines[i].requestTalkScript = 0; + g_FieldLines[i].requestPushScript = 0; + g_FieldLines[i].across = 0; + g_FieldLines[i].touch = 0; + g_FieldLines[i].requestTouchOnScript = 0; + g_FieldLines[i].requestTouchOffScript = 0; + g_FieldLines[i].isActive = 0; + g_FieldLines[i].entityId = 0; + g_FieldLines[i].slipDisabled = 0; + g_FieldLines[i].pos.x1 = 0; + g_FieldLines[i].pos.y1 = 0; + g_FieldLines[i].pos.z1 = 0; + g_FieldLines[i].pos.x2 = 0; + g_FieldLines[i].pos.y2 = 0; + g_FieldLines[i].pos.z2 = 0; + } + g_FieldLineCount = 0; + for (i = 0; i < 9; i++) { + g_CharIdToEntity[i] = 0xFF; + } + g_EntityForSplitJoin = 0xFF; + g_PosCursorDisabled = 0; + Savemap.memory_bank_1[31] |= 3; // Locks PHS and save menus +} -INCLUDE_ASM("asm/us/field/nonmatchings/field_event", FieldEventRunInit); +void FieldEventRunInit(void) { + g_FieldModelCount = 0; + for (g_CurrentEntity = 0; g_CurrentEntity < g_FieldScripts->numEntities; g_CurrentEntity++) { + s16 extrasHeaderSize; + + if (D_80071E24 & 3) { + FieldDebugStringCopy(g_DebugText, D_800E0628); + FieldDebugStringConcat(g_DebugText, GET_ENTITY_NAME(g_CurrentEntity)); + if (D_80071E24 & 1) { + SetStrToDebugRow(4, 0, g_DebugText); + } + if (D_80071E24 & 2) { + DebugPrintToFieldWindow(g_DebugText); + } + } + + extrasHeaderSize = g_FieldScripts->numExtras * 4; + GET_FIELD_SCRIPT_OFFSET(g_FieldScriptPC[g_CurrentEntity], 0, + 8 * g_FieldScripts->numEntities + 64 * g_CurrentEntity, extrasHeaderSize); + + // Keep executing the init script until we reach 0x00 = RET opcode. + while ((g_FieldCurrentOpcode = ((u8*)g_FieldScripts)[g_FieldScriptPC[g_CurrentEntity]]) != 0) { + g_FieldOpcodes[g_FieldCurrentOpcode](); + } + g_FieldScriptPC[g_CurrentEntity]++; // Advance PC to the start of the + // next script. + } + g_CurrentEntity = 0; +} INCLUDE_ASM("asm/us/field/nonmatchings/field_event", FieldEnablePartyModels); @@ -198,11 +423,11 @@ void FieldUpdateAnimationState(void) { for (i = 0; i < g_FieldScripts->numEntities; i++) { if (g_EntityToModel[i] != 0xFF && (g_pFieldState->pcModelId != g_EntityToModel[i] || g_pFieldState->characterLock)) { - switch (D_800756E8[g_EntityToModel[i]]) { - case 0: - if (g_FieldModels[g_EntityToModel[i]].activeAnimId != D_8008325C[g_EntityToModel[i]]) { - g_FieldModels[g_EntityToModel[i]].activeAnimId = D_8008325C[g_EntityToModel[i]]; - g_FieldModels[g_EntityToModel[i]].animSpeed = D_80082248[g_EntityToModel[i]]; + switch (g_FieldModelAnimStatus[g_EntityToModel[i]]) { + case ANIMSTATUS_DEFAULT_LOOP: + if (g_FieldModels[g_EntityToModel[i]].activeAnimId != g_FieldModelAnimId[g_EntityToModel[i]]) { + g_FieldModels[g_EntityToModel[i]].activeAnimId = g_FieldModelAnimId[g_EntityToModel[i]]; + g_FieldModels[g_EntityToModel[i]].animSpeed = g_FieldModelEffAnimSpeed[g_EntityToModel[i]]; g_FieldModels[g_EntityToModel[i]].animCurrentFrame = 0; modelEntryId = g_FieldModelLoaderData[g_EntityToModel[i]].modelEntryIndex; model = &g_FieldModelData->modelEntries[modelEntryId]; @@ -221,35 +446,35 @@ void FieldUpdateAnimationState(void) { } } break; - case 1: + case ANIMSTATUS_SCRIPTED_LOOP: if ((g_FieldModels[g_EntityToModel[i]].animCurrentFrame >> 4) >= g_FieldModels[g_EntityToModel[i]].animLastFrame) { g_FieldModels[g_EntityToModel[i]].animCurrentFrame = 0; } break; - case 2: + case ANIMSTATUS_PLAY_ONCE_SYNC: if ((g_FieldModels[g_EntityToModel[i]].animCurrentFrame >> 4) >= g_FieldModels[g_EntityToModel[i]].animLastFrame) { - D_800756E8[g_EntityToModel[i]] = 4; + g_FieldModelAnimStatus[g_EntityToModel[i]] = ANIMSTATUS_PLAY_ONCE_SYNC_DONE; g_FieldModels[g_EntityToModel[i]].animCurrentFrame = g_FieldModels[g_EntityToModel[i]].animLastFrame << 4; } break; - case 3: - case 4: + case ANIMSTATUS_HOLD_FRAME: + case ANIMSTATUS_PLAY_ONCE_SYNC_DONE: g_FieldModels[g_EntityToModel[i]].animCurrentFrame = g_FieldModels[g_EntityToModel[i]].animLastFrame << 4; break; - case 5: + case ANIMSTATUS_PLAY_ONCE_THEN_RESET: if ((g_FieldModels[g_EntityToModel[i]].animCurrentFrame >> 4) >= g_FieldModels[g_EntityToModel[i]].animLastFrame) { - D_800756E8[g_EntityToModel[i]] = 0; + g_FieldModelAnimStatus[g_EntityToModel[i]] = ANIMSTATUS_DEFAULT_LOOP; } break; - case 6: + case ANIMSTATUS_PLAY_ONCE_THEN_HOLD: if ((g_FieldModels[g_EntityToModel[i]].animCurrentFrame >> 4) >= g_FieldModels[g_EntityToModel[i]].animLastFrame) { - D_800756E8[g_EntityToModel[i]] = 3; + g_FieldModelAnimStatus[g_EntityToModel[i]] = ANIMSTATUS_HOLD_FRAME; } break; } @@ -284,8 +509,8 @@ u8 FieldEventRequestRun(s16 entityId, s16 priority, s16 scriptId) { FieldDebugStringCopy(g_DebugMessageBuffer, "TochOFF="); break; } - // Prints entity name. - FieldDebugStringConcat(g_DebugMessageBuffer, (char*)g_FieldScripts + sizeof(FieldScriptHeader) + entityId * 8); + + FieldDebugStringConcat(g_DebugMessageBuffer, GET_ENTITY_NAME(entityId)); FieldDebugAddParseValueToPage2(g_DebugMessageBuffer, 0, 0); } @@ -302,7 +527,7 @@ u8 FieldEventRequestRun(s16 entityId, s16 priority, s16 scriptId) { entityDataSize = entityId * 64; entityDataSize += g_FieldScripts->numEntities * 8; - GET_FIELD_SCRIPT_PC(offset, scriptOffset, entityDataSize, extrasHeaderSize); + GET_FIELD_SCRIPT_OFFSET(offset, scriptOffset, entityDataSize, extrasHeaderSize); // Empty event scripts consist of just a RET (0x00) opcode. if (((u8*)g_FieldScripts)[offset] != 0) { @@ -343,8 +568,101 @@ u8 FieldEventRequestRun(s16 entityId, s16 priority, s16 scriptId) { return 0; } -INCLUDE_ASM("asm/us/field/nonmatchings/field_event", ResetFieldRenderState); +void ResetPositionCursorPrimitives(void) { + s16 tpage; + + g_PosCursorX = 32767; + g_PosCursorY = 32767; + g_PosCursorPrimId = 0; + setPolyFT4(&g_PosCursorPrims[0]); + setPolyFT4(&g_PosCursorPrims[1]); + setSemiTrans(&g_PosCursorPrims[0], 0); + setSemiTrans(&g_PosCursorPrims[1], 0); + setShadeTex(&g_PosCursorPrims[0], 1); + setShadeTex(&g_PosCursorPrims[1], 1); + tpage = getTPage(0, 0, 960, 256); + g_PosCursorPrims[1].tpage = tpage; + g_PosCursorPrims[0].tpage = tpage; + g_PosCursorPrims[1].clut = getClut(256, 481); + g_PosCursorPrims[0].clut = getClut(256, 481); + g_PosCursorPrims[0].r0 = 0; + g_PosCursorPrims[1].r0 = 0; + g_PosCursorPrims[0].g0 = 0; + g_PosCursorPrims[1].g0 = 0; + g_PosCursorPrims[0].b0 = 0; + g_PosCursorPrims[1].b0 = 0; +} + +void UpdatePositionCursor(OT_TYPE* ot) { + if (g_pFieldState->pressedKeys & PADselect) { + Savemap.memory_bank_4[30] ^= 1; + } + if (((Savemap.memory_bank_4[30] == 1) && (!g_pFieldState->characterLock)) || Savemap.memory_bank_4[30] & 2) { + DrawPositionCursor(ot); + } +} -INCLUDE_ASM("asm/us/field/nonmatchings/field_event", UpdateFieldExitArrows); +void DrawPositionCursor(OT_TYPE* ot) { + s16 x, y; -INCLUDE_ASM("asm/us/field/nonmatchings/field_event", DrawFieldExitArrow); + if (!g_PosCursorDisabled && ((g_PosCursorX != 32767) || (g_PosCursorY != 32767))) { + if (g_PosCursorX > 320) { + x = 320; + } else { + x = g_PosCursorX; + } + if (g_PosCursorX < 0) { + x = 0; + } + if (g_PosCursorY > 224) { + y = 224; + } else { + y = g_PosCursorY; + } + if (g_PosCursorY < 0) { + y = 0; + } + g_PosCursorPrimId ^= 1; + // Rotate cursor about the Y axis when player is on right edge of screen. + if (x > 290) { + g_PosCursorPrims[g_PosCursorPrimId].u0 = 143; + g_PosCursorPrims[g_PosCursorPrimId].u1 = 127; + g_PosCursorPrims[g_PosCursorPrimId].u2 = 143; + g_PosCursorPrims[g_PosCursorPrimId].u3 = 127; + g_PosCursorPrims[g_PosCursorPrimId].x0 = x - 16; + g_PosCursorPrims[g_PosCursorPrimId].x1 = x; + g_PosCursorPrims[g_PosCursorPrimId].x2 = x - 16; + g_PosCursorPrims[g_PosCursorPrimId].x3 = x; + } else { + g_PosCursorPrims[g_PosCursorPrimId].u0 = 128; + g_PosCursorPrims[g_PosCursorPrimId].u1 = 144; + g_PosCursorPrims[g_PosCursorPrimId].u2 = 128; + g_PosCursorPrims[g_PosCursorPrimId].u3 = 144; + g_PosCursorPrims[g_PosCursorPrimId].x0 = x; + g_PosCursorPrims[g_PosCursorPrimId].x1 = x + 16; + g_PosCursorPrims[g_PosCursorPrimId].x2 = x; + g_PosCursorPrims[g_PosCursorPrimId].x3 = x + 16; + } + // Rotate cursor about the X axis when player is at the top of the screen. + if (y <= 16) { + g_PosCursorPrims[g_PosCursorPrimId].v0 = 111; + g_PosCursorPrims[g_PosCursorPrimId].v1 = 111; + g_PosCursorPrims[g_PosCursorPrimId].v2 = 95; + g_PosCursorPrims[g_PosCursorPrimId].v3 = 95; + g_PosCursorPrims[g_PosCursorPrimId].y0 = y; + g_PosCursorPrims[g_PosCursorPrimId].y1 = y; + g_PosCursorPrims[g_PosCursorPrimId].y2 = y + 16; + g_PosCursorPrims[g_PosCursorPrimId].y3 = y + 16; + } else { + g_PosCursorPrims[g_PosCursorPrimId].v0 = 96; + g_PosCursorPrims[g_PosCursorPrimId].v1 = 96; + g_PosCursorPrims[g_PosCursorPrimId].v2 = 112; + g_PosCursorPrims[g_PosCursorPrimId].v3 = 112; + g_PosCursorPrims[g_PosCursorPrimId].y0 = y - 16; + g_PosCursorPrims[g_PosCursorPrimId].y1 = y - 16; + g_PosCursorPrims[g_PosCursorPrimId].y2 = y; + g_PosCursorPrims[g_PosCursorPrimId].y3 = y; + } + addPrim(ot, &g_PosCursorPrims[g_PosCursorPrimId]); + } +} diff --git a/src/field/field_opcodes.c b/src/field/field_opcodes.c index e41761de..41de11b0 100644 --- a/src/field/field_opcodes.c +++ b/src/field/field_opcodes.c @@ -34,14 +34,14 @@ extern u8 D_80114498[]; extern u8 g_RandomTableStep; extern u8 g_RandomTableIndex; extern u8 g_RandomTable[256]; +extern char D_800E0628[]; +extern char D_800E0630[]; extern char g_DebugText[]; extern char g_DebugMessageBuffer[]; -extern char D_800E0628[]; extern s8 D_800716C8; extern s16 D_80071E38; extern s16 D_80071E3C; extern u32 D_80075E10; -extern s8 D_800E0630; extern SVECTOR (*D_800E4274)[3]; extern u8* D_800E48E0; @@ -94,7 +94,7 @@ void DebugUpdateActor(s16 arg0, s16 entityId) { FieldDebugStringCopy(g_DebugText, "ctrl:"); } - FieldDebugStringConcat(g_DebugText, (char*)g_FieldScripts + 32 + (entityId * 8)); + FieldDebugStringConcat(g_DebugText, GET_ENTITY_NAME(entityId)); if (D_8009FE8C | (D_80071E24 & 1)) { SetStrToDebugRow(arg0, 0, g_DebugText); } @@ -192,7 +192,7 @@ void DebugUpdateActor(s16 arg0, s16 entityId) { if (D_80071E24 & 2) { DebugPrintToFieldWindow(g_DebugText); } - FieldDebugStringU8hex(D_800756E8[g_EntityToModel[entityId]], g_DebugText); + FieldDebugStringU8hex(g_FieldModelAnimStatus[g_EntityToModel[entityId]], g_DebugText); FieldDebugStringConcat(g_DebugText, "am"); FieldDebugStringU16hex(g_FieldModels[g_EntityToModel[entityId]].activeAnimId, g_DebugMessageBuffer); FieldDebugStringConcat(g_DebugText, g_DebugMessageBuffer); @@ -550,7 +550,7 @@ void DebugPrintOpcode(const char* name, s32 arg1) { var_s1 = arg1; if (!(D_80071E24 & 4) || (D_80114498[g_CurrentEntity] != 0)) { - FieldDebugStringCopy(g_DebugText, &D_800E0630); + FieldDebugStringCopy(g_DebugText, D_800E0630); FieldDebugStringConcat(g_DebugText, name); if (g_DebugLevel & 1) { SetStrToDebugRow(3, 0, g_DebugText); @@ -1906,7 +1906,7 @@ s32 FieldEventRequest(s16 type, u8 target, u8 priority, u8 scriptId) { if (g_DebugLevel & 3) { FieldDebugStringCopy(g_DebugMessageBuffer, "rq="); - FieldDebugStringConcat(g_DebugMessageBuffer, (char*)g_FieldScripts + sizeof(FieldScriptHeader) + target * 8); + FieldDebugStringConcat(g_DebugMessageBuffer, GET_ENTITY_NAME(target)); FieldDebugStringConcat(g_DebugMessageBuffer, "/"); FieldDebugAddParseValueToPage2(g_DebugMessageBuffer, scriptId, 2); } @@ -1972,8 +1972,8 @@ s32 FieldEventRequest(s16 type, u8 target, u8 priority, u8 scriptId) { entityDataSize = target * 64; extrasHeaderSize = (s16)(g_FieldScripts->numExtras * 4); - GET_FIELD_SCRIPT_PC(g_SavedFieldScriptPC[target][priority], scriptOffset, - entityDataSize + (g_FieldScripts->numEntities << 3), extrasHeaderSize); + GET_FIELD_SCRIPT_OFFSET(g_SavedFieldScriptPC[target][priority], scriptOffset, + entityDataSize + (g_FieldScripts->numEntities << 3), extrasHeaderSize); if (g_DebugLevel & 3) { FieldDebugAddParseValueToPage2("rq=send", 0, 0); @@ -2002,8 +2002,8 @@ s32 FieldEventRequest(s16 type, u8 target, u8 priority, u8 scriptId) { entityDataSize = target * 64; extrasHeaderSize = (s16)(g_FieldScripts->numExtras * 4); - GET_FIELD_SCRIPT_PC(g_FieldScriptPC[target], scriptOffset, entityDataSize + (g_FieldScripts->numEntities << 3), - extrasHeaderSize); + GET_FIELD_SCRIPT_OFFSET(g_FieldScriptPC[target], scriptOffset, + entityDataSize + (g_FieldScripts->numEntities << 3), extrasHeaderSize); g_FieldScriptPriority[target] = priority; @@ -2108,8 +2108,8 @@ s32 OpcodeFuncRetto(void) { scriptId *= 2; extrasHeaderSize = (s16)(g_FieldScripts->numExtras * 4); - GET_FIELD_SCRIPT_PC(g_FieldScriptPC[g_CurrentEntity], scriptId, - (g_FieldScripts->numEntities * 8) + (g_CurrentEntity * 64), extrasHeaderSize); + GET_FIELD_SCRIPT_OFFSET(g_FieldScriptPC[g_CurrentEntity], scriptId, + (g_FieldScripts->numEntities * 8) + (g_CurrentEntity * 64), extrasHeaderSize); g_FieldScriptPriority[g_CurrentEntity] = priority; if (g_DebugLevel & 3) { @@ -2436,7 +2436,7 @@ s32 OpcodeFuncUc(void) { } g_CharacterLock = g_pFieldState->characterLock = GET_PARAM_U8(1); if (g_CharacterLock == 0) { - D_800756E8[g_pFieldState->pcModelId] = 0; + g_FieldModelAnimStatus[g_pFieldState->pcModelId] = ANIMSTATUS_DEFAULT_LOOP; } PC_INC(2); return 0; @@ -2532,11 +2532,12 @@ s32 OpcodeFuncDfanm(void) { DebugPrintOpcode("dfanm", 2); } if (g_EntityToModel[g_CurrentEntity] != 0xFF) { - D_8008325C[g_EntityToModel[g_CurrentEntity]] = GET_PARAM_U8(1); - D_80082248[g_EntityToModel[g_CurrentEntity]] = D_8009D828[g_EntityToModel[g_CurrentEntity]] / GET_PARAM_U8(2); + g_FieldModelAnimId[g_EntityToModel[g_CurrentEntity]] = GET_PARAM_U8(1); + g_FieldModelEffAnimSpeed[g_EntityToModel[g_CurrentEntity]] = + g_FieldModelBaseAnimSpeed[g_EntityToModel[g_CurrentEntity]] / GET_PARAM_U8(2); modelIdx = g_EntityToModel[g_CurrentEntity]; - if (D_800756E8[modelIdx] == 3) { - D_800756E8[modelIdx] = 0; + if (g_FieldModelAnimStatus[modelIdx] == ANIMSTATUS_HOLD_FRAME) { + g_FieldModelAnimStatus[modelIdx] = ANIMSTATUS_DEFAULT_LOOP; } } PC_INC(3); @@ -2580,7 +2581,7 @@ void StartModelAnimation(void) { g_FieldModels[g_EntityToModel[g_CurrentEntity]].activeAnimId = GET_PARAM_U8(1); g_FieldModels[g_EntityToModel[g_CurrentEntity]].animSpeed = - D_8009D828[g_EntityToModel[g_CurrentEntity]] / GET_PARAM_U8(2); + g_FieldModelBaseAnimSpeed[g_EntityToModel[g_CurrentEntity]] / GET_PARAM_U8(2); g_FieldModels[g_EntityToModel[g_CurrentEntity]].animCurrentFrame = 0; modelIdx = g_EntityToModel[g_CurrentEntity]; model = &g_FieldModelData->modelEntries[g_FieldModelLoaderData[modelIdx].modelEntryIndex]; @@ -2606,20 +2607,20 @@ s32 OpcodeFuncAnime(void) { return 0; } - switch (D_800756E8[g_EntityToModel[g_CurrentEntity]]) { - case 0: - case 1: - case 3: + switch (g_FieldModelAnimStatus[g_EntityToModel[g_CurrentEntity]]) { + case ANIMSTATUS_DEFAULT_LOOP: + case ANIMSTATUS_SCRIPTED_LOOP: + case ANIMSTATUS_HOLD_FRAME: StartModelAnimation(); if (g_FieldCurrentOpcode == 0xAE) { - D_800756E8[g_EntityToModel[g_CurrentEntity]] = 5; + g_FieldModelAnimStatus[g_EntityToModel[g_CurrentEntity]] = 5; PC_INC(3); return 0; } - D_800756E8[g_EntityToModel[g_CurrentEntity]] = 2; + g_FieldModelAnimStatus[g_EntityToModel[g_CurrentEntity]] = 2; break; - case 4: - D_800756E8[g_EntityToModel[g_CurrentEntity]] = 0; + case ANIMSTATUS_PLAY_ONCE_SYNC_DONE: + g_FieldModelAnimStatus[g_EntityToModel[g_CurrentEntity]] = 0; PC_INC(3); return 0; } @@ -2642,20 +2643,20 @@ s32 OpcodeFuncAnimEx(void) { return 0; } - switch (D_800756E8[g_EntityToModel[g_CurrentEntity]]) { - case 0: - case 1: - case 3: + switch (g_FieldModelAnimStatus[g_EntityToModel[g_CurrentEntity]]) { + case ANIMSTATUS_DEFAULT_LOOP: + case ANIMSTATUS_SCRIPTED_LOOP: + case ANIMSTATUS_HOLD_FRAME: StartModelAnimation(); if (g_FieldCurrentOpcode == 0xAF) { - D_800756E8[g_EntityToModel[g_CurrentEntity]] = 6; + g_FieldModelAnimStatus[g_EntityToModel[g_CurrentEntity]] = 6; PC_INC(3); return 0; } - D_800756E8[g_EntityToModel[g_CurrentEntity]] = 2; + g_FieldModelAnimStatus[g_EntityToModel[g_CurrentEntity]] = 2; break; - case 4: - D_800756E8[g_EntityToModel[g_CurrentEntity]] = 3; + case ANIMSTATUS_PLAY_ONCE_SYNC_DONE: + g_FieldModelAnimStatus[g_EntityToModel[g_CurrentEntity]] = 3; PC_INC(3); return 0; } diff --git a/src/field/field_private.h b/src/field/field_private.h index dac5ea1f..fe86b6de 100644 --- a/src/field/field_private.h +++ b/src/field/field_private.h @@ -1,7 +1,9 @@ #ifndef FIELD_PRIVATE_H #define FIELD_PRIVATE_H -#define GET_FIELD_SCRIPT_PC(dst, scriptOffset, entityDataOffset, extrasHeaderSize) \ +#define GET_ENTITY_NAME(entityId) ((char*)g_FieldScripts + sizeof(FieldScriptHeader) + (entityId) * 8) + +#define GET_FIELD_SCRIPT_OFFSET(dst, scriptOffset, entityDataOffset, extrasHeaderSize) \ (dst) = *((u8*)((scriptOffset) + (entityDataOffset) + (extrasHeaderSize) + (s32)g_FieldScripts) + \ sizeof(FieldScriptHeader)); \ (dst) |= *((u8*)((scriptOffset) + ((entityDataOffset) + (s32)g_FieldScripts) + (extrasHeaderSize)) + \