]> git.sur5r.net Git - cc65/blob - libsrc/atari/shadow_ram_prepare.s
78e7ba4f0de5c103cc9413c407b89cb78aef6cc8
[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 .if .defined(__ATARIXL__)
15
16         .export         sramprep
17         .import         __SRPREP_LOAD__, __SRPREP_SIZE__
18         .import         __SHADOW_RAM_LOAD__, __SHADOW_RAM_SIZE__
19         .import         __SHADOW_RAM_RUN__
20         .import         __CHARGEN_START__, __CHARGEN_SIZE__
21         .import         __SAVEAREA_LOAD__
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   __SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__ - 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
152
153 .ifdef DEBUG
154         print_string "copy chargen to low memory"
155 .endif
156
157         lda     #>(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
158         sta     ptr3+1
159         lda     #<(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
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
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 chargen to its new (final) location
244
245         lda     ptr3
246         sta     ptr1
247         lda     ptr3+1
248         sta     ptr1+1
249         lda     #<__CHARGEN_START__
250         sta     ptr2
251         lda     #>__CHARGEN_START__
252         sta     ptr2+1
253         lda     #>__CHARGEN_SIZE__
254         sta     tmp2
255         lda     #<__CHARGEN_SIZE__
256         sta     tmp1
257         jsr     memcopy
258
259 ; re-enable ROM
260
261         lda     PORTB
262         ora     #1
263         ldx     #>DCSORG
264         sta     WSYNC                   ; wait for horiz. retrace
265         sta     PORTB
266         stx     CHBASE
267         stx     CHBAS
268         lda     #$40
269         sta     NMIEN                   ; enable VB again
270         cli                             ; and enable IRQs
271
272 .ifdef DEBUG
273         print_string "Stage #2 OK"
274         print_string "loading main chunk"
275         jsr     delay
276 .endif
277         rts
278
279 .include "findfreeiocb.inc"
280
281 ; routine taken from http://www.obelisk.demon.co.uk/6502/algorithms.html
282 ;
283 ; copy memory
284 ; ptr1      - source
285 ; ptr2      - destination
286 ; tmp2:tmp1 - len
287
288 .proc   memcopy
289
290         ldy     #0
291         ldx     tmp2
292         beq     last
293 pagecp: lda     (ptr1),y
294         sta     (ptr2),y
295         iny
296         bne     pagecp
297         inc     ptr1+1
298         inc     ptr2+1
299         dex
300         bne     pagecp
301 last:   cpy     tmp1
302         beq     done
303         lda     (ptr1),y
304         sta     (ptr2),y
305         iny
306         bne     last
307 done:   rts
308
309 .endproc
310
311
312 ; clean up after a fatal error
313
314 restore:lda     RAMTOP_save
315         sta     RAMTOP
316         lda     MEMTOP_save
317         sta     MEMTOP
318         lda     MEMTOP_save+1
319         sta     MEMTOP+1
320         lda     APPMHI_save
321         sta     APPMHI
322         lda     APPMHI_save+1
323         sta     APPMHI+1
324         rts
325
326
327 .ifdef DEBUG
328
329 .byte "HERE ****************** HERE ***************>>>>>>"
330
331 sramsize:
332         .word   __SHADOW_RAM_SIZE__
333
334 ; short delay
335 .proc   delay
336
337         lda     #10
338 l:      jsr     delay1
339         clc
340         sbc     #0
341         bne     l
342         rts
343
344 delay1: ldx     #0
345         ldy     #0
346 loop:   dey
347         bne     loop
348         dex
349         bne     loop
350         rts
351
352 .endproc
353
354 .endif          ; .ifdef DEBUG
355
356 screen_device:  .byte "S:",0
357 screen_device_length = * - screen_device
358
359 .ifdef DEBUG
360         .byte   " ** srprep ** end-->"
361 .endif
362
363 ; ------------------------------------------------------------------------
364 ; Provide an empty SHADOW_RAM segment in order that the linker is happy
365 ; if the user program doesn't have a SHADOW_RAM segment.
366
367 .segment        "SHADOW_RAM"
368
369
370 ; ------------------------------------------------------------------------
371 ; EXE load chunk "trailer" - sets INITAD
372
373 .segment        "SRPREPTRL"
374
375         .word   INITAD
376         .word   INITAD+1
377         .word   sramprep
378
379 .endif  ; .if .defined(__ATARIXL__)