Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion HackSources/Ghosts/additional hacks.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<--- Hooks the ghost update function into area_update_objects --->
US:
US:
8027B188: 0C 10 20 00

JP:
Expand Down
8 changes: 8 additions & 0 deletions HackSources/Ghosts/export_moving_code_references.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.create "./build/DynamicOffsets.bin", 0x00000000
.word orga(FirstAnimationBufferAddrHi_LUI_1)
.word orga(GhostBaseHi_LUI_PLUS_1)
.word orga(GhostBaseHi_LUI_1)
.word orga(GhostBaseHi_LUI_2)
.word orga(GhostBaseHi_LUI_3)
.word orga(GhostBaseHi_LUI_4)
.close
25 changes: 13 additions & 12 deletions HackSources/Ghosts/geo_switch_mario_cap_effect.asm
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
.n64

addiu SP, SP, 0xFFF8
lui t9, gBodyStatesAddrHi
addiu t9, t9, gBodyStatesAddrLo
lui t0, gCurGraphNodeObjectHi
lw t0, gCurGraphNodeObjectLo (t0)
lb t2, 0x61 (t0)
beq t2, r0, @@RETURN
lb t1, 0x8 (t8)
sh t1, 0x1E (a1)
lui at, MarioObjectAddrHi
lw at, MarioObjectAddrLo (at)
beq t0, at, @@RETURN
nop
bne t0, at, @@IsGhost

; render Mario as usual
lui t9, gBodyStatesAddrHi
lh t2, gBodyStatesAddrLo + 0x8 (t9)
srl t2, t2, 0x8
beq r0, r0, @@RETURN
sh t2, 0x1e (a1)

@@IsGhost:
; apply the chosen effect from the ghost node
lb t2, 0x61 (t0)
sh t2, 0x1e (a1)

@@RETURN:
or v0, r0, r0
jr ra
addiu SP, SP, 0x0008
or v0, r0, r0
14 changes: 8 additions & 6 deletions HackSources/Ghosts/gfx_generate_colored_hats.asm
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ lui at, MarioObjectAddrHi
lw at, MarioObjectAddrLo (at)
lui t8, gCurGraphNodeObjectHi
lw t8, gCurGraphNodeObjectLo (t8)
beq t8, at, @@SkipGhostRead
beq t8, at, @SkipGhostRead
or t2, r0, r0
lb t2, 0x60 (t8)

@@SkipGhostRead:
@SkipGhostRead:
ori t1, t1, 0x1978

sw t0, 0x18 (sp)
sw t1, 0x1C (sp)
sw t2, 0x20 (sp)
addiu at, r0, 0x1
bne at, a0, @@FinishTheJob
bne at, a0, @FinishTheJob
ori a0, r0, 0x38
jal alloc_display_list
nop
Expand All @@ -32,7 +32,9 @@ lui at, 0x0388
ori at, at, 0x0010
sw at, 0x18 (v0)
sw at, 0x0 (v0)
lui t0, 0x8040

GhostBaseHi_LUI_1:
lui t0, GhostBaseHi ; defined in ghost_loop.asm (included first); with the ori below, must match COLORED_HATS_LIGHTS_ADDR in ColoredHats.cs
ori t0, t0, 0x8300
lw t1, 0x20 (sp)
sll t1, t1, 0x5
Expand All @@ -49,10 +51,10 @@ sw t3, 0xC (v0)
sw t4, 0x28 (v0)
lw t0, 0x1C (sp)

@@FinishTheJob:
@FinishTheJob:
sw t0, 0x2C (v0)
lui at, 0xB800
sw at, 0x30 (v0)
lw ra, 0x14 (sp)
jr ra
addiu sp, sp, 0x40
addiu sp, sp, 0x40
4 changes: 3 additions & 1 deletion HackSources/Ghosts/ghost_hack_JP.asm
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@ alloc_display_list equ 0x8027897c

.create "./build/JP_80408200_gfx_generate_colored_hats.bin", 0x00000000
.include "./gfx_generate_colored_hats.asm"
.close
.close

.include "./export_moving_code_references.asm"
4 changes: 3 additions & 1 deletion HackSources/Ghosts/ghost_hack_US.asm
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@ alloc_display_list equ 0x80278f2c

