]> git.sur5r.net Git - cc65/blob - libsrc/atari/shadow_ram_prepare.s
use first free IOCB for "GRAPHICS 0" call instead of using a hard-coded one
[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         .import         zpsave
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 ; Chunk header
48
49 .segment        "SRPREPHDR"
50
51         .word   __SRPREP_LOAD__
52         .word   __SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__ - 1
53
54 ; ------------------------------------------------------------------------
55 ; Actual code
56
57 .segment        "SRPREP"
58
59 sramprep:
60 .ifdef DEBUG
61         print_string "entering stage #2"
62 .endif
63
64 ; save values of modified system variables and ports
65
66         lda     RAMTOP
67         sta     RAMTOP_save
68         lda     MEMTOP
69         sta     MEMTOP_save
70         lda     MEMTOP+1
71         sta     MEMTOP_save+1
72         lda     APPMHI
73         sta     APPMHI_save
74         lda     APPMHI+1
75         sta     APPMHI_save+1
76         lda     PORTB
77         sta     PORTB_save
78         lda     CIOV            ; zero-page wrapper
79         sta     ZP_CIOV_save
80         lda     CIOV+1
81         sta     ZP_CIOV_save+1
82         lda     CIOV+2
83         sta     ZP_CIOV_save+2
84         lda     SIOV            ; zero-page wrapper
85         sta     ZP_SIOV_save
86         lda     SIOV+1
87         sta     ZP_SIOV_save+1
88         lda     SIOV+2
89         sta     ZP_SIOV_save+2
90
91         lda     $fffe
92         sta     IRQ_save
93         lda     $ffff
94         sta     IRQ_save+1
95         lda     $fffc
96         sta     RESET_save
97         lda     $fffd
98         sta     RESET_save+1
99         lda     $fffa
100         sta     NMI_save
101         lda     $fffb
102         sta     NMI_save+1
103
104 ; disable BASIC
105
106         lda     PORTB
107         ora     #2
108         sta     PORTB
109
110         .include "xlmemchk.inc" ; calculate lowest address used and new value for RAMTOP
111
112         ldx     lowadr
113         stx     MEMTOP
114         stx     APPMHI
115         lda     lowadr+1
116         sta     MEMTOP+1
117         sta     APPMHI+1
118         lda     lodadr+1
119         sta     RAMTOP
120
121
122 ; ... issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers)
123
124
125         jsr     findfreeiocb
126 .ifdef DEBUG            ; only check in debug version, this shouldn't happen normally(tm)
127         beq     iocbok
128         print_string "Internal error, no free IOCB!"
129         jsr     delay
130         jsr     delay
131         jsr     delay
132         jsr     restore                 ; restore stuff we've changed
133         jmp     (DOSVEC)                ; abort loading
134 iocbok:
135 .endif
136
137         ; Reopen it in Graphics 0
138         lda     #OPEN
139         sta     ICCOM,x
140         lda     #OPNIN | OPNOT
141         sta     ICAX1,x
142         lda     #0
143         sta     ICAX2,x
144         lda     #<screen_device
145         sta     ICBAL,x
146         lda     #>screen_device
147         sta     ICBAH,x
148         lda     #<screen_device_length
149         sta     ICBLL,x
150         lda     #>screen_device_length
151         sta     ICBLH,x
152         jsr     CIOV_org
153         bpl     scrok
154
155 ; shouldn't happen(tm)
156         print_string "Internal error, aborting..."
157         jsr     delay
158         jsr     delay
159         jsr     delay
160         jsr     restore                 ; restore stuff we've changed
161         jmp     (DOSVEC)                ; abort loading
162
163
164 scrok:  ; now close it again -- we don't need it anymore
165         lda     #CLOSE
166         sta     ICCOM,x
167         jsr     CIOV_org
168
169
170 ; Save the zero page locations we need
171
172         ldx     #zpspace-1
173 L1:     lda     sp,x
174         sta     zpsave,x
175         dex
176         bpl     L1
177
178 ; copy chargen to low memory
179
180 .ifdef DEBUG
181         print_string "copy chargen to low memory"
182         print_string "set up high memory"
183 .endif
184
185         lda     #>(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
186         sta     ptr3+1
187         lda     #<(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
188         sta     ptr3
189         beq     cg_addr_ok
190
191         ; page align the new chargen address
192         inc     ptr3+1
193         lda     #0
194         sta     ptr3
195
196 cg_addr_ok:
197         lda     #<DCSORG
198         sta     ptr1
199         lda     #>DCSORG
200         sta     ptr1+1
201         lda     ptr3
202         sta     ptr2
203         lda     ptr3+1
204         sta     ptr2+1
205         lda     #>__CHARGEN_SIZE__
206         sta     tmp2
207         lda     #<__CHARGEN_SIZE__
208         sta     tmp2+1
209         jsr     memcopy
210
211 ; TODO: switch to this temp. chargen
212
213 ; disable ROMs
214         sei
215         ldx     #0
216         stx     NMIEN           ; disable NMI
217         lda     PORTB
218         and     #$fe
219         sta     PORTB           ; now ROM is mapped out
220
221 ; copy shadow RAM contents to their destination
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 chargen to its new (final) location
247
248         lda     ptr3
249         sta     ptr1
250         lda     ptr3+1
251         sta     ptr1+1
252         lda     #<__CHARGEN_START__
253         sta     ptr2
254         lda     #>__CHARGEN_START__
255         sta     ptr2+1
256         lda     #>__CHARGEN_SIZE__
257         sta     tmp2
258         lda     #<__CHARGEN_SIZE__
259         sta     tmp1
260         jsr     memcopy
261
262 ; re-enable ROM
263
264         lda     PORTB
265         ora     #1
266         sta     PORTB
267         lda     #$40
268         sta     NMIEN                   ; enable VB again
269         cli                             ; and enable IRQs
270
271 .ifdef DEBUG
272         print_string "Stage #2 OK"
273         jsr     delay
274 .endif
275         rts
276
277 .include "findfreeiocb.inc"
278
279 ; my 6502 fu is rusty, so I took a routine from the internet (http://www.obelisk.demon.co.uk/6502/algorithms.html)
280
281 ; copy memory
282 ; ptr1      - source
283 ; ptr2      - destination
284 ; tmp2:tmp1 - len
285
286 .proc   memcopy
287
288         ldy     #0
289         ldx     tmp2
290         beq     last
291 pagecp: lda     (ptr1),y
292         sta     (ptr2),y
293         iny
294         bne     pagecp
295         inc     ptr1+1
296         inc     ptr2+1
297         dex
298         bne     pagecp
299 last:   cpy     tmp1
300         beq     done
301         lda     (ptr1),y
302         sta     (ptr2),y
303         iny
304         bne     last
305 done:   rts
306
307 .endproc
308
309
310 ; clean up after a fatal error
311
312 restore:lda     RAMTOP_save
313         sta     RAMTOP
314         lda     MEMTOP_save
315         sta     MEMTOP
316         lda     MEMTOP_save+1
317         sta     MEMTOP+1
318         lda     APPMHI_save
319         sta     APPMHI
320         lda     APPMHI_save+1
321         sta     APPMHI+1
322         rts
323
324
325 .byte "HERE ****************** HERE ***************>>>>>>"
326
327 sramsize:
328         .word   __SHADOW_RAM_SIZE__
329
330 ; short delay
331 .proc   delay
332
333         lda     #10
334 l:      jsr     delay1
335         clc
336         sbc     #0
337         bne     l
338         rts
339
340 delay1: ldx     #0
341         ldy     #0
342 loop:   dey
343         bne     loop
344         dex
345         bne     loop
346         rts
347
348 .endproc
349
350 screen_device:  .byte "S:",0
351 screen_device_length = * - screen_device
352
353         .byte   " ** srprep ** end-->"
354
355 ; ------------------------------------------------------------------------
356 ; Provide an empty SHADOW_RAM segment in order that the linker is happy
357 ; if the user program doesn't have a SHADOW_RAM segment.
358
359 .segment        "SHADOW_RAM"
360
361
362 ; ------------------------------------------------------------------------
363 ; Chunk "trailer" - sets INITAD
364
365 .segment        "SRPREPTRL"
366
367         .word   INITAD
368         .word   INITAD+1
369         .word   __SRPREP_LOAD__
370
371 .endif  ; .if .defined(__ATARIXL__)