diff --git a/asm/non_matching/vram/LoadSwapGFX.inc b/asm/non_matching/vram/LoadSwapGFX.inc new file mode 100644 index 00000000..c0b5b146 --- /dev/null +++ b/asm/non_matching/vram/LoadSwapGFX.inc @@ -0,0 +1,91 @@ + .syntax unified +.ifdef EU + push {r4, r5, r6, lr} + adds r6, r0, #0 + adds r5, r1, #0 + adds r4, r2, #0 + cmp r4, #0 + bne _080AD79C + adds r0, r5, #0 + bl FindFreeGFXSlots + adds r4, r0, #0 + cmp r4, #0 + beq _080AD7C4 +_080AD79C: + ldr r0, _080AD7D0 @ =gGFXSlots + lsls r1, r4, #1 + adds r1, r1, r4 + lsls r1, r1, #2 + adds r1, r1, r0 + ldrb r0, [r1, #4] + lsls r0, r0, #0x1c + lsrs r2, r0, #0x1c + cmp r2, #6 + beq _080AD7BC + adds r0, r4, #0 + movs r1, #0 + adds r2, r5, #0 + bl ReserveGFXSlots + movs r2, #5 +_080AD7BC: + adds r0, r4, #0 + adds r1, r6, #0 + bl sub_080AE0C8 +_080AD7C4: + adds r0, r4, #0 + cmp r0, #0 + beq _080AD7CC + movs r0, #1 +_080AD7CC: + pop {r4, r5, r6, pc} + .align 2, 0 +_080AD7D0: .4byte gGFXSlots +.else + push {r4, r5, r6, lr} + adds r6, r0, #0 + adds r5, r1, #0 + adds r4, r2, #0 + cmp r4, #0 + bne _080AE030 + adds r0, r5, #0 + bl FindFreeGFXSlots + adds r4, r0, #0 + cmp r4, #0 + bne _080AE030 + bl CleanUpGFXSlots + adds r0, r5, #0 + bl FindFreeGFXSlots + adds r4, r0, #0 + cmp r4, #0 + beq _080AE058 +_080AE030: + ldr r0, _080AE064 @ =gGFXSlots + lsls r1, r4, #1 + adds r1, r1, r4 + lsls r1, r1, #2 + adds r1, r1, r0 + ldrb r0, [r1, #4] + lsls r0, r0, #0x1c + lsrs r2, r0, #0x1c + cmp r2, #6 + beq _080AE050 + adds r0, r4, #0 + movs r1, #0 + adds r2, r5, #0 + bl ReserveGFXSlots + movs r2, #5 +_080AE050: + adds r0, r4, #0 + adds r1, r6, #0 + bl sub_080AE0C8 +_080AE058: + adds r0, r4, #0 + cmp r0, #0 + beq _080AE060 + movs r0, #1 +_080AE060: + pop {r4, r5, r6, pc} + .align 2, 0 +_080AE064: .4byte gGFXSlots +.endif + .syntax divided diff --git a/asm/non_matching/vram/sub_080ADDD8.inc b/asm/non_matching/vram/sub_080ADDD8.inc new file mode 100644 index 00000000..24959b7c --- /dev/null +++ b/asm/non_matching/vram/sub_080ADDD8.inc @@ -0,0 +1,39 @@ + .syntax unified + push {lr} + adds r2, r1, #0 + lsls r1, r0, #1 + adds r1, r1, r0 + lsls r1, r1, #2 + ldr r0, _080ADDFC @ =gUnk_02024494 + adds r3, r1, r0 + ldr r0, _080ADE00 @ =0x00FFFFFC + ands r0, r2 + ldr r1, _080ADE04 @ =gGlobalGfxAndPalettes + adds r0, r0, r1 + str r0, [r3, #8] + movs r0, #1 + ands r0, r2 + cmp r0, #0 + beq _080ADE0C + ldr r0, _080ADE08 @ =0x0000FFFF + b _080ADE14 + .align 2, 0 +_080ADDFC: .4byte gUnk_02024494 +_080ADE00: .4byte 0x00FFFFFC +_080ADE04: .4byte gGlobalGfxAndPalettes +_080ADE08: .4byte 0x0000FFFF +_080ADE0C: + movs r0, #0xfe + lsls r0, r0, #0x17 + ands r0, r2 + lsrs r0, r0, #0x14 +_080ADE14: + strh r0, [r3, #6] + ldrb r0, [r3] + movs r1, #0xf + ands r1, r0 + movs r0, #0x30 + orrs r1, r0 + strb r1, [r3] + pop {pc} + .syntax divided diff --git a/asm/non_matching/vram/sub_080ADE74.inc b/asm/non_matching/vram/sub_080ADE74.inc new file mode 100644 index 00000000..ce864510 --- /dev/null +++ b/asm/non_matching/vram/sub_080ADE74.inc @@ -0,0 +1,135 @@ + .syntax unified + push {r4, r5, r6, lr} + adds r2, r0, #0 + lsls r0, r2, #1 + adds r0, r0, r2 + lsls r0, r0, #2 + ldr r1, _080ADF00 @ =gUnk_02024494 + adds r3, r0, r1 + ldrb r1, [r3] + movs r0, #0xf0 + ands r0, r1 + cmp r0, #0 + beq _080ADF7C + movs r0, #0xf + ands r0, r1 + movs r1, #0x10 + orrs r0, r1 + strb r0, [r3] + ldrh r1, [r3, #6] + ldr r0, _080ADF04 @ =0x0000FFFF + cmp r1, r0 + beq _080ADF18 + ldrb r0, [r3, #3] + cmp r0, #0 + beq _080ADF18 + lsls r0, r0, #6 + ldr r1, _080ADF08 @ =gUnk_020000C0 + adds r4, r0, r1 + movs r5, #4 + movs r6, #9 + rsbs r6, r6, #0 +_080ADEB0: + ldrb r1, [r4] + movs r0, #4 + ands r0, r1 + cmp r0, #0 + beq _080ADEF6 + ldr r0, _080ADF0C @ =gGFXSlots + ldrb r0, [r0, #3] + cmp r0, #0 + bne _080ADECA + movs r0, #8 + ands r0, r1 + cmp r0, #0 + beq _080ADEF6 +_080ADECA: + adds r0, r6, #0 + ands r0, r1 + strb r0, [r4] + ldrb r0, [r4, #9] + lsls r2, r0, #5 + cmp r2, #0 + beq _080ADEF6 + ldrh r0, [r4, #0xa] + lsls r0, r0, #5 + ldr r3, _080ADF10 @ =0x06010000 + adds r1, r0, r3 + ldr r3, _080ADF14 @ =0x040000D4 + ldr r0, [r4, #0xc] + str r0, [r3] + str r1, [r3, #4] + adds r0, r2, #0 + asrs r0, r0, #2 + movs r1, #0x84 + lsls r1, r1, #0x18 + orrs r0, r1 + str r0, [r3, #8] + ldr r0, [r3, #8] +_080ADEF6: + adds r4, #0x10 + subs r5, #1 + cmp r5, #0 + bgt _080ADEB0 + b _080ADF7C + .align 2, 0 +_080ADF00: .4byte gUnk_02024494 +_080ADF04: .4byte 0x0000FFFF +_080ADF08: .4byte gUnk_020000C0 +_080ADF0C: .4byte gGFXSlots +_080ADF10: .4byte 0x06010000 +_080ADF14: .4byte 0x040000D4 +_080ADF18: + lsls r0, r2, #9 + ldr r2, _080ADF4C @ =0x06012800 + adds r1, r0, r2 + ldrh r2, [r3, #6] + cmp r2, #0 + beq _080ADF58 + ldr r0, _080ADF50 @ =0x0000FFFF + cmp r2, r0 + beq _080ADF62 + ldr r2, _080ADF54 @ =0x040000D4 + ldr r0, [r3, #8] + str r0, [r2] + str r1, [r2, #4] + ldrh r0, [r3, #6] + lsls r0, r0, #3 + movs r1, #0x84 + lsls r1, r1, #0x18 + orrs r0, r1 + str r0, [r2, #8] + ldr r0, [r2, #8] + ldrh r2, [r3, #6] + subs r2, #0x10 + cmp r2, #0 + ble _080ADF7C + b _080ADF70 + .align 2, 0 +_080ADF4C: .4byte 0x06012800 +_080ADF50: .4byte 0x0000FFFF +_080ADF54: .4byte 0x040000D4 +_080ADF58: + ldrb r1, [r3] + movs r0, #0xf + ands r0, r1 + strb r0, [r3] + b _080ADF7C +_080ADF62: + ldrb r0, [r3, #3] + cmp r0, #0 + bne _080ADF7C + ldr r0, [r3, #8] + bl LZ77UnCompVram + b _080ADF7C +_080ADF70: + adds r3, #0xc + movs r0, #0 + strh r0, [r3, #6] + subs r2, #0x10 + cmp r2, #0 + bgt _080ADF70 +_080ADF7C: + pop {r4, r5, r6, pc} + .align 2, 0 + .syntax divided diff --git a/asm/non_matching/vram/sub_080AE218.inc b/asm/non_matching/vram/sub_080AE218.inc new file mode 100644 index 00000000..04329b49 --- /dev/null +++ b/asm/non_matching/vram/sub_080AE218.inc @@ -0,0 +1,138 @@ + .syntax unified + push {r4, r5, r6, r7, lr} + mov r7, sl + mov r6, sb + mov r5, r8 + push {r5, r6, r7} + mov sl, r0 + mov r8, r1 + lsls r0, r1, #4 + movs r1, #0xa0 + lsls r1, r1, #1 + adds r0, r0, r1 + mov ip, r0 + mov r2, sl + lsls r0, r2, #4 + adds r3, r0, r1 + ldr r1, _080AE30C @ =gGFXSlots + lsls r0, r2, #1 + add r0, sl + lsls r0, r0, #2 + adds r0, r0, r1 + ldrb r0, [r0, #5] + lsls r0, r0, #4 + adds r7, r3, r0 + movs r4, #0 + ldr r6, _080AE310 @ =gUnk_020000C0 + mov sb, r6 + ldr r0, _080AE314 @ =gPlayerEntity + adds r2, r0, #0 + adds r2, #0x26 + adds r5, r0, #0 +_080AE254: + ldr r0, [r5, #4] + cmp r0, #0 + beq _080AE276 + ldrb r0, [r2] + cmp sl, r0 + bne _080AE264 + mov r1, r8 + strb r1, [r2] +_080AE264: + ldrh r0, [r2, #0x3a] + cmp r3, r0 + bhi _080AE276 + cmp r7, r0 + bls _080AE276 + subs r0, r0, r3 + mov r6, ip + adds r1, r0, r6 + strh r1, [r2, #0x3a] +_080AE276: + adds r2, #0x88 + adds r5, #0x88 + adds r4, #1 + cmp r4, #0x4f + bls _080AE254 + movs r0, #0 +_080AE282: + movs r4, #0 + adds r1, r0, #1 + mov r8, r1 + lsls r5, r0, #6 +_080AE28A: + lsls r0, r4, #4 + add r0, sb + adds r2, r5, r0 + ldrb r1, [r2] + movs r0, #1 + ands r0, r1 + cmp r0, #0 + beq _080AE2B4 + movs r0, #2 + ands r0, r1 + cmp r0, #0 + bne _080AE2B4 + ldrh r1, [r2, #0xa] + cmp r3, r1 + bhi _080AE2B4 + cmp r7, r1 + bls _080AE2B4 + subs r0, r1, r3 + mov r6, ip + adds r1, r0, r6 + strh r1, [r2, #0xa] +_080AE2B4: + adds r4, #1 + cmp r4, #3 + bls _080AE28A + mov r0, r8 + cmp r0, #0x2f + bls _080AE282 + movs r4, #0 + ldr r0, _080AE318 @ =0xFFFFFC00 + mov sl, r0 + ldr r5, _080AE31C @ =gOAMControls + adds r5, #0x24 + ldr r1, _080AE320 @ =0x000003FF + mov sb, r1 + movs r2, #1 + mov r8, r2 +_080AE2D2: + ldrh r2, [r5] + lsls r0, r2, #0x16 + lsrs r1, r0, #0x16 + cmp r3, r1 + bhi _080AE2F8 + cmp r7, r1 + bls _080AE2F8 + subs r0, r1, r3 + mov r6, ip + adds r1, r0, r6 + mov r0, sb + ands r1, r0 + mov r0, sl + ands r0, r2 + orrs r0, r1 + strh r0, [r5] + mov r2, r8 + ldr r1, _080AE31C @ =gOAMControls + strb r2, [r1] +_080AE2F8: + adds r5, #8 + adds r4, #1 + cmp r4, #0x7f + bls _080AE2D2 + pop {r3, r4, r5} + mov r8, r3 + mov sb, r4 + mov sl, r5 + pop {r4, r5, r6, r7, pc} + .align 2, 0 +_080AE30C: .4byte gGFXSlots +_080AE310: .4byte gUnk_020000C0 +_080AE314: .4byte gPlayerEntity +_080AE318: .4byte 0xFFFFFC00 +_080AE31C: .4byte gOAMControls +_080AE320: .4byte 0x000003FF + .syntax divided diff --git a/asm/non_matching/vram/sub_080AE324.inc b/asm/non_matching/vram/sub_080AE324.inc new file mode 100644 index 00000000..b46bd50f --- /dev/null +++ b/asm/non_matching/vram/sub_080AE324.inc @@ -0,0 +1,50 @@ + .syntax unified + push {r4, r5, r6, r7, lr} + mov r7, r8 + push {r7} + adds r3, r1, #0 + ldr r2, _080AE380 @ =gGFXSlots + lsls r1, r0, #1 + adds r1, r1, r0 + lsls r1, r1, #2 + adds r5, r1, r2 + ldrb r4, [r5, #5] + subs r4, #1 + movs r0, #1 + rsbs r0, r0, #0 + cmp r4, r0 + beq _080AE372 + lsls r0, r3, #1 + adds r0, r0, r3 + lsls r0, r0, #2 + adds r0, r0, r2 + mov r8, r0 + adds r0, r1, #4 + adds r6, r0, r2 +_080AE350: + mov r0, r8 + adds r0, #4 + adds r1, r5, #4 + ldm r1!, {r2, r3, r7} + stm r0!, {r2, r3, r7} + adds r0, r6, #0 + movs r1, #0xc + bl MemClear + adds r6, #0xc + adds r5, #0xc + movs r0, #0xc + add r8, r0 + subs r4, #1 + subs r0, #0xd + cmp r4, r0 + bne _080AE350 +_080AE372: + ldr r1, _080AE380 @ =gGFXSlots + movs r0, #1 + strb r0, [r1, #3] + pop {r3} + mov r8, r3 + pop {r4, r5, r6, r7, pc} + .align 2, 0 +_080AE380: .4byte gGFXSlots + .syntax divided diff --git a/asm/vram.s b/asm/vram.s index 89e66f11..31e20355 100644 --- a/asm/vram.s +++ b/asm/vram.s @@ -395,7 +395,7 @@ _080AD72C: ands r0, r7 lsrs r6, r0, #0x18 adds r0, r6, #0 - bl FindFreeGFXSlot + bl FindFreeGFXSlots adds r4, r0, #0 cmp r4, #0 beq _080AD77C @@ -450,13 +450,13 @@ _080ADF94: ands r0, r1 lsrs r6, r0, #0x18 adds r0, r6, #0 - bl FindFreeGFXSlot + bl FindFreeGFXSlots adds r5, r0, #0 cmp r5, #0 bne _080ADFDC bl CleanUpGFXSlots adds r0, r6, #0 - bl FindFreeGFXSlot + bl FindFreeGFXSlots adds r5, r0, #0 cmp r5, #0 bne _080ADFDC @@ -500,7 +500,7 @@ LoadSwapGFX: @ 0x080AE008 cmp r4, #0 bne _080AD79C adds r0, r5, #0 - bl FindFreeGFXSlot + bl FindFreeGFXSlots adds r4, r0, #0 cmp r4, #0 beq _080AD7C4 @@ -542,13 +542,13 @@ _080AD7D0: .4byte gGFXSlots cmp r4, #0 bne _080AE030 adds r0, r5, #0 - bl FindFreeGFXSlot + bl FindFreeGFXSlots adds r4, r0, #0 cmp r4, #0 bne _080AE030 bl CleanUpGFXSlots adds r0, r5, #0 - bl FindFreeGFXSlot + bl FindFreeGFXSlots adds r4, r0, #0 cmp r4, #0 beq _080AE058 @@ -583,8 +583,8 @@ _080AE060: _080AE064: .4byte gGFXSlots .endif - thumb_func_start sub_080AE068 -sub_080AE068: @ 0x080AE068 + thumb_func_start UnloadGFXSlots +UnloadGFXSlots: @ 0x080AE068 push {r4, r5, lr} adds r0, #0x26 ldrb r2, [r0] @@ -664,7 +664,7 @@ sub_080AE0C8: @ 0x080AE0C8 _080AE0F6: adds r0, r1, #0 adds r1, r4, #0 - bl sub_080AE134 + bl SetGFXSlotStatus pop {r4, pc} .align 2, 0 _080AE100: .4byte gUnk_02024494 @@ -688,13 +688,13 @@ ReserveGFXSlots: @ 0x080AE104 strh r6, [r4, #4] adds r0, r4, #0 movs r1, #4 - bl sub_080AE134 + bl SetGFXSlotStatus pop {r4, r5, r6, pc} .align 2, 0 _080AE130: .4byte gUnk_02024494 - thumb_func_start sub_080AE134 -sub_080AE134: @ 0x080AE134 + thumb_func_start SetGFXSlotStatus +SetGFXSlotStatus: @ 0x080AE134 push {r4, r5, r6, lr} adds r3, r0, #0 adds r4, r1, #0 @@ -731,8 +731,8 @@ _080AE170: pop {r4, r5, r6, pc} .align 2, 0 - thumb_func_start FindFreeGFXSlot -FindFreeGFXSlot: @ 0x080AE174 + thumb_func_start FindFreeGFXSlots +FindFreeGFXSlots: @ 0x080AE174 push {r4, lr} adds r4, r0, #0 movs r1, #0 @@ -807,7 +807,7 @@ CleanUpGFXSlots: @ 0x080AE1D8 .align 2, 0 _080AE1E8: .4byte gGFXSlots _080AE1EC: - bl sub_080AE3B8 + bl FindFirstFreeGFXSlot adds r4, r0, #0 cmp r4, r5 bhi _080AE208 @@ -822,7 +822,7 @@ _080AE208: adds r5, #1 _080AE20A: adds r0, r5, #0 - bl sub_080AE384 + bl FindNextOccupiedGFXSlot adds r5, r0, #0 cmp r5, #0 bne _080AE1EC @@ -1019,8 +1019,8 @@ _080AE372: .align 2, 0 _080AE380: .4byte gGFXSlots - thumb_func_start sub_080AE384 -sub_080AE384: @ 0x080AE384 + thumb_func_start FindNextOccupiedGFXSlot +FindNextOccupiedGFXSlot: @ 0x080AE384 push {lr} adds r2, r0, #0 cmp r2, #0x2a @@ -1052,8 +1052,8 @@ _080AE3B4: _080AE3B6: pop {pc} - thumb_func_start sub_080AE3B8 -sub_080AE3B8: @ 0x080AE3B8 + thumb_func_start FindFirstFreeGFXSlot +FindFirstFreeGFXSlot: @ 0x080AE3B8 push {lr} movs r1, #4 ldr r0, _080AE3D4 @ =gGFXSlots diff --git a/include/color.h b/include/color.h index e6db795a..2a728474 100644 --- a/include/color.h +++ b/include/color.h @@ -25,6 +25,7 @@ typedef struct { union SplitWord unk_08; u32 unk_0C; } struct_gUnk_020000C0_1; + typedef struct { struct_gUnk_020000C0_1 unk_00[4]; } struct_gUnk_020000C0; diff --git a/include/functions.h b/include/functions.h index b89a1a80..4fdc5222 100644 --- a/include/functions.h +++ b/include/functions.h @@ -241,7 +241,7 @@ extern void sub_080A57F4(void); extern void sub_080A71C4(u32, u32, u32, u32); extern void sub_080A7C18(u32, u32, u32); extern void sub_080ADD70(void); -extern void sub_080AE068(Entity*); +extern void UnloadGFXSlots(Entity*); extern bool32 sub_080AE4CC(Entity*, u32, u32, u32); extern void sub_080AE58C(Entity*, u32, u32); extern void sub_080AF284(void); diff --git a/include/structures.h b/include/structures.h index d2762da5..b87b9672 100644 --- a/include/structures.h +++ b/include/structures.h @@ -56,10 +56,45 @@ typedef struct { } struct_0200AF00; extern struct_0200AF00 gUnk_0200AF00; +#define MAX_GFX_SLOTS 44 + +typedef enum { + GFX_SLOT_FREE, + GFX_SLOT_UNLOADED, // some sort of free? no longer in use? + GFX_SLOT_STATUS2, // some sort of free? + GFX_SLOT_FOLLOWER, // Set by SetGFXSlotStatus for the following slots + GFX_SLOT_RESERVED, // maybe ready to be loaded? + GFX_SLOT_GFX, + GFX_SLOT_PALETTE +} GfxSlotStatus; + +typedef enum { + GFX_VRAM_0, + GFX_VRAM_1, // uploaded to vram? + GFX_VRAM_2, + GFX_VRAM_3, // not yet uploaded to vram? +} GfxSlotVramStatus; + +typedef struct { + u8 status : 4; + u8 vramStatus : 4; // Whether the gfx was uploaded to the vram? + u8 slotCount; + u8 referenceCount; /**< How many entities use this gfx slot */ + u8 unk_3; + u16 gfxIndex; + u16 paletteIndex; + const void* palettePointer; +} GfxSlot; typedef struct { u8 unk0; -} struct_02024490; -extern struct_02024490 gGFXSlots; + u8 unk_1; + u8 unk_2; + u8 unk_3; + GfxSlot slots[MAX_GFX_SLOTS]; +} GfxSlotList; +extern GfxSlotList gGFXSlots; + +static_assert(sizeof(GfxSlotList) == 0x214); typedef struct { u16 unk_00; diff --git a/linker.ld b/linker.ld index bec571fb..826528e2 100644 --- a/linker.ld +++ b/linker.ld @@ -879,7 +879,7 @@ SECTIONS { src/title.o(.text); src/affine.o(.text); src/playerItem/playerItemGustJar.o(.text); - asm/vram.o(.text); + src/vram.o(.text); src/movement.o(.text); /* library functions */ asm/lib/m4a_asm.o(.text); diff --git a/src/enemy/businessScrub.c b/src/enemy/businessScrub.c index 939381b0..6c71441d 100644 --- a/src/enemy/businessScrub.c +++ b/src/enemy/businessScrub.c @@ -419,7 +419,7 @@ void sub_08028FFC(Entity* this) { this->action = 1; COLLISION_OFF(this); this->spritePriority.b1 = 0; - sub_080AE068(this); + UnloadGFXSlots(this); UnloadOBJPalette(this); this->spriteVramOffset = 0xe8; this->palette.b.b0 = 2; diff --git a/src/enemy/octorokBoss.c b/src/enemy/octorokBoss.c index cd45f7cf..b984eb85 100644 --- a/src/enemy/octorokBoss.c +++ b/src/enemy/octorokBoss.c @@ -263,7 +263,7 @@ void OctorokBoss_Hit_SubAction1(Entity* this) { if (GET_TIMER(this) == 0) { this->subAction = 2; GET_BOSS_PHASE(this)++; - sub_080AE068(this); + UnloadGFXSlots(this); if (IS_FROZEN(this) == FALSE) { this->hitType = 0x5f; LoadFixedGFX(this, 0x108); diff --git a/src/enemy/rupeeLike.c b/src/enemy/rupeeLike.c index 1a12801c..903ddc0b 100644 --- a/src/enemy/rupeeLike.c +++ b/src/enemy/rupeeLike.c @@ -280,7 +280,7 @@ void sub_080297F0(Entity* this) { COLLISION_ON(this); this->spriteSettings.draw = TRUE; this->hitType = 0x8e; - sub_080AE068(this); + UnloadGFXSlots(this); #ifdef EU this->spriteIndex = 0x142; #else diff --git a/src/enemy/vaatiWrath.c b/src/enemy/vaatiWrath.c index 38115022..af31d2f8 100644 --- a/src/enemy/vaatiWrath.c +++ b/src/enemy/vaatiWrath.c @@ -574,7 +574,7 @@ void sub_08041BE8(Entity* this) { entity = ((VaatiWrathHeapStruct*)this->myHeap)->type2; entity->updatePriority = PRIO_NO_BLOCK; - sub_080AE068(entity); + UnloadGFXSlots(entity); LoadFixedGFX(entity, 0x1f5); ChangeObjPalette(entity, 0x16b); InitializeAnimation(entity, 0x1a); diff --git a/src/entity.c b/src/entity.c index 864b9482..0cb64131 100644 --- a/src/entity.c +++ b/src/entity.c @@ -341,7 +341,7 @@ void DeleteEntityAny(Entity* ent) { void DeleteEntity(Entity* ent) { if (ent->next) { - sub_080AE068(ent); + UnloadGFXSlots(ent); UnloadOBJPalette(ent); sub_0806FE84(ent); sub_080788E0(ent); diff --git a/src/object/blockPushed.c b/src/object/blockPushed.c index f79a0ae0..58280fcd 100644 --- a/src/object/blockPushed.c +++ b/src/object/blockPushed.c @@ -30,7 +30,7 @@ void sub_08082EB4(BlockPushedEntity* this) { u32 pos; if (gRoomControls.area == 0x11) { - sub_080AE068(super); + UnloadGFXSlots(super); if (LoadFixedGFX(super, 0x1c1) == 0) { super->spriteSettings.draw = 0; return; diff --git a/src/object/minishSizedEntrance.c b/src/object/minishSizedEntrance.c index a4c9c296..bf235ee0 100644 --- a/src/object/minishSizedEntrance.c +++ b/src/object/minishSizedEntrance.c @@ -16,7 +16,7 @@ void sub_08090EC0(Entity* this) { this->frameIndex = this->type2; if (AreaIsDungeon()) { this->frameIndex += 4; - sub_080AE068(this); + UnloadGFXSlots(this); LoadFixedGFX(this, 0x184); } } diff --git a/src/object/waterfallOpening.c b/src/object/waterfallOpening.c index ce9e092b..34216c0d 100644 --- a/src/object/waterfallOpening.c +++ b/src/object/waterfallOpening.c @@ -36,7 +36,7 @@ void WaterfallOpening(Entity* this) { this->field_0xf = 0; this->subAction = 1; this->type = 1; - sub_080AE068(this); + UnloadGFXSlots(this); LoadFixedGFX(this, 0x18c); #ifndef EU SoundReq(SFX_EVAPORATE); @@ -49,7 +49,7 @@ void WaterfallOpening(Entity* this) { this->actionDelay = 1; this->subAction = 2; this->type = 2; - sub_080AE068(this); + UnloadGFXSlots(this); LoadFixedGFX(this, 0x18d); } break; diff --git a/src/vram.c b/src/vram.c new file mode 100644 index 00000000..fd3ff67e --- /dev/null +++ b/src/vram.c @@ -0,0 +1,339 @@ +#include "global.h" +#include "common.h" +#include "structures.h" +#include "fileselect.h" + +extern u32 gFixedTypeGfxData[]; + +void ReserveGFXSlots(u32, u32, u32); +void sub_080ADE74(u32); +void sub_080ADE24(void); +u32 FindFreeGFXSlots(u32); +void CleanUpGFXSlots(void); +void sub_080ADDD8(u32, u32); +void sub_080AE0C8(u32, Entity*, u32); +void SetGFXSlotStatus(GfxSlot*, u32); +u32 FindNextOccupiedGFXSlot(u32); +u32 FindFirstFreeGFXSlot(void); +void sub_080AE218(u32, u32); +void sub_080AE324(u32, u32); + +void ResetPalettes(void) { + GfxSlot* slots; + GfxSlot* slot; + u32 index; + MemClear(&gGFXSlots, sizeof(gGFXSlots)); + // Reserve the first four slots for palettes. + for (index = 0; index < 4; index++) { + slots = gGFXSlots.slots; + slot = &slots[index]; + ReserveGFXSlots(index, 0, 1); + slot->status = GFX_SLOT_PALETTE; + slot->referenceCount = 0x80; + } +} + +void sub_080ADD70(void) { + u32 index; + GfxSlot* slot; + if (gGFXSlots.unk0 != 0) { +#ifndef EU + if (gGFXSlots.unk_3 != 0) { + sub_080ADE24(); + } else { +#endif + index = 0; + for (index = 0; index < MAX_GFX_SLOTS; index++) { + slot = &gGFXSlots.slots[index]; + switch (slot->status) { + case GFX_SLOT_STATUS2: + slot->status = GFX_SLOT_UNLOADED; + break; + case GFX_SLOT_RESERVED: + case GFX_SLOT_GFX: + case GFX_SLOT_PALETTE: + if (slot->vramStatus == GFX_VRAM_3) { + sub_080ADE74(index); + } + break; + } + } +#ifndef EU + } +#endif + } +} + +NONMATCH("asm/non_matching/vram/sub_080ADDD8.inc", void sub_080ADDD8(u32 index, u32 paletteIndex)) { + GfxSlot* slot = &gGFXSlots.slots[index]; + slot->palettePointer = gGlobalGfxAndPalettes + (paletteIndex & 0xfffffc); + if ((paletteIndex & 1) != 0) { + slot->paletteIndex = 0xffff; + } else { + // TODO some cast here? + slot->paletteIndex = ((paletteIndex)&0x7f00) >> 4; + } + slot->vramStatus = GFX_VRAM_3; +} +END_NONMATCH + +void sub_080ADE24(void) { + u32 index; + GfxSlot* slot; + gGFXSlots.unk_3 = 1; + for (index = 0; index < MAX_GFX_SLOTS; index++) { + slot = &gGFXSlots.slots[index]; + switch (slot->status) { + case GFX_SLOT_FOLLOWER: + break; + case GFX_SLOT_RESERVED: + case GFX_SLOT_GFX: + case GFX_SLOT_PALETTE: + sub_080ADE74(index); + break; + default: + MemClear(slot, sizeof(GfxSlot)); + break; + } + } + gGFXSlots.unk_3 = 0; +} + +// Transfer gfx slot data to vram? +ASM_FUNC("asm/non_matching/vram/sub_080ADE74.inc", void sub_080ADE74(u32 index)) + +bool32 LoadFixedGFX(Entity* entity, u32 gfxIndex) { +#ifdef EU + GfxSlot* slot; + u32 index; + u32 count; + u32 result; + u32 data; + if (gfxIndex == 0) { + result = TRUE; + } else { + for (index = 4; index < MAX_GFX_SLOTS; index++) { + if (gfxIndex == gGFXSlots.slots[index].gfxIndex) { + // Gfx is already loaded to a slot. + sub_080AE0C8(index, entity, GFX_SLOT_RESERVED); + result = TRUE; + return result; + } + } + data = gFixedTypeGfxData[gfxIndex]; + count = (data & 0x7f000000) >> 0x18; + index = FindFreeGFXSlots(count); + if (index != 0) { + ReserveGFXSlots(index, gfxIndex, count); + sub_080ADDD8(index, data); + _080ADFF2: + sub_080AE0C8(index, entity, GFX_SLOT_RESERVED); + result = TRUE; + } else { + result = FALSE; + } + } + return result; +#else + + GfxSlot* slot; + u32 index; + u32 count; + + if (gfxIndex != 0) { + for (index = 4; index < MAX_GFX_SLOTS; index++) { + if (gfxIndex == gGFXSlots.slots[index].gfxIndex) { + // Gfx is already loaded to a slot. + goto _080ADFF2; + } + } + count = (gFixedTypeGfxData[gfxIndex] & 0x7f000000) >> 0x18; + index = FindFreeGFXSlots(count); + if (index == 0) { + CleanUpGFXSlots(); + index = FindFreeGFXSlots(count); + if (index == 0) { + return 0; + } + } + ReserveGFXSlots(index, gfxIndex, count); + sub_080ADDD8(index, gFixedTypeGfxData[gfxIndex]); + _080ADFF2: + sub_080AE0C8(index, entity, GFX_SLOT_RESERVED); + } + return TRUE; +#endif +} + +// If slotIndex != 0 the gfx loaded starting from that slot, else in the first fitting free one. +NONMATCH("asm/non_matching/vram/LoadSwapGFX.inc", u32 LoadSwapGFX(Entity* entity, u32 count, u32 slotIndex)) { + u32 status; + if ((slotIndex == 0) && (slotIndex = FindFreeGFXSlots(count), slotIndex == 0)) { +#ifndef EU + CleanUpGFXSlots(); +#endif + slotIndex = FindFreeGFXSlots(count); + if (slotIndex == 0) { + goto _080AE058; + } + } + status = gGFXSlots.slots[slotIndex].status; + if (status != GFX_SLOT_PALETTE) { + ReserveGFXSlots(slotIndex, 0, count); + status = GFX_SLOT_GFX; + } + sub_080AE0C8(slotIndex, entity, status); +_080AE058: + if (slotIndex != 0) { + slotIndex = 1; + } + return slotIndex; +} +END_NONMATCH + +void UnloadGFXSlots(Entity* param_1) { + u32 slotIndex; + GfxSlot* slot; + s32 slotCount; + + slotIndex = param_1->spriteAnimation[0]; + param_1->spriteAnimation[0] = 0; + if (slotIndex != 0) { + slot = &gGFXSlots.slots[slotIndex]; + switch (slot->status) { + case GFX_SLOT_RESERVED: + case GFX_SLOT_GFX: + if (slot->referenceCount != 0) { + if (--slot->referenceCount == 0) { + slotCount = slot->slotCount; + while (slotCount-- > 0) { + slot->status = GFX_SLOT_UNLOADED; + slot++; + } + } + } + break; + } + } +} + +void sub_080AE0C8(u32 index, Entity* entity, u32 status) { + GfxSlot* slot; + entity->spriteVramOffset = index * 0x10 + 0x140; + entity->spriteAnimation[0] = index; + slot = &gGFXSlots.slots[index]; + if (*(s8*)&slot->referenceCount >= 0) { + slot->referenceCount++; + } + SetGFXSlotStatus(slot, status); +} + +void ReserveGFXSlots(u32 index, u32 gfxIndex, u32 slotCount) { + GfxSlot* slot = &gGFXSlots.slots[index]; + MemClear(slot, slotCount * sizeof(GfxSlot)); + slot->slotCount = slotCount; + slot->gfxIndex = gfxIndex; + SetGFXSlotStatus(slot, GFX_SLOT_RESERVED); +} + +void SetGFXSlotStatus(GfxSlot* slot, u32 status) { + s32 index; + slot->status = status; + index = slot->slotCount; + if (status != GFX_SLOT_PALETTE) { + status = GFX_SLOT_FOLLOWER; + } + for (index--; index > 0; index--) { + slot++; + slot->status = status; + } +} + +/** + * Finds slotCount continous free slots and returns the index of the first slot or 0 if not enough free slots could be + * found. + */ +u32 FindFreeGFXSlots(u32 slotCount) { + u32 index; + u32 continuousFreeSlots = 0; + + // First search for enough continous free slots. + for (index = 4; index < MAX_GFX_SLOTS; index++) { + if (gGFXSlots.slots[index].status == GFX_SLOT_FREE) { + continuousFreeSlots++; + if (slotCount <= continuousFreeSlots) { + return (index - continuousFreeSlots) + 1; + } + + } else { + continuousFreeSlots = 0; + } + } + + // Now also search for enough continous free or unused slots. + continuousFreeSlots = 0; + index = 4; + for (index = 4; index < MAX_GFX_SLOTS; index++) { +#ifdef EU + if (gGFXSlots.slots[index].status == GFX_SLOT_UNLOADED) { +#else + if (gGFXSlots.slots[index].status == GFX_SLOT_FREE || gGFXSlots.slots[index].status == GFX_SLOT_UNLOADED) { +#endif + continuousFreeSlots++; + if (slotCount <= continuousFreeSlots) { + return (index - continuousFreeSlots) + 1; + } + } else { + continuousFreeSlots = 0; + } + } + return 0; +} + +#ifndef EU +void CleanUpGFXSlots(void) { + u32 occupiedIndex; + u32 firstFreeIndex; + if (gGFXSlots.unk0 != 0) { + for (occupiedIndex = 4; (occupiedIndex = FindNextOccupiedGFXSlot(occupiedIndex)) != 0; occupiedIndex++) { + firstFreeIndex = FindFirstFreeGFXSlot(); + if (firstFreeIndex <= occupiedIndex) { + sub_080AE218(occupiedIndex, firstFreeIndex); + sub_080AE324(occupiedIndex, firstFreeIndex); + occupiedIndex = firstFreeIndex; + } + } + } +} + +// Swap gfx +ASM_FUNC("asm/non_matching/vram/sub_080AE218.inc", void sub_080AE218(u32 a, u32 b)) + +// Swap palettes +ASM_FUNC("asm/non_matching/vram/sub_080AE324.inc", void sub_080AE324(u32 a, u32 b)) + +u32 FindNextOccupiedGFXSlot(u32 index) { + for (; index < MAX_GFX_SLOTS - 1; index++) { + switch (gGFXSlots.slots[index].status) { + case GFX_SLOT_RESERVED: + case GFX_SLOT_GFX: + return index; + } + } + return 0; +} + +u32 FindFirstFreeGFXSlot(void) { + u32 index; + for (index = 4; index < MAX_GFX_SLOTS; index++) { + switch (gGFXSlots.slots[index].status) { + case GFX_SLOT_FREE: + case GFX_SLOT_UNLOADED: + return index; + default: + break; + } + } + return 0; +} +#endif