Browse Source

started to make npcs dynamic once again

SBird1337 7 years ago
parent
commit
88c14ea5e1
6 changed files with 147 additions and 22 deletions
  1. 2
    0
      bpre.sym
  2. 1
    1
      g3headers
  3. 1
    2
      main.asm
  4. 20
    2
      patches/dynamic_overworld_hooks.asm
  5. 25
    6
      src/overworld/dyn_npc_hooks.S
  6. 98
    11
      src/overworld/dynamic_overworld.c

+ 2
- 0
bpre.sym View File

@@ -83,6 +83,8 @@ wram_decompress = 0x081E3B70|1;
83 83
 battle_script_push = 0x08017544|1;
84 84
 objects = 0x0202063C;
85 85
 
86
+stored_palettes = 0x0203FF00;
87
+
86 88
 fade_screen = 0x08070589;
87 89
 fade_update = 0x080704D1;
88 90
 

+ 1
- 1
g3headers

@@ -1 +1 @@
1
-Subproject commit 22ac0f74bd5d9c9a951e6d7f17cd8912a0ca2d39
1
+Subproject commit f7f112b0d286765a4396669278cb0595a7a69ff5

+ 1
- 2
main.asm View File

@@ -7,8 +7,7 @@
7 7
 .include "patches/hooks.asm"
8 8
 
9 9
 
10
-//no dynamic overworlds, sorry :T
11
-//.include "patches/dynamic_overworld_hooks.asm"
10
+.include "patches/dynamic_overworld_hooks.asm"
12 11
 
13 12
 
14 13
 .include "patches/special.asm"

+ 20
- 2
patches/dynamic_overworld_hooks.asm View File

@@ -1,4 +1,4 @@
1
-.org 0x5f574 + 0x08000000
1
+/*.org 0x5f574 + 0x08000000
2 2
 ldr r0, =ClearAllPalettes|1
3 3
 bx r0
4 4
 .pool
@@ -247,4 +247,22 @@ lsl r0, #0
247 247
 .byte 1
248 248
 .byte 0x22
249 249
 .byte 0x5
250
-.byte 0xE0
250
+.byte 0xE0*/
251
+
252
+.org 0x0805E590
253
+ldr r5, =npc_spawn_with_provided_template|1
254
+bx r5
255
+
256
+.pool
257
+
258
+.org 0x08007280
259
+ldr r1, =obj_delete_and_free_tiles_hook|1
260
+bx r1
261
+
262
+.pool
263
+
264
+.org 0x0800779A
265
+ldr r1, =obj_delete_all_hook|1
266
+bx r1
267
+
268
+.pool

+ 25
- 6
src/overworld/dyn_npc_hooks.S View File

@@ -1,9 +1,28 @@
1 1
 .align 2
2
-.text
3 2
 .thumb
