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