]> git.sur5r.net Git - cc65/blob - libsrc/atari/shadow_ram_prepare.s
6bc3ab87ed137cdf2127baa37761ac7130a235b0
[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 .if .defined(__ATARIXL__)
13
14         .export         sramprep
15         .import         __SRPREP_LOAD__, __SRPREP_SIZE__
16         .import         __SHADOW_RAM_LOAD__, __SHADOW_RAM_SIZE__
17         .import         __SHADOW_RAM_RUN__
18         .import         __CHARGEN_START__, __CHARGEN_SIZE__
19         .import         __SAVEAREA_LOAD__
20         .import         zpsave
21
22         .include        "zeropage.inc"
23         .include        "atari.inc"
24         .include        "save_area.inc"
25
26 .macro print_string text
27         .local  start, cont
28         jmp     cont
29 start:  .byte   text, ATEOL
30 cont:   ldx     #0              ; channel 0
31         lda     #<start
32         sta     ICBAL,x         ; address
33         lda     #>start
34         sta     ICBAH,x
35         lda     #<(cont - start)
36         sta     ICBLL,x         ; length
37         lda     #>(cont - start)
38         sta     ICBLH,x
39         lda     #PUTCHR
40         sta     ICCOM,x
41         jsr     CIOV_org
42 .endmacro
43
44 ; ------------------------------------------------------------------------
45 ; Chunk header
46
47 .segment        "SRPREPHDR"
48
49         .word   __SRPREP_LOAD__
50         .word   __SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__ - 1
51
52 ; ------------------------------------------------------------------------
53 ; Actual code
54
55 .segment        "SRPREP"
56
57 sramprep:
58         print_string "in sramprep"
59
60 ; save values of modified system variables and ports
61
62         lda     RAMTOP
63         sta     RAMTOP_save
64         lda     MEMTOP
65         sta     MEMTOP_save
66         lda     MEMTOP+1
67         sta     MEMTOP_save+1
68         lda     APPMHI
69         sta     APPMHI_save
70         lda     APPMHI+1
71         sta     APPMHI_save+1
72         lda     PORTB
73         sta     PORTB_save
74         lda     CIOV            ; zero-page wrapper
75         sta     ZP_CIOV_save
76         lda     CIOV+1
77         sta     ZP_CIOV_save+1
78         lda     CIOV+2
79         sta     ZP_CIOV_save+2
80         lda     SIOV            ; zero-page wrapper
81         sta     ZP_SIOV_save
82         lda     SIOV+1
83         sta     ZP_SIOV_save+1
84         lda     SIOV+2
85         sta     ZP_SIOV_save+2
86
87         lda     $fffe
88         sta     IRQ_save
89         lda     $ffff
90         sta     IRQ_save+1
91         lda     $fffc
92         sta     RESET_save
93         lda     $fffd
94         sta     RESET_save+1
95         lda     $fffa
96         sta     NMI_save
97         lda     $fffb
98         sta     NMI_save+1
99
100 ; disable BASIC
101
102         lda     PORTB
103         ora     #2
104         sta     PORTB
105
106
107 ; ... change system memory variables bla
108
109 CMPVAL = 64+255+992             ; you may ask, why these values...   @@@ document
110
111 sys_ok: lda     #<__SAVEAREA_LOAD__
112         sec
113         sbc     #<CMPVAL
114         sta     MEMTOP
115         sta     APPMHI
116         lda     #>__SAVEAREA_LOAD__
117         sbc     #>CMPVAL
118         sta     MEMTOP+1
119         sta     APPMHI+1
120
121         lda     #>__SAVEAREA_LOAD__ - 1
122         sta     RAMTOP
123
124
125
126 ; ... issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers)
127
128
129         ldx     #$50            ; take any IOCB, hopefully free (@@@ fixme)
130
131         ; Reopen it in Graphics 0
132         lda     #OPEN
133         sta     ICCOM,x
134         lda     #OPNIN | OPNOT
135         sta     ICAX1,x
136         lda     #0
137         sta     ICAX2,x
138         lda     #<screen_device
139         sta     ICBAL,x
140         lda     #>screen_device
141         sta     ICBAH,x
142         lda     #<screen_device_length
143         sta     ICBLL,x
144         lda     #>screen_device_length
145         sta     ICBLH,x
146         jsr     CIOV_org
147         bpl     okoko
148
149         print_string "GR 0 FAILED"
150         jsr     delay
151         jsr     delay
152         jsr     delay
153
154         jmp     (DOSVEC)                ; abort loading
155
156
157 okoko:
158
159
160         ; Now close it again; we don't need it anymore :)
161         lda     #CLOSE
162         sta     ICCOM,x
163         jsr     CIOV_org
164
165         print_string "GR 0 OKOKO"
166         jsr     delay
167
168
169 ; Save the zero page locations we need
170
171         ldx     #zpspace-1
172 L1:     lda     sp,x
173         sta     zpsave,x
174         dex
175         bpl     L1
176
177 ; copy chargen to low memory
178
179         lda     #>(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
180         sta     ptr3+1
181         lda     #<(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
182         sta     ptr3
183         beq     cg_addr_ok
184
185         ; page align the new chargen address
186         inc     ptr3+1
187         lda     #0
188         sta     ptr3
189
190 cg_addr_ok:
191         lda     #<DCSORG
192         sta     ptr1
193         lda     #>DCSORG
194         sta     ptr1+1
195         lda     ptr3
196         sta     ptr2
197         lda     ptr3+1
198         sta     ptr2+1
199         lda     #>__CHARGEN_SIZE__
200         sta     tmp2
201         lda     #<__CHARGEN_SIZE__
202         sta     tmp2+1
203         jsr     memcopy
204
205 ; TODO: switch to this temp. chargen
206
207 ; disable ROMs
208         sei
209         ldx     #0
210         stx     NMIEN           ; disable NMI
211         lda     PORTB
212         and     #$fe
213         sta     PORTB           ; now ROM is mapped out
214
215 ; copy shadow RAM contents to their destination
216
217         lda     #<__SHADOW_RAM_SIZE__
218         bne     do_copy
219         lda     #>__SHADOW_RAM_SIZE__
220         beq     no_copy                         ; we have no shadow RAM contents
221
222         ; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
223 do_copy:lda     #<__SHADOW_RAM_LOAD__
224         sta     ptr1
225         lda     #>__SHADOW_RAM_LOAD__
226         sta     ptr1+1
227         lda     #<__SHADOW_RAM_RUN__
228         sta     ptr2
229         lda     #>__SHADOW_RAM_RUN__
230         sta     ptr2+1
231         lda     #<__SHADOW_RAM_SIZE__
232         sta     tmp1
233         lda     #>__SHADOW_RAM_SIZE__
234         sta     tmp2
235
236         jsr     memcopy
237
238 no_copy:
239
240 ; copy chargen to its new location
241
242         lda     ptr3
243         sta     ptr1
244         lda     ptr3+1
245         sta     ptr1+1
246         lda     #<__CHARGEN_START__
247         sta     ptr2
248         lda     #>__CHARGEN_START__
249         sta     ptr2+1
250         lda     #>__CHARGEN_SIZE__
251         sta     tmp2
252         lda     #<__CHARGEN_SIZE__
253         sta     tmp1
254         jsr     memcopy
255
256 ; re-enable ROM
257
258         lda     PORTB
259         ora     #1
260         sta     PORTB
261         lda     #$40
262         sta     NMIEN                   ; enable VB again
263         cli                             ; and enable IRQs
264
265         rts
266
267
268 ; my 6502 fu is rusty, so I took a routine from the internet (http://www.obelisk.demon.co.uk/6502/algorithms.html)
269
270 ; copy memory
271 ; ptr1      - source
272 ; ptr2      - destination
273 ; tmp2:tmp1 - len
274
275 .proc   memcopy
276
277         ldy     #0
278         ldx     tmp2
279         beq     last
280 pagecp: lda     (ptr1),y
281         sta     (ptr2),y
282         iny
283         bne     pagecp
284         inc     ptr1+1
285         inc     ptr2+1
286         dex
287         bne     pagecp
288 last:   cpy     tmp1
289         beq     done
290         lda     (ptr1),y
291         sta     (ptr2),y
292         iny
293         bne     last
294 done:   rts
295
296 .endproc
297
298
299 .byte "HERE ****************** HERE ***************>>>>>>"
300
301 sramsize:
302         .word   __SHADOW_RAM_SIZE__
303
304 ; short delay
305 .proc   delay
306
307         lda     #10
308 l:      jsr     delay1
309         clc
310         sbc     #0
311         bne     l
312         rts
313
314 delay1: ldx     #0
315         ldy     #0
316 loop:   dey
317         bne     loop
318         dex
319         bne     loop
320         rts
321
322 .endproc
323
324 screen_device:  .byte "S:",0
325 screen_device_length = * - screen_device
326
327         .byte   " ** srprep ** end-->"
328
329 ; ------------------------------------------------------------------------
330 ; Provide an empty SHADOW_RAM segment in order that the linker is happy
331 ; if the user program doesn't have a SHADOW_RAM segment.
332
333 .segment        "SHADOW_RAM"
334
335
336 ; ------------------------------------------------------------------------
337 ; Chunk "trailer" - sets INITAD
338
339 .segment        "SRPREPTRL"
340
341         .word   INITAD
342         .word   INITAD+1
343         .word   __SRPREP_LOAD__
344
345 .endif  ; .if .defined(__ATARIXL__)