]> git.sur5r.net Git - cc65/blob - libsrc/c64/emd/c64-ramcart.s
Merge pull request #504 from jedeoric/master
[cc65] / libsrc / c64 / emd / c64-ramcart.s
1 ;
2 ; Extended memory driver for the RamCart 64/128KB cartridge. Driver works
3 ; without problems when statically linked.
4 ; Code is based on GEORAM code by Ullrich von Bassewitz.
5 ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl>
6 ; 06,22.12.2002
7 ;
8
9
10         .include        "zeropage.inc"
11
12         .include        "em-kernel.inc"
13         .include        "em-error.inc"
14
15
16         .macpack        generic
17         .macpack        module
18
19
20 ; ------------------------------------------------------------------------
21 ; Header. Includes jump table
22
23         module_header   _c64_ramcart_emd
24
25 ; Driver signature
26
27         .byte   $65, $6d, $64           ; "emd"
28         .byte   EMD_API_VERSION         ; EM API version number
29
30 ; Library reference
31
32         .addr   $0000
33
34 ; Jump table
35
36         .addr   INSTALL
37         .addr   UNINSTALL
38         .addr   PAGECOUNT
39         .addr   MAP
40         .addr   USE
41         .addr   COMMIT
42         .addr   COPYFROM
43         .addr   COPYTO
44
45 ; ------------------------------------------------------------------------
46 ; Constants
47
48 RAMC_WINDOW       = $DF00                 ; Address of RamCart window
49 RAMC_PAGE_LO      = $DE00                 ; Page register low
50 RAMC_PAGE_HI      = $DE01                 ; Page register high (only for RC128)
51
52 ; ------------------------------------------------------------------------
53 ; Data.
54
55 .bss
56
57 pagecount:      .res    2               ; Number of available pages
58
59 .code
60
61 ; ------------------------------------------------------------------------
62 ; INSTALL routine. Is called after the driver is loaded into memory. If
63 ; possible, check if the hardware is present and determine the amount of
64 ; memory available.
65 ; Must return an EM_ERR_xx code in a/x.
66 ;
67
68 INSTALL:
69         ldx     RAMC_WINDOW
70         cpx     RAMC_WINDOW
71         bne     @notpresent
72
73         lda     #0
74         sta     RAMC_PAGE_LO
75         sta     RAMC_PAGE_HI
76         ldx     RAMC_WINDOW
77         cpx     RAMC_WINDOW
78         bne     @notpresent
79         lda     #2
80         sta     RAMC_WINDOW
81         cmp     RAMC_WINDOW
82         beq     @cont
83         cpx     RAMC_WINDOW
84         beq     @readonly
85 @cont:  ldy     #1
86         sty     RAMC_PAGE_HI
87         sty     RAMC_WINDOW
88         dey
89         sty     RAMC_PAGE_HI
90         iny
91         cpy     RAMC_WINDOW
92         beq     @rc64
93         ; we're on rc128
94         ldx     #>512
95         bne     @setsize
96 @rc64:  ldx     #>256
97 @setsize:
98         lda     #0
99         sta     pagecount
100         stx     pagecount+1
101         lda     #<EM_ERR_OK
102         ldx     #>EM_ERR_OK
103         rts
104 @notpresent:
105 @readonly:
106         lda     #<EM_ERR_NO_DEVICE
107         ldx     #>EM_ERR_NO_DEVICE
108 ;       rts                             ; Run into UNINSTALL instead
109
110 ; ------------------------------------------------------------------------
111 ; UNINSTALL routine. Is called before the driver is removed from memory.
112 ; Can do cleanup or whatever. Must not return anything.
113 ;
114
115 UNINSTALL:
116         rts
117
118
119 ; ------------------------------------------------------------------------
120 ; PAGECOUNT: Return the total number of available pages in a/x.
121 ;
122
123 PAGECOUNT:
124         lda     pagecount
125         ldx     pagecount+1
126         rts
127
128 ; ------------------------------------------------------------------------
129 ; USE: Tell the driver that the window is now associated with a given page.
130 ; The RamCart cartridge does not copy but actually map the window, so USE is
131 ; identical to MAP.
132
133 USE     = MAP
134
135
136 ; ------------------------------------------------------------------------
137 ; MAP: Map the page in a/x into memory and return a pointer to the page in
138 ; a/x. The contents of the currently mapped page (if any) may be discarded
139 ; by the driver.
140 ;
141
142 MAP:    sta     RAMC_PAGE_LO
143         stx     RAMC_PAGE_HI
144         lda     #<RAMC_WINDOW
145         ldx     #>RAMC_WINDOW
146
147 ; Use the RTS from COMMIT below to save a precious byte of storage
148
149 ; ------------------------------------------------------------------------
150 ; COMMIT: Commit changes in the memory window to extended storage.
151
152 COMMIT: rts
153
154 ; ------------------------------------------------------------------------
155 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
156 ; describing the request is passed in a/x.
157 ; The function must not return anything.
158 ;
159
160 COPYFROM:
161         jsr     setup
162
163 ; Setup is:
164 ;
165 ;   - ptr1 contains the struct pointer
166 ;   - ptr2 contains the linear memory buffer
167 ;   - ptr3 contains -(count-1)
168 ;   - tmp1 contains the low page register value
169 ;   - tmp2 contains the high page register value
170 ;   - X contains the page offset
171 ;   - Y contains zero
172
173         jmp     @L5
174
175 @L1:    lda     RAMC_WINDOW,x
176         sta     (ptr2),y
177         iny
178         bne     @L2
179         inc     ptr2+1
180 @L2:    inx
181         beq     @L4
182
183 ; Bump count and repeat
184
185 @L3:    inc     ptr3
186         bne     @L1
187         inc     ptr3+1
188         bne     @L1
189         rts
190
191 ; Bump page register
192
193 @L4:    inc     tmp1
194         bne     @L5
195         inc     tmp2
196 @L5:    lda     tmp1
197         sta     RAMC_PAGE_LO
198         lda     tmp2
199         sta     RAMC_PAGE_HI
200         jmp     @L3
201
202 ; ------------------------------------------------------------------------
203 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
204 ; describing the request is passed in a/x.
205 ; The function must not return anything.
206 ;
207
208 COPYTO:
209         jsr     setup
210
211 ; Setup is:
212 ;
213 ;   - ptr1 contains the struct pointer
214 ;   - ptr2 contains the linear memory buffer
215 ;   - ptr3 contains -(count-1)
216 ;   - tmp1 contains the low page register value
217 ;   - tmp2 contains the high page register value
218 ;   - X contains the page offset
219 ;   - Y contains zero
220
221         jmp     @L5
222
223 @L1:    lda     (ptr2),y
224         sta     RAMC_WINDOW,x
225         iny
226         bne     @L2
227         inc     ptr2+1
228 @L2:    inx
229         beq     @L4
230
231 ; Bump count and repeat
232
233 @L3:    inc     ptr3
234         bne     @L1
235         inc     ptr3+1
236         bne     @L1
237         rts
238
239 ; Bump page register
240
241 @L4:    inc     tmp1
242         bne     @L5
243         inc     tmp2
244 @L5:    lda     tmp1
245         sta     RAMC_PAGE_LO
246         lda     tmp2
247         sta     RAMC_PAGE_HI
248         jmp     @L3
249
250 ; ------------------------------------------------------------------------
251 ; Helper function for COPYFROM and COPYTO: Store the pointer to the request
252 ; structure and prepare data for the copy
253
254 setup:  sta     ptr1
255         stx     ptr1+1          ; Save passed pointer
256
257 ; Get the page number from the struct and adjust it so that it may be used
258 ; with the hardware. That is: lower 6 bits in tmp1, high bits in tmp2.
259
260         ldy     #EM_COPY::PAGE+1
261         lda     (ptr1),y
262         sta     tmp2
263         dey
264         lda     (ptr1),y
265         sta     tmp1
266
267 ; Get the buffer pointer into ptr2
268
269         ldy     #EM_COPY::BUF
270         lda     (ptr1),y
271         sta     ptr2
272         iny
273         lda     (ptr1),y
274         sta     ptr2+1
275
276 ; Get the count, calculate -(count-1) and store it into ptr3
277
278         ldy     #EM_COPY::COUNT
279         lda     (ptr1),y
280         eor     #$FF
281         sta     ptr3
282         iny
283         lda     (ptr1),y
284         eor     #$FF
285         sta     ptr3+1
286
287 ; Get the page offset into X and clear Y
288
289         ldy     #EM_COPY::OFFS
290         lda     (ptr1),y
291         tax
292         ldy     #$00
293
294 ; Done
295
296         rts
297