]> git.sur5r.net Git - cc65/blob - libsrc/atari/shadow_ram_prepare.s
atari: split color.s into bordercolor.s and bgcolor.s
[cc65] / libsrc / atari / shadow_ram_prepare.s
1 ;
2 ; Atari XL shadow RAM preparation routines
3 ;
4 ; Tasks:
5 ; - move screen memory below load address
6 ; - copy ROM chargen to its new place
7 ; - copy shadow RAM contents to their destination
8 ;
9 ; Christian Groessler, chris@groessler.org, 2013
10 ;
11
12 ;DEBUG   =       1
13
14 .ifdef __ATARIXL__
15
16         .export         sramprep
17
18         .import         __SRPREP_LOAD__, __SRPREPCHNK_LAST__
19         .import         __SHADOW_RAM_LOAD__, __SHADOW_RAM_SIZE__, __SHADOW_RAM_RUN__
20         .import         __SHADOW_RAM2_LOAD__, __SHADOW_RAM2_SIZE__, __SHADOW_RAM2_RUN__
21         .import         __CHARGEN_START__, __CHARGEN_SIZE__
22         .import         __STARTADDRESS__       ; needed by xlmemchk.inc
23
24         .include        "zeropage.inc"
25         .include        "atari.inc"
26         .include        "save_area.inc"
27
28 .macro print_string text
29         .local  start, cont
30         jmp     cont
31 start:  .byte   text, ATEOL
32 cont:   ldx     #0              ; channel 0
33         lda     #<start
34         sta     ICBAL,x         ; address
35         lda     #>start
36         sta     ICBAH,x
37         lda     #<(cont - start)
38         sta     ICBLL,x         ; length
39         lda     #>(cont - start)
40         sta     ICBLH,x
41         lda     #PUTCHR
42         sta     ICCOM,x
43         jsr     CIOV_org
44 .endmacro
45
46 ; ------------------------------------------------------------------------
47 ; EXE load chunk header
48
49 .segment        "SRPREPHDR"
50
51         .word   __SRPREP_LOAD__
52         .word   __SRPREPCHNK_LAST__ - 1
53
54 ; ------------------------------------------------------------------------
55 ; Actual code
56
57 .segment        "SRPREP"
58
59 ; ***** entry point *****
60
61 sramprep:
62 .ifdef DEBUG
63         print_string "entering stage #2"
64 .endif
65
66 ; save values of modified system variables and ports
67
68         lda     RAMTOP
69         sta     RAMTOP_save
70         lda     MEMTOP
71         sta     MEMTOP_save
72         lda     MEMTOP+1
73         sta     MEMTOP_save+1
74         lda     APPMHI
75         sta     APPMHI_save
76         lda     APPMHI+1
77         sta     APPMHI_save+1
78         lda     PORTB
79         sta     PORTB_save
80
81 ; disable BASIC
82
83         lda     PORTB
84         ora     #2
85         sta     PORTB
86
87         .include "xlmemchk.inc" ; calculate lowest address used and new value for RAMTOP
88
89         ldx     lowadr
90         stx     MEMTOP
91         lda     lowadr+1
92         sta     MEMTOP+1
93         lda     lodadr+1
94         sta     RAMTOP
95
96         ; set APPMHI to MEMLO (+ 1 for sanity)
97         lda     MEMLO
98         clc
99         adc     #1
100         sta     APPMHI
101         lda     MEMLO+1
102         adc     #0
103         sta     APPMHI+1
104
105
106 ; issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers) to move screen memory down
107
108
109         jsr     findfreeiocb
110 .ifdef DEBUG            ; only check in debug version, this shouldn't really happen(tm)
111         beq     iocbok
112         print_string "Internal error, no free IOCB!"
113         jsr     delay
114         jsr     delay
115         jsr     delay
116         jsr     restore                 ; restore stuff we've changed
117         jmp     (DOSVEC)                ; abort loading
118 iocbok:
119 .endif
120
121         ; reopen it in Graphics 0
122         lda     #OPEN
123         sta     ICCOM,x
124         lda     #OPNIN | OPNOT
125         sta     ICAX1,x
126         lda     #0
127         sta     ICAX2,x
128         lda     #<screen_device
129         sta     ICBAL,x
130         lda     #>screen_device
131         sta     ICBAH,x
132         lda     #<screen_device_length
133         sta     ICBLL,x
134         lda     #>screen_device_length
135         sta     ICBLH,x
136         jsr     CIOV_org
137         bpl     scrok
138
139 ; shouldn't happen(tm)
140         print_string "Internal error, aborting..."
141         jsr     delay
142         jsr     delay
143         jsr     delay
144         jsr     restore                 ; restore stuff we've changed
145         jmp     (DOSVEC)                ; abort loading
146
147
148 scrok:  ; now close it again -- we don't need it anymore
149         lda     #CLOSE
150         sta     ICCOM,x
151         jsr     CIOV_org
152
153
154 ; copy chargen to low memory, just after the next possible address beyond our loaded chunk data
155
156 .ifdef DEBUG
157         print_string "copy chargen to low memory"
158 .endif
159
160         lda     #>__SRPREPCHNK_LAST__
161         sta     ptr3+1
162         lda     #<__SRPREPCHNK_LAST__
163         sta     ptr3
164         beq     cg_addr_ok
165
166         ; page align the new chargen address
167         inc     ptr3+1
168         lda     #0
169         sta     ptr3
170
171 cg_addr_ok:
172
173         lda     ptr3+1
174         and     #3
175         beq     cg_addr_ok2
176
177         ; align to next 1K boundary
178         lda     ptr3+1
179         and     #$fc
180         clc
181         adc     #4
182         sta     ptr3+1
183
184 cg_addr_ok2:
185
186         lda     #<DCSORG
187         sta     ptr1
188         lda     #>DCSORG
189         sta     ptr1+1
190         lda     ptr3
191         sta     ptr2
192         lda     ptr3+1
193         pha                             ; needed later to set CHBAS/CHBASE
194         sta     ptr2+1
195         lda     #>__CHARGEN_SIZE__
196         sta     tmp2
197         lda     #<__CHARGEN_SIZE__
198         sta     tmp1
199         jsr     memcopy
200
201 .ifdef DEBUG
202         print_string "now setting up high memory"
203 .endif
204
205 ; disable ROM
206         sei
207         ldx     #0
208         stx     NMIEN                   ; disable NMI
209         lda     PORTB
210         and     #$fe
211         tax
212         pla                             ; get temp. chargen address
213         sta     WSYNC                   ; wait for horiz. retrace
214         stx     PORTB                   ; now ROM is mapped out
215
216 ; switch to temporary chargen
217
218         sta     CHBASE
219         sta     CHBAS
220
221 ; copy shadow RAM contents to their destination (segment SHADOW_RAM)
222
223         lda     #<__SHADOW_RAM_SIZE__
224         bne     do_copy
225         lda     #>__SHADOW_RAM_SIZE__
226         beq     no_copy                 ; we have no shadow RAM contents
227
228         ; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
229 do_copy:lda     #<__SHADOW_RAM_LOAD__
230         sta     ptr1
231         lda     #>__SHADOW_RAM_LOAD__
232         sta     ptr1+1
233         lda     #<__SHADOW_RAM_RUN__
234         sta     ptr2
235         lda     #>__SHADOW_RAM_RUN__
236         sta     ptr2+1
237         lda     #<__SHADOW_RAM_SIZE__
238         sta     tmp1
239         lda     #>__SHADOW_RAM_SIZE__
240         sta     tmp2
241
242         jsr     memcopy
243
244 no_copy:
245
246 ; copy shadow RAM #2 contents to their destination (segment SHADOW_RAM2)
247
248         lda     #<__SHADOW_RAM2_SIZE__
249         bne     do_copy2
250         lda     #>__SHADOW_RAM2_SIZE__
251         beq     no_copy2                ; we have no shadow RAM #2 contents
252
253         ; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
254 do_copy2:
255         lda     #<__SHADOW_RAM2_LOAD__
256         sta     ptr1
257         lda     #>__SHADOW_RAM2_LOAD__
258         sta     ptr1+1
259         lda     #<__SHADOW_RAM2_RUN__
260         sta     ptr2
261         lda     #>__SHADOW_RAM2_RUN__
262         sta     ptr2+1
263         lda     #<__SHADOW_RAM2_SIZE__
264         sta     tmp1
265         lda     #>__SHADOW_RAM2_SIZE__
266         sta     tmp2
267
268         jsr     memcopy
269
270 no_copy2:
271
272 ; copy chargen to its new (final) location
273
274         lda     ptr3
275         sta     ptr1
276         lda     ptr3+1
277         sta     ptr1+1
278         lda     #<__CHARGEN_START__
279         sta     ptr2
280         lda     #>__CHARGEN_START__
281         sta     ptr2+1
282         lda     #>__CHARGEN_SIZE__
283         sta     tmp2
284         lda     #<__CHARGEN_SIZE__
285         sta     tmp1
286         jsr     memcopy
287
288 ; re-enable ROM
289
290         lda     PORTB
291         ora     #1
292         ldx     #>DCSORG
293         sta     WSYNC                   ; wait for horiz. retrace
294         sta     PORTB
295         stx     CHBASE
296         stx     CHBAS
297         lda     #$40
298         sta     NMIEN                   ; enable VB again
299         cli                             ; and enable IRQs
300
301 .ifdef DEBUG
302         print_string "Stage #2 OK"
303         print_string "loading main chunk"
304         jsr     delay
305 .endif
306         rts
307
308 .include "findfreeiocb.inc"
309
310 ; routine taken from http://www.obelisk.demon.co.uk/6502/algorithms.html
311 ;
312 ; copy memory
313 ; ptr1      - source
314 ; ptr2      - destination
315 ; tmp2:tmp1 - len
316
317 .proc   memcopy
318
319         ldy     #0
320         ldx     tmp2
321         beq     last
322 pagecp: lda     (ptr1),y
323         sta     (ptr2),y
324         iny
325         bne     pagecp
326         inc     ptr1+1
327         inc     ptr2+1
328         dex
329         bne     pagecp
330 last:   cpy     tmp1
331         beq     done
332         lda     (ptr1),y
333         sta     (ptr2),y
334         iny
335         bne     last
336 done:   rts
337
338 .endproc
339
340
341 ; clean up after a fatal error
342
343 restore:lda     RAMTOP_save
344         sta     RAMTOP
345         lda     MEMTOP_save
346         sta     MEMTOP
347         lda     MEMTOP_save+1
348         sta     MEMTOP+1
349         lda     APPMHI_save
350         sta     APPMHI
351         lda     APPMHI_save+1
352         sta     APPMHI+1
353         rts
354
355 ; short delay
356 .proc   delay
357
358         lda     #10
359 @loop:  jsr     delay1
360         clc
361         sbc     #0
362         bne     @loop
363         rts
364
365 delay1: ldx     #0
366         ldy     #0
367 @loop:   dey
368         bne     @loop
369         dex
370         bne     @loop
371         rts
372
373 .endproc
374
375 .ifdef DEBUG
376
377 .byte "HERE ****************** HERE ***************>>>>>>"
378
379 sramsize:
380         .word   __SHADOW_RAM_SIZE__
381
382 .endif          ; .ifdef DEBUG
383
384 screen_device:  .byte "S:",0
385 screen_device_length = * - screen_device
386
387 .ifdef DEBUG
388         .byte   " ** srprep ** end-->"
389 .endif
390
391 ; ------------------------------------------------------------------------
392 ; Provide empty SHADOW_RAM and SHADOW_RAM2 segments in order that the
393 ; linker is happy if the user program doesn't have these segments.
394
395 .segment        "SHADOW_RAM"
396 .segment        "SHADOW_RAM2"
397
398
399 ; ------------------------------------------------------------------------
400 ; EXE load chunk "trailer" - sets INITAD
401
402 .segment        "SRPREPTRL"
403
404         .word   INITAD
405         .word   INITAD+1
406         .word   sramprep
407
408 .endif  ; .ifdef __ATARIXL__