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