]> git.sur5r.net Git - cc65/blob - libsrc/atari/shadow_ram_prepare.s
6458ffdb121c17cb0faf439d2f0d4a9284fcdde8
[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 ; disable BASIC
92
93         lda     PORTB
94         ora     #2
95         sta     PORTB
96
97         .include "xlmemchk.inc" ; calculate lowest address used and new value for RAMTOP
98
99         ldx     lowadr
100         stx     MEMTOP
101         stx     APPMHI
102         lda     lowadr+1
103         sta     MEMTOP+1
104         sta     APPMHI+1
105         lda     lodadr+1
106         sta     RAMTOP
107
108
109 ; ... issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers)
110
111
112         jsr     findfreeiocb
113 .ifdef DEBUG            ; only check in debug version, this shouldn't happen normally(tm)
114         beq     iocbok
115         print_string "Internal error, no free IOCB!"
116         jsr     delay
117         jsr     delay
118         jsr     delay
119         jsr     restore                 ; restore stuff we've changed
120         jmp     (DOSVEC)                ; abort loading
121 iocbok:
122 .endif
123
124         ; Reopen it in Graphics 0
125         lda     #OPEN
126         sta     ICCOM,x
127         lda     #OPNIN | OPNOT
128         sta     ICAX1,x
129         lda     #0
130         sta     ICAX2,x
131         lda     #<screen_device
132         sta     ICBAL,x
133         lda     #>screen_device
134         sta     ICBAH,x
135         lda     #<screen_device_length
136         sta     ICBLL,x
137         lda     #>screen_device_length
138         sta     ICBLH,x
139         jsr     CIOV_org
140         bpl     scrok
141
142 ; shouldn't happen(tm)
143         print_string "Internal error, aborting..."
144         jsr     delay
145         jsr     delay
146         jsr     delay
147         jsr     restore                 ; restore stuff we've changed
148         jmp     (DOSVEC)                ; abort loading
149
150
151 scrok:  ; now close it again -- we don't need it anymore
152         lda     #CLOSE
153         sta     ICCOM,x
154         jsr     CIOV_org
155
156
157 ; Save the zero page locations we need
158
159         ldx     #zpspace-1
160 L1:     lda     sp,x
161         sta     zpsave,x
162         dex
163         bpl     L1
164
165 ; copy chargen to low memory
166
167 .ifdef DEBUG
168         print_string "copy chargen to low memory"
169         print_string "set up high memory"
170 .endif
171
172         lda     #>(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
173         sta     ptr3+1
174         lda     #<(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
175         sta     ptr3
176         beq     cg_addr_ok
177
178         ; page align the new chargen address
179         inc     ptr3+1
180         lda     #0
181         sta     ptr3
182
183 cg_addr_ok:
184         lda     #<DCSORG
185         sta     ptr1
186         lda     #>DCSORG
187         sta     ptr1+1
188         lda     ptr3
189         sta     ptr2
190         lda     ptr3+1
191         sta     ptr2+1
192         lda     #>__CHARGEN_SIZE__
193         sta     tmp2
194         lda     #<__CHARGEN_SIZE__
195         sta     tmp2+1
196         jsr     memcopy
197
198 ; TODO: switch to this temp. chargen
199
200 ; disable ROMs
201         sei
202         ldx     #0
203         stx     NMIEN           ; disable NMI
204         lda     PORTB
205         and     #$fe
206         sta     PORTB           ; now ROM is mapped out
207
208 ; copy shadow RAM contents to their destination
209
210         lda     #<__SHADOW_RAM_SIZE__
211         bne     do_copy
212         lda     #>__SHADOW_RAM_SIZE__
213         beq     no_copy                         ; we have no shadow RAM contents
214
215         ; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
216 do_copy:lda     #<__SHADOW_RAM_LOAD__
217         sta     ptr1
218         lda     #>__SHADOW_RAM_LOAD__
219         sta     ptr1+1
220         lda     #<__SHADOW_RAM_RUN__
221         sta     ptr2
222         lda     #>__SHADOW_RAM_RUN__
223         sta     ptr2+1
224         lda     #<__SHADOW_RAM_SIZE__
225         sta     tmp1
226         lda     #>__SHADOW_RAM_SIZE__
227         sta     tmp2
228
229         jsr     memcopy
230
231 no_copy:
232
233 ; copy chargen to its new (final) location
234
235         lda     ptr3
236         sta     ptr1
237         lda     ptr3+1
238         sta     ptr1+1
239         lda     #<__CHARGEN_START__
240         sta     ptr2
241         lda     #>__CHARGEN_START__
242         sta     ptr2+1
243         lda     #>__CHARGEN_SIZE__
244         sta     tmp2
245         lda     #<__CHARGEN_SIZE__
246         sta     tmp1
247         jsr     memcopy
248
249 ; re-enable ROM
250
251         lda     PORTB
252         ora     #1
253         sta     PORTB
254         lda     #$40
255         sta     NMIEN                   ; enable VB again
256         cli                             ; and enable IRQs
257
258 .ifdef DEBUG
259         print_string "Stage #2 OK"
260         jsr     delay
261 .endif
262         rts
263
264 .include "findfreeiocb.inc"
265
266 ; my 6502 fu is rusty, so I took a routine from the internet (http://www.obelisk.demon.co.uk/6502/algorithms.html)
267
268 ; copy memory
269 ; ptr1      - source
270 ; ptr2      - destination
271 ; tmp2:tmp1 - len
272
273 .proc   memcopy
274
275         ldy     #0
276         ldx     tmp2
277         beq     last
278 pagecp: lda     (ptr1),y
279         sta     (ptr2),y
280         iny
281         bne     pagecp
282         inc     ptr1+1
283         inc     ptr2+1
284         dex
285         bne     pagecp
286 last:   cpy     tmp1
287         beq     done
288         lda     (ptr1),y
289         sta     (ptr2),y
290         iny
291         bne     last
292 done:   rts
293
294 .endproc
295
296
297 ; clean up after a fatal error
298
299 restore:lda     RAMTOP_save
300         sta     RAMTOP
301         lda     MEMTOP_save
302         sta     MEMTOP
303         lda     MEMTOP_save+1
304         sta     MEMTOP+1
305         lda     APPMHI_save
306         sta     APPMHI
307         lda     APPMHI_save+1
308         sta     APPMHI+1
309         rts
310
311
312 .byte "HERE ****************** HERE ***************>>>>>>"
313
314 sramsize:
315         .word   __SHADOW_RAM_SIZE__
316
317 ; short delay
318 .proc   delay
319
320         lda     #10
321 l:      jsr     delay1
322         clc
323         sbc     #0
324         bne     l
325         rts
326
327 delay1: ldx     #0
328         ldy     #0
329 loop:   dey
330         bne     loop
331         dex
332         bne     loop
333         rts
334
335 .endproc
336
337 screen_device:  .byte "S:",0
338 screen_device_length = * - screen_device
339
340         .byte   " ** srprep ** end-->"
341
342 ; ------------------------------------------------------------------------
343 ; Provide an empty SHADOW_RAM segment in order that the linker is happy
344 ; if the user program doesn't have a SHADOW_RAM segment.
345
346 .segment        "SHADOW_RAM"
347
348
349 ; ------------------------------------------------------------------------
350 ; Chunk "trailer" - sets INITAD
351
352 .segment        "SRPREPTRL"
353
354         .word   INITAD
355         .word   INITAD+1
356         .word   __SRPREP_LOAD__
357
358 .endif  ; .if .defined(__ATARIXL__)