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