3
+.text
4
+
5
+.global obj_delete_and_free_tiles_hook
6
+obj_delete_and_free_tiles_hook:
7
+	push {r4-r7,lr}
8
+	mov r5, r0
9
+    ldrb r0, [r5,#5]
10
+    lsr r0, #4
11
+    bl npc_dynamic_remove_entry
12
+	mov r0, r5
13
+	add r0, #0x3E
14
+	ldrb r1, [r0]
15
+	ldr r0, =0x8007288+1
16
+	bx r0
17
+
18
+.global obj_delete_all_hook
19
+obj_delete_all_hook:
20
+ldr r1, =obj_delete
21
+bl bxr1
22
+bl npc_dynamic_reset
23
+pop {r4-r5}
24
+pop {r0}
25
+bx r0
4 26
 
5
-.global npc_spawn_hook:
6
-npc_spawn_hook:
7
-    ldrh r0, [r6, #2]
8
-    bl dynamic_npc_load_palette
9
-    lsl r1, r0, #4
27
+bxr1:
28
+bx r1

+ 98
- 11
src/overworld/dynamic_overworld.c View File

@@ -1,22 +1,109 @@
1 1
 #include <pokeagb/pokeagb.h>
2 2
 
3
-enum PalStoreType{
4
-    UNUSED,
5
-    NPC,
6
-    REFLECTION,
7
-    OTHER
8
-};
3
+#define MAX_PAL_STORE 16
9 4
 
10
-struct PalStoreEntry{
11
-    enum PalStoreType type;
5
+struct PalStoreEntry {
12 6
     u8 reference_count;
13
-    u16 tag; 
7
+    u16 tag;
14 8
 };
15 9
 
16 10
 extern struct PalStoreEntry stored_palettes[16];
17 11
 
18
-u8 dynamic_npc_load_palette(u16 tag)
19
-{
12
+extern struct NpcType *npc_get_type(u16 id);
13
+
14
+extern void dprintf(const char *str, ...);
15
+
16
+s8 npc_dynamic_find_palette(u16 tag) {
17
+    for (s8 i = 0; i < MAX_PAL_STORE; ++i) {
18
+        if (stored_palettes[i].reference_count > 0 && stored_palettes[i].tag == tag)
19
+            return i;
20
+    }
21
+    return -1;
22
+}
23
+
24
+s8 npc_dynamic_allocate_palette(u16 tag) {
25
+    for (s8 i = 0; i < MAX_PAL_STORE; ++i) {
26
+        if (stored_palettes[i].reference_count == 0) {
27
+            stored_palettes[i].tag = tag;
28
+            stored_palettes[i].reference_count++;
29
+            return i;
30
+        }
31
+    }
32
+    return -1;
33
+}
34
+
35
+u8 npc_dynamic_load_palette(u16 tag) {
36
+    s8 store_entry = npc_dynamic_find_palette(tag);
37
+    if (store_entry != -1) {
38
+        stored_palettes[store_entry].reference_count++;
39
+        return store_entry;
40
+    }
41
+    store_entry = npc_dynamic_allocate_palette(tag);
42
+    if (store_entry == -1) {
43
+        /* we do not have allocation space left */
44
+        dprintf("ATTENTION: TRIED TO ALLOCATE DYNOVER PALETTE WITHOUT SPACE LEFT, INCREASING ZERO REFERENCE\n");
45
+        stored_palettes[0].reference_count++;
46
+        return 0;
47
+    }
48
+
49
+    pal_patch_for_npc(tag, (u8)store_entry);
50
+
51
+    return (u8)store_entry;
52
+}
53
+
54
+void npc_dynamic_reset() {
55
+    for (u8 i = 0; i < MAX_PAL_STORE; ++i) {
56
+        stored_palettes[i].reference_count = 0;
57
+        stored_palettes[i].tag = 0;
58
+    }
59
+}
20 60
 
61
+void npc_dynamic_remove_entry(u8 id) {
62
+    if (stored_palettes[id].reference_count > 0) {
63
+        stored_palettes[id].reference_count--;
64
+        dprintf("npc_dynamic: removed entry #%d\n", id);
65
+        if (stored_palettes[id].reference_count == 0)
66
+            stored_palettes[id].tag = 0;
67
+    }
21 68
 }
22 69
 
70
+u8 npc_spawn_with_provided_template(struct RomNpc *npc, struct Template *template, u8 map, u8 bank, s16 x, s16 y) {
71
+    u8 state = rom_npc_to_npc_state(npc, map, bank);
72
+    if (state >= 16)
73
+        return 16;
74
+
75
+    struct NpcState *created_state = &npc_states[state];
76
+    struct NpcType *type = npc_get_type(created_state->type_id | (npc->field3 << 8));
77
+    s8 pal_slot = npc_dynamic_load_palette(type->pal_num);
78
+
79
+    if (created_state->running_behavior == 76)
80
+        created_state->field1 |= 0x20;
81
+    template->pal_tag = 0xFFFF;
82
+    u8 obj_id = template_instanciate_forward_search(template, 0, 0, 0);
83
+    if (obj_id == 64) {
84
+        created_state->bitfield &= 0xFE;
85
+        return 16;
86
+    }
87
+
88
+    struct Object *npc_object = &objects[obj_id];
89
+    npc_fix_position(x + created_state->to.x, y + created_state->to.y, &npc_object->pos1.x, &npc_object->pos1.y);
90
+    npc_object->shift.x = -(type->pos_neg_center.x / 2);
91
+    npc_object->shift.y = -(type->pos_neg_center.y / 2);
92
+    npc_object->pos1.x += 8;
93
+    npc_object->pos1.y += (s8)npc_object->shift.y + 16;
94
+
95
+    /* Set our allocated index */
96
+    npc_object->final_oam.palette_num = pal_slot;
97
+    npc_object->bitfield2 |= 2;
98
+    npc_object->priv[0] = state;
99
+    created_state->oam_id = obj_id;
100
+
101
+    u8 unknown = (created_state->field1 & 0xEF) | (16 * (type->pal_slot_unk << 25 >> 31));
102
+    created_state->field1 = unknown;
103
+    if (!(unknown & 0x10)) {
104
+        obj_anim_image_start(npc_object, npc_direction_to_obj_anim_image_number(created_state->direction));
105
+    }
106
+    npc_y_height_related(created_state->height >> 4, npc_object, 1);
107
+    npc_obj_offscreen_culling_and_flag_update(created_state, npc_object);
108
+    return state;
109
+}