.create "./build/US_80408200_gfx_generate_colored_hats.bin", 0x00000000
.include "./gfx_generate_colored_hats.asm"
.close
.close

.include "./export_moving_code_references.asm"
49 changes: 28 additions & 21 deletions HackSources/Ghosts/ghost_loop.asm
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ RegPointerToCurrentGhost equ s1 ; Pointer to the currently processed ghost node
RegProcessedGhostCount equ s0 ; Iteration counter for loops that process all ghosts

; hardcoded offsets
ExtendedRAMStartHi equ 0x8040 ; The Hi part of the address pointing to the start of extended RAM
GhostBaseHi equ 0x8040 ; The Hi part of the address pointing to the start of extended RAM
NumRequestedGhosts equ 0x7FFF ; Offset from extended RAM start to the byte indicating the number of ghosts to display. This value is written by STROOP.
PointerToFirstGhost equ 0x7FF8 ; Offset from extended RAM start to the 4 byte pointer to the first ghost node
NegativeGhostStructSize equ 0xFF98 ; The negative size of a single ghost node, used to iterate ghosts like a reversed array
Expand All @@ -22,7 +22,7 @@ addiu SP, SP, 0xFFC0
; return early if there's no Mario object
lui t0, MarioObjectAddrHi
lw t0, MarioObjectAddrLo (t0)
beq r0, t0, @@EARLY_RETURN
beq r0, t0, @EARLY_RETURN

; push static registers to stack
sw ra, 0x34 (SP)
Expand All @@ -36,20 +36,22 @@ sw RegProcessedGhostCount, 0x20 (SP)
or RegMarioObject, r0, t0
lh t0, 0x2 (RegMarioObject)
andi t1, t0, InitializedGhostsFlag
bnez t1, @@SKIP_INIT
bnez t1, @SKIP_INIT

; set initialized flag on Mario object
ori t1, t0, InitializedGhostsFlag
sh t1, 0x2 (RegMarioObject)
beq r0, r0, @@RETURN
beq r0, r0, @RETURN

; clean up (this can cause failure?)
lui RegPointerToCurrentGhost, ExtendedRAMStartHi
beq r0, r0, @@CLEAN_UP_EARLY
GhostBaseHi_LUI_2:
lui RegPointerToCurrentGhost, GhostBaseHi
beq r0, r0, @CLEAN_UP_EARLY
ori RegPointerToCurrentGhost, RegPointerToCurrentGhost, PointerToFirstGhost
@@SKIP_INIT:
@SKIP_INIT:

; set up dummy Mario struct
FirstAnimationBufferAddrHi_LUI_1:
lui RegAnimationBuffer, FirstAnimationBufferAddrHi
lui t8, 0x8037
ori at, r0, 0xBD
Expand All @@ -61,17 +63,18 @@ sw at, 0x5B8 (t8)

; clean up if no ghosts are requested
or RegProcessedGhostCount, r0, r0
lui at, ExtendedRAMStartHi
GhostBaseHi_LUI_3:
lui at, GhostBaseHi
ori RegPointerToCurrentGhost, at, PointerToFirstGhost
lb at, NumRequestedGhosts (at)
beq r0, at, @@CLEAN_UP_EARLY
beq r0, at, @CLEAN_UP_EARLY
nop

@@ITERATE_GHOSTS:
@ITERATE_GHOSTS:

; skip initialization if ghost already exists
lw t0, 0x0 (RegPointerToCurrentGhost)
bnez t0, @@GHOST_EXISTS
bnez t0, @GHOST_EXISTS

; create a new ghost object graph node
or a0, r0, r0
Expand All @@ -91,7 +94,7 @@ lw a0, 0xC (RegMarioObject)
jal 0x8037C044
or a1, v0, r0

@@GHOST_EXISTS:
@GHOST_EXISTS:

; copy Mario's area and animation ID into the ghost node
lw RegCurrentGhost, 0x0 (RegPointerToCurrentGhost)
Expand All @@ -107,7 +110,9 @@ andi t0, t0, 0x7F
sll t0, t0, 0x5
sll t1, RegProcessedGhostCount, 0xC
addu t0, t0, t1
lui at, 0x8041

GhostBaseHi_LUI_PLUS_1:
lui at, GhostBaseHi + 1
addu t0, t0, at
addiu t0, t0, 0x9B00

