-
Notifications
You must be signed in to change notification settings - Fork 15
/
file.s
359 lines (340 loc) · 12.1 KB
/
file.s
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
356
357
358
359
C_LEVEL = 0 ;Level chunk is fixed, and will be loaded from different filenames
; Set file number, add file type
;
; Parameters: A file number, X file type add
; Returns: fileNumber (also in A), C=0
; Modifies: A,X,zpSrcLo
MakeFileNumber: stx zpSrcLo
clc
adc zpSrcLo
sta fileNumber
OFWR_OK: rts
; Allocate & load a resource file, and return address of object from inside.
; If no memory, purge unused files.
;
; Parameters: A object number, Y chunk file number (or X script number for GetScriptResource)
; Returns: loadRes chunk file number, zpDestLo-Hi file address, zpSrcLo-Hi object address (hi also in A)
; Modifies: A,X,Y,loader temp vars,resource load vars
GetLevelResourceObject:
ldy #C_LEVEL
bpl GetResourceObject
GetScriptResource:
pha
txa
clc
adc #C_FIRSTSCRIPT
tay
pla
GetResourceObject:
LoadResource: sta LR_ObjNum+1
sty loadRes
LR_WasLoaded: lda fileHi,y
beq LR_NotInMemory
sta zpDestHi
lda fileLo,y
sta zpDestLo ;Reset file age whenever accessed
lda #$00
sta fileAge,y
LR_ObjNum: lda #$00
asl
tay
LR_GetObjectAddress:
lda (zpDestLo),y
sta zpSrcLo
iny
lda (zpDestLo),y
sta zpSrcHi
rts
LR_NotInMemory: tya
ldx #F_CHUNK
jsr MakeFileNumber
LoadResourceCustomFileName:
ldx #C_FIRSTPURGEABLE ;When loading, age all other chunkfiles
LR_AgeLoop: ldy fileHi,x
beq LR_AgeSkip
lda fileAge,x ;Needless to age past $80
bmi LR_AgeSkip
inc fileAge,x
LR_AgeSkip: inx
cpx #MAX_CHUNKFILES
bcc LR_AgeLoop
lda fileNumber
jsr OpenFile
jsr GetByte ;Get datasize lowbyte
sta dataSizeLo
jsr GetByte ;Get datasize highbyte
sta dataSizeHi
jsr GetByte ;Get object count
ldy loadRes
sta fileNumObjects,y
jsr PurgeUntilFree
lda freeMemLo
ldx freeMemHi
jsr Depack
; Finish loading, relocate chunk object pointers
ldy loadRes
lda freeMemLo ;Increment free mem pointer
sta zpBitsLo
sta zpDestLo
sta fileLo,y
clc
adc dataSizeLo
sta freeMemLo
lda freeMemHi
sta zpBitsHi
sta zpDestHi
sta fileHi,y
adc dataSizeHi
sta freeMemHi
cpy #C_FIRSTSCRIPT ;Is script that requires code relocation?
bcc LR_NotScript
lda zpBitsHi ;Scripts are initially relocated at $8000
sbc #>scriptCodeRelocStart ;to distinguish between resident & loadable code
sta zpBitsHi
LR_NotScript: jsr LR_Relocate
ldy loadRes
jmp LR_WasLoaded ;Retry getting the object address now
LR_Relocate: ldx fileNumObjects,y
sty zpBitBuf
;txa ;There are no objectless files
;beq LR_RelocDone
ldy #$00
LR_RelocateLoop:jsr LR_RelocAddDelta
iny
dex
bne LR_RelocateLoop
LR_RelocDone: lda zpBitBuf
cmp #C_FIRSTSCRIPT
bcc LR_NoCodeReloc
tya ;Go past the object pointers to get into code
LR_CodeRelocLoop:
ldx #<zpDestLo
jsr Add8
ldy #$00
lda (zpDestLo),y ;Read instruction
beq LR_CodeRelocDone ;BRK - done
lsr
lsr
lsr
bcc LR_LookupLength
and #$01 ;Instructions xc - xf are always 3 bytes
ora #$02 ;Instructions x4 - x7 are always 2 bytes
bne LR_HasLength
LR_LookupLength:tax
lda (zpDestLo),y
and #$03
tay
lda instrLenTbl,x ;4 lengths packed into one byte
LR_DecodeLength:dey
bmi LR_DecodeLengthDone
lsr ;Shift until we have the one we want
lsr
bpl LR_DecodeLength
LR_DecodeLengthDone:
and #$03
LR_HasLength: cmp #$03 ;3 byte long instructions need relocation
bne LR_CodeRelocLoop
ldy #$02
lda (zpDestLo),y ;Read absolute address highbyte
cmp #>(fileAreaStart+$100) ;Is it a reference to self or to resident code/data?
bcc LR_NoRelocation ;(filearea start may not be page-aligned, but the common sprites
cmp #>fileAreaEnd ;will always be first)
bcs LR_NoRelocation
dey
jsr LR_RelocAddDelta
LR_NoRelocation:lda #$03
bne LR_CodeRelocLoop
LR_RelocAddDelta:
lda (zpDestLo),y
clc
adc zpBitsLo
sta (zpDestLo),y
iny
lda (zpDestLo),y
adc zpBitsHi
sta (zpDestLo),y
LR_CodeRelocDone:
LR_NoCodeReloc:
PF_Done: rts
; Remove a chunk-file from memory
;
; Parameters: Y file number
; Returns: -
; Modifies: A,X,loader temp vars
PurgeFile: lda fileHi,y
beq PF_Done
sty zpLenLo
lda fileLo,y
sta zpDestLo
lda fileHi,y
sta zpDestHi
lda freeMemLo
sta zpSrcLo
lda freeMemHi
sta zpSrcHi
ldx #MAX_CHUNKFILES-1
PF_FindSizeLoop:cpx zpLenLo
beq PF_FindSizeSkip
ldy fileLo,x
cpy zpDestLo
lda fileHi,x
sbc zpDestHi
bcc PF_FindSizeSkip
cpy zpSrcLo
lda fileHi,x
sbc zpSrcHi
bcs PF_FindSizeSkip
sty zpSrcLo
lda fileHi,x
sta zpSrcHi
PF_FindSizeSkip:dex
bpl PF_FindSizeLoop
ldx #<freeMemLo
jsr PF_Sub
jsr CopyMemory
ldx #<zpDestLo
jsr PF_Sub
ldx #<freeMemLo
ldy #<zpBitsLo
jsr Add16 ;Shift the free memory pointer
tsx
inx
ldy zpLenLo
PF_RelocateStack: ;If the stack contains references to the relocated file or files above it,
lda fileLo,y ;move the reference (stack must only contain return addresses)
cmp $0100,x
lda fileHi,y
sbc $0101,x
bcs PF_RelocateStackSkip
lda $0100,x
adc zpBitsLo
sta $0100,x
lda $0101,x
adc zpBitsHi
sta $0101,x
PF_RelocateStackSkip:
inx
inx
bne PF_RelocateStack
lda textLo ;Relocate current text pointer if necessary
cmp fileLo,y
lda textHi
beq PF_RelocateTextSkip
sbc fileHi,y
bcc PF_RelocateTextSkip
ldx #<textLo
ldy #<zpBitsLo
jsr Add16
PF_RelocateTextSkip:
ldy #MAX_CHUNKFILES-1
PF_RelocLoop: ldx zpLenLo
lda fileLo,x ;Need relocation? (higher in memory than purged file)
cmp fileLo,y ;Unloaded files (ptr 0) are by definition lower so will be skipped,
lda fileHi,x ;as well as when indices are the same
sbc fileHi,y
bcs PF_RelocNext
lda fileLo,y ;Relocate the file pointer
adc zpBitsLo
sta fileLo,y
sta zpDestLo
lda fileHi,y
adc zpBitsHi
sta fileHi,y
sta zpDestHi
jsr LR_Relocate ;Relocate the object pointers
ldy zpBitBuf
PF_RelocNext: dey
bpl PF_RelocLoop
ldy zpLenLo
lda #$00
sta fileHi,y ;Mark chunk not in memory
sta fileAge,y ;and reset age for eventual reload
PUF_HasFreeMemory:
rts
PF_Sub: lda $00,x
sec
sbc zpSrcLo
sta zpBitsLo
lda $01,x
sbc zpSrcHi
sta zpBitsHi
rts
; Remove files until enough memory to load the new file
;
; Parameters: dataSizeLo-Hi new object size, zoneBufferLo-Hi zone buffer start (alloc area end)
; Returns: -
; Modifies: A,X,Y,loader temp vars
PurgeUntilFreeNoNew:
lda #$00
sta dataSizeLo
sta dataSizeHi
PurgeUntilFree: lda freeMemLo
clc
adc dataSizeLo
sta zpBitsLo
tax
lda freeMemHi
adc dataSizeHi
cpx zoneBufferLo
sbc zoneBufferHi
bcc PUF_HasFreeMemory
PUF_Loop: ldx #$01
stx zpBitBuf
txa ;The first chunk (level) is exempt from purge
PUF_FindOldestLoop:
ldy fileAge,x
cpy zpBitBuf
bcc PUF_FindOldestSkip
sty zpBitBuf
txa
PUF_FindOldestSkip:
inx
cpx #MAX_CHUNKFILES
bcc PUF_FindOldestLoop
tay
jsr PurgeFile
jmp PurgeUntilFree
; Save player state to in-memory checkpoint
;
; Parameters: -
; Returns: -
; Modifies: A,X,Y,loader temp vars, temp vars
SavePlayerState:ldx #NUM_SAVEMISCVARS-1
SPS_Loop: jsr GetSaveMiscVar
lda (zpSrcLo),y
sta saveMiscVars,x
dex
bpl SPS_Loop
ldx #<zpSrcLo
ldy #<zpDestLo
CopySaveState: lda #<playerStateStart
sta $00,x
lda #>playerStateStart
sta $01,x
lda #<savePlayerState
sta $00,y
lda #>savePlayerState
sta $01,y
lda #<(playerStateEnd-playerStateStart)
sta zpBitsLo
lda #>(playerStateEnd-playerStateStart)
sta zpBitsHi
; Copy a block of memory
;
; Parameters: zpSrcLo,Hi source zpDestLo,Hi dest zpBitsLo,Hi amount of bytes
; Returns: N=1, X=0
; Modifies: A,X,Y,loader temp vars
CopyMemory: ldy #$00
ldx zpBitsLo ;Predecrement highbyte if lowbyte 0 at start
beq CM_Predecrement
CM_Loop: lda (zpSrcLo),y
sta (zpDestLo),y
iny
bne CM_NotOver
inc zpSrcHi
inc zpDestHi
CM_NotOver: dex
bne CM_Loop
CM_Predecrement:dec zpBitsHi
bpl CM_Loop
rts