]> git.sur5r.net Git - cc65/blob - libsrc/c64/c64-georam.s
Added size checking routine contributed by Marco van den Heuvel.
[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         tya
66         pha
67         ldx     GR_WINDOW
68         cpx     GR_WINDOW
69         bne     @notpresent
70         inc     GR_WINDOW
71         cpx     GR_WINDOW
72         beq     @notpresent
73
74         lda     #4
75         jsr     check
76         cpy     GR_WINDOW
77         beq     @has64k
78         lda     #8
79         jsr     check
80         cpy     GR_WINDOW
81         beq     @has128k
82         lda     #16
83         jsr     check
84         cpy     GR_WINDOW
85         beq     @has256k
86         lda     #32
87         jsr     check
88         cpy     GR_WINDOW
89         beq     @has512k
90         lda     #64
91         jsr     check
92         cpy     GR_WINDOW
93         beq     @has1024k
94         lda     #128
95         jsr     check
96         cpy     GR_WINDOW
97         beq     @has2048k
98         ldx     #>16384
99         bne     @setok
100
101 @has64k:
102         ldx     #>256
103         bne     @setok
104 @has128k:
105         ldx     #>512
106         bne     @setok
107 @has256k:
108         ldx     #>1024
109         bne     @setok
110 @has512k:
111         ldx     #>2048
112         bne     @setok
113 @has1024k:
114         ldx     #>4096
115         bne     @setok
116 @has2048k:
117         ldx     #>8192
118         bne     @setok
119
120 @notpresent:
121         pla
122         tay
123         lda     #<EM_ERR_NO_DEVICE
124         ldx     #>EM_ERR_NO_DEVICE
125         rts
126
127 @setok:
128         lda     #0
129         sta     pagecount
130         stx     pagecount+1
131         pla
132         tay
133         lda     #<EM_ERR_OK
134         ldx     #>EM_ERR_OK
135         rts
136
137 check:
138         ldx     #0
139         stx     GR_PAGE_LO
140         stx     GR_PAGE_HI
141         ldy     GR_WINDOW
142         iny
143         sta     GR_PAGE_HI
144         sty     GR_WINDOW
145         ldx     #0
146         stx     GR_PAGE_HI
147 ;       rts                     ; Run into UNINSTALL instead
148
149 ; ------------------------------------------------------------------------
150 ; UNINSTALL routine. Is called before the driver is removed from memory.
151 ; Can do cleanup or whatever. Must not return anything.
152 ;
153
154 UNINSTALL:
155         rts
156
157
158 ; ------------------------------------------------------------------------
159 ; PAGECOUNT: Return the total number of available pages in a/x.
160 ;
161
162 PAGECOUNT:
163         lda     pagecount
164         ldx     pagecount+1
165         rts
166
167 ; ------------------------------------------------------------------------
168 ; USE: Tell the driver that the window is now associated with a given page.
169 ; The GeoRAM cartridge does not copy but actually map the window, so USE is
170 ; identical to MAP.
171
172 USE     = MAP
173
174 ; ------------------------------------------------------------------------
175 ; MAP: Map the page in a/x into memory and return a pointer to the page in
176 ; a/x. The contents of the currently mapped page (if any) may be discarded
177 ; by the driver.
178 ;
179
180 MAP:    sta     tmp1
181         txa
182         asl     tmp1
183         rol     a
184         asl     tmp1
185         rol     a
186
187         sta     GR_PAGE_HI
188         lda     tmp1
189         lsr     a
190         lsr     a
191         sta     GR_PAGE_LO
192
193         lda     #<GR_WINDOW
194         ldx     #>GR_WINDOW
195
196 ; Use the RTS from COMMIT below to save a precious byte of storage
197
198 ; ------------------------------------------------------------------------
199 ; COMMIT: Commit changes in the memory window to extended storage.
200
201 COMMIT: rts
202
203 ; ------------------------------------------------------------------------
204 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
205 ; describing the request is passed in a/x.
206 ; The function must not return anything.
207 ;
208
209 COPYFROM:
210         jsr     setup
211
212 ; Setup is:
213 ;
214 ;   - ptr1 contains the struct pointer
215 ;   - ptr2 contains the linear memory buffer
216 ;   - ptr3 contains -(count-1)
217 ;   - tmp1 contains the low page register value
218 ;   - tmp2 contains the high page register value
219 ;   - X contains the page offset
220 ;   - Y contains zero
221
222         jmp     @L5
223
224 @L1:    lda     GR_WINDOW,x
225         sta     (ptr2),y
226         iny
227         bne     @L2
228         inc     ptr2+1
229 @L2:    inx
230         beq     @L4
231
232 ; Bump count and repeat
233
234 @L3:    inc     ptr3
235         bne     @L1
236         inc     ptr3+1
237         bne     @L1
238         rts
239
240 ; Bump page register
241
242 @L4:    inc     tmp1            ; Bump low page register
243         bit     tmp1            ; Check for overflow in bit 6
244         bvc     @L6             ; Jump if no overflow
245         inc     tmp2
246 @L5:    lda     tmp2
247         sta     GR_PAGE_HI
248 @L6:    lda     tmp1
249         sta     GR_PAGE_LO
250         jmp     @L3
251
252 ; ------------------------------------------------------------------------
253 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
254 ; describing the request is passed in a/x.
255 ; The function must not return anything.
256 ;
257
258 COPYTO:
259         jsr     setup
260
261 ; Setup is:
262 ;
263 ;   - ptr1 contains the struct pointer
264 ;   - ptr2 contains the linear memory buffer
265 ;   - ptr3 contains -(count-1)
266 ;   - tmp1 contains the low page register value
267 ;   - tmp2 contains the high page register value
268 ;   - X contains the page offset
269 ;   - Y contains zero
270
271         jmp     @L5
272
273 @L1:    lda     (ptr2),y
274         sta     GR_WINDOW,x
275         iny
276         bne     @L2
277         inc     ptr2+1
278 @L2:    inx
279         beq     @L4
280
281 ; Bump count and repeat
282
283 @L3:    inc     ptr3
284         bne     @L1
285         inc     ptr3+1
286         bne     @L1
287         rts
288
289 ; Bump page register
290
291 @L4:    inc     tmp1            ; Bump low page register
292         bit     tmp1            ; Check for overflow in bit 6
293         bvc     @L6             ; Jump if no overflow
294         inc     tmp2
295 @L5:    lda     tmp2
296         sta     GR_PAGE_HI
297 @L6:    lda     tmp1
298         sta     GR_PAGE_LO
299         jmp     @L3
300
301 ; ------------------------------------------------------------------------
302 ; Helper function for COPYFROM and COPYTO: Store the pointer to the request
303 ; structure and prepare data for the copy
304
305 setup:  sta     ptr1
306         stx     ptr1+1          ; Save passed pointer
307
308 ; Get the page number from the struct and adjust it so that it may be used
309 ; with the hardware. That is: lower 6 bits in tmp1, high bits in tmp2.
310
311         ldy     #EM_COPY::PAGE+1
312         lda     (ptr1),y
313         sta     tmp2
314         dey
315         lda     (ptr1),y
316         asl     a
317         rol     tmp2
318         asl     a
319         rol     tmp2
320         lsr     a
321         lsr     a
322         sta     tmp1
323
324 ; Get the buffer pointer into ptr2
325
326         ldy     #EM_COPY::BUF
327         lda     (ptr1),y
328         sta     ptr2
329         iny
330         lda     (ptr1),y
331         sta     ptr2+1
332
333 ; Get the count, calculate -(count-1) and store it into ptr3
334
335         ldy     #EM_COPY::COUNT
336         lda     (ptr1),y
337         eor     #$FF
338         sta     ptr3
339         iny
340         lda     (ptr1),y
341         eor     #$FF
342         sta     ptr3+1
343
344 ; Get the page offset into X and clear Y
345
346         ldy     #EM_COPY::OFFS
347         lda     (ptr1),y
348         tax
349         ldy     #$00
350
351 ; Done
352
353         rts
354
355