]> git.sur5r.net Git - cc65/blob - libsrc/atari/shadow_ram_prepare.s
cleanups and add more comments
[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 "in sramprep"
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         ldx     #$50            ; take any IOCB, hopefully free (@@@ fixme)
126
127         ; Reopen it in Graphics 0
128         lda     #OPEN
129         sta     ICCOM,x
130         lda     #OPNIN | OPNOT
131         sta     ICAX1,x
132         lda     #0
133         sta     ICAX2,x
134         lda     #<screen_device
135         sta     ICBAL,x
136         lda     #>screen_device
137         sta     ICBAH,x
138         lda     #<screen_device_length
139         sta     ICBLL,x
140         lda     #>screen_device_length
141         sta     ICBLH,x
142         jsr     CIOV_org
143         bpl     okoko
144
145         print_string "Internal error, aborting..."
146         jsr     delay
147         jsr     delay
148         jsr     delay
149
150         jmp     (DOSVEC)                ; abort loading
151
152
153 okoko:
154
155
156         ; Now close it again; we don't need it anymore :)
157         lda     #CLOSE
158         sta     ICCOM,x
159         jsr     CIOV_org
160
161 .ifdef DEBUG
162         print_string "Stage #2 OK"
163         jsr     delay
164 .endif
165
166
167 ; Save the zero page locations we need
168
169         ldx     #zpspace-1
170 L1:     lda     sp,x
171         sta     zpsave,x
172         dex
173         bpl     L1
174
175 ; copy chargen to low memory
176
177         lda     #>(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
178         sta     ptr3+1
179         lda     #<(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
180         sta     ptr3
181         beq     cg_addr_ok
182
183         ; page align the new chargen address
184         inc     ptr3+1
185         lda     #0
186         sta     ptr3
187
188 cg_addr_ok:
189         lda     #<DCSORG
190         sta     ptr1
191         lda     #>DCSORG
192         sta     ptr1+1
193         lda     ptr3
194         sta     ptr2
195         lda     ptr3+1
196         sta     ptr2+1
197         lda     #>__CHARGEN_SIZE__
198         sta     tmp2
199         lda     #<__CHARGEN_SIZE__
200         sta     tmp2+1
201         jsr     memcopy
202
203 ; TODO: switch to this temp. chargen
204
205 ; disable ROMs
206         sei
207         ldx     #0
208         stx     NMIEN           ; disable NMI
209         lda     PORTB
210         and     #$fe
211         sta     PORTB           ; now ROM is mapped out
212
213 ; copy shadow RAM contents to their destination
214
215         lda     #<__SHADOW_RAM_SIZE__
216         bne     do_copy
217         lda     #>__SHADOW_RAM_SIZE__
218         beq     no_copy                         ; we have no shadow RAM contents
219
220         ; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
221 do_copy:lda     #<__SHADOW_RAM_LOAD__
222         sta     ptr1
223         lda     #>__SHADOW_RAM_LOAD__
224         sta     ptr1+1
225         lda     #<__SHADOW_RAM_RUN__
226         sta     ptr2
227         lda     #>__SHADOW_RAM_RUN__
228         sta     ptr2+1
229         lda     #<__SHADOW_RAM_SIZE__
230         sta     tmp1
231         lda     #>__SHADOW_RAM_SIZE__
232         sta     tmp2
233
234         jsr     memcopy
235
236 no_copy:
237
238 ; copy chargen to its new location
239
240         lda     ptr3
241         sta     ptr1
242         lda     ptr3+1
243         sta     ptr1+1
244         lda     #<__CHARGEN_START__
245         sta     ptr2
246         lda     #>__CHARGEN_START__
247         sta     ptr2+1
248         lda     #>__CHARGEN_SIZE__
249         sta     tmp2
250         lda     #<__CHARGEN_SIZE__
251         sta     tmp1
252         jsr     memcopy
253
254 ; re-enable ROM
255
256         lda     PORTB
257         ora     #1
258         sta     PORTB
259         lda     #$40
260         sta     NMIEN                   ; enable VB again
261         cli                             ; and enable IRQs
262
263         rts
264
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 .byte "HERE ****************** HERE ***************>>>>>>"
298
299 sramsize:
300         .word   __SHADOW_RAM_SIZE__
301
302 ; short delay
303 .proc   delay
304
305         lda     #10
306 l:      jsr     delay1
307         clc
308         sbc     #0
309         bne     l
310         rts
311
312 delay1: ldx     #0
313         ldy     #0
314 loop:   dey
315         bne     loop
316         dex
317         bne     loop
318         rts
319
320 .endproc
321
322 screen_device:  .byte "S:",0
323 screen_device_length = * - screen_device
324
325         .byte   " ** srprep ** end-->"
326
327 ; ------------------------------------------------------------------------
328 ; Provide an empty SHADOW_RAM segment in order that the linker is happy
329 ; if the user program doesn't have a SHADOW_RAM segment.
330
331 .segment        "SHADOW_RAM"
332
333
334 ; ------------------------------------------------------------------------
335 ; Chunk "trailer" - sets INITAD
336
337 .segment        "SRPREPTRL"
338
339         .word   INITAD
340         .word   INITAD+1
341         .word   __SRPREP_LOAD__
342
343 .endif  ; .if .defined(__ATARIXL__)