Expand Down Expand Up @@ -147,25 +152,27 @@ sh t1, 0x40 (RegCurrentGhost)
addiu RegAnimationBuffer, RegAnimationBuffer, AnimationBufferSize
addiu RegPointerToCurrentGhost, RegPointerToCurrentGhost, NegativeGhostStructSize
addiu RegProcessedGhostCount, RegProcessedGhostCount, 0x1
lui at, ExtendedRAMStartHi

GhostBaseHi_LUI_4:
lui at, GhostBaseHi
lb at, NumRequestedGhosts (at)
sltu t0, RegProcessedGhostCount, at
bnez t0, @@ITERATE_GHOSTS
bnez t0, @ITERATE_GHOSTS
sb RegProcessedGhostCount, 0x60 (RegCurrentGhost)

; delete leftover ghosts
lw RegCurrentGhost, 0x0 (RegPointerToCurrentGhost)
beq RegCurrentGhost, r0, @@RETURN
beq RegCurrentGhost, r0, @RETURN
or a0, r0, RegCurrentGhost
@@CLEAN_UP_LOOP:
@CLEAN_UP_LOOP:
jal 0x8037C0BC
sw r0, 0x0 (RegPointerToCurrentGhost)
@@CLEAN_UP_EARLY:
@CLEAN_UP_EARLY:
lw a0, 0x0 (RegPointerToCurrentGhost)
bnez a0, @@CLEAN_UP_LOOP
bnez a0, @CLEAN_UP_LOOP
addiu RegPointerToCurrentGhost, RegPointerToCurrentGhost, NegativeGhostStructSize

@@RETURN:
@RETURN:

; pop static registers from stack
lw ra, 0x34 (SP)
Expand All @@ -175,6 +182,6 @@ lw RegCurrentGhost, 0x28 (SP)
lw RegPointerToCurrentGhost, 0x24 (SP)
lw RegProcessedGhostCount, 0x20 (SP)

@@EARLY_RETURN:
@EARLY_RETURN:
jr ra
addiu SP, SP, 0x40
2 changes: 1 addition & 1 deletion STROOP/Resources/Hacks/GhostHackJP.hck
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@

80276AF4: 27 BD FF D0 AF BF 00 14 24 01 00 01 14 81 00 1A 00 00 10 25 00 A0 20 25 3C 08 80 34 25 08 A0 40 8C B8 00 18 00 18 C8 80 03 38 C8 21 00 19 C8 C0 03 28 48 21 3C 08 80 33 8D 08 CF A0 3C 01 80 36 8C 21 FD E8 15 01 00 06 85 2C 00 08 31 8D 01 00 11 A0 00 07 34 05 00 FF 10 00 00 05 31 85 00 FF 81 18 00 61 13 00 00 02 34 05 00 FF 34 05 00 7F 0C 09 DA 78 00 00 00 00 8F BF 00 14 03 E0 00 08 27 BD 00 30

80277128: 27 BD FF F8 3C 19 80 34 27 39 A0 40 3C 08 80 33 8D 08 CF A0 81 0A 00 61 11 40 00 07 83 09 00 08 A4 A9 00 1E 3C 01 80 36 8C 21 FD E8 11 01 00 02 00 00 00 00 A4 AA 00 1E 00 00 10 25 03 E0 00 08 27 BD 00 08
80277128: 3C 08 80 33 8D 08 CF A0 3C 01 80 36 8C 21 FD E8 15 01 00 05 3C 19 80 34 87 2A A0 48 00 0A 52 02 10 00 00 03 A4 AA 00 1E 81 0A 00 61 A4 AA 00 1E 03 E0 00 08 00 00 10 25
2 changes: 1 addition & 1 deletion STROOP/Resources/Hacks/GhostHackUS.hck
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@

802770A4: 27 BD FF D0 AF BF 00 14 24 01 00 01 14 81 00 1A 00 00 10 25 00 A0 20 25 3C 08 80 34 25 08 B3 B0 8C B8 00 18 00 18 C8 80 03 38 C8 21 00 19 C8 C0 03 28 48 21 3C 08 80 33 8D 08 DF 00 3C 01 80 36 8C 21 11 58 15 01 00 06 85 2C 00 08 31 8D 01 00 11 A0 00 07 34 05 00 FF 10 00 00 05 31 85 00 FF 81 18 00 61 13 00 00 02 34 05 00 FF 34 05 00 7F 0C 09 DB E4 00 00 00 00 8F BF 00 14 03 E0 00 08 27 BD 00 30

