-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathsprite.s
362 lines (351 loc) · 12.7 KB
/
sprite.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
360
361
362
MAX_SPRX = 335
MIN_SPRY = 34
MAX_SPRY = IRQ3_LINE-1
FIRSTCACHEFRAME = (spriteCache-$c000)/$40
EMPTYSPRITEFRAME = (emptySprite-$c000)/$40
SPRH_MASK = 0
SPRH_COLOR = 1
SPRH_HOTSPOTX = 2
SPRH_HOTSPOTXFLIP = 3
SPRH_CONNECTSPOTX = 4
SPRH_CONNECTSPOTXFLIP = 5
SPRH_HOTSPOTY = 6
SPRH_CONNECTSPOTY = 7
SPRH_CACHEFRAME = 8
SPRH_CACHEFRAMEFLIP = 9
SPRH_DATA = 10
; Load a sprite file
;
; Parameters: Y sprite file number
; Returns: A sprite file address highbyte
; Modifies: A,temp6-temp8,loader temp vars
EnsureSpriteFile:
lda fileHi,y
bne ESF_Loaded
LoadSpriteFile: stx LSF_SaveX+1
tya
sec
sbc #C_FIRSTSPR
ldx #F_SPRITE
jsr MakeFileName
LSF_Retry: jsr LoadAllocFile
bcc LSF_NoError
jsr LFR_ErrorPrompt
ldy temp6
bpl LSF_Retry
LSF_NoError: jsr PostLoad
ldy temp6 ;LoadAllocFile puts chunk number to temp6
lda fileHi,y
LSF_SaveX: ldx #$00
ESF_Loaded: rts
; Get and store a sprite. Cache (depack) if not cached yet.
;
; Parameters: A frame number, X sprite index, temp1 X coord,
; temp3 Y coord, actIndex actor index, sprFileLo-Hi spritefile
; Returns: X incremented if sprite accepted, temp1-temp4 modified for next sprite
; Modifies: A,X,Y,temp1-temp4
GetAndStoreSprite:
sta zpBitsLo ;Framenumber with direction in high bit
asl
tay
lda (sprFileLo),y ;Get sprite header address
sta frameLo
iny
lda (sprFileLo),y
sta frameHi
lda #$80
rol ;C=1 for the subtraction below
sta zpLenLo ;Sprite direction
ora #SPRH_HOTSPOTX
tay
lda temp1 ;Subtract X-hotspot
sbc (frameLo),y
sta temp2
iny
iny
clc
adc (frameLo),y ;Add X-connect spot
sta temp1
ldy #SPRH_HOTSPOTY
lda temp3 ;Subtract Y-hotspot
sec
sbc (frameLo),y
sta temp4
iny
clc
adc (frameLo),y ;Add Y-connect spot
sta temp3
cpx #MAX_SPR ;Ran out of sprites?
bcs GASS_DoNotAccept
ldy #$00 ;Finalize Y-pos
lda temp4
bpl GASS_YLo
dey
GASS_YLo: adc #$00
sta sprY,x
tya
GASS_YHi: adc #$00
bne GASS_DoNotAccept ;Y high byte must be zero (visible)
lda sprY,x ;Check Y visibility
cmp #MIN_SPRY
bcc GASS_DoNotAccept
cmp #MAX_SPRY
bcs GASS_DoNotAccept
ldy #$00
lda temp2 ;Finalize X-pos
bpl GASS_XLo
dey
GASS_XLo: adc #$00 ;C=0 here
sta sprXL,x
tya
GASS_XHi: adc #$00
sta sprXH,x
beq GASS_XOK
lda sprXL,x ;Check X visibility
cmp #MAX_SPRX-256
bcs GASS_DoNotAccept
GASS_XOK: lda actIndex ;Sprite was accepted: store actor index
sta sprAct,x ;for interpolation
ldy #SPRH_COLOR
lda (frameLo),y
GASS_ColorAnd: and #$00
GASS_ColorOr: ora #$00
sta sprC,x ;Store color
lda #SPRH_CACHEFRAME
ora zpLenLo
tay
lda (frameLo),y ;Check if already cached
beq GASS_CacheSprite
GASS_StoreFrame:sta sprF,x
tay
lda GASS_CurrentFrame+1 ;Mark cached sprite in use
sta cacheSprAge-FIRSTCACHEFRAME,y
inx ;Finally increment sprite count
GASS_DoNotAccept:
rts
; Cache (depack) a sprite
GASS_CacheSprite:
if SHOW_SPRITEDEPACK_TIME > 0
inc $d020
endif
stx zpBitsHi
GASS_CachePos: ldx #$7f ;Continue from where we left off last time
GASS_Loop: inx
bpl GASS_NotOver
ldx #FIRSTCACHEFRAME+1 ;First frame is used for the empty sprite
GASS_NotOver: lda cacheSprAge-FIRSTCACHEFRAME,x
GASS_CurrentFrame:
cmp #$01
beq GASS_Loop
GASS_LastFrame: cmp #$01
beq GASS_Loop
GASS_Found: stx GASS_CachePos+1 ;Store cache position for next search
txa
sta (frameLo),y ;Store cache frame into sprite header
ldy cacheSprFile-FIRSTCACHEFRAME,x ;Clear the old cache mapping if the old file still in memory
bmi GASS_NoOldSprite
lda fileHi,y
beq GASS_NoOldSprite
sta zpSrcHi
lda fileLo,y
sta zpSrcLo
lda cacheSprFrame-FIRSTCACHEFRAME,x
asl
tay
lda (zpSrcLo),y
sta zpDestLo
iny
lda (zpSrcLo),y
sta zpDestHi
lda #SPRH_CACHEFRAME/2
rol
tay
lda #$00
sta (zpDestLo),y
GASS_NoOldSprite:
lda sprFileNum ;Save new file & frame numbers so that this mapping
sta cacheSprFile-FIRSTCACHEFRAME,x ;can be cleared in the future
tay
lda #$00
sta fileAge,y ;Reset file age, only done when depacking a new sprite
lda zpBitsLo
sta cacheSprFrame-FIRSTCACHEFRAME,x
lda #$34 ;Need access to RAM under the I/O area
sta irqSave01
sta $01
lda zpLenLo ;Use normal or flipped routine?
bne GASS_Flipped
jmp GASS_NonFlipped
GASS_Flipped: lda #$08
sta zpBitBuf
txa ;Calculate sprite address
lsr
ror zpBitBuf
lsr
ror zpBitBuf
ora #>videoBank
cmp GASS_FlipFullSlice1+2 ;Modify STA-instructions as necessary
beq GASS_FlipAddressOk
sta GASS_FlipFullSlice1+2
sta GASS_FlipFullSlice2+2
sta GASS_FlipFullSlice3+2
sta GASS_FlipFullSlice4+2
sta GASS_FlipFullSlice5+2
sta GASS_FlipFullSlice6+2
sta GASS_FlipFullSlice7+2
sta GASS_FlipEmptySlice1+2
sta GASS_FlipEmptySlice2+2
sta GASS_FlipEmptySlice3+2
sta GASS_FlipEmptySlice4+2
sta GASS_FlipEmptySlice5+2
sta GASS_FlipEmptySlice6+2
sta GASS_FlipEmptySlice7+2
GASS_FlipAddressOk:
ldy #SPRH_COLOR
lda (frameLo),y ;Get slice bitmask high bit
asl
dey
lda (frameLo),y ;Get rest of the bits
ror
sta zpBitsLo ;C=1 if first slice has data
ldx zpBitBuf
ldy #SPRH_DATA
bcc GASS_FlipEmptySlice
GASS_FlipFullSlice:
lda (frameLo),y
sta GASS_GetFlipped1+1
GASS_GetFlipped1:
lda flipTbl
GASS_FlipFullSlice1:sta $1000,x
iny
lda (frameLo),y
sta GASS_GetFlipped2+1
GASS_GetFlipped2:
lda flipTbl
GASS_FlipFullSlice2:sta $1000+3,x
iny
lda (frameLo),y
sta GASS_GetFlipped3+1
GASS_GetFlipped3:
lda flipTbl
GASS_FlipFullSlice3:sta $1000+6,x
iny
lda (frameLo),y
sta GASS_GetFlipped4+1
GASS_GetFlipped4:
lda flipTbl
GASS_FlipFullSlice4:sta $1000+9,x
iny
lda (frameLo),y
sta GASS_GetFlipped5+1
GASS_GetFlipped5:
lda flipTbl
GASS_FlipFullSlice5:sta $1000+12,x
iny
lda (frameLo),y
sta GASS_GetFlipped6+1
GASS_GetFlipped6:
lda flipTbl
GASS_FlipFullSlice6:sta $1000+15,x
iny
lda (frameLo),y
sta GASS_GetFlipped7+1
GASS_GetFlipped7:
lda flipTbl
GASS_FlipFullSlice7:sta $1000+18,x
iny
GASS_FlipNextSlice:
lda flipNextSliceTbl,x
beq GASS_DepackDone
tax
dex
lsr zpBitsLo
bcs GASS_FlipFullSlice
GASS_FlipEmptySlice:lda #$00
GASS_FlipEmptySlice1:sta $1000,x
GASS_FlipEmptySlice2:sta $1000+3,x
GASS_FlipEmptySlice3:sta $1000+6,x
GASS_FlipEmptySlice4:sta $1000+9,x
GASS_FlipEmptySlice5:sta $1000+12,x
GASS_FlipEmptySlice6:sta $1000+15,x
GASS_FlipEmptySlice7:sta $1000+18,x
beq GASS_FlipNextSlice
GASS_DepackDone:lda #$35 ;Restore I/O registers
sta irqSave01
sta $01
ldx zpBitsHi
lda GASS_CachePos+1
if SHOW_SPRITEDEPACK_TIME > 0
dec $d020
endif
jmp GASS_StoreFrame
GASS_DepackDone2:
beq GASS_DepackDone
GASS_NonFlipped:sta zpBitBuf
txa ;Calculate sprite address
lsr
ror zpBitBuf
lsr
ror zpBitBuf
ora #>videoBank
cmp GASS_FullSlice1+2 ;Modify STA-instructions as necessary
beq GASS_AddressOk
sta GASS_FullSlice1+2
sta GASS_FullSlice2+2
sta GASS_FullSlice3+2
sta GASS_FullSlice4+2
sta GASS_FullSlice5+2
sta GASS_FullSlice6+2
sta GASS_FullSlice7+2
sta GASS_EmptySlice1+2
sta GASS_EmptySlice2+2
sta GASS_EmptySlice3+2
sta GASS_EmptySlice4+2
sta GASS_EmptySlice5+2
sta GASS_EmptySlice6+2
sta GASS_EmptySlice7+2
GASS_AddressOk: ldy #SPRH_COLOR
lda (frameLo),y ;Get slice bitmask high bit
asl
dey
lda (frameLo),y ;Get rest of the bits
ror
sta zpBitsLo ;C=1 if first slice has data
ldx zpBitBuf
ldy #SPRH_DATA
bcc GASS_EmptySlice
GASS_FullSlice: lda (frameLo),y
GASS_FullSlice1:sta $1000,x
iny
lda (frameLo),y
GASS_FullSlice2:sta $1000+3,x
iny
lda (frameLo),y
GASS_FullSlice3:sta $1000+6,x
iny
lda (frameLo),y
GASS_FullSlice4:sta $1000+9,x
iny
lda (frameLo),y
GASS_FullSlice5:sta $1000+12,x
iny
lda (frameLo),y
GASS_FullSlice6:sta $1000+15,x
iny
lda (frameLo),y
GASS_FullSlice7:sta $1000+18,x
iny
GASS_NextSlice: lda nextSliceTbl,x
beq GASS_DepackDone2
tax
lsr zpBitsLo
bcs GASS_FullSlice
GASS_EmptySlice:lda #$00
GASS_EmptySlice1:sta $1000,x
GASS_EmptySlice2:sta $1000+3,x
GASS_EmptySlice3:sta $1000+6,x
GASS_EmptySlice4:sta $1000+9,x
GASS_EmptySlice5:sta $1000+12,x
GASS_EmptySlice6:sta $1000+15,x
GASS_EmptySlice7:sta $1000+18,x
beq GASS_NextSlice