]> git.sur5r.net Git - cc65/blob - libsrc/atari/shadow_ram_prepare.s
Merge pull request #56 from groessler/something_to_pull
[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 .ifdef __ATARIXL__
15
16         .export         sramprep
17         .import         __SRPREP_LOAD__, __SRPREPCHNK_LAST__
18         .import         __SHADOW_RAM_LOAD__, __SHADOW_RAM_SIZE__, __SHADOW_RAM_RUN__
19         .import         __SHADOW_RAM2_LOAD__, __SHADOW_RAM2_SIZE__, __SHADOW_RAM2_RUN__
20         .import         __CHARGEN_START__, __CHARGEN_SIZE__
21         .import         __STARTADDRESS__       ; needed by xlmemchk.inc
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 ; EXE load chunk header
47
48 .segment        "SRPREPHDR"
49
50         .word   __SRPREP_LOAD__
51         .word   __SRPREPCHNK_LAST__ - 1
52
53 ; ------------------------------------------------------------------------
54 ; Actual code
55
56 .segment        "SRPREP"
57
58 ; ***** entry point *****
59
60 sramprep:
61 .ifdef DEBUG
62         print_string "entering stage #2"
63 .endif
64
65 ; save values of modified system variables and ports
66
67         lda     RAMTOP
68         sta     RAMTOP_save
69         lda     MEMTOP
70         sta     MEMTOP_save
71         lda     MEMTOP+1
72         sta     MEMTOP_save+1
73         lda     APPMHI
74         sta     APPMHI_save
75         lda     APPMHI+1
76         sta     APPMHI_save+1
77         lda     PORTB
78         sta     PORTB_save
79
80 ; disable BASIC
81
82         lda     PORTB
83         ora     #2
84         sta     PORTB
85
86         .include "xlmemchk.inc" ; calculate lowest address used and new value for RAMTOP
87
88         ldx     lowadr
89         stx     MEMTOP
90         lda     lowadr+1
91         sta     MEMTOP+1
92         lda     lodadr+1
93         sta     RAMTOP
94
95         ; set APPMHI to MEMLO (+ 1 for sanity)
96         lda     MEMLO
97         clc
98         adc     #1
99         sta     APPMHI
100         lda     MEMLO+1
101         adc     #0
102         sta     APPMHI+1
103
104
105 ; issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers) to move screen memory down
106
107
108         jsr     findfreeiocb
109 .ifdef DEBUG            ; only check in debug version, this shouldn't really happen(tm)
110         beq     iocbok
111         print_string "Internal error, no free IOCB!"
112         jsr     delay
113         jsr     delay
114         jsr     delay
115         jsr     restore                 ; restore stuff we've changed
116         jmp     (DOSVEC)                ; abort loading
117 iocbok:
118 .endif
119
120         ; reopen it in Graphics 0
121         lda     #OPEN
122         sta     ICCOM,x
123         lda     #OPNIN | OPNOT
124         sta     ICAX1,x
125         lda     #0
126         sta     ICAX2,x
127         lda     #<screen_device
128         sta     ICBAL,x
129         lda     #>screen_device
130         sta     ICBAH,x
131         lda     #<screen_device_length
132         sta     ICBLL,x
133         lda     #>screen_device_length
134         sta     ICBLH,x
135         jsr     CIOV_org
136         bpl     scrok
137
138 ; shouldn't happen(tm)
139         print_string "Internal error, aborting..."
140         jsr     delay
141         jsr     delay
142         jsr     delay
143         jsr     restore                 ; restore stuff we've changed
144         jmp     (DOSVEC)                ; abort loading
145
146
147 scrok:  ; now close it again -- we don't need it anymore
148         lda     #CLOSE
149         sta     ICCOM,x
150         jsr     CIOV_org
151
152
153 ; copy chargen to low memory, just after the next possible address beyond our loaded chunk data
154
155 .ifdef DEBUG
156         print_string "copy chargen to low memory"
157 .endif
158
159         lda     #>__SRPREPCHNK_LAST__
160         sta     ptr3+1
161         lda     #<__SRPREPCHNK_LAST__
162         sta     ptr3
163         beq     cg_addr_ok
164
165         ; page align the new chargen address
166         inc     ptr3+1
167         lda     #0
168         sta     ptr3
169
170 cg_addr_ok:
171
172         lda     ptr3+1
173         and     #3
174         beq     cg_addr_ok2
175
176         ; align to next 1K boundary
177         lda     ptr3+1
178         and     #$fc
179         clc
180         adc     #4
181         sta     ptr3+1
182
183 cg_addr_ok2:
184
185         lda     #<DCSORG
186         sta     ptr1
187         lda     #>DCSORG
188         sta     ptr1+1
189         lda     ptr3
190         sta     ptr2
191         lda     ptr3+1
192         pha                             ; needed later to set CHBAS/CHBASE
193         sta     ptr2+1
194         lda     #>__CHARGEN_SIZE__
195         sta     tmp2
196         lda     #<__CHARGEN_SIZE__
197         sta     tmp1
198         jsr     memcopy
199
200 .ifdef DEBUG
201         print_string "now setting up high memory"
202 .endif
203
204 ; disable ROM
205         sei
206         ldx     #0
207         stx     NMIEN                   ; disable NMI
208         lda     PORTB
209         and     #$fe
210         tax
211         pla                             ; get temp. chargen address
212         sta     WSYNC                   ; wait for horiz. retrace
213         stx     PORTB                   ; now ROM is mapped out
214
215 ; switch to temporary chargen
216
217         sta     CHBASE
218         sta     CHBAS
219
220 ; copy shadow RAM contents to their destination (segment SHADOW_RAM)
221
222         lda     #<__SHADOW_RAM_SIZE__
223         bne     do_copy
224         lda     #>__SHADOW_RAM_SIZE__
225         beq     no_copy                 ; we have no shadow RAM contents
226
227         ; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
228 do_copy:lda     #<__SHADOW_RAM_LOAD__
229         sta     ptr1
230         lda     #>__SHADOW_RAM_LOAD__
231         sta     ptr1+1
232         lda     #<__SHADOW_RAM_RUN__
233         sta     ptr2
234         lda     #>__SHADOW_RAM_RUN__
235         sta     ptr2+1
236         lda     #<__SHADOW_RAM_SIZE__
237         sta     tmp1
238         lda     #>__SHADOW_RAM_SIZE__
239         sta     tmp2
240
241         jsr     memcopy
242
243 no_copy:
244
245 ; copy shadow RAM #2 contents to their destination (segment SHADOW_RAM2)
246
247         lda     #<__SHADOW_RAM2_SIZE__
248         bne     do_copy2
249         lda     #>__SHADOW_RAM2_SIZE__
250         beq     no_copy2                ; we have no shadow RAM #2 contents
251
252         ; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
253 do_copy2:
254         lda     #<__SHADOW_RAM2_LOAD__
255         sta     ptr1
256         lda     #>__SHADOW_RAM2_LOAD__
257         sta     ptr1+1
258         lda     #<__SHADOW_RAM2_RUN__
259         sta     ptr2
260         lda     #>__SHADOW_RAM2_RUN__
261         sta     ptr2+1
262         lda     #<__SHADOW_RAM2_SIZE__
263         sta     tmp1
264         lda     #>__SHADOW_RAM2_SIZE__
265         sta     tmp2
266
267         jsr     memcopy
268
269 no_copy2:
270
271 ; copy chargen to its new (final) location
272
273         lda     ptr3
274         sta     ptr1
275         lda     ptr3+1
276         sta     ptr1+1
277         lda     #<__CHARGEN_START__
278         sta     ptr2
279         lda     #>__CHARGEN_START__
280         sta     ptr2+1
281         lda     #>__CHARGEN_SIZE__
282         sta     tmp2
283         lda     #<__CHARGEN_SIZE__
284         sta     tmp1
285         jsr     memcopy
286
287 ; re-enable ROM
288
289         lda     PORTB
290         ora     #1
291         ldx     #>DCSORG
292         sta     WSYNC                   ; wait for horiz. retrace
293         sta     PORTB
294         stx     CHBASE
295         stx     CHBAS
296         lda     #$40
297         sta     NMIEN                   ; enable VB again
298         cli                             ; and enable IRQs
299
300 .ifdef DEBUG
301         print_string "Stage #2 OK"
302         print_string "loading main chunk"
303         jsr     delay
304 .endif
305         rts
306
307 .include "findfreeiocb.inc"
308
309 ; routine taken from http://www.obelisk.demon.co.uk/6502/algorithms.html
310 ;
311 ; copy memory
312 ; ptr1      - source
313 ; ptr2      - destination
314 ; tmp2:tmp1 - len
315
316 .proc   memcopy
317
318         ldy     #0
319         ldx     tmp2
320         beq     last
321 pagecp: lda     (ptr1),y
322         sta     (ptr2),y
323         iny
324         bne     pagecp
325         inc     ptr1+1
326         inc     ptr2+1
327         dex
328         bne     pagecp
329 last:   cpy     tmp1
330         beq     done
331         lda     (ptr1),y
332         sta     (ptr2),y
333         iny
334         bne     last
335 done:   rts
336
337 .endproc
338
339
340 ; clean up after a fatal error
341
342 restore:lda     RAMTOP_save
343         sta     RAMTOP
344         lda     MEMTOP_save
345         sta     MEMTOP
346         lda     MEMTOP_save+1
347         sta     MEMTOP+1
348         lda     APPMHI_save
349         sta     APPMHI
350         lda     APPMHI_save+1
351         sta     APPMHI+1
352         rts
353
354 ; short delay
355 .proc   delay
356
357         lda     #10
358 @loop:  jsr     delay1
359         clc
360         sbc     #0
361         bne     @loop
362         rts
363
364 delay1: ldx     #0
365         ldy     #0
366 @loop:   dey
367         bne     @loop
368         dex
369         bne     @loop
370         rts
371
372 .endproc
373
374 .ifdef DEBUG
375
376 .byte "HERE ****************** HERE ***************>>>>>>"
377
378 sramsize:
379         .word   __SHADOW_RAM_SIZE__
380
381 .endif          ; .ifdef DEBUG
382
383 screen_device:  .byte "S:",0
384 screen_device_length = * - screen_device
385
386 .ifdef DEBUG
387         .byte   " ** srprep ** end-->"
388 .endif
389
390 ; ------------------------------------------------------------------------
391 ; Provide empty SHADOW_RAM and SHADOW_RAM2 segments in order that the
392 ; linker is happy if the user program doesn't have these segments.
393
394 .segment        "SHADOW_RAM"
395 .segment        "SHADOW_RAM2"
396
397
398 ; ------------------------------------------------------------------------
399 ; EXE load chunk "trailer" - sets INITAD
400
401 .segment        "SRPREPTRL"
402
403         .word   INITAD
404         .word   INITAD+1
405         .word   sramprep
406
407 .endif  ; .ifdef __ATARIXL__