]> git.sur5r.net Git - cc65/blob - libsrc/atari/shadow_ram_prepare.s
small memory optimization: appmsav not needed in the xl target
[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         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
162 ; Save the zero page locations we need
163
164         ldx     #zpspace-1
165 L1:     lda     sp,x
166         sta     zpsave,x
167         dex
168         bpl     L1
169
170 ; copy chargen to low memory
171
172 .ifdef DEBUG
173         print_string "copy chargen to low memory"
174         print_string "set up high memory"
175 .endif
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 (final) 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 .ifdef DEBUG
264         print_string "Stage #2 OK"
265         jsr     delay
266 .endif
267         rts
268
269
270 ; my 6502 fu is rusty, so I took a routine from the internet (http://www.obelisk.demon.co.uk/6502/algorithms.html)
271
272 ; copy memory
273 ; ptr1      - source
274 ; ptr2      - destination
275 ; tmp2:tmp1 - len
276
277 .proc   memcopy
278
279         ldy     #0
280         ldx     tmp2
281         beq     last
282 pagecp: lda     (ptr1),y
283         sta     (ptr2),y
284         iny
285         bne     pagecp
286         inc     ptr1+1
287         inc     ptr2+1
288         dex
289         bne     pagecp
290 last:   cpy     tmp1
291         beq     done
292         lda     (ptr1),y
293         sta     (ptr2),y
294         iny
295         bne     last
296 done:   rts
297
298 .endproc
299
300
301 .byte "HERE ****************** HERE ***************>>>>>>"
302
303 sramsize:
304         .word   __SHADOW_RAM_SIZE__
305
306 ; short delay
307 .proc   delay
308
309         lda     #10
310 l:      jsr     delay1
311         clc
312         sbc     #0
313         bne     l
314         rts
315
316 delay1: ldx     #0
317         ldy     #0
318 loop:   dey
319         bne     loop
320         dex
321         bne     loop
322         rts
323
324 .endproc
325
326 screen_device:  .byte "S:",0
327 screen_device_length = * - screen_device
328
329         .byte   " ** srprep ** end-->"
330
331 ; ------------------------------------------------------------------------
332 ; Provide an empty SHADOW_RAM segment in order that the linker is happy
333 ; if the user program doesn't have a SHADOW_RAM segment.
334
335 .segment        "SHADOW_RAM"
336
337
338 ; ------------------------------------------------------------------------
339 ; Chunk "trailer" - sets INITAD
340
341 .segment        "SRPREPTRL"
342
343         .word   INITAD
344         .word   INITAD+1
345         .word   __SRPREP_LOAD__
346
347 .endif  ; .if .defined(__ATARIXL__)