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