diff --git a/AGENTS.md b/AGENTS.md index 170b0c6a..db9bceb7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -106,11 +106,54 @@ Each line shows **one** instruction. When the marker is ` ` or `~`, both target Differing operands are wrapped in `{braces}` for easy identification. -Matching instruction runs are collapsed by default (shows 3 lines of context). Options: +By default, long runs of fully matching instructions are **collapsed** into a summary line like `... 10 matching instructions ...`. +This is only a display shortcut: those instructions still exist and still match; they are just hidden to keep the diff compact. + +With `--no-collapse`, those summary lines disappear and every instruction in matching regions is printed explicitly. +This is useful when mapping source lines to exact instruction neighborhoods or when checking whether a mismatch cluster is truly contiguous. + +Quick rule of thumb for agents: +- default (collapsed): better for scanning large functions and finding mismatch hotspots quickly. +- `--no-collapse`: better for deep analysis when you need complete sequential instruction flow. + +Options: - `-C 5` — show 5 context lines instead of 3 -- `--no-collapse` — show every instruction +- `--no-collapse` — disable match-run collapsing and show every instruction - `--range 100-300` — only show instructions at hex offsets 0x100–0x300 +### Using `m2c` for raw draft decompilation + +If a local clone of [`m2c`](https://github.com/matt-kempster/m2c) is available, it can be used to produce a **rough first-pass C draft** from an extracted assembly file. +For this repository, the relevant input files are the dtk-generated assembly files under `build/GMSJ01/asm/.s`. + +`m2c` works here as an asm-to-draft tool, not as a source-of-truth decompiler. +Treat its output as scaffolding for understanding control flow and rough data flow, then verify everything against objdiff and the binary. + +Tested example: + +```bash +python D:/Develop/m2c/m2c.py -t ppc -f __dt__22TNerveFireWanwanEscapeFv --globals=none build/GMSJ01/asm/Enemy/fireWanwan.s +``` + +That command decompiles the function named by the `.fn` symbol in the asm file and prints a raw draft to stdout. +For larger functions, the same pattern works with the mangled symbol name, for example: + +```bash +python D:/Develop/m2c/m2c.py -t ppc -f "execute__22TNerveFireWanwanEscapeCFP24TSpineBase<10TLiveActor>" --globals=none build/GMSJ01/asm/Enemy/fireWanwan.s +``` + +Practical workflow: +- find the TU assembly file in `build/GMSJ01/asm/...` +- open it and copy the mangled function name from the `.fn` line +- run `m2c` with `-t ppc` (`ppc` is the right alias for this CodeWarrior PowerPC output) +- use `--globals=none` when you only want the function body draft +- redirect stdout to a scratch file if needed for longer functions + +Important limitations: +- `m2c` output is often rough for this codebase: inferred placeholder structs, bad field names, missing types, and occasional broken expressions are normal. +- `m2c` does **not** support the C++ context flow needed for this repository's real types, so do not try to feed it SMS C++ context files and expect good typed output. +- use `m2c` for orientation only; never trust it over the asm or decomp-diff. + ## Source Organization Each `.o` file maps 1:1 to a `.cpp` file. The path is listed in `configure.py` under `config.libs`. Each object has a status: @@ -302,4 +345,6 @@ UNUSED functions must still be reconstructed in the source because: - **Don't try to process diff tool output with external utilities**. It is designed to be read by agents, and filtering out certain lines via regex will miss crucial context. The diff shows the disassembly of the original binary and current code simultaneously and should be read directly and sequentially in an attempt to understand what the current code does differently from the original. - **Read the full diff before acting**. Use `--no-collapse` to see every instruction. Identify all problem clusters before making changes, then work on the largest cluster first. - **Focus on one part of the function at a time**. Identify what exact lines in the source code a non-matching part of the disassembly corresponds. Use `--range` argument of the diff tool to only see the asm for the part being worked on. +- **Use temporary marker calls to map source to asm when anchors are missing**. If there are no obvious anchors (for example, no calls to known functions nearby), temporarily add a fake external marker like `extern void marker__();` and call it at a candidate point in the function. The call will show up clearly in diff output and helps bracket surrounding instructions, and you can repeat this process to narrow correspondence precisely. +- **Always remove marker calls after mapping**. Any extra call can change register allocation/scheduling and inhibit matching, so markers are strictly temporary debugging aids. - **Read [docs/AGENT_MATCHING_TIPS.md](docs/AGENT_MATCHING_TIPS.md)** for detailed MWCC codegen patterns that come up repeatedly. diff --git a/docs/AGENT_MATCHING_TIPS.md b/docs/AGENT_MATCHING_TIPS.md index a95464e6..2c6603b9 100644 --- a/docs/AGENT_MATCHING_TIPS.md +++ b/docs/AGENT_MATCHING_TIPS.md @@ -4,50 +4,78 @@ This document collects practical knowledge about how the Metrowerks CodeWarrior Read this document before attempting to match functions. The patterns described here are recurring and will save significant trial-and-error time. Expand the document as needed. Ask for human review whenever the contents of the document disagree with observed reality. -## TVec3 / Vector Codegen Patterns +## MWCC dislikes reordering -`JGeometry::TVec3` is a 12-byte struct with `x`, `y`, `z` float members. How you read/write it drastically affects code generation. +The compiler never reorders memory stores, loads and function calls relative to one another. +They always should be performed in source code in the exact order they appear in target assembly. -### Construction: component-by-component vs constructor +## MWCC can eliminate redundant reads, but not writes -```cpp -// Constructor form — compiler batches all loads, then all stores: -// lfs f0, ...; lfs f1, ...; lfs f2, ... -// stfs f0, 0(rN); stfs f1, 4(rN); stfs f2, 8(rN) -JGeometry::TVec3 pos(x, y, z); +All writes to memory that happen in code will be reproduced in assembly, and vice-versa, when reconstructing code from assembly, you MUST do repeated redundant stores into memory -- that's just the way the original code was written. -// Component-by-component — compiler interleaves load/store pairs: -// lfs f0, ...; stfs f0, 0(rN) -// lfs f0, ...; stfs f0, 4(rN) -// lfs f0, ...; stfs f0, 8(rN) -JGeometry::TVec3 pos; -pos.x = x; -pos.y = y; -pos.z = z; -``` +Redundant reads, on the other hand, can be eliminated by MWCC, but not always, e.g. function inlining might inhibit this. -Check the target assembly to see which pattern (batched vs interleaved) is used, and write the source accordingly. +## MWCC is very reluctant to optimize anything that uses stores ints to memory -### Assignment: `operator=` vs `.set()` +If a Vec struct that contains 3 floats is copied via it's compiler-generated copy ctor or assignment operator -- it will be compiled to integer loads/stores. This makes the compiler unable to keep the values used in registers and forces it to spill them to stack, even if the surrounding code clearly allows for them to stay in floating point registers. -```cpp -// operator= (struct copy) — generates lwz/stw (word load/store): -// lwz r0, 0(rSrc); stw r0, 0(rDst) -// lwz r0, 4(rSrc); stw r0, 4(rDst) -// lwz r0, 8(rSrc); stw r0, 8(rDst) -node.mPos = param_1; +Same logic applies to a Color struct that contains four 8-bit ints: if the ints are initialized one by one, then the compiler will not be able to optimize it to simple bit manipulations in integral registers and will keep the struct on the stack. -// .set(vec) (float copy) — generates lfs/stfs (float load/store): -// lfs f0, 0(rSrc); stfs f0, 0(rDst) -// lfs f0, 4(rSrc); stfs f0, 4(rDst) -// lfs f0, 8(rSrc); stfs f0, 8(rDst) -node.mPos.set(param_1); +## MWCC 1.2.5 stack padding bugs -// .set(x, y, z) (3-arg form) — generates lfs/stfs like component assignment -node.mPos.set(expr_x, expr_y, expr_z); +Our version of MWCC has a bug where the backend allocates more stack than necessary. + +Most commonly this happens when functions were inlined: inlined function calls often inflate the stack frame size. To correctly match a function with stack frame size issues, UNUSED inlines from the MAP need to be reconstructed based on their size, and sometimes new inlines need to be fabricated based on own's best judgement. + +Another instance of it is using a ternary operator sometimes taking up more stack than using ifs. + +Next, local variables can expand the stack even if they are always stored in a register and never actually spilled to the stack. + +When no obviously correct way to make stack frame size match exists, a trick should be used to correctly match the function's context: a temporary char array of required size to inflate the stack. Such hacks however should be removed or commented out after the function is matching to allow for a possible proper solution in the future. + +## Ifs + +Ifs are always compiled to very simple code: +- compare (`cmpwi`/`cmplwi`/etc, or arithmetic instruction with a dot) +- conditional branch (`beq`/`bne`/`ble`/etc) +- the true block +- unconditional branch to end of false block (`b`) +- the false block + +The compiler **NEVER** swaps the order of the true block and false block. +It is also very reluctant in changing the control flow, so C++ control flow usually corresponds to assembly one to one. + +Ternary operator is compiled similarly, but it is the one exception to control flow being the same. In the following case MWCC might initialize the variable's register with the "otherwise" value (zero) instead of doing so in the false branch, which eliminates the false branch entirely. +``` +int b = thing == nullptr ? thing->field : 0; ``` -The target assembly will clearly show `lwz`/`stw` (integer move) vs `lfs`/`stfs` (float move). Choose the source pattern that matches. +## Sequential integer comparisons in a disjunction + +Whe MWCC sees code like `if (a == 8 || a == 9 || a == 10)` it can optimize it to be `if (a - 8 <= 2)` sometimes. When the latter pattern is encountered with enums -- it should be reversed into multiple disjuncted equality comparisons. + +## Switches + +MWCC can compile switches in one of two ways: jump table or branching. +Jump tables are easily identifiable via `mtctr` and `bctr` instructions being used. +Switches that became branches usually have control flow that doesn't look like an if: multiple conditional branch instructions follow a single comparison instruction. E.g. +``` +cmpwi r0, 0x1 +beq ... +bge ... +cmpwi r0, 0x0 +bge ... +b ... +... the code block inside the switch ... +``` + +## Nonsensical control flow + +As MWCC inlines functions, sometimes nonsensical control flow will be encountered in the assembly, one that doesn't correspond to any structured control flow constructions like switches, ifs or loops. Such cases are usually explained by **function inlining** rather than gotos. The place where a goto was supposedly used would actually correspond to a return statement, and the place where it points to would be the boundary of the inlined call. + +## Keep track of known relevant inlines + +Reconstructing correct inline calls is crucial in matching code correctly. When a similar block of code reoccurs -- always consider the possibility that it's an inline, but never disregard the possibility that the original authors simply copy-pasted it. When starting on a new function, explore the inlines already available in the different classes that it uses, as well as in the current translation unit. ## Reference Locals Affect Register Allocation @@ -115,3 +143,48 @@ When a TU is compiled with `-inline deferred` (see TU-specific flags in `configu - In practice, function-definition order in the `.cpp` should be reversed for those TUs. - If order-sensitive matching drifts for an `-inline deferred` TU, verify definition order before attempting smaller codegen tweaks. + +## TVec3 / Vector Codegen Patterns + +`JGeometry::TVec3` is a 12-byte struct with `x`, `y`, `z` float members. How you read/write it drastically affects code generation. + +### Construction: component-by-component vs constructor + +```cpp +// Constructor form — compiler batches all loads, then all stores: +// lfs f0, ...; lfs f1, ...; lfs f2, ... +// stfs f0, 0(rN); stfs f1, 4(rN); stfs f2, 8(rN) +JGeometry::TVec3 pos(x, y, z); + +// Component-by-component — compiler interleaves load/store pairs: +// lfs f0, ...; stfs f0, 0(rN) +// lfs f0, ...; stfs f0, 4(rN) +// lfs f0, ...; stfs f0, 8(rN) +JGeometry::TVec3 pos; +pos.x = x; +pos.y = y; +pos.z = z; +``` + +Check the target assembly to see which pattern (batched vs interleaved) is used, and write the source accordingly. + +### Assignment: `operator=` vs `.set()` + +```cpp +// operator= (struct copy) — generates lwz/stw (word load/store): +// lwz r0, 0(rSrc); stw r0, 0(rDst) +// lwz r0, 4(rSrc); stw r0, 4(rDst) +// lwz r0, 8(rSrc); stw r0, 8(rDst) +node.mPos = param_1; + +// .set(vec) (float copy) — generates lfs/stfs (float load/store): +// lfs f0, 0(rSrc); stfs f0, 0(rDst) +// lfs f0, 4(rSrc); stfs f0, 4(rDst) +// lfs f0, 8(rSrc); stfs f0, 8(rDst) +node.mPos.set(param_1); + +// .set(x, y, z) (3-arg form) — generates lfs/stfs like component assignment +node.mPos.set(expr_x, expr_y, expr_z); +``` + +The target assembly will clearly show `lwz`/`stw` (integer move) vs `lfs`/`stfs` (float move). Choose the source pattern that matches. diff --git a/include/GC2D/CardSave.hpp b/include/GC2D/CardSave.hpp index 274556b0..3cacd9cf 100644 --- a/include/GC2D/CardSave.hpp +++ b/include/GC2D/CardSave.hpp @@ -2,15 +2,22 @@ #define GC2D_CARD_SAVE_HPP #include +#include #include class TMarioGamePad; +class J2DScreen; +class J2DPane; class J2DTextBox; class J2DPicture; +class JUTTexture; +class JPABaseEmitter; +class TExPane; +class TPauseMenu2; class TCardSave : public JDrama::TViewObj { public: - void changeMode(long); + TEProgress changeMode(long); TCardSave(const char* name = "", bool = false); @@ -20,25 +27,132 @@ class TCardSave : public JDrama::TViewObj { void perform(unsigned long, JDrama::TGraphics*); void makeBuffer(J2DTextBox*, int); void setMessage(J2DTextBox*, long, unsigned long); - void waitForStop(TEProgress); + s8 waitForStop(TEProgress); void endWaitForChoice(); - void waitForChoice(TEProgress, TEProgress, signed char); - void waitForChoiceBM(TEProgress, TEProgress, signed char); + s8 waitForChoice(TEProgress, TEProgress, signed char); + s8 waitForChoiceBM(TEProgress, TEProgress, signed char); void endDrawMessage(); - void drawMessage(TEProgress); - void drawMessageBM(TEProgress); - void waitForAnyKey(TEProgress); - void waitForSelectOver(); - void waitForSelect2(TEProgress, TEProgress); - void waitForSelect3(TEProgress, TEProgress, TEProgress); - void waitForAnyKeyBM(TEProgress); + s8 drawMessage(TEProgress); + s8 drawMessageBM(TEProgress); + s8 waitForAnyKey(TEProgress); + s8 waitForSelectOver(); + s8 waitForSelect2(TEProgress, TEProgress); + s8 waitForSelect3(TEProgress, TEProgress, TEProgress); + s8 waitForAnyKeyBM(TEProgress); void selectBookmarks(TEProgress, TEProgress, TEProgress, TEProgress); void changePattern(J2DPicture*, short, unsigned long); void execMovement_(); u8 getNextState(); void execIssueGX_(JDrama::TGraphics*); - static int cMessageID; // TODO: wrong type + static u32 cMessageID[]; + + // fabricated + u16 getCurMessageID() { return cMessageID[unk310]; } + TCardBookmarkInfo& getBookmarkInfo() { return unk278[unk2EA]; } + +public: + /* 0x10 */ int unk10; + /* 0x14 */ J2DScreen* unk14; + /* 0x18 */ bool unk18; + /* 0x1C */ JUTTexture* unk1C[10]; + /* 0x44 */ JPABaseEmitter* unk44; + /* 0x48 */ TExPane* unk48; + /* 0x4C */ JUTRect unk4C; + /* 0x5C */ u32 unk5C; + /* 0x60 */ u32 unk60; + /* 0x64 */ char unk64[0xA0 - 0x64]; + /* 0xA0 */ J2DTextBox* unkA0; + /* 0xA4 */ J2DTextBox* unkA4; + /* 0xA8 */ TExPane* unkA8; + /* 0xAC */ JUTRect unkAC; + /* 0xBC */ u32 unkBC; + /* 0xC0 */ u32 unkC0; + /* 0xC4 */ TExPane* unkC4; + /* 0xC8 */ JUTRect unkC8; + /* 0xD8 */ J2DTextBox* unkD8; + /* 0xDC */ J2DTextBox* unkDC; + /* 0xE0 */ TExPane* unkE0; + /* 0xE4 */ JUTRect unkE4; + /* 0xF4 */ J2DTextBox* unkF4; + /* 0xF8 */ J2DTextBox* unkF8; + /* 0xFC */ TExPane* unkFC; + /* 0x100 */ TExPane* unk100; + /* 0x104 */ JUTRect unk104; + /* 0x114 */ JUTRect unk114; + /* 0x124 */ J2DTextBox* unk124; + /* 0x128 */ J2DTextBox* unk128; + /* 0x12C */ J2DTextBox* unk12C; + /* 0x130 */ J2DTextBox* unk130; + /* 0x134 */ J2DPane* unk134; + /* 0x138 */ J2DPane* unk138; + /* 0x13C */ J2DPicture* unk13C; + /* 0x140 */ J2DPicture* unk140; + /* 0x144 */ J2DPicture* unk144; + /* 0x148 */ J2DPicture* unk148; + /* 0x14C */ J2DPicture* unk14C; + /* 0x150 */ J2DPane* unk150; + /* 0x154 */ J2DPane* unk154[3]; + /* 0x160 */ TExPane* unk160; + /* 0x164 */ JUTRect unk164; + /* 0x174 */ J2DTextBox* unk174; + /* 0x178 */ J2DTextBox* unk178; + /* 0x17C */ TExPane* unk17C; + /* 0x180 */ JUTRect unk180; + /* 0x190 */ J2DTextBox* unk190; + /* 0x194 */ J2DTextBox* unk194; + /* 0x198 */ J2DTextBox* unk198[2][2]; + /* 0x1A8 */ J2DPane* unk1A8[2][2]; + /* 0x1B8 */ u16 unk1B8; + /* 0x1BC */ TExPane* unk1BC; + /* 0x1C0 */ JUTRect unk1C0; + /* 0x1D0 */ J2DTextBox* unk1D0[3][2]; + /* 0x1E8 */ J2DTextBox* unk1E8[3][2]; + /* 0x200 */ J2DTextBox* unk200; + /* 0x204 */ J2DTextBox* unk204; + /* 0x208 */ J2DTextBox* unk208; + /* 0x20C */ J2DTextBox* unk20C; + /* 0x210 */ J2DPane* unk210; + /* 0x214 */ J2DPane* unk214; + /* 0x218 */ J2DPane* unk218; + /* 0x21C */ J2DPane* unk21C; + /* 0x220 */ J2DPane* unk220; + /* 0x224 */ J2DPane* unk224; + /* 0x228 */ J2DPane* unk228; + /* 0x22C */ J2DPane* unk22C; + /* 0x230 */ J2DPane* unk230[3]; + /* 0x23C */ u16 unk23C; + /* 0x240 */ TExPane* unk240; + /* 0x244 */ JUTRect unk244; + /* 0x254 */ J2DTextBox* unk254[2][2]; + /* 0x264 */ J2DTextBox* unk264[2]; + /* 0x26C */ u16 unk26C; + /* 0x270 */ TMarioGamePad* unk270; + /* 0x274 */ char unk274[0x4]; + /* 0x278 */ TCardBookmarkInfo unk278[3]; + /* 0x2D8 */ TPauseMenu2* unk2D8; + /* 0x2DC */ u8 unk2DC; + /* 0x2DD */ u8 unk2DD; + /* 0x2DE */ u8 unk2DE; + /* 0x2DF */ u8 unk2DF; + /* 0x2E0 */ int unk2E0; + /* 0x2E4 */ void* unk2E4; + /* 0x2E8 */ u8 unk2E8; + /* 0x2E9 */ s8 unk2E9; + /* 0x2EA */ s8 unk2EA; + /* 0x2EB */ char unk2EB[0x2F8 - 0x2EB]; + /* 0x2F8 */ u8 unk2F8; + /* 0x2F9 */ u8 unk2F9; + /* 0x2FC */ s32 unk2FC; + /* 0x300 */ s16 unk300; + /* 0x302 */ s16 unk302; + /* 0x304 */ s16 unk304; + /* 0x308 */ int unk308; + /* 0x30C */ u8 unk30C; + /* 0x310 */ TEProgress unk310; + /* 0x314 */ TEProgress unk314; + /* 0x318 */ u32 unk318; + /* 0x31C */ char unk31C[0x4]; }; #endif diff --git a/include/GC2D/Progress.hpp b/include/GC2D/Progress.hpp index daa30294..50bcfe7b 100644 --- a/include/GC2D/Progress.hpp +++ b/include/GC2D/Progress.hpp @@ -22,7 +22,12 @@ enum TEProgress { PROGRESS_UNK11 = 0x11, PROGRESS_UNK12 = 0x12, PROGRESS_UNK13 = 0x13, + PROGRESS_UNK14 = 0x14, PROGRESS_UNK15 = 0x15, + PROGRESS_UNK16 = 0x16, + PROGRESS_UNK17 = 0x17, + PROGRESS_UNK18 = 0x18, + PROGRESS_UNK19 = 0x19, PROGRESS_UNK1A = 0x1A, PROGRESS_UNK1B = 0x1B, PROGRESS_UNK1C = 0x1C, @@ -32,17 +37,24 @@ enum TEProgress { PROGRESS_UNK20 = 0x20, PROGRESS_UNK21 = 0x21, PROGRESS_UNK22 = 0x22, + PROGRESS_UNK23 = 0x23, PROGRESS_UNK24 = 0x24, PROGRESS_UNK25 = 0x25, PROGRESS_UNK26 = 0x26, PROGRESS_UNK27 = 0x27, PROGRESS_UNK28 = 0x28, PROGRESS_UNK29 = 0x29, + PROGRESS_UNK2A = 0x2A, + PROGRESS_UNK2B = 0x2B, + PROGRESS_UNK2C = 0x2C, PROGRESS_UNK2D = 0x2D, + PROGRESS_UNK2E = 0x2E, PROGRESS_UNK2F = 0x2F, PROGRESS_UNK30 = 0x30, PROGRESS_UNK31 = 0x31, PROGRESS_UNK32 = 0x32, + PROGRESS_UNK33 = 0x33, + PROGRESS_UNK34 = 0x34, }; #endif diff --git a/include/JSystem/JDrama/JDRGraphics.hpp b/include/JSystem/JDrama/JDRGraphics.hpp index 349a9d7e..e2bd0407 100644 --- a/include/JSystem/JDrama/JDRGraphics.hpp +++ b/include/JSystem/JDrama/JDRGraphics.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include namespace JDrama { @@ -22,11 +23,19 @@ struct TRect : JUTRect { }; struct TGraphics { - void setViewport(const TRect&, float, float); + void setViewport(const TRect&, f32, f32); + void setScissor(const TRect& scissor) + { + mScissorRect = scissor; + GXSetScissor(mScissorRect.x1, mScissorRect.y1, mScissorRect.getWidth(), + mScissorRect.getHeight()); + } + + // fabricated TRect& getUnk44() { return mDisplayRect; } - TRect& getUnk54() { return mViewportRect; } - const TRect& getUnk64() { return mScissorRect; } + TRect& getViewport() { return mViewportRect; } + const TRect& getScissor() { return mScissorRect; } MtxPtr getUnkB4() { return mViewMtx.mMtx; } f32 getNearPlane() { return mNearPlane; } diff --git a/include/JSystem/JSupport/JSUMemoryOutputStream.hpp b/include/JSystem/JSupport/JSUMemoryOutputStream.hpp index 3034c8c3..d0824b2d 100644 --- a/include/JSystem/JSupport/JSUMemoryOutputStream.hpp +++ b/include/JSystem/JSupport/JSUMemoryOutputStream.hpp @@ -11,14 +11,13 @@ class JSUMemoryOutputStream : public JSURandomOutputStream { virtual int writeData(const void* buf, s32 count); virtual int seekPos(s32 offset, JSUStreamSeekFrom from); - virtual ~JSUMemoryOutputStream() { } virtual int getLength() const { return mLength; } virtual int getPosition() const { return mPosition; } void setBuffer(void* buffer, s32 size); public: - const void* mBuffer; + void* mBuffer; s32 mLength; s32 mPosition; }; diff --git a/include/JSystem/JSupport/JSURandomInputStream.hpp b/include/JSystem/JSupport/JSURandomInputStream.hpp index 1424bc31..90a48300 100644 --- a/include/JSystem/JSupport/JSURandomInputStream.hpp +++ b/include/JSystem/JSupport/JSURandomInputStream.hpp @@ -6,8 +6,6 @@ class JSURandomInputStream : public JSUInputStream { public: - virtual ~JSURandomInputStream() { } - virtual int getAvailable() const { return getLength() - getPosition(); } virtual int skip(s32 amount); virtual int readData(void* buf, s32 count) = 0; diff --git a/include/JSystem/JSupport/JSURandomOutputStream.hpp b/include/JSystem/JSupport/JSURandomOutputStream.hpp index bd49c19d..15e19ee6 100644 --- a/include/JSystem/JSupport/JSURandomOutputStream.hpp +++ b/include/JSystem/JSupport/JSURandomOutputStream.hpp @@ -5,8 +5,6 @@ class JSURandomOutputStream : public JSUOutputStream { public: - virtual ~JSURandomOutputStream() { } - virtual int getLength() const = 0; virtual int getPosition() const = 0; virtual void seek(s32 offset, JSUStreamSeekFrom from); diff --git a/include/System/FlagManager.hpp b/include/System/FlagManager.hpp index b9e7c8a1..00f4ed9b 100644 --- a/include/System/FlagManager.hpp +++ b/include/System/FlagManager.hpp @@ -42,6 +42,8 @@ class TFlagManager { static TFlagManager* smInstance; + s64 getLastSaveTime() const { return mLastSaveTime; } + private: TFlagManager(); diff --git a/src/GC2D/CardLoad.cpp b/src/GC2D/CardLoad.cpp index ad4af394..b5563ac3 100644 --- a/src/GC2D/CardLoad.cpp +++ b/src/GC2D/CardLoad.cpp @@ -749,8 +749,8 @@ void TCardLoad::perform(u32 param_1, JDrama::TGraphics* param_2) } if (param_1 & 8) { - const JUTRect& rect = param_2->getUnk64(); - J2DOrthoGraph graph(param_2->getUnk54()); + const JDrama::TRect& rect = param_2->getScissor(); + J2DOrthoGraph graph(param_2->getViewport()); graph.setup2D(); switch (unk14) { case 0: @@ -775,14 +775,7 @@ void TCardLoad::perform(u32 param_1, JDrama::TGraphics* param_2) break; } - // TODO: are these actually TVec2s or something? - param_2->mScissorRect.x1 = rect.x1; - param_2->mScissorRect.y1 = rect.y1; - param_2->mScissorRect.x2 = rect.x2; - param_2->mScissorRect.y2 = rect.y2; - GXSetScissor(param_2->mScissorRect.x1, param_2->mScissorRect.y1, - param_2->mScissorRect.getWidth(), - param_2->mScissorRect.getHeight()); + param_2->setScissor(rect); } } diff --git a/src/GC2D/CardSave.cpp b/src/GC2D/CardSave.cpp index 8b137891..5816bdc5 100644 --- a/src/GC2D/CardSave.cpp +++ b/src/GC2D/CardSave.cpp @@ -1 +1,2067 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// rogue includes needed for matching sinit & bss +#include +#include + +extern JPAEmitterManager* gpEmitterManager4D2; + +u32 TCardSave::cMessageID[] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC, 0xF, 0x12, + 0x4, 0x5, 0x6, 0x16, 0x1A, 0x14, + 0xE, 0xD, 0x1, 0xA, 0x10, 0x19, + 0x13, 0x18, 0x2, 0x8, 0x17, 0x1B, + 0x15, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x3, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0x11, 0xB, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x9, 0x7, +}; + +TEProgress TCardSave::changeMode(s32 param_1) +{ + TEProgress result = PROGRESS_UNK4; + switch (param_1) { + case CARD_RESULT_NOCARD: + result = PROGRESS_UNK3; + break; + case CARD_RESULT_FATAL_ERROR: + case CARD_RESULT_WRONGDEVICE: + result = PROGRESS_UNK4; + break; + case CARD_RESULT_IOERROR: + result = PROGRESS_UNK2D; + break; + case -0x100: + result = PROGRESS_UNK5; + break; + case CARD_RESULT_BROKEN: + result = PROGRESS_UNK6; + break; + case CARD_RESULT_ENCODING: + result = PROGRESS_UNK7; + break; + case CARD_RESULT_INSSPACE: + result = PROGRESS_UNKC; + break; + case CARD_RESULT_NOENT: + result = PROGRESS_UNKD; + break; + case CARD_RESULT_NOFILE: + result = PROGRESS_UNKE; + break; + } + return result; +} + +TCardSave::TCardSave(const char* name, bool param_2) + : JDrama::TViewObj(name) + , unk18(param_2) + , unk48(nullptr) + , unk5C(0) + , unk60(0) + , unkA0(nullptr) + , unkA4(nullptr) + , unkA8(nullptr) + , unkBC(0) + , unkC0(0) + , unkE0(nullptr) + , unkF4(nullptr) + , unkF8(nullptr) + , unkFC(nullptr) + , unk100(nullptr) + , unk124(nullptr) + , unk128(nullptr) + , unk12C(nullptr) + , unk130(nullptr) + , unk134(nullptr) + , unk160(nullptr) + , unk174(nullptr) + , unk178(nullptr) + , unk2DC(1) + , unk2DE(0) + , unk2DF(1) + , unk2E0(0) + , unk2E8(0) + , unk2E9(0) + , unk2FC(0) + , unk300(200) + , unk302(200) + , unk304(1) + , unk310(PROGRESS_UNK1) + , unk314(PROGRESS_UNK1) +{ +} + +void TCardSave::load(JSUMemoryInputStream& stream) +{ + JDrama::TViewObj::load(stream); + initData(gpMarDirector->unk18[0]); +} + +void TCardSave::initData(TMarioGamePad* param_1) +{ + + if (unk18) { + JKRArchive* arch = (JKRArchive*)JKRFileLoader::getVolume("endsave"); + unk14 = new J2DSetScreen("save_end.blo", arch); + } else { + JKRArchive* arch = (JKRArchive*)JKRFileLoader::getVolume("game_6"); + unk14 = new J2DSetScreen("save.blo", arch); + } + + unk14->setCullBack(GX_CULL_BACK); + + for (int i = 0; i < 10; ++i) { + char acStack_48[0x28]; + if (unk18) { + snprintf(acStack_48, 0x28, "/endsave/timg/coin_number_%d.bti", i); + } else { + snprintf(acStack_48, 0x28, "/game_6/timg/coin_number_%d.bti", i); + } + + unk1C[i] = new JUTTexture((ResTIMG*)JKRGetResource(acStack_48)); + } + unk48 = new TExPane(unk14, 0x775f30); + unk4C = unk48->getPane()->getBounds(); + + unkA0 = (J2DTextBox*)unk14->search(0x6d5f3561); + unkA4 = (J2DTextBox*)unk14->search(0x6d5f3562); + makeBuffer(unkA0, 0x200); + makeBuffer(unkA4, 0x200); + + unkA8 = new TExPane(unk14, 0x775f33); + unkAC = unkA8->getPane()->getBounds(); + unkC4 = new TExPane(unk14, 0x775f33); + unkC8 = unkC4->getPane()->getBounds(); + + unkD8 = (J2DTextBox*)unk14->search(0x6d5f3761); + unkDC = (J2DTextBox*)unk14->search(0x6d5f3762); + makeBuffer(unkD8, 0x200); + makeBuffer(unkDC, 0x200); + unkE0 = new TExPane(unk14, 0x775f31); + unkE4 = unkE0->getPane()->getBounds(); + + unkF4 = (J2DTextBox*)unk14->search(0x6d5f3261); + unkF8 = (J2DTextBox*)unk14->search(0x6d5f3262); + makeBuffer(unkF4, 0x200); + makeBuffer(unkF8, 0x200); + unkFC = new TExPane(unk14, 0x735f36); + unk104 = unkFC->getPane()->getBounds(); + + unk100 = new TExPane(unk14, 0x735f37); + unk114 = unk100->getPane()->getBounds(); + + unk124 = (J2DTextBox*)unk14->search(0x6d5f3361); + unk128 = (J2DTextBox*)unk14->search(0x6d5f3362); + makeBuffer(unk124, 0x20); + makeBuffer(unk128, 0x20); + unk12C = (J2DTextBox*)unk14->search(0x6d5f3461); + unk130 = (J2DTextBox*)unk14->search(0x6d5f3462); + makeBuffer(unk12C, 0x200); + makeBuffer(unk130, 0x200); + + unk134 = unk14->search(0x665f7369); + unk138 = unk14->search(0x665f7368); + unk13C = (J2DPicture*)unk14->search(0x6e5f3461); + unk140 = (J2DPicture*)unk14->search(0x6e5f3462); + unk144 = (J2DPicture*)unk14->search(0x6e5f3463); + unk148 = (J2DPicture*)unk14->search(0x6e5f3361); + unk14C = (J2DPicture*)unk14->search(0x6e5f3362); + unk150 = unk14->search(0x745f30); + + for (int i = 0; i < 3; ++i) + unk154[i] = unk14->search(0x745f31 + i); + + unk160 = new TExPane(unk14, 0x775f32); + unk164 = unk160->getPane()->getBounds(); + + unk174 = (J2DTextBox*)unk14->search(0x6d5f3661); + unk178 = (J2DTextBox*)unk14->search(0x6d5f3662); + makeBuffer(unk174, 0x200); + makeBuffer(unk178, 0x200); + unk17C = new TExPane(unk14, 0x775f34); + unk180 = unk17C->getPane()->getBounds(); + + unk190 = (J2DTextBox*)unk14->search(0x736d3061); + unk194 = (J2DTextBox*)unk14->search(0x736d3062); + makeBuffer(unk190, 0x200); + makeBuffer(unk194, 0x200); + + for (int i = 0; i < 2; ++i) { + unk198[i][0] = (J2DTextBox*)unk14->search(0x736d3161 + 0x100 * i); + unk198[i][0]->setFont((JUTFont*)gpSystemFont); + + unk198[i][1] = (J2DTextBox*)unk14->search(0x736d3162 + 0x100 * i); + unk198[i][1]->setFont((JUTFont*)gpSystemFont); + + unk1A8[i][0] = unk14->search(0x73633161 + 0x100 * i); + unk1A8[i][1] = unk14->search(0x73633162 + 0x100 * i); + } + unk1B8 = unk1A8[0][0]->getBounds().x1; + + unk1BC = new TExPane(unk14, 0x775f35); + unk1C0 = unk1BC->getPane()->getBounds(); + + unk200 = (J2DTextBox*)unk14->search(0x736d3661); + unk204 = (J2DTextBox*)unk14->search(0x736d3662); + makeBuffer(unk200, 0x200); + makeBuffer(unk204, 0x200); + + unk208 = (J2DTextBox*)unk14->search(0x6d5f3861); + unk20C = (J2DTextBox*)unk14->search(0x6d5f3862); + makeBuffer(unk208, 0x20); + makeBuffer(unk20C, 0x20); + + unk210 = unk14->search(0x665f736b); + unk214 = unk14->search(0x665f736a); + unk218 = unk14->search(0x6e5f3661); + unk21C = unk14->search(0x6e5f3662); + unk220 = unk14->search(0x6e5f3663); + unk224 = unk14->search(0x6e5f3561); + unk228 = unk14->search(0x6e5f3562); + unk22C = unk14->search(0x745f34); + + for (int i = 0; i < 3; ++i) + unk230[i] = unk14->search(0x745f35 + i); + + for (int i = 0; i < 3; ++i) { + unk1E8[i][0] = (J2DTextBox*)unk14->search(0x736d3361 + 0x100 * i); + unk1E8[i][0]->setFont((JUTFont*)gpSystemFont); + unk1E8[i][1] = (J2DTextBox*)unk14->search(0x736d3362 + 0x100 * i); + unk1E8[i][1]->setFont((JUTFont*)gpSystemFont); + + unk1D0[i][0] = (J2DTextBox*)unk14->search(0x73633361 + 0x100 * i); + unk1D0[i][1] = (J2DTextBox*)unk14->search(0x73633362 + 0x100 * i); + } + unk23C = unk1D0[0][0]->getBounds().x1; + + unk240 = new TExPane(unk14, 0x775f36); + unk244 = unk240->getPane()->getBounds(); + + for (int i = 0; i < 2; ++i) { + unk254[i][0] = (J2DTextBox*)unk14->search(0x73633661 + 0x100 * i); + unk254[i][1] = (J2DTextBox*)unk14->search(0x73633662 + 0x100 * i); + unk264[i] = (J2DTextBox*)unk14->search(0x736d3762 + 0x100 * i); + + ((J2DTextBox*)unk14->search(0x736d3761 + 0x100 * i)) + ->setFont((JUTFont*)gpSystemFont); + unk264[i]->setFont((JUTFont*)gpSystemFont); + } + + unk26C = unk254[0][0]->getBounds().x1; + + unk14->search(0x6d61736b)->hide(); + unk2E4 = JKRGetResource("/common/2d/savemessage.bmg"); + if (!unk18) + unk2D8 = JDrama::TNameRefGen::search("ポーズメニュー"); + unk270 = param_1; +} + +void TCardSave::init(int param_1) +{ + unk310 = PROGRESS_UNK0; + unk2DF = 0; + unk308 = param_1; + unk2F8 = 0; + unk2F9 = 1; + if (unk308 == 7 || unk308 == 8 || unk308 == 9) { + unk14->search('mask')->show(); + unk14->search('mask')->setAlpha(255); + } else { + unk14->search('mask')->hide(); + } +} + +void TCardSave::perform(u32 param_1, JDrama::TGraphics* param_2) +{ + if (unk2DF) + return; + + if (param_1 & 1) + execMovement_(); + + if (param_1 & 8) + execIssueGX_(param_2); +} + +void TCardSave::makeBuffer(J2DTextBox* param_1, int size) +{ + SMSMakeTextBuffer(param_1, size); + param_1->setFont((JUTFont*)gpSystemFont); +} + +void TCardSave::setMessage(J2DTextBox* text_box, s32 param_2, u32 param_3) +{ + strncpy(text_box->getStringPtr(), SMSGetMessageData(unk2E4, param_3), + param_2); +} + +s8 TCardSave::waitForStop(TEProgress param_1) +{ + s8 result = -1; + + switch (unk10) { + case 0: + setMessage(unkA0, 0x200, getCurMessageID()); + setMessage(unkA4, 0x200, getCurMessageID()); + setMessage(unkD8, 0x200, 0); + setMessage(unkDC, 0x200, 0); + + unkA4->hide(); + unk48->getPane()->show(); + unk48->setCenteredSize(20, unk4C.getWidth(), unk4C.getHeight(), 0, 0); + + unkDC->hide(); + unkC4->setCenteredSize(20, unkC8.getWidth(), unkC8.getHeight(), 0, 0); + + if (unk310 == PROGRESS_UNK4 || unk310 == PROGRESS_UNK3 + || unk310 == PROGRESS_UNK5 || unk310 == PROGRESS_UNKC + || unk310 == PROGRESS_UNKD || unk310 == PROGRESS_UNK2D) { + unkC4->getPane()->show(); + } else { + unkC4->getPane()->hide(); + } + + unk10 = 1; + break; + + case 1: { + u8 done = 1; + done &= unk48->update(); + done &= unkC4->update(); + if (done) { + unk10 = 2; + unkA4->show(); + unkDC->show(); + } + break; + } + + case 2: + if (unk270->mEnabledFrameMeaning & 0x20) { + gpMSound->startSoundSystemSE(0x481CU, 0, nullptr, 0); + + unk48->setCenteredSize(20, 0, 0, unk4C.getWidth(), + unk4C.getHeight()); + unkC4->setCenteredSize(20, 0, 0, unkC8.getWidth(), + unkC8.getHeight()); + unkA4->hide(); + unkDC->hide(); + unk10 = 3; + } + break; + + case 3: { + u8 done = 1; + done &= unk48->update(); + done &= unkC4->update(); + if (done) { + unk48->getPane()->hide(); + unkC4->getPane()->hide(); + unk10 = 5; + } + break; + } + + case 5: + unk310 = param_1; + result = 0; + break; + } + + return result; +} + +void TCardSave::endWaitForChoice() +{ + if (unk10 != 2) + return; + + unk134->hide(); + unk138->hide(); + unk128->hide(); + unkF8->hide(); + unk130->hide(); + unk150->hide(); + unkFC->getPane()->hide(); + unk100->getPane()->hide(); + unk10 = 3; + unkE0->setCenteredSize(20, 0, 0, unkE4.getWidth(), unkE4.getHeight()); +} + +s8 TCardSave::waitForChoice(TEProgress param_1, TEProgress param_2, s8 param_3) +{ + s8 result = -1; + + switch (unk10) { + case 0: + setMessage(unkF4, 0x200, getCurMessageID()); + setMessage(unkF8, 0x200, getCurMessageID()); + + unk134->hide(); + unk138->hide(); + unk128->hide(); + unkF8->hide(); + unk130->hide(); + unk150->hide(); + unkFC->getPane()->hide(); + unk100->getPane()->hide(); + + unkE0->getPane()->show(); + unkE0->setCenteredSize(20, unkE4.getWidth(), unkE4.getHeight(), 0, 0); + unk10 = 1; + break; + + case 1: + if (unkE0->update()) { + unkF8->show(); + unkFC->getPane()->show(); + unk100->getPane()->show(); + + unk2E9 = param_3; + if (param_3 == 0) { + ((J2DPicture*)unkFC->getPane())->mWhite + = JUtility::TColor(0, 0xFF, 0, 0xFF); + ((J2DPicture*)unk100->getPane())->mWhite + = JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF); + } else { + ((J2DPicture*)unkFC->getPane())->mWhite + = JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF); + ((J2DPicture*)unk100->getPane())->mWhite + = JUtility::TColor(0, 0xFF, 0, 0xFF); + } + + unkFC->updateCenteredSize(1, unk104.getWidth(), unk104.getHeight()); + unk100->updateCenteredSize(1, unk114.getWidth(), + unk114.getHeight()); + unkFC->update(); + unk100->update(); + + unk2FC = 0; + unk10 = 2; + } + break; + + case 2: { + s8 old = unk2E9; + u32 input = unk270->mEnabledFrameMeaning; + + if (input & 0x20) { + if (unk44 != nullptr) + gpEmitterManager4D2->forceDeleteEmitter(unk44); + + if (unk2E9 == 0) { + gpMSound->startSoundSystemSE(0x481CU, 0, nullptr, 0); + } else { + gpMSound->startSoundSystemSE(0x481DU, 0, nullptr, 0); + } + + unkF8->hide(); + unk150->hide(); + unkFC->getPane()->hide(); + unk100->getPane()->hide(); + unk10 = 3; + unkE0->setCenteredSize(20, 0, 0, unkE4.getWidth(), + unkE4.getHeight()); + } else if (input & 0x40) { + if (unk44 != nullptr) + gpEmitterManager4D2->forceDeleteEmitter(unk44); + + gpMSound->startSoundSystemSE(0x481DU, 0, nullptr, 0); + + unkF8->hide(); + unk150->hide(); + unkFC->getPane()->hide(); + unk100->getPane()->hide(); + unk10 = 3; + unkE0->setCenteredSize(20, 0, 0, unkE4.getWidth(), + unkE4.getHeight()); + unk2E9 = 1; + } else if (input & 0x8) { + unk2E9 = 0; + } else if (input & 0x10) { + unk2E9 = 1; + } + + TExPane* selectedPane; + JUTRect selectedRect; + if (unk2E9 == 0) { + selectedPane = unkFC; + selectedRect = unk104; + } else { + selectedPane = unk100; + selectedRect = unk114; + } + + if (unk2FC == 4) { + selectedPane->setCenteredSize(40, selectedRect.getWidth() * 1.5f, + selectedRect.getHeight() * 1.5f, + selectedRect.getWidth(), + selectedRect.getHeight()); + if (!unk18) { + JUTRect bounds = selectedPane->getPane()->mGlobalBounds; + JGeometry::TVec3 pos; + pos.x = bounds.x1 + bounds.getWidth() * 0.5f; + pos.y = bounds.y1 + bounds.getHeight() * 0.5f; + pos.z = 0.0f; + gpEmitterManager4D2->createEmitter(pos, 0x1FA, nullptr, + nullptr); + + unk44 = gpEmitterManager4D2->unkC8[0][0]; + unk44->setRotation(0, 0, DEG2SHORTANGLE(12)); + unk44->setUnk190(0.9f, 1.0f, 0.1f); + } + } else if (unk2FC == 44) { + selectedPane->setCenteredSize(40, selectedRect.getWidth(), + selectedRect.getHeight(), + selectedRect.getWidth() * 1.5f, + selectedRect.getHeight() * 1.5f); + } + + s32 thing = unk2FC < 40 ? unk2FC : 80 - unk2FC; + thing = (s32)(thing * 255.0f / 40.0f); + ((J2DPicture*)selectedPane->getPane())->mWhite + = (thing << 24) + 0xFF00FF; + selectedPane->update(); + + unk2FC += 1; + if (unk2FC > 80) + unk2FC = 0; + + if (old != unk2E9) { + if (!unk18 && unk44 != nullptr) + gpEmitterManager4D2->forceDeleteEmitter(unk44); + + unk2FC = 0; + + gpMSound->startSoundSystemSE(0x481EU, 0, nullptr, 0); + + unkFC->updateCenteredSize(1, unk104.getWidth(), unk104.getHeight()); + unk100->updateCenteredSize(1, unk114.getWidth(), + unk114.getHeight()); + unkFC->update(); + unk100->update(); + + if (unk2E9 == 0) { + ((J2DPicture*)unkFC->getPane())->mWhite + = JUtility::TColor(0, 0xFF, 0, 0xFF); + ((J2DPicture*)unk100->getPane())->mWhite + = JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF); + } else { + ((J2DPicture*)unkFC->getPane())->mWhite + = JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF); + ((J2DPicture*)unk100->getPane())->mWhite + = JUtility::TColor(0, 0xFF, 0, 0xFF); + } + } + break; + } + + case 3: + if (unkE0->update()) { + unkE0->getPane()->hide(); + unk10 = 5; + } + break; + + case 5: + unk310 = unk2E9 == 0 ? param_1 : param_2; + result = unk2E9; + break; + } + + return result; +} + +s8 TCardSave::waitForChoiceBM(TEProgress param_1, TEProgress param_2, + s8 param_3) +{ + s8 result = -1; + + switch (unk10) { + case 0: + if (unk2EA == -1) { + unk10 = 5; + } + + setMessage(unk12C, 0x200, getCurMessageID()); + setMessage(unk130, 0x200, getCurMessageID()); + + unk134->hide(); + unk138->hide(); + unk128->hide(); + unkF8->hide(); + unk130->hide(); + unk150->hide(); + unkFC->getPane()->hide(); + unk100->getPane()->hide(); + unk154[0]->hide(); + unk154[1]->hide(); + unk154[2]->hide(); + + unkE0->getPane()->show(); + unkE0->setCenteredSize(20, unkE4.getWidth(), unkE4.getHeight(), 0, 0); + unk10 = 1; + break; + + case 1: + if (unkE0->update()) { + unk154[unk2EA]->show(); + unk150->show(); + unk130->show(); + + if (unk310 == PROGRESS_UNK17) { + unk128->hide(); + u16 score = TFlagManager::getInstance()->getFlag(0x40000); + if (score < 100) { + unk148->changeTexture(unk1C[score / 10]->getTexInfo(), 0); + unk14C->changeTexture(unk1C[score % 10]->getTexInfo(), 0); + unk134->hide(); + unk138->show(); + } else { + unk13C->changeTexture(unk1C[score / 100]->getTexInfo(), 0); + score -= 100; + unk140->changeTexture(unk1C[score / 10]->getTexInfo(), 0); + unk144->changeTexture(unk1C[score % 10]->getTexInfo(), 0); + unk134->show(); + unk138->hide(); + } + } else { + if (getBookmarkInfo().unk0 == 1) { + strncpy(unk124->getStringPtr(), "こわれています", 0x14); + strncpy(unk128->getStringPtr(), "こわれています", 0x14); + unk128->show(); + unk134->hide(); + unk138->hide(); + } else if (getBookmarkInfo().unk18 == 0) { + strncpy(unk124->getStringPtr(), "NEW", 0x14); + strncpy(unk128->getStringPtr(), "NEW", 0x14); + unk128->show(); + unk134->hide(); + unk138->hide(); + } else { + if (getBookmarkInfo().unk1C >= 100) { + unk134->show(); + unk138->hide(); + } else { + unk134->hide(); + unk138->show(); + } + unk128->hide(); + } + } + + unkFC->getPane()->show(); + unk100->getPane()->show(); + unkFC->updateCenteredSize(1, unk104.getWidth(), unk104.getHeight()); + unk100->updateCenteredSize(1, unk114.getWidth(), + unk114.getHeight()); + unkFC->update(); + unk100->update(); + unk2E9 = param_3; + + if (param_3 == 0) { + ((J2DPicture*)unkFC->getPane())->mWhite + = JUtility::TColor(0, 0xFF, 0, 0xFF); + ((J2DPicture*)unk100->getPane())->mWhite + = JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF); + } else { + ((J2DPicture*)unkFC->getPane())->mWhite + = JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF); + ((J2DPicture*)unk100->getPane())->mWhite + = JUtility::TColor(0, 0xFF, 0, 0xFF); + } + + unk10 = 2; + } + break; + + case 2: { + s8 old = unk2E9; + u32 input = unk270->mEnabledFrameMeaning; + + if (input & 0x20) { + if (unk44 != nullptr) + gpEmitterManager4D2->forceDeleteEmitter(unk44); + + if (unk2E9 == 0) { + gpMSound->startSoundSystemSE(0x481CU, 0, nullptr, 0); + } else { + gpMSound->startSoundSystemSE(0x481DU, 0, nullptr, 0); + } + + unk134->hide(); + unk138->hide(); + unk128->hide(); + unkF8->hide(); + unk130->hide(); + unk150->hide(); + unkFC->getPane()->hide(); + unk100->getPane()->hide(); + unk10 = 3; + unkE0->setCenteredSize(20, 0, 0, unkE4.getWidth(), + unkE4.getHeight()); + } else if (input & 0x8) { + unk2E9 = 0; + } else if (input & 0x10) { + unk2E9 = 1; + } + + TExPane* selectedPane; + JUTRect selectedRect; + if (unk2E9 == 0) { + selectedPane = unkFC; + selectedRect = unk104; + } else { + selectedPane = unk100; + selectedRect = unk114; + } + + if (unk2FC == 4) { + selectedPane->setCenteredSize(40, selectedRect.getWidth() * 1.5f, + selectedRect.getHeight() * 1.5f, + selectedRect.getWidth(), + selectedRect.getHeight()); + if (!unk18) { + JUTRect bounds = selectedPane->getPane()->getGlobalBounds(); + JGeometry::TVec3 pos; + pos.x = bounds.x1 + bounds.getWidth() * 0.5f; + pos.y = bounds.y1 + bounds.getHeight() * 0.5f; + pos.z = 0.0f; + gpEmitterManager4D2->createEmitter(pos, 0x1FA, nullptr, + nullptr); + + unk44 = gpEmitterManager4D2->unkC8[0][0]; + unk44->setRotation(0, 0, DEG2SHORTANGLE(12)); + unk44->setUnk190(0.9f, 1.0f, 0.1f); + } + } else if (unk2FC == 44) { + selectedPane->setCenteredSize(40, selectedRect.getWidth(), + selectedRect.getHeight(), + selectedRect.getWidth() * 1.5f, + selectedRect.getHeight() * 1.5f); + } + + s32 thing = unk2FC < 40 ? unk2FC : 80 - unk2FC; + thing = (s32)(thing * 255.0f / 40.0f); + ((J2DPicture*)selectedPane->getPane())->mWhite + = (thing << 24) + 0xFF00FF; + selectedPane->update(); + + unk2FC += 1; + if (unk2FC > 80) + unk2FC = 0; + + if (old != unk2E9) { + if (!unk18 && unk44 != nullptr) + gpEmitterManager4D2->forceDeleteEmitter(unk44); + + unk2FC = 0; + + gpMSound->startSoundSystemSE(0x481EU, 0, nullptr, 0); + + unkFC->updateCenteredSize(1, unk104.getWidth(), unk104.getHeight()); + unk100->updateCenteredSize(1, unk114.getWidth(), + unk114.getHeight()); + unkFC->update(); + unk100->update(); + if (unk2E9 == 0) { + ((J2DPicture*)unkFC->getPane())->mWhite + = JUtility::TColor(0, 0xFF, 0, 0xFF); + ((J2DPicture*)unk100->getPane())->mWhite + = JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF); + } else { + ((J2DPicture*)unkFC->getPane())->mWhite + = JUtility::TColor(0xFF, 0xFF, 0xFF, 0xFF); + ((J2DPicture*)unk100->getPane())->mWhite + = JUtility::TColor(0, 0xFF, 0, 0xFF); + } + } + break; + } + + case 3: + if (unkE0->update()) { + unkE0->getPane()->hide(); + unk10 = 5; + } + break; + + case 5: + unk310 = unk2E9 == 0 ? param_1 : param_2; + result = unk2E9; + break; + } + + return result; +} + +void TCardSave::endDrawMessage() +{ + if (unk10 != 2) + return; + + unk134->hide(); + unk138->hide(); + unk128->hide(); + unkF8->hide(); + unk130->hide(); + unk150->hide(); + unkFC->getPane()->hide(); + unk100->getPane()->hide(); + unk10 = 3; + unkE0->setCenteredSize(20, 0, 0, unkE4.getWidth(), unkE4.getHeight()); +} + +s8 TCardSave::drawMessage(TEProgress param_1) +{ + s8 result = -1; + switch (unk10) { + case 0: + setMessage(unk174, 0x200, getCurMessageID()); + setMessage(unk178, 0x200, getCurMessageID()); + unk178->hide(); + unk160->getPane()->show(); + unk160->setCenteredSize(20, unk164.getWidth(), unk164.getHeight(), 0, + 0); + unk10 = 1; + break; + + case 1: + if (unk160->update()) { + unk178->show(); + unk10 = 2; + } + break; + + case 3: + if (unk160->update()) { + unk160->getPane()->hide(); + unk10 = 5; + } + break; + + case 5: + unk310 = param_1; + result = 0; + break; + } + return result; +} + +s8 TCardSave::drawMessageBM(TEProgress param_1) +{ + + s8 result = -1; + + switch (unk10) { + case 0: + if (unk2EA == -1) { + unk10 = 5; + } + + setMessage(unk12C, 0x200, getCurMessageID()); + setMessage(unk130, 0x200, getCurMessageID()); + + unk134->hide(); + unk138->hide(); + unk128->hide(); + unkF8->hide(); + unk130->hide(); + unk150->hide(); + unkFC->getPane()->hide(); + unk100->getPane()->hide(); + unk154[0]->hide(); + unk154[1]->hide(); + unk154[2]->hide(); + + unkE0->getPane()->show(); + unkE0->setCenteredSize(20, unkE4.getWidth(), unkE4.getHeight(), 0, 0); + unk10 = 1; + break; + + case 1: + if (unkE0->update()) { + unk130->show(); + unk154[unk2EA]->show(); + unk150->show(); + + if (unk308 == 0 || unk308 == 6 || unk308 == 8) { + if (getBookmarkInfo().unk0 == 1) { + strncpy(unk124->getStringPtr(), "こわれています", 0x14); + strncpy(unk128->getStringPtr(), "こわれています", 0x14); + unk128->show(); + unk134->hide(); + unk138->hide(); + } else if (getBookmarkInfo().unk18 == 0) { + strncpy(unk124->getStringPtr(), "NEW", 0x14); + strncpy(unk128->getStringPtr(), "NEW", 0x14); + unk128->show(); + unk134->hide(); + unk138->hide(); + } else { + unk128->hide(); + if (getBookmarkInfo().unk1C >= 100) { + unk134->show(); + unk138->hide(); + } else { + unk134->hide(); + unk138->show(); + } + } + } + + unk10 = 2; + } + break; + + case 3: + if (unkE0->update()) { + unkE0->getPane()->hide(); + unk10 = 5; + } + break; + + case 5: + unk310 = param_1; + result = 0; + break; + } + + return result; +} + +s8 TCardSave::waitForAnyKey(TEProgress param_1) +{ + s32 result = -1; + + switch (unk10) { + case 0: + setMessage(unk174, 0x200, getCurMessageID()); + setMessage(unk178, 0x200, getCurMessageID()); + unk178->hide(); + unk160->getPane()->show(); + unk160->setCenteredSize(20, unk164.getWidth(), unk164.getHeight(), 0, + 0); + unk10 = 1; + break; + + case 1: + if (unk160->update()) { + unk178->show(); + unk10 = 2; + } + break; + + case 2: + if (unk2E0 > 300) { + unk178->hide(); + unk160->setCenteredSize(20, 0, 0, unk164.getWidth(), + unk164.getHeight()); + unk10 = 3; + } else { + unk2E0++; + } + break; + + case 3: + if (unk160->update()) { + unk160->getPane()->hide(); + unk10 = 5; + } + break; + + case 5: + unk310 = param_1; + result = 0; + break; + } + + return result; +} + +s8 TCardSave::waitForSelectOver() +{ + s8 result = -1; + + switch (unk10) { + case 0: + unk240->getPane()->show(); + unk240->setCenteredSize(20, unk244.getWidth(), unk244.getHeight(), 0, + 0); + unk264[0]->hide(); + unk254[0][0]->hide(); + unk254[0][1]->hide(); + unk264[1]->hide(); + unk254[1][0]->hide(); + unk254[1][1]->hide(); + unk10 = 1; + break; + + case 1: + if (unk240->update()) { + unk10 = 2; + unk2E9 = 0; + unk264[0]->show(); + unk264[1]->show(); + unk254[0][0]->show(); + unk254[0][1]->show(); + } + break; + + case 2: { + s8 oldSelect = unk2E9; + u32 input = unk270->mEnabledFrameMeaning; + + if (input & 0x20) { + gpMSound->startSoundSystemSE(0x481CU, 0, nullptr, 0); + unk10 = 4; + } else if (input & 0x2) { + unk2E9 = 0; + } else if (input & 0x4) { + unk2E9 = 1; + } + + if (oldSelect != unk2E9) { + gpMSound->startSoundSystemSE(0x481EU, 0, nullptr, 0); + + unk254[oldSelect][0]->hide(); + unk254[oldSelect][1]->hide(); + unk254[unk2E9][0]->show(); + unk254[unk2E9][1]->show(); + } + break; + } + + case 4: + unk240->setCenteredSize(20, 0, 0, unk244.getWidth(), + unk244.getHeight()); + unk264[0]->hide(); + unk264[1]->hide(); + unk254[unk2E9][0]->hide(); + unk254[unk2E9][1]->hide(); + unk10 = 3; + break; + + case 3: + if (unk240->update()) { + unk240->getPane()->hide(); + unk10 = 5; + } + break; + + case 5: + if (unk2E9 == 0) { + unk310 = PROGRESS_UNK1; + } else { + unk310 = PROGRESS_UNK19; + } + result = unk2E9; + break; + } + + return result; +} + +s8 TCardSave::waitForSelect2(TEProgress param_1, TEProgress param_2) +{ + s8 result = -1; + + switch (unk10) { + case 0: { + u32 messageID = cMessageID[unk310]; + switch (unk308) { + case 1: + messageID = 0x1C; + break; + case 2: + messageID = 0x1D; + break; + case 3: + messageID = 0x1E; + break; + case 4: + messageID = 0x1F; + break; + case 5: + messageID = 0x20; + break; + } + + setMessage(unk190, 0x200, (u16)messageID); + setMessage(unk194, 0x200, (u16)messageID); + + unk194->hide(); + unk17C->getPane()->show(); + unk17C->setCenteredSize(20, unk180.getWidth(), unk180.getHeight(), 0, + 0); + + unk198[0][1]->hide(); + unk1A8[0][0]->hide(); + unk1A8[0][1]->hide(); + unk198[1][1]->hide(); + unk1A8[1][0]->hide(); + unk1A8[1][1]->hide(); + + unk10 = 1; + break; + } + + case 1: + if (unk17C->update()) { + unk194->show(); + unk10 = 2; + unk2E9 = 0; + + unk198[0][1]->show(); + unk198[1][1]->show(); + unk1A8[0][0]->show(); + unk1A8[0][1]->show(); + + unk2F8 = 0; + unk2F9 = 1; + } + break; + + case 2: { + s8 oldSelect = unk2E9; + u32 input = unk270->mEnabledFrameMeaning; + + if (input & 0x20) { + gpMSound->startSoundSystemSE(0x481CU, 0, nullptr, 0); + unk10 = 4; + } else if (input & 0x2) { + unk2E9 = 0; + } else if (input & 0x4) { + unk2E9 = 1; + } + + if (oldSelect != unk2E9) { + gpMSound->startSoundSystemSE(0x481EU, 0, nullptr, 0); + + unk1A8[oldSelect][0]->hide(); + unk1A8[oldSelect][1]->hide(); + unk1A8[unk2E9][0]->show(); + unk1A8[unk2E9][1]->show(); + + unk2F8 = 0; + unk2F9 = 1; + } + break; + } + + case 4: + unk194->hide(); + unk17C->setCenteredSize(20, 0, 0, unk180.getWidth(), + unk180.getHeight()); + + unk198[0][1]->hide(); + unk198[1][1]->hide(); + unk1A8[unk2E9][0]->hide(); + unk1A8[unk2E9][1]->hide(); + + unk10 = 3; + break; + + case 3: + if (unk17C->update()) { + unk17C->getPane()->hide(); + unk10 = 5; + } + break; + + case 5: + if (unk2E9 == 0) { + unk310 = param_1; + } else { + unk310 = param_2; + } + result = unk2E9; + break; + } + + return result; +} + +s8 TCardSave::waitForSelect3(TEProgress param_1, TEProgress param_2, + TEProgress param_3) +{ + s8 result = -1; + + switch (unk10) { + case 0: + unk1BC->getPane()->show(); + unk1BC->setCenteredSize(20, unk1C0.getWidth(), unk1C0.getHeight(), 0, + 0); + + unk204->hide(); + setMessage(unk200, 0x200, 0x21); + setMessage(unk204, 0x200, 0x21); + + unk1E8[0][1]->hide(); + unk1D0[0][0]->hide(); + unk1D0[0][1]->hide(); + unk1E8[1][1]->hide(); + unk1D0[1][0]->hide(); + unk1D0[1][1]->hide(); + unk1E8[2][1]->hide(); + unk1D0[2][0]->hide(); + unk1D0[2][1]->hide(); + + unk230[0]->hide(); + unk230[1]->hide(); + unk230[2]->hide(); + unk20C->hide(); + unk210->hide(); + unk214->hide(); + unk22C->hide(); + + unk10 = 1; + break; + + case 1: + if (unk1BC->update()) { + unk10 = 2; + unk2E9 = 0; + + unk1E8[0][1]->show(); + unk1E8[1][1]->show(); + unk1E8[2][1]->show(); + unk1D0[0][0]->show(); + unk1D0[0][1]->show(); + unk204->show(); + + unk230[unk2EA]->show(); + unk22C->show(); + + if (getBookmarkInfo().unk0 == 1) { + strncpy(unk208->getStringPtr(), "こわれています", 0x14); + strncpy(unk20C->getStringPtr(), "こわれています", 0x14); + unk20C->show(); + unk210->hide(); + unk214->hide(); + } else if (getBookmarkInfo().unk18 == 0) { + strncpy(unk208->getStringPtr(), "NEW", 0x14); + strncpy(unk20C->getStringPtr(), "NEW", 0x14); + unk20C->show(); + unk210->hide(); + unk214->hide(); + } else { + s16 score = (s16)getBookmarkInfo().unk1C; + if (score < 0) { + score = 0; + } + + if (score < 100) { + ((J2DPicture*)unk224) + ->changeTexture(unk1C[score / 10]->getTexInfo(), 0); + ((J2DPicture*)unk228) + ->changeTexture(unk1C[score % 10]->getTexInfo(), 0); + unk214->show(); + } else { + ((J2DPicture*)unk218) + ->changeTexture(unk1C[score / 100]->getTexInfo(), 0); + score -= 100; + ((J2DPicture*)unk21C) + ->changeTexture(unk1C[score / 10]->getTexInfo(), 0); + ((J2DPicture*)unk220) + ->changeTexture(unk1C[score % 10]->getTexInfo(), 0); + unk210->show(); + } + + unk20C->hide(); + } + } + break; + + case 2: { + u8 oldSelect = unk2E9; + u32 input = unk270->mEnabledFrameMeaning; + + if (input & 0x20) { + gpMSound->startSoundSystemSE(0x481CU, 0, nullptr, 0); + unk10 = 4; + } else if (input & 0x2) { + if (oldSelect > 0) { + unk2E9 = oldSelect - 1; + } + } else if (input & 0x4) { + if (oldSelect < 2) { + unk2E9 = oldSelect + 1; + } + } + + if (oldSelect != unk2E9) { + gpMSound->startSoundSystemSE(0x481EU, 0, nullptr, 0); + + unk1D0[oldSelect][0]->hide(); + unk1D0[oldSelect][1]->hide(); + unk1D0[unk2E9][0]->show(); + unk1D0[unk2E9][1]->show(); + } + break; + } + + case 4: + unk1BC->setCenteredSize(20, 0, 0, unk1C0.getWidth(), + unk1C0.getHeight()); + + unk1E8[0][1]->hide(); + unk1E8[1][1]->hide(); + unk1E8[2][1]->hide(); + unk1D0[unk2E9][0]->hide(); + unk1D0[unk2E9][1]->hide(); + + unk230[0]->hide(); + unk230[1]->hide(); + unk230[2]->hide(); + unk204->hide(); + unk20C->hide(); + unk210->hide(); + unk214->hide(); + unk22C->hide(); + + unk10 = 3; + break; + + case 3: + if (unk1BC->update()) { + unk1BC->getPane()->hide(); + unk10 = 5; + } + break; + + case 5: + if (unk2E9 == 0) { + unk310 = param_1; + } else if (unk2E9 == 1) { + unk310 = param_2; + } else { + unk310 = param_3; + } + result = unk2E9; + break; + } + + return result; +} + +s8 TCardSave::waitForAnyKeyBM(TEProgress param_1) +{ + s8 result = -1; + + switch (unk10) { + case 0: + setMessage(unk12C, 0x200, getCurMessageID()); + setMessage(unk130, 0x200, getCurMessageID()); + + unkF8->hide(); + unk128->hide(); + unk134->hide(); + unk138->hide(); + unk128->hide(); + unk134->hide(); + unk138->hide(); + unk128->hide(); + unk134->hide(); + unk138->hide(); + unkFC->getPane()->hide(); + unk100->getPane()->hide(); + + unkE0->getPane()->show(); + unkE0->setCenteredSize(20, unkE4.getWidth(), unkE4.getHeight(), 0, 0); + unk10 = 1; + break; + + case 1: + if (unkE0->update()) { + unk154[unk2EA]->show(); + unk150->show(); + unk130->show(); + + if (getBookmarkInfo().unk0 == 1) { + strncpy(unk124->getStringPtr(), "こわれています", 0x14); + strncpy(unk128->getStringPtr(), "こわれています", 0x14); + unk128->show(); + unk134->hide(); + unk138->hide(); + } else if (getBookmarkInfo().unk18 == 0) { + strncpy(unk124->getStringPtr(), "NEW", 0x14); + strncpy(unk128->getStringPtr(), "NEW", 0x14); + unk128->show(); + unk134->hide(); + unk138->hide(); + } else { + unk128->hide(); + u16 score = getBookmarkInfo().unk1C; + if (score < 100) { + ((J2DPicture*)unk148) + ->changeTexture(unk1C[score / 10]->getTexInfo(), 0); + ((J2DPicture*)unk14C) + ->changeTexture(unk1C[score % 10]->getTexInfo(), 0); + unk134->hide(); + unk138->show(); + } else { + ((J2DPicture*)unk13C) + ->changeTexture(unk1C[score / 100]->getTexInfo(), 0); + score -= 100; + ((J2DPicture*)unk140) + ->changeTexture(unk1C[score / 10]->getTexInfo(), 0); + ((J2DPicture*)unk144) + ->changeTexture(unk1C[score % 10]->getTexInfo(), 0); + unk134->show(); + unk138->hide(); + } + } + + unk10 = 2; + } + break; + + case 2: + if (unk2E0 > 300) { + endWaitForChoice(); + unk10 = 3; + } else { + unk2E0++; + } + break; + + case 3: + if (unkE0->update()) { + unkE0->getPane()->hide(); + unk10 = 5; + } + break; + + case 5: + unk310 = param_1; + result = 0; + break; + } + + return result; +} + +void saveBookmark(u32 idx) +{ + JSUMemoryOutputStream stream; + gpCardManager->getWriteStream(&stream); + TFlagManager::getInstance()->save(stream); + gpCardManager->writeBlock(idx); +} + +void TCardSave::selectBookmarks(TEProgress, TEProgress, TEProgress, TEProgress) +{ +} + +void TCardSave::changePattern(J2DPicture*, s16, u32) { } + +void TCardSave::execMovement_() +{ + + TEProgress prevState = unk310; + s32 prevMode = unk10; + + unk270->onFlag(0x1); + + switch (unk310) { + case PROGRESS_UNK0: + unk2EA = gpApplication.mSaveFile; + + if (unk308 == 7) { + unk310 = PROGRESS_UNK2E; + break; + } + if (unk308 == 9) { + unk310 = PROGRESS_UNK34; + break; + } + + unk310 = PROGRESS_UNK2; + gpCardManager->getBookmarkInfos(&unk278[0]); + break; + + case PROGRESS_UNK1: + case PROGRESS_UNK19: + unk270->offFlag(0x1); + gpCardManager->unmount(); + + if (!unk18 && unk308 == 0) + unk2D8->setDrawEnd(); + + unk2DF = 1; + break; + + case PROGRESS_UNK2: { + s32 status = gpCardManager->getLastStatus(); + if (status == CARD_RESULT_BUSY) + break; + + if (status == CARD_RESULT_READY) { + u16 score = getBookmarkInfo().unk1C; + if (score > 0x3E7) + score = 0x3E7; + + if (score < 100) { + unk148->changeTexture(unk1C[score / 10]->getTexInfo(), 0); + unk14C->changeTexture(unk1C[score % 10]->getTexInfo(), 0); + } else { + unk13C->changeTexture(unk1C[score / 100]->getTexInfo(), 0); + score -= int(score * 0.01f) * 100; + unk140->changeTexture(unk1C[score / 10]->getTexInfo(), 0); + unk144->changeTexture(unk1C[score % 10]->getTexInfo(), 0); + } + + switch (unk308) { + case 0: + unk310 = PROGRESS_UNK15; + break; + case 6: + unk310 = PROGRESS_UNK2B; + break; + case 8: + unk310 = PROGRESS_UNK33; + break; + default: + unk310 = PROGRESS_UNK2A; + break; + } + } else { + unk310 = changeMode(status); + } + break; + } + + case PROGRESS_UNK3: + if (gpCardManager->getLastStatus() == CARD_RESULT_NOCARD) { + waitForStop(PROGRESS_UNK1); + gpCardManager->probe(); + } else { + if (unkA4->isVisible()) { + unk48->setCenteredSize(20, 0, 0, unk4C.getWidth(), + unk4C.getHeight()); + unkA4->hide(); + unk10 = 3; + } + + if (waitForStop(PROGRESS_UNK2) != -1) + gpCardManager->getBookmarkInfos(&unk278[0]); + } + break; + + case PROGRESS_UNK4: + case PROGRESS_UNK5: + case PROGRESS_UNKC: + case PROGRESS_UNKD: + case PROGRESS_UNK2D: + if (gpCardManager->getLastStatus() != CARD_RESULT_NOCARD) { + waitForStop(PROGRESS_UNK1); + gpCardManager->probe(); + } else { + if (unkA4->isVisible()) { + unk48->setCenteredSize(20, 0, 0, unk4C.getWidth(), + unk4C.getHeight()); + unkA4->hide(); + unk10 = 3; + } + waitForStop(PROGRESS_UNK3); + } + break; + + case PROGRESS_UNK6: + case PROGRESS_UNK7: + if (gpCardManager->getLastStatus() != CARD_RESULT_NOCARD) { + waitForChoice(PROGRESS_UNK8, PROGRESS_UNK4, 1); + gpCardManager->probe(); + } else { + if (unkF8->isVisible()) + endWaitForChoice(); + + waitForChoice(PROGRESS_UNK3, PROGRESS_UNK3, 1); + } + break; + + case PROGRESS_UNK8: { + s32 status = gpCardManager->getLastStatus(); + if (status == CARD_RESULT_BUSY) + break; + + if (status == CARD_RESULT_READY) { + s8 r = waitForChoice(PROGRESS_UNK9, PROGRESS_UNK4, 1); + if (r == 0) { + unk2E0 = 0; + gpCardManager->format(); + } + gpCardManager->probe(); + } else { + endWaitForChoice(); + + TEProgress mode = changeMode(status); + waitForChoice(mode, mode, 1); + } + break; + } + + case PROGRESS_UNK9: { + s32 status = gpCardManager->getLastStatus(); + if (status != CARD_RESULT_BUSY) { + if (status == CARD_RESULT_READY) { + drawMessage(PROGRESS_UNKA); + if (unk2E0 > 0x12C) { + if (unk178->isVisible()) { + unk178->hide(); + unk160->setCenteredSize(20, 0, 0, unk164.getWidth(), + unk164.getHeight()); + unk10 = 3; + } + } else { + unk2E0++; + } + } else { + if (unk178->isVisible()) { + unk178->hide(); + unk160->setCenteredSize(20, 0, 0, unk164.getWidth(), + unk164.getHeight()); + unk10 = 3; + } + drawMessage(PROGRESS_UNKB); + } + } else { + drawMessage(PROGRESS_UNK0); + } + break; + } + + case PROGRESS_UNKA: + if (gpCardManager->getLastStatus() == CARD_RESULT_READY) { + s32 r = waitForAnyKey(PROGRESS_UNK2); + gpCardManager->probe(); + if (r != -1) + gpCardManager->getBookmarkInfos(&unk278[0]); + } else { + if (unk178->isVisible()) { + unk160->setCenteredSize(20, 0, 0, unk164.getWidth(), + unk164.getHeight()); + unk178->hide(); + } + waitForAnyKey(PROGRESS_UNK3); + } + break; + + case PROGRESS_UNKB: + if (waitForAnyKey(PROGRESS_UNK2) != -1) + gpCardManager->getBookmarkInfos(&unk278[0]); + break; + + case PROGRESS_UNKE: + if (unk10 == 0) + gpCardManager->probe(); + + if (gpCardManager->getLastStatus() == CARD_RESULT_READY) { + s32 r = waitForChoice(PROGRESS_UNKF, PROGRESS_UNK10, 0); + gpCardManager->probe(); + if (r == 0) + gpCardManager->createFile(); + } else { + endWaitForChoice(); + waitForChoice(PROGRESS_UNK3, PROGRESS_UNK3, 1); + } + break; + + case PROGRESS_UNKF: { + s32 status = gpCardManager->getLastStatus(); + if (status != CARD_RESULT_BUSY) { + if (status == CARD_RESULT_READY) { + drawMessage(PROGRESS_UNK11); + if (unk2E0 > 0x12C) { + if (unk178->isVisible()) { + unk178->hide(); + unk160->setCenteredSize(20, 0, 0, unk164.getWidth(), + unk164.getHeight()); + unk10 = 3; + } + } else { + unk2E0++; + } + } else { + if (unk178->isVisible()) { + unk178->hide(); + unk160->setCenteredSize(20, 0, 0, unk164.getWidth(), + unk164.getHeight()); + unk10 = 3; + } + drawMessage(PROGRESS_UNK12); + } + } else { + drawMessage(PROGRESS_UNK0); + } + break; + } + + case PROGRESS_UNK11: + if (waitForAnyKey(PROGRESS_UNK2) != -1) + gpCardManager->getBookmarkInfos(&unk278[0]); + break; + + case PROGRESS_UNK12: + if (waitForAnyKey(PROGRESS_UNK2) != -1) + gpCardManager->getBookmarkInfos(&unk278[0]); + break; + + case PROGRESS_UNK10: + waitForStop(PROGRESS_UNK1); + break; + + case PROGRESS_UNK13: { + unk2E8 = unk2EA; + + TCardBookmarkInfo& bm = getBookmarkInfo(); + if (bm.unk0 == 1) { + unk310 = PROGRESS_UNK14; + } else if (bm.unk18 == 0) { + unk310 = PROGRESS_UNK16; + saveBookmark(unk2EA); + } else if (bm.unk18 == 0 + || bm.unk8 + == TFlagManager::getInstance()->getLastSaveTime()) { + unk310 = PROGRESS_UNK2C; + } else { + unk310 = PROGRESS_UNK16; + } + break; + } + + case PROGRESS_UNK14: + case PROGRESS_UNK1E: { + s32 status = gpCardManager->getLastStatus(); + if (status == CARD_RESULT_READY) { + s32 r = waitForChoiceBM(PROGRESS_UNK16, PROGRESS_UNK2, 1); + gpCardManager->probe(); + if (r == 0) + saveBookmark(unk2EA); + } else { + endWaitForChoice(); + + TEProgress mode = changeMode(status); + waitForChoiceBM(mode, mode, 1); + } + break; + } + + case PROGRESS_UNK15: { + s32 status = gpCardManager->getLastStatus(); + if (status == CARD_RESULT_READY) { + s32 r = waitForChoiceBM(PROGRESS_UNK16, PROGRESS_UNK1, 1); + gpCardManager->probe(); + if (r == 0) { + TCardBookmarkInfo& bm = getBookmarkInfo(); + if (bm.unk0 == 1) { + unk310 = PROGRESS_UNK1E; + } else { + if (bm.unk18 == 0 + || bm.unk8 + == TFlagManager::getInstance() + ->getLastSaveTime()) { + + saveBookmark(unk2EA); + } else { + unk310 = PROGRESS_UNK2C; + } + } + } + } else { + endWaitForChoice(); + + waitForChoiceBM(PROGRESS_UNK3, PROGRESS_UNK3, 1); + } + break; + } + + case PROGRESS_UNK16: { + s32 status = gpCardManager->getLastStatus(); + + if (status != CARD_RESULT_BUSY) { + if (status == CARD_RESULT_READY) { + if (unk2DC != 0) { + unk2DC = 0; + if (unk2DD == 0) + TFlagManager::getInstance()->saveSuccess(); + } + + s8 r = drawMessageBM(PROGRESS_UNK17); + if (r != -1 && unk2DE != 0) + unk310 = PROGRESS_UNK19; + + if (unk2E0 > 0x12C) { + if (unk2DD != 0) { + endWaitForChoice(); + } else { + JSUMemoryOutputStream stream; + gpCardManager->getOptionWriteStream(&stream); + TFlagManager::getInstance()->saveOption(stream); + gpCardManager->writeOptionBlock(); + unk2DD = 1; + } + } else { + if (unk2DD == 0 && unk2E0 == 0xC8) { + gpMSound->startSoundSystemSE(0x481B, 0, nullptr, 0); + + if (unk308 == 0 || unk308 == 6 || unk308 == 8) { + unk128->hide(); + u16 score + = TFlagManager::smInstance->getFlag(0x40000); + if (score > 0x3E7) + score = 0x3E7; + + if (score < 100) { + unk138->show(); + unk134->hide(); + unk148->changeTexture( + unk1C[score / 10]->getTexInfo(), 0); + unk14C->changeTexture( + unk1C[score % 10]->getTexInfo(), 0); + } else { + unk134->show(); + unk138->hide(); + unk13C->changeTexture( + unk1C[score / 100]->getTexInfo(), 0); + score -= ((s32)((f32)score * 0.01f)) * 100; + unk140->changeTexture( + unk1C[score / 10]->getTexInfo(), 0); + unk144->changeTexture( + unk1C[score % 10]->getTexInfo(), 0); + } + } + + unk2E0++; + } else { + unk2E0++; + } + } + gpCardManager->probe(); + } else { + drawMessageBM(PROGRESS_UNK18); + + endWaitForChoice(); + + if (unk2DC != 0) { + unk2DC = 0; + if (unk2DD == 0) + TFlagManager::smInstance->saveFail(); + } + } + } else { + gpCardManager->probe(); + drawMessageBM(PROGRESS_UNK0); + unk2E0++; + } + break; + } + + case PROGRESS_UNK17: + if (unk308 != 0 || unk18) { + unk310 = PROGRESS_UNK1; + } else { + waitForChoiceBM(PROGRESS_UNK1, PROGRESS_UNK19, 0); + } + break; + + case PROGRESS_UNK18: + if (waitForAnyKeyBM(PROGRESS_UNK2) != -1) + gpCardManager->getBookmarkInfos(&unk278[0]); + break; + + case PROGRESS_UNK2A: + if (gpCardManager->getLastStatus() == CARD_RESULT_READY) { + s32 r = waitForSelect2(PROGRESS_UNK16, PROGRESS_UNK1); + gpCardManager->probe(); + if (r == 0) { + TCardBookmarkInfo& bm = getBookmarkInfo(); + if (bm.unk0 == 1) { + unk310 = PROGRESS_UNK1E; + } else { + if (bm.unk18 == 0 + || bm.unk8 + == TFlagManager::getInstance() + ->getLastSaveTime()) { + saveBookmark(unk2EA); + unk310 = PROGRESS_UNK16; + } else { + unk310 = PROGRESS_UNK2C; + } + } + } + } else { + if (unk10 < 3) + unk10 = 4; + waitForSelect2(PROGRESS_UNK3, PROGRESS_UNK3); + } + break; + + case PROGRESS_UNK2B: + if (gpCardManager->getLastStatus() == CARD_RESULT_READY) { + s32 r + = waitForSelect3(PROGRESS_UNK16, PROGRESS_UNK16, PROGRESS_UNK1); + gpCardManager->probe(); + + if (r != -1) { + if (r == 0 || r == 1) { + TCardBookmarkInfo& bm = getBookmarkInfo(); + if (bm.unk0 == 1) { + unk310 = PROGRESS_UNK1E; + } else { + if (bm.unk18 == 0 + || bm.unk8 + == TFlagManager::getInstance() + ->getLastSaveTime()) { + saveBookmark(unk2EA); + unk310 = PROGRESS_UNK16; + } else { + unk310 = PROGRESS_UNK2C; + } + } + + if (r == 0) { + unk2DE = 0; + } else if (r == 1) { + unk2DE = 1; + } + } else { + unk310 = PROGRESS_UNK1; + } + } + } else { + if (unk10 < 3) + unk10 = 4; + waitForSelect3(PROGRESS_UNK3, PROGRESS_UNK3, PROGRESS_UNK3); + } + break; + + case PROGRESS_UNK2C: + if (gpCardManager->getLastStatus() != CARD_RESULT_NOCARD) { + waitForStop(PROGRESS_UNK1); + gpCardManager->probe(); + } else { + if (unkA4->isVisible()) { + unk48->setCenteredSize(20, 0, 0, unk4C.getWidth(), + unk4C.getHeight()); + unkA4->hide(); + unk10 = 3; + } + waitForStop(PROGRESS_UNK3); + } + break; + + case PROGRESS_UNK2E: + waitForSelectOver(); + break; + + case PROGRESS_UNK33: { + s32 status = gpCardManager->getLastStatus(); + if (status == CARD_RESULT_READY) { + s32 r = waitForChoiceBM(PROGRESS_UNK16, PROGRESS_UNK1, 1); + gpCardManager->probe(); + if (r == 0) { + TCardBookmarkInfo& bm = getBookmarkInfo(); + if (bm.unk0 == 1) { + unk310 = PROGRESS_UNK1E; + } else { + if (bm.unk18 == 0 + || bm.unk8 + == TFlagManager::getInstance() + ->getLastSaveTime()) { + saveBookmark(unk2EA); + unk310 = PROGRESS_UNK16; + } else { + unk310 = PROGRESS_UNK2C; + } + } + } + } else { + endWaitForChoice(); + + TEProgress mode = changeMode(status); + waitForChoiceBM(mode, mode, 1); + } + break; + } + + case PROGRESS_UNK34: + waitForChoice(PROGRESS_UNK19, PROGRESS_UNK1, 1); + break; + + default: + break; + } + + if (prevState != unk310) { + unk314 = unk310; + unk318 = 0; + unk2E0 = 0; + unk2F8 = 0; + unk2F9 = 1; + unk2DC = 1; + unk30C = 0; + unk2DD = 0; + unk10 = 0; + unk44 = nullptr; + } + + if (prevMode != unk10) { + if (prevMode == 1) { + gpMSound->startSoundSystemSE(0x4819, 0, nullptr, 0); + } + + if (unk10 == 3) { + gpMSound->startSoundSystemSE(0x481A, 0, nullptr, 0); + } + } +} + +u8 TCardSave::getNextState() +{ + if (unk2DF != 0) { + if (unk310 == 0x19) + return 1; + + if (unk310 == PROGRESS_UNK1) + return 0; + + return 3; + } + + return 3; +} + +void TCardSave::execIssueGX_(JDrama::TGraphics* param_1) +{ + const JDrama::TRect& scissorRect = param_1->getScissor(); + { + J2DOrthoGraph graph(param_1->getViewport()); + graph.setup2D(); + unk14->draw(0, 0, &graph); + } + + param_1->setScissor(scissorRect); +} diff --git a/src/GC2D/ConsoleStr.cpp b/src/GC2D/ConsoleStr.cpp index 05280e27..063a1d0b 100644 --- a/src/GC2D/ConsoleStr.cpp +++ b/src/GC2D/ConsoleStr.cpp @@ -219,9 +219,9 @@ void TConsoleStr::perform(u32 param_1, JDrama::TGraphics* param_2) } if ((param_1 & 0x8) && unk2B8 != 0) { - const JDrama::TRect& rect = param_2->getUnk64(); + const JDrama::TRect& rect = param_2->getScissor(); - J2DOrthoGraph local_1a0(param_2->getUnk54()); + J2DOrthoGraph local_1a0(param_2->getViewport()); local_1a0.setup2D(); if (unk2B8 == 1 && unk18 > 60.0f) { @@ -261,10 +261,7 @@ void TConsoleStr::perform(u32 param_1, JDrama::TGraphics* param_2) } local_1a0.setup2D(); - param_2->mScissorRect = rect; - GXSetScissor(param_2->mScissorRect.x1, param_2->mScissorRect.y1, - param_2->mScissorRect.getWidth(), - param_2->mScissorRect.getHeight()); + param_2->setScissor(rect); } } diff --git a/src/GC2D/Menu.cpp b/src/GC2D/Menu.cpp index f4d704e1..cb608bc4 100644 --- a/src/GC2D/Menu.cpp +++ b/src/GC2D/Menu.cpp @@ -8,10 +8,10 @@ void TMenuBase::perform(u32 param_1, JDrama::TGraphics* param_2) { if (param_1 & 0x8) { - J2DOrthoGraph orthoGraph(param_2->getUnk54()); + J2DOrthoGraph orthoGraph(param_2->getViewport()); orthoGraph.setup2D(); unk10->draw(0, 0, &orthoGraph); - const JUTRect& rect = param_2->getUnk64(); + const JUTRect& rect = param_2->getScissor(); GXSetScissor(rect.x1, rect.y1, rect.getWidth(), rect.getHeight()); } } diff --git a/src/GC2D/MovieSubtitle.cpp b/src/GC2D/MovieSubtitle.cpp index 9e52ed41..b1dcab9f 100644 --- a/src/GC2D/MovieSubtitle.cpp +++ b/src/GC2D/MovieSubtitle.cpp @@ -137,7 +137,7 @@ void TMovieSubTitle::makeBmgName(char* buffer, int, const char* param_3) void TMovieSubTitle::draw(JDrama::TGraphics* param_1) { - J2DOrthoGraph graph(param_1->getUnk54()); + J2DOrthoGraph graph(param_1->getViewport()); graph.setup2D(); unk14->draw(0, 0, &graph); } diff --git a/src/GC2D/ProgSelect.cpp b/src/GC2D/ProgSelect.cpp index dd90d061..28c95613 100644 --- a/src/GC2D/ProgSelect.cpp +++ b/src/GC2D/ProgSelect.cpp @@ -95,7 +95,7 @@ void TProgSelect::perform(u32 param_1, JDrama::TGraphics* param_2) } if (param_1 & 0x8) { - J2DOrthoGraph local_110(param_2->getUnk54()); + J2DOrthoGraph local_110(param_2->getViewport()); local_110.setup2D(); J2DPrint JStack_174(gpSystemFont, 0); JStack_174.setUnk50(32); diff --git a/src/JSystem/JDrama/JDRGraphics.cpp b/src/JSystem/JDrama/JDRGraphics.cpp index 3a56fc29..071ccf78 100644 --- a/src/JSystem/JDrama/JDRGraphics.cpp +++ b/src/JSystem/JDrama/JDRGraphics.cpp @@ -4,7 +4,7 @@ using namespace JDrama; -void TGraphics::setViewport(const TRect& param_1, float param_2, float param_3) +void TGraphics::setViewport(const TRect& param_1, f32 param_2, f32 param_3) { mViewportRect = param_1; diff --git a/src/JSystem/JDrama/JDRViewport.cpp b/src/JSystem/JDrama/JDRViewport.cpp index 958eeb19..3fede163 100644 --- a/src/JSystem/JDrama/JDRViewport.cpp +++ b/src/JSystem/JDrama/JDRViewport.cpp @@ -22,10 +22,7 @@ void TViewport::perform(u32 param_1, TGraphics* param_2) TRect rect(param_2->getUnk44()); rect.intersect(unk10); - param_2->mScissorRect = rect; - GXSetScissor(param_2->mScissorRect.x1, param_2->mScissorRect.y1, - param_2->mScissorRect.getWidth(), - param_2->mScissorRect.getHeight()); + param_2->setScissor(rect); } void TViewport::load(JSUMemoryInputStream& stream) diff --git a/src/MarioUtil/EffectUtil.cpp b/src/MarioUtil/EffectUtil.cpp index ade13c48..fca0bb4e 100644 --- a/src/MarioUtil/EffectUtil.cpp +++ b/src/MarioUtil/EffectUtil.cpp @@ -50,32 +50,31 @@ void SMS_EmitSinkInPollutionEffect(const JGeometry::TVec3& arg0, { if ((gpMarDirector->unk58 % 20) != 0) return; - + using namespace JGeometry; - + const TVec3 fwd(1.f, 0.0f, 0.0f); TVec3 B; B.cross(fwd, arg1); - TPosition3f matrix; - TVec3 C; C.cross(arg1, B); - TVec3 Cnorm; - Cnorm.normalize(C); - TVec3 Bnorm; - Bnorm.normalize(B); - - matrix.mMtx[0][0] = Cnorm.x; - matrix.mMtx[1][0] = Cnorm.y; - matrix.mMtx[2][0] = Cnorm.z; + + C.normalize(); + B.normalize(); + + TPosition3f matrix; + + matrix.mMtx[0][0] = C.x; + matrix.mMtx[1][0] = C.y; + matrix.mMtx[2][0] = C.z; matrix.mMtx[0][1] = arg1.x; matrix.mMtx[1][1] = arg1.y; matrix.mMtx[2][1] = arg1.z; - matrix.mMtx[0][2] = Bnorm.x; - matrix.mMtx[1][2] = Bnorm.y; - matrix.mMtx[2][2] = Bnorm.z; + matrix.mMtx[0][2] = B.x; + matrix.mMtx[1][2] = B.y; + matrix.mMtx[2][2] = B.z; matrix.mMtx[0][3] = arg0.x; matrix.mMtx[1][3] = arg0.y; matrix.mMtx[2][3] = arg0.z; diff --git a/src/MarioUtil/ScreenUtil.cpp b/src/MarioUtil/ScreenUtil.cpp index 556db87e..a9f45aa5 100644 --- a/src/MarioUtil/ScreenUtil.cpp +++ b/src/MarioUtil/ScreenUtil.cpp @@ -115,7 +115,7 @@ void TAfterEffect::perform(u32 param_1, JDrama::TGraphics* param_2) color.b = 0; color.a = 0; - JDrama::TRect& rect = param_2->getUnk54(); + const JDrama::TRect& rect = param_2->getViewport(); unk20 += unk48 * (unk1B - unk20); unk24 += unk48 * (unk1C - unk24);