]> git.sur5r.net Git - cc65/blob - libsrc/c64/c64-georam.s
No need to save the Y register in INSTALL.
[cc65] / libsrc / c64 / c64-georam.s
1 ;
2 ; Extended memory driver for the GEORAM cartridge. Driver works without
3 ; problems when statically linked.
4 ;
5 ; Ullrich von Bassewitz, 2002-11-29
6 ;
7 ; GEORAM page size checking routine by
8 ; Marco van den Heuvel, 2010-01-21
9 ;
10
11         .include        "zeropage.inc"
12
13         .include        "em-kernel.inc"
14         .include        "em-error.inc"
15
16
17         .macpack        generic
18
19
20 ; ------------------------------------------------------------------------
21 ; Header. Includes jump table
22
23 .segment        "JUMPTABLE"
24
25 ; Driver signature
26
27         .byte   $65, $6d, $64           ; "emd"
28         .byte   EMD_API_VERSION         ; EM API version number
29
30 ; Jump table.
31
32         .word   INSTALL
33         .word   UNINSTALL
34         .word   PAGECOUNT
35         .word   MAP
36         .word   USE
37         .word   COMMIT
38         .word   COPYFROM
39         .word   COPYTO
40
41 ; ------------------------------------------------------------------------
42 ; Constants
43
44 GR_WINDOW       = $DE00                 ; Address of GEORAM window
45 GR_PAGE_LO      = $DFFE                 ; Page register low
46 GR_PAGE_HI      = $DFFF                 ; Page register high
47
48 ; ------------------------------------------------------------------------
49 ; Data.
50
51 .data
52
53 pagecount:      .res    2               ; Number of available pages
54
55 .code
56
57 ; ------------------------------------------------------------------------
58 ; INSTALL routine. Is called after the driver is loaded into memory. If
59 ; possible, check if the hardware is present and determine the amount of
60 ; memory available.
61 ; Must return an EM_ERR_xx code in a/x.
62 ;
63
64 INSTALL:
65         ldx     GR_WINDOW
66         cpx     GR_WINDOW
67         bne     @notpresent
68         inc     GR_WINDOW
69         cpx     GR_WINDOW
70         beq     @notpresent
71
72         lda     #4
73         jsr     check
74         cpy     GR_WINDOW
75         beq     @has64k
76         lda     #8
77         jsr     check
78         cpy     GR_WINDOW
79         beq     @has128k
80         lda     #16
81         jsr     check
82         cpy     GR_WINDOW
83         beq     @has256k
84         lda     #32
85         jsr     check
86         cpy     GR_WINDOW
87         beq     @has512k
88         lda     #64
89         jsr     check
90         cpy     GR_WINDOW
91         beq     @has1024k
92         lda     #128
93         jsr     check
94         cpy     GR_WINDOW
95         beq     @has2048k
96         ldx     #>16384
97         bne     @setok
98
99 @has64k:
100         ldx     #>256
101         bne     @setok
102 @has128k:
103         ldx     #>512
104         bne     @setok
105 @has256k:
106         ldx     #>1024
107         bne     @setok
108 @has512k:
109         ldx     #>2048
110         bne     @setok
111 @has1024k:
112         ldx     #>4096
113         bne     @setok
114 @has2048k:
115         ldx     #>8192
116         bne     @setok
117
118 @notpresent:
119         lda     #<EM_ERR_NO_DEVICE
120         ldx     #>EM_ERR_NO_DEVICE
121         rts
122
123 @setok:
124         lda     #0
125         sta     pagecount
126         stx     pagecount+1
127         lda     #<EM_ERR_OK
128         ldx     #>EM_ERR_OK
129         rts
130
131 check:
132         ldx     #0
133         stx     GR_PAGE_LO
134         stx     GR_PAGE_HI
135         ldy     GR_WINDOW
136         iny
137         sta     GR_PAGE_HI
138         sty     GR_WINDOW
139         ldx     #0
140         stx     GR_PAGE_HI
141 ;       rts                     ; Run into UNINSTALL instead
142
143 ; ------------------------------------------------------------------------
144 ; UNINSTALL routine. Is called before the driver is removed from memory.
145 ; Can do cleanup or whatever. Must not return anything.
146 ;
147
148 UNINSTALL:
149         rts
150
151
152 ; ------------------------------------------------------------------------
153 ; PAGECOUNT: Return the total number of available pages in a/x.
154 ;
155
156 PAGECOUNT:
157         lda     pagecount
158         ldx     pagecount+1
159         rts
160
161 ; ------------------------------------------------------------------------
162 ; USE: Tell the driver that the window is now associated with a given page.
163 ; The GeoRAM cartridge does not copy but actually map the window, so USE is
164 ; identical to MAP.
165
166 USE     = MAP
167
168 ; ------------------------------------------------------------------------
169 ; MAP: Map the page in a/x into memory and return a pointer to the page in
170 ; a/x. The contents of the currently mapped page (if any) may be discarded
171 ; by the driver.
172 ;
173
174 MAP:    sta     tmp1
175         txa
176         asl     tmp1
177         rol     a
178         asl     tmp1
179         rol     a
180
181         sta     GR_PAGE_HI
182         lda     tmp1
183         lsr     a
184         lsr     a
185         sta     GR_PAGE_LO
186
187         lda     #<GR_WINDOW
188         ldx     #>GR_WINDOW
189
190 ; Use the RTS from COMMIT below to save a precious byte of storage
191
192 ; ------------------------------------------------------------------------
193 ; COMMIT: Commit changes in the memory window to extended storage.
194
195 COMMIT: rts
196
197 ; ------------------------------------------------------------------------
198 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
199 ; describing the request is passed in a/x.
200 ; The function must not return anything.
201 ;
202
203 COPYFROM:
204         jsr     setup
205
206 ; Setup is:
207 ;
208 ;   - ptr1 contains the struct pointer
209 ;   - ptr2 contains the linear memory buffer
210 ;   - ptr3 contains -(count-1)
211 ;   - tmp1 contains the low page register value
212 ;   - tmp2 contains the high page register value
213 ;   - X contains the page offset
214 ;   - Y contains zero
215
216         jmp     @L5
217
218 @L1:    lda     GR_WINDOW,x
219         sta     (ptr2),y
220         iny
221         bne     @L2
222         inc     ptr2+1
223 @L2:    inx
224         beq     @L4
225
226 ; Bump count and repeat
227
228 @L3:    inc     ptr3
229         bne     @L1
230         inc     ptr3+1
231         bne     @L1
232         rts
233
234 ; Bump page register
235
236 @L4:    inc     tmp1            ; Bump low page register
237         bit     tmp1            ; Check for overflow in bit 6
238         bvc     @L6             ; Jump if no overflow
239         inc     tmp2
240 @L5:    lda     tmp2
241         sta     GR_PAGE_HI
242 @L6:    lda     tmp1
243         sta     GR_PAGE_LO
244         jmp     @L3
245
246 ; ------------------------------------------------------------------------
247 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
248 ; describing the request is passed in a/x.
249 ; The function must not return anything.
250 ;
251
252 COPYTO:
253         jsr     setup
254
255 ; Setup is:
256 ;
257 ;   - ptr1 contains the struct pointer
258 ;   - ptr2 contains the linear memory buffer
259 ;   - ptr3 contains -(count-1)
260 ;   - tmp1 contains the low page register value
261 ;   - tmp2 contains the high page register value
262 ;   - X contains the page offset
263 ;   - Y contains zero
264
265         jmp     @L5
266
267 @L1:    lda     (ptr2),y
268         sta     GR_WINDOW,x
269         iny
270         bne     @L2
271         inc     ptr2+1
272 @L2:    inx
273         beq     @L4
274
275 ; Bump count and repeat
276
277 @L3:    inc     ptr3
278         bne     @L1
279         inc     ptr3+1
280         bne     @L1
281         rts
282
283 ; Bump page register
284
285 @L4:    inc     tmp1            ; Bump low page register
286         bit     tmp1            ; Check for overflow in bit 6
287         bvc     @L6             ; Jump if no overflow
288         inc     tmp2
289 @L5:    lda     tmp2
290         sta     GR_PAGE_HI
291 @L6:    lda     tmp1
292         sta     GR_PAGE_LO
293         jmp     @L3
294
295 ; ------------------------------------------------------------------------
296 ; Helper function for COPYFROM and COPYTO: Store the pointer to the request
297 ; structure and prepare data for the copy
298
299 setup:  sta     ptr1
300         stx     ptr1+1          ; Save passed pointer
301
302 ; Get the page number from the struct and adjust it so that it may be used
303 ; with the hardware. That is: lower 6 bits in tmp1, high bits in tmp2.
304
305         ldy     #EM_COPY::PAGE+1
306         lda     (ptr1),y
307         sta     tmp2
308         dey
309         lda     (ptr1),y
310         asl     a
311         rol     tmp2
312         asl     a
313         rol     tmp2
314         lsr     a
315         lsr     a
316         sta     tmp1
317
318 ; Get the buffer pointer into ptr2
319
320         ldy     #EM_COPY::BUF
321         lda     (ptr1),y
322         sta     ptr2
323         iny
324         lda     (ptr1),y
325         sta     ptr2+1
326
327 ; Get the count, calculate -(count-1) and store it into ptr3
328
329         ldy     #EM_COPY::COUNT
330         lda     (ptr1),y
331         eor     #$FF
332         sta     ptr3
333         iny
334         lda     (ptr1),y
335         eor     #$FF
336         sta     ptr3+1
337
338 ; Get the page offset into X and clear Y
339
340         ldy     #EM_COPY::OFFS
341         lda     (ptr1),y
342         tax
343         ldy     #$00
344
345 ; Done
346
347         rts
348
349