Welcome to mirror list, hosted at ThFree Co, Russian Federation.

saves.asm - github.com/ClusterM/coolboy-multirom-builder.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 20cfa3071db699c0aa213d2611572fa839e0e190 (plain)
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
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
SAVES_BANK .rs 1 ; bank with saves
LAST_STARTED_SAVE .rs 1 ; last used save ID

CLEAN_AFTER .equ 128 ; clean flash after this number of menu states

  ; saving last selected game
save_state:
  .if USE_FLASH_WRITING=0
  rts
  .endif
  ; detect flash memory type
  jsr flash_detect
  lda <FLASH_TYPE
  beq .end ; not writable flash
  lda <SAVES_BANK
  bne .bank_already_formatted
  lda #($100 - 8) ; last bank - 8*16kb
  sta <SAVES_BANK
  jsr flash_format_sector
.bank_already_formatted:
  jsr write_state
.end:
  rts

write_state:
  lda #0
  sta BUFFER ; marker
  ; last started game
  lda <SELECTED_GAME
  sta BUFFER+1
  lda <SELECTED_GAME+1
  sta BUFFER+2
  ; line
  lda <SCROLL_LINES_TARGET
  sta BUFFER+3
  lda <SCROLL_LINES_TARGET+1
  sta BUFFER+4
  lda <LAST_STARTED_SAVE
  sta BUFFER+5
  lda <STATE_CELL_NEXT
  sta COPY_DEST_ADDR
  clc
  adc #8
  sta <STATE_CELL_NEXT
  lda <STATE_CELL_NEXT+1
  sta COPY_DEST_ADDR+1
  adc #0
  sta <STATE_CELL_NEXT+1
  lda <SAVES_BANK
  sta <NROM_BANK_L ; storing saves bank number
  lda #$FF
  sta <NROM_BANK_H ; at the very end of flash memory
  ldx #6; 6 bytes
  jsr flash_write
  rts

load_state:
  .if USE_FLASH_WRITING=0
  rts
  .endif
  ; detect flash memory type
  jsr flash_detect
  lda <FLASH_TYPE
  beq .end
  lda BUTTONS
  cmp #$5C ; Up+Left+Select+Start = full erase
  bne .no_force_erase
  jsr flash_force_erase
  rts
.no_force_erase:
  jsr find_saves_bank ; checks for saves bank
  beq .end ; no saves bank?
  sta <NROM_BANK_L ; storing saves bank number
  lda #$FF
  sta <NROM_BANK_H ; at the very end of flash memory
  jsr flash_find_empty_cell ; searching for first empty cell
  lda <STATE_CELL_NEXT+1
  cmp #$80
  bne .state_exists
  lda <STATE_CELL_NEXT
  cmp #$20
  bne .state_exists
  jmp .end ; if it's at the very beginning ($8020), there is no saved status
.state_exists:
  lda <STATE_CELL_NEXT
  sec
  sbc #8
  sta COPY_SOURCE_ADDR
  lda <STATE_CELL_NEXT+1
  sbc #0
  sta COPY_SOURCE_ADDR+1
  ldx #8
  jsr flash_read ; loading 8 bytes of data
  .if ENABLE_LAST_GAME_SAVING!=0
  ; loading last started game
  lda BUFFER+1
  sta <SELECTED_GAME
  lda BUFFER+2
  sta <SELECTED_GAME+1
  lda BUFFER+3
  sta <SCROLL_LINES_TARGET
  lda BUFFER+4
  sta <SCROLL_LINES_TARGET+1
  .else
  lda #0
  sta <SELECTED_GAME
  sta <SELECTED_GAME+1
  sta <SCROLL_LINES_TARGET
  sta <SCROLL_LINES_TARGET+1
  .endif
  ; loading last save ID
  lda BUFFER+5
  sta <LAST_STARTED_SAVE
  ;beq .end
  ; maybe it's time to clean flash?
  lda <STATE_CELL_NEXT+1
  cmp #$80 + (CLEAN_AFTER / ($100 / 8)) ; 32 saves per 256 bytes
  bcc .clean_not_required
  jsr saving_warning_show
  jsr flash_cleanup
