1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
|
INCLUDE "constants.asm"
SECTION "home/talk_to_npc.asm", ROM0
MapDefaultText::
ld hl, GameplayText
call OpenTextbox
ret
GameplayText::
text "ゲームフりーク!"
done
Function3036::
ld hl, EmptyText
ret
EmptyText::
db "@"
CallMapTextSubroutine::
ld a, [wTalkingTargetType]
bit 0, a
jr z, asm_3062
call Function3055
ret z
ld hl, hCurMapTextSubroutinePtr
ld a, [hli]
ld h, [hl]
ld l, a
ld de, .Return
push de
jp hl
.Return:
call Function307a
ret
Function3055::
ldh a, [hFFEA]
ld b, a
.Loop:
ld a, [hli]
cp $ff
ret z
cp b
jp z, SetFFInAccumulator
jr .Loop
asm_3062:
ld a, [wTalkingTargetType]
bit 1, a
ret z
ld h, d
ld l, e
ldh a, [hFFEE]
dec a
ld d, $0
ld e, a
add hl, de
add hl, de
ld a, [hli]
ld h, [hl]
ld l, a
ld de, Function307a
push de
jp hl
Function307a::
ld hl, wTalkingTargetType
res 0, [hl]
res 1, [hl]
call SetFFInAccumulator
ret
PrintTextboxDebugNumbers::
push hl
push de
push bc
ld de, $0099 ; default address to print from (not a sign or NPC)
ld a, [wTalkingTargetType]
bit 0, a
jr z, .CheckSign
ld de, hFFEA
jr .PrintNum
.CheckSign:
bit 1, a
jr z, .PrintNum
ld de, hFFEE
.PrintNum:
hlcoord 4, 12
lb bc, PRINTNUM_LEADINGZEROS | 1, 2
call PrintNumber
ld de, wMapScriptNumber
hlcoord 1, 12
lb bc, PRINTNUM_LEADINGZEROS | 1, 2
call PrintNumber
pop bc
pop de
pop hl
ret
QueueMapTextSubroutine::
ldh a, [hJoyState]
bit A_BUTTON_F, a
jp z, ClearAccumulator ; if we didn't press a
call GetFacingPersonText
jp nc, Function30e8 ; if not talking to a person
ld d, $0
ld e, a
ld a, [wDebugFlags]
bit DEBUG_FIELD_F, a
call nz, PrintTextboxDebugNumbers ; if debug, print these
ld hl, wMapTextPtr
ld a, [hli]
ld h, [hl]
ld l, a
add hl, de
add hl, de
ld de, hCurMapTextSubroutinePtr
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
ld hl, wTalkingTargetType
set 0, [hl] ; we're talking to an NPC
call SetFFInAccumulator
ret
Function30e8::
call GetFacingSignpost
jp nc, ClearAccumulator ; if not facing person or sign
ld a, e
ldh [hFFEB], a
ld a, d
ldh [hFFEC], a
ld a, b
ldh [hFFED], a
ld a, [hl]
ldh [hFFEE], a
ld hl, wTalkingTargetType
set 1, [hl] ; we're talking to a sign
call SetFFInAccumulator
ret
GetFacingPersonText::
callba Function776e
ret nc
call TurnNPCTalkingTo
scf
ret
OpenTextbox::
; Opens a textbox and waits for input
push hl
call PrepareTextbox
ld a, [wDebugFlags]
bit DEBUG_FIELD_F, a
call nz, PrintTextboxDebugNumbers
pop hl
call TextboxIdle
ret
OpenTextboxNoInput::
push hl
call PrepareTextbox
pop hl
TextboxIdle::
; Prints text, then waits for A or B to be pressed, unless bit 5 of JoypadFlags is set.
call PrintTextBoxText
.Loop
ld a, [wJoypadFlags]
bit 5, a
res 5, a
ld [wJoypadFlags], a
jr nz, .Escape
call GetJoypad
ldh a, [hJoyDown]
and A_BUTTON | B_BUTTON
jr nz, .Escape
call UpdateTime
call UpdateTimeOfDayPalettes
call DelayFrame
jr .Loop
.Escape
call TextboxCleanup
ret
PrepareTextbox::
call ClearWindowData
ldh a, [hROMBank]
push af
ld a, 01
call Bankswitch
call ReanchorBGMap_NoOAMUpdate
hlcoord 0, 12 ;in the tilemap in WRAM
ld b, 04
ld c, $12
call DrawTextBox
call WaitBGMap
call LoadFonts_NoOAMUpdate
pop af
call Bankswitch
ret
TextboxCleanup:
callab ReanchorBGMap_NoOAMUpdate
call UpdateSprites
xor a
ldh [hBGMapMode], a
ld a, $90
ldh [hWY], a
call Function318f
ld hl, wToolgearFlags
res 7, [hl]
call InitToolgearBuffer
ret
Function318f:
callab Function140ea
call RedrawPlayerSprite
ret
TurnNPCTalkingTo::
; If an NPC is allowed to turn when talked to, turn it.
ldh a, [hObjectStructIndexBuffer]
call GetObjectStruct
ld hl, OBJECT_SPRITE
add hl, bc
ld a, [hl]
call IsAnimatedSprite
jr c, .Jump
ld a, [wPlayerWalking]
xor 04
ld hl, OBJECT_DIRECTION_WALKING
add hl, bc
ld [hl], a
push bc
call UpdateSprites
pop bc
.Jump
ld hl, OBJECT_MAP_OBJECT_INDEX
add hl, bc
ld a, [hl]
sub 02
ldh [hFFEA], a
ret
Function31C3::
ret
CheckInlineTrainer::
; Passed de is the pointer to a map_object struct. If it's an inline trainer, write to relevant wram region.
ld hl, MAPOBJECT_OBJECT_STRUCT_ID
add hl, de
ld a, [hl]
call GetObjectStruct
call GetInlineMapObject
jr nc, .Escape
ld hl, MAPOBJECT_POINTER_HI
add hl, de
ld a, [hl]
cp b
jr c, .Escape
ld hl, MAPOBJECT_OBJECT_STRUCT_ID
add hl, de
ld a, [hl]
add a, a
ld hl, wCurrMapInlineTrainers
add a, l
ld l, a
jr nc, .NoCarry
inc h
.NoCarry
ld [hl], b
inc hl
ld [hl], c
.Escape
ret
GetInlineMapObject::
;bc is start of object struct. if c flag set, returns distance in B and direction in C
ld hl, OBJECT_NEXT_MAP_X
add hl, bc
ld a, [wPlayerNextMapX]
cp [hl]
jr z, .EqualX
ld hl, OBJECT_NEXT_MAP_Y
add hl, bc
ld a, [wPlayerNextMapY]
cp [hl]
jr z, .EqualY
and a
ret
.EqualX
ld hl, OBJECT_NEXT_MAP_Y
add hl, bc
ld a, [wPlayerNextMapY]
sub [hl]
jr z, .Reset
jr nc, .SetDown
cpl
inc a
ld b, a
ld c, UP
scf
ret
.SetDown
ld b, a
ld c, DOWN
scf
ret
.EqualY
ld hl, OBJECT_NEXT_MAP_X
add hl, bc
ld a, [wPlayerNextMapX]
sub [hl]
jr z, .Reset ; (this condition is impossible to meet)
jr nc, .SetRight
cpl
inc a
ld b, a
ld c, LEFT
scf
ret
.SetRight
ld b, a
ld c, RIGHT
scf
ret
.Reset
and a
ret
CheckBPressedDebug:
; If in debug mode, returns a check on the B button.
ld a, [wDebugFlags]
bit DEBUG_FIELD_F, a
ret z
ldh a, [hJoyState]
bit B_BUTTON_F, a
ret
ClearAccumulator::
xor a
ret
SetFFInAccumulator::
xor a
dec a
ret
|