802776D8: 27 BD FF F8 3C 19 80 34 27 39 B3 B0 3C 08 80 33 8D 08 DF 00 81 0A 00 61 11 40 00 07 83 09 00 08 A4 A9 00 1E 3C 01 80 36 8C 21 11 58 11 01 00 02 00 00 00 00 A4 AA 00 1E 00 00 10 25 03 E0 00 08 27 BD 00 08
802776D8: 3C 08 80 33 8D 08 DF 00 3C 01 80 36 8C 21 11 58 15 01 00 05 3C 19 80 34 87 2A B3 B8 00 0A 52 02 10 00 00 03 A4 AA 00 1E 81 0A 00 61 A4 AA 00 1E 03 E0 00 08 00 00 10 25
9 changes: 5 additions & 4 deletions STROOP/Structs/RomHack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void LoadHackFromFile(string hackFileName)
} while (nextEnd != -1);
}

public void LoadPayload()
public void LoadPayload(Dictionary<uint, uint> destinationRemap = null)
{
bool success = true;

Expand All @@ -85,10 +85,11 @@ public void LoadPayload()

using (Config.Stream.Suspend())
{
foreach (var (address, data) in _payload)
foreach (var (originalAddress, data) in _payload)
{
// Hacks are entered as big endian; we need to swap the address endianess before writing
var fixedAddress = EndiannessUtilities.SwapAddressEndianness(address, data.Length);
var effectiveAddress = destinationRemap?.GetValueOrDefault(originalAddress, originalAddress) ?? originalAddress;
// Hacks are entered as big endian; we need to swap the address endianess before writing
var fixedAddress = EndiannessUtilities.SwapAddressEndianness(effectiveAddress, data.Length);

// Read original memory before replacing
_originalMemory.Add(new Tuple<uint, byte[]>(fixedAddress, Config.Stream.ReadRam((UIntPtr)fixedAddress, data.Length, EndiannessType.Big)));
Expand Down
13 changes: 7 additions & 6 deletions STROOP/Tabs/GhostTab/ColoredHats.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ partial class GhostTab
{
// <--- static utility and information --->

const uint COLORED_HATS_CODE_OFFSET = 0x8200u;

private static int defaultGhostColorCounter = 1;

private static readonly Vector4[] DefaultGhostColors = new[]
Expand All @@ -29,17 +31,16 @@ partial class GhostTab
new Vector4(0.2f, 0.2f, 0.2f, 1),
};

Vector4 marioHatColor = new Vector4(1, 0, 0, 1);

const uint VANILLA_BANK_04_OFFSET_US = 0x0007EC20;
const uint VANILLA_BANK_04_OFFSET_JP = 0x0007BDC0;
const uint S_SEGMENT_TABLE_OFFSET_JP = 0x8033a090;
const uint S_SEGMENT_TABLE_OFFSET_US = 0x8033b400;

const uint COLORED_HATS_CODE_TARGET_ADDR = 0x80408200;
const uint COLORED_HATS_LIGHTS_ADDR = 0x80408300;
Vector4 marioHatColor = new Vector4(1, 0, 0, 1);

uint COLORED_HATS_LIGHTS_ADDR => ghostRegionBase + 0x8300u;

private static void EnableColoredHats()
private void EnableColoredHats()
{
using (Config.Stream.Suspend())
{
Expand Down Expand Up @@ -68,7 +69,7 @@ private static void EnableColoredHats()
var foundPointer = Config.Stream.GetUInt32(addr + 0x14);
if (Array.IndexOf(originalDisplayListPointers, foundPointer) != -1)
{
Config.Stream.SetValue(COLORED_HATS_CODE_TARGET_ADDR, addr + 0x14);
Config.Stream.SetValue(ghostRegionBase + COLORED_HATS_CODE_OFFSET, addr + 0x14);
Config.Stream.SetValue((ushort)0x12A, addr);
}
}
Expand Down
Loading
Loading