.clean_not_required:
  lda <LAST_STARTED_SAVE
  beq .save_last_game_not_required
  jsr saving_warning_show
  jsr save_last_game
.save_last_game_not_required:
  jsr saving_warning_hide
.end:
  rts

save_last_game:
.save_last_game_again:
  lda <SAVES_BANK
  sta <NROM_BANK_L ; storing saves bank number
  lda #$FF
  sta <NROM_BANK_H ; at the very end of flash memory
  lda #$10
  sta COPY_SOURCE_ADDR ;$8010
  lda #$80
  sta COPY_SOURCE_ADDR+1
  ldx #16
  jsr flash_read ; reading 16 bytes to buffer
  ; searching for free slot
  lda #$FF
  ldx #1
.loop:
  cmp BUFFER, x
  beq .found
  inx
  cpx #16
  bne .loop
  jsr flash_cleanup ; not found, cleanup
  jmp .save_last_game_again ; repeat
.found:
  txa
  pha  ; storing save slot number
  clc
  adc #$10
  sta COPY_DEST_ADDR
  lda #$80
  sta COPY_DEST_ADDR+1
  lda <LAST_STARTED_SAVE
  sta BUFFER
  ldx #1
  jsr flash_write
  pla
  tax
  lsr A
  clc
  adc <SAVES_BANK
  sta <NROM_BANK_L
  lda #$00
  sta COPY_DEST_ADDR
  txa
  and #1
  bne .subbankA0
  lda #$80
  bmi .subbank
.subbankA0:
  lda #$A0
.subbank:
  sta COPY_DEST_ADDR+1
  jsr flash_write_prg_ram
  lda #0
  sta <LAST_STARTED_SAVE
  jsr write_state
  rts

find_saves_bank:
  lda #$00
  sta COPY_SOURCE_ADDR
  lda #$80
  sta COPY_SOURCE_ADDR+1
  lda #$FF
  sta <NROM_BANK_H
  lda #($100 - 8 * 2) ; last - 8 (8 banks*16kb = sector size) * 2
.bloop:
  sta <NROM_BANK_L
  ldx #8
  jsr flash_read
  ldx #0
.loop:
  lda saves_signature, x
  cmp BUFFER, x
  bne .failed
  inx
  cpx #8
  bne .loop
  lda <NROM_BANK_L
  jmp .end
.failed:
  lda <NROM_BANK_L
  clc
  adc #8 ; +128kb, next sector
  bne .bloop
.end:
  sta <SAVES_BANK
  rts

; A - game save number
; Returns Y - slot number (or zero if no save)
find_save_slot:
  cmp #0
  bne .savable_game
  tay
  rts
.savable_game:
  ldx <SAVES_BANK
  stx <NROM_BANK_L ; storing saves bank number
  ldx #$FF
  stx <NROM_BANK_H ; at the very end of flash memory
  ldx #$10
  stx COPY_SOURCE_ADDR ;$8010
  ldx #$80
  stx COPY_SOURCE_ADDR+1
  ldx #16
  pha
  jsr flash_read
  pla
  ; searching for last save slot
  ldy #0
  ldx #1
.save_search_loop:
  cmp BUFFER, x
  bne .save_search_next
  pha ; copy X to Y, keep A
  txa
  tay
  pla
.save_search_next:
  inx
  cpx #16
  bne .save_search_loop
  ; Y contains slot number... or zero
  rts

flash_write_prg_ram:
  lda #$00
  sta COPY_SOURCE_ADDR
  lda #$60
  sta COPY_SOURCE_ADDR+1
.loop:
  lda #$80
  sta $A001
  ldy #0
.read_loop:
  lda [COPY_SOURCE_ADDR], y
  sta BUFFER, y
  iny
  bne .read_loop
  ldx #0
  jsr flash_write
  inc COPY_DEST_ADDR+1
  inc COPY_SOURCE_ADDR+1
  bpl .loop
  rts

flash_force_erase:
  jsr error_sound
  jsr saving_warning_show
  lda #$F0
  sta NROM_BANK_L
  lda #$FF
  sta NROM_BANK_H
  jsr flash_erase_sector
  jsr switch_sector
  jsr flash_erase_sector
  lda #0
  sta SAVES_BANK
  jsr saving_warning_hide
  rts

flash_format_sector:
  ldx <SAVES_BANK
  stx <NROM_BANK_L ; storing saves bank number
  ldx #$FF
  stx <NROM_BANK_H ; at the very end of flash memory
  jsr flash_erase_sector
  ldy #8
.load:
  lda saves_signature, y
  sta BUFFER, y
  dey
  bpl .load
  lda #$00
  sta COPY_DEST_ADDR
  lda #$80
  sta COPY_DEST_ADDR+1
  ldx #8
  jsr flash_write
  lda #$20
  sta <STATE_CELL_NEXT
  lda #$80
  sta <STATE_CELL_NEXT+1
  rts

flash_cleanup:
  lda #SAVES_COUNT
  beq flash_format_sector ; no games with saves
  ; format other sector (erase, write signature)
  ; go to dest bank
  jsr switch_sector ; dest
  jsr flash_format_sector ; write signature
  jsr switch_sector ; source
  lda #0
.save_id_loop:
  cmp #SAVES_COUNT
  beq .end
  clc
  adc #1 ; next
  cmp <LAST_STARTED_SAVE
  beq .save_id_loop ; skip actual save
  jsr find_save_slot
  cpy #0 ; if save slop is 0...
  beq .save_id_loop ; not found, next
  pha ; save current save id
  sta BUFFER
  tya
  pha ; save slot id
  clc
  adc #$10
  sta COPY_DEST_ADDR
  lda #$80
  sta COPY_DEST_ADDR+1
  jsr switch_sector ; dest
  ldx #1
  jsr flash_write
  jsr switch_sector ; source
  pla ; load slot id
  pha ; but still keep it in stack
  lsr A
  clc
  adc <SAVES_BANK
  sta <NROM_BANK_L
  lda #$FF
  sta <NROM_BANK_H
  lda #$00
  sta COPY_SOURCE_ADDR
  sta COPY_DEST_ADDR
  pla ; load slot id
  and #1
  bne .subbankA0
  lda #$80
  bmi .subbank
.subbankA0:
  lda #$A0
.subbank:
  sta COPY_SOURCE_ADDR+1
  sta COPY_DEST_ADDR+1
.copy_loop:
  ldx #0
  jsr flash_read ; read 256 bytes to buffer
  jsr switch_sector ; dest sector
  ldx #0
  jsr flash_write ; write 256 bytes from buffer
  jsr switch_sector ; source sector
  inc COPY_SOURCE_ADDR+1 ; +256 of source address
  inc COPY_DEST_ADDR+1 ; +256 of dest address
  lda COPY_DEST_ADDR+1 ; load high byte of dest address and check it
  cmp #$A0 ; $A0? it's end of data
  beq .copy_end ; go to end
  cmp #$C0 ; $C0? it's end too...
  bne .copy_loop ; continue copying otherwise
.copy_end:
  pla ; restore save id from stack
  jmp .save_id_loop ; repeat with next game
.end:
  ldx <SAVES_BANK
  stx <NROM_BANK_L ; storing saves bank number
  ldx #$FF
  stx <NROM_BANK_H ; at the very end of flash memory
  jsr flash_erase_sector ; erasing source sector
  jsr switch_sector ; finally switching to new sector
  rts

switch_sector:
  pha
  lda <SAVES_BANK
  eor #8 ; 8 banks*16kb = sector size
  sta <SAVES_BANK
  lda <NROM_BANK_L
  eor #8 ; 8 banks*16kb = sector size
  sta <NROM_BANK_L
  pla
  rts

saves_signature:
  .db 'C','O','O','L','S','A','V','E'