]> git.sur5r.net Git - cc65/blob - libsrc/c64/emd/c64-65816.s
Merge remote-tracking branch 'refs/remotes/cc65/master' into doc-cc65-intern
[cc65] / libsrc / c64 / emd / c64-65816.s
1 ;\r
2 ; Extended memory driver for 65816 based extra RAM. Driver works without\r
3 ; problems when statically linked.\r
4 ;\r
5 ; Marco van den Heuvel, 2015-12-01\r
6 ;\r
7 \r
8         .include        "zeropage.inc"\r
9 \r
10         .include        "em-kernel.inc"\r
11         .include        "em-error.inc"\r
12 \r
13 \r
14         .macpack        generic\r
15         .macpack        module\r
16 \r
17 \r
18 ; ------------------------------------------------------------------------\r
19 ; Header. Includes jump table\r
20 \r
21         module_header   _c64_65816_emd\r
22 \r
23 ; Driver signature\r
24 \r
25         .byte   $65, $6d, $64           ; "emd"\r
26         .byte   EMD_API_VERSION         ; EM API version number\r
27 \r
28 ; Library reference\r
29 \r
30         .addr   $0000\r
31 \r
32 ; Jump table\r
33 \r
34         .addr   INSTALL\r
35         .addr   UNINSTALL\r
36         .addr   PAGECOUNT\r
37         .addr   MAP\r
38         .addr   USE\r
39         .addr   COMMIT\r
40         .addr   COPYFROM\r
41         .addr   COPYTO\r
42 \r
43 ; ------------------------------------------------------------------------\r
44 ; Data.\r
45 \r
46 .bss\r
47 isnotscpu:      .res    1               ; SuperCPU not present\r
48 curpage:        .res    1               ; Current page number\r
49 curbank:        .res    1               ; Current bank number (+1)\r
50 bankcount:      .res    1               ; Number of available banks (pages = banks * 256)\r
51 window:         .res    256             ; Memory "window"\r
52 \r
53 .code\r
54 \r
55 ; ------------------------------------------------------------------------\r
56 ; INSTALL routine. Is called after the driver is loaded into memory. If\r
57 ; possible, check if the hardware is present and determine the amount of\r
58 ; memory available.\r
59 ; Must return an EM_ERR_xx code in a/x.\r
60 ;\r
61 \r
62 INSTALL:\r
63         sei\r
64         clc\r
65         sed\r
66         lda     #$99\r
67         adc     #$01                    ; on 65C02, 65SC02, 65CE02, 65802 and 65816 sets the zero flag correctly\r
68         cld\r
69         bne     @not_present\r
70         clc\r
71 .P816\r
72         sep     #$01                    ; nop #$01 on 65C02/65SC02 and lda ($01,s),y on 65CE02\r
73 .P02\r
74         bcc     @not_present\r
75         lda     $d0bc\r
76         and     #$80\r
77         sta     isnotscpu\r
78         lda     $07e8\r
79         pha                             ; save value incase it was used somewhere else\r
80         ldx     #$ff\r
81 @fillloop:                              ; fill from top (bank 255) to bottom\r
82         txa\r
83         pha\r
84 .P816\r
85         plb                             ; pull dbr\r
86 .P02\r
87         stx     $07e8\r
88         dex\r
89         cpx     #$ff\r
90         bne     @fillloop\r
91         inx\r
92 @compareloop:                           ; check from bottom to top\r
93         txa\r
94         pha\r
95 .P816\r
96         plb\r
97 .P02\r
98         cmp     $07e8\r
99         bne     @found_pages\r
100 .P816\r
101         inc\r
102 .P02\r
103         sta     $07e8\r
104         cmp     $07e8\r
105         bne     @found_pages\r
106         inx\r
107         bne     @compareloop\r
108 @found_pages:\r
109         dex\r
110         lda     #$00\r
111         pha\r
112 .P816\r
113         plb\r
114 .P02\r
115         pla\r
116         sta     $07e8\r
117         cli\r
118         lda     isnotscpu\r
119         bne     @noextradex\r
120         dex\r
121 @noextradex:\r
122         stx     bankcount\r
123         lda     #<EM_ERR_OK\r
124         ldx     #>EM_ERR_OK\r
125         rts\r
126 @not_present:\r
127         cli\r
128         lda     #<EM_ERR_NO_DEVICE\r
129         ldx     #>EM_ERR_NO_DEVICE\r
130 ;       rts                             ; Run into UNINSTALL instead\r
131 \r
132 \r
133 ; ------------------------------------------------------------------------\r
134 ; UNINSTALL routine. Is called before the driver is removed from memory.\r
135 ; Can do cleanup or whatever. Must not return anything.\r
136 ;\r
137 \r
138 UNINSTALL:\r
139         rts\r
140 \r
141 \r
142 ; ------------------------------------------------------------------------\r
143 ; PAGECOUNT: Return the total number of available pages in a/x.\r
144 ;\r
145 \r
146 PAGECOUNT:\r
147         lda     #$00                   ; a whole bank is either usable or not\r
148         ldx     bankcount\r
149         rts\r
150 \r
151 ; ------------------------------------------------------------------------\r
152 ; MAP: Map the page in a/x into memory and return a pointer to the page in\r
153 ; a/x. The contents of the currently mapped page (if any) may be discarded\r
154 ; by the driver.\r
155 ;\r
156 \r
157 MAP:    sta     curpage                 ; Remember the new page\r
158         stx     curbank                 ; Remember the new bank\r
159 \r
160         sta     ptr2+1                  ; src address low\r
161         lda     #$00\r
162         sta     ptr2                    ; src address high\r
163         inx\r
164         ldy     isnotscpu               ; check if not scpu\r
165         bne     @notscpu\r
166         inx\r
167 @notscpu:\r
168         stx     tmp2                    ; src bank\r
169 \r
170         sta     tmp1                    ; dst bank\r
171 \r
172         sta     ptr3+1                  ; length high\r
173         lda     #$ff\r
174         sta     ptr3                    ; length low\r
175 \r
176         lda     #<window\r
177         sta     ptr1                    ; dst address low\r
178         ldx     #>window\r
179         stx     ptr1+1                  ; dst address high\r
180 \r
181         jsr     transfer\r
182 \r
183         rts\r
184 \r
185 ; ------------------------------------------------------------------------\r
186 ; USE: Tell the driver that the window is now associated with a given page.\r
187 \r
188 USE:    sta     curpage                 ; Remember the page\r
189         stx     curbank                 ; Remember the bank\r
190         lda     #<window\r
191         ldx     #>window                ; Return the window\r
192         rts\r
193 \r
194 ; ------------------------------------------------------------------------\r
195 ; COMMIT: Commit changes in the memory window to extended storage.\r
196 \r
197 COMMIT: lda     curpage                 ; Get the current page\r
198         sta     ptr1+1                  ; dst high\r
199         ldx     #$00\r
200         stx     ptr1                    ; dst low\r
201 \r
202         lda     #<window\r
203         sta     ptr2                    ; src low\r
204         lda     #>window\r
205         sta     ptr2+1                  ; src high\r
206 \r
207         stx     ptr3+1                  ; length high\r
208         lda     #$ff\r
209         sta     ptr3                    ; length low\r
210 \r
211         stx     tmp2                    ; src bank\r
212         ldy     curbank                 ; Get the current bank\r
213         iny\r
214         ldx     isnotscpu\r
215         bne     @notascpu\r
216         iny\r
217 @notascpu:\r
218         sty     tmp1                    ; dst bank\r
219 \r
220         jsr     transfer\r
221 \r
222         rts\r
223 \r
224 ; ------------------------------------------------------------------------\r
225 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure\r
226 ; describing the request is passed in a/x.\r
227 ; The function must not return anything.\r
228 ;\r
229 \r
230 COPYFROM:\r
231         sta     ptr4\r
232         stx     ptr4+1                  ; Save the passed em_copy pointer\r
233 \r
234         ldy     #EM_COPY::COUNT+1       ; start at the end of the struct\r
235         lda     (ptr4),y                ; get high byte of count\r
236         tax\r
237         dey\r
238         lda     (ptr4),y                ; get low byte of count\r
239         bne     @nodex\r
240         dex\r
241 @nodex:\r
242 .P816\r
243         dec\r
244 .P02\r
245         sta     ptr3                    ; length low\r
246         stx     ptr3+1                  ; length high\r
247         dey\r
248         lda     (ptr4),y                ; get bank\r
249 .P816\r
250         inc\r
251 .P02\r
252         ldx     isnotscpu\r
253         bne     @notscpu64\r
254 .P816\r
255         inc\r
256 .P02\r
257 @notscpu64:\r
258         sta     tmp2                    ; src bank\r
259         dey\r
260         lda     (ptr4),y                ; get page\r
261         sta     ptr2+1                  ; src high\r
262         dey\r
263         lda     (ptr4),y                ; get offset in page\r
264         sta     ptr2                    ; src low\r
265         dey\r
266         lda     (ptr4),y                ; get memory buffer high\r
267         sta     ptr1+1                  ; dst high\r
268         dey\r
269         lda     (ptr4),y                ; get memory buffer low\r
270         sta     ptr1                    ; dst low\r
271         lda     #$00\r
272         sta     tmp1                    ; dst bank\r
273 \r
274         jsr     transfer\r
275 \r
276         rts\r
277 \r
278 ; ------------------------------------------------------------------------\r
279 ; COPYTO: Copy from linear into extended memory. A pointer to a structure\r
280 ; describing the request is passed in a/x.\r
281 ; The function must not return anything.\r
282 ;\r
283 \r
284 COPYTO: sta     ptr4\r
285         stx     ptr4+1                  ; Save the passed em_copy pointer\r
286 \r
287         ldy     #EM_COPY::COUNT+1       ; start at the end of the struct\r
288         lda     (ptr4),y                ; get high byte of count\r
289         tax\r
290         dey\r
291         lda     (ptr4),y                ; get low byte of count\r
292         bne     @nodex2\r
293         dex\r
294 @nodex2:\r
295 .P816\r
296         dec\r
297 .P02\r
298         sta     ptr3                    ; length low\r
299         txa\r
300         sta     ptr3+1                  ; length high\r
301         dey\r
302         lda     (ptr4),y                ; get bank\r
303 .P816\r
304         inc\r
305 .P02\r
306         ldx     isnotscpu\r
307         bne     @notascpu64\r
308 .P816\r
309         inc\r
310 .P02\r
311 @notascpu64:\r
312         sta     tmp1                    ; dst bank\r
313         dey\r
314         lda     (ptr4),y                ; get page\r
315         sta     ptr1+1                  ; dst high\r
316         dey\r
317         lda     (ptr4),y                ; get page offset\r
318         sta     ptr1                    ; dst low\r
319         dey\r
320         lda     (ptr4),y                ; get memory buffer high\r
321         sta     ptr2+1                  ; src low\r
322         dey\r
323         lda     (ptr4),y                ; get memory buffer low\r
324         sta     ptr2                    ; src high\r
325         lda     #$00\r
326         sta     tmp2                    ; src bank\r
327 \r
328         jsr     transfer\r
329 \r
330         rts\r
331 \r
332 ; ------------------------------------------------------------------------\r
333 ; Helper function for moving a block, the following is used:\r
334 ; ptr1: dst\r
335 ; ptr2: src\r
336 ; ptr3: length\r
337 ; tmp1: dst bank\r
338 ; tmp2: src bank\r
339 \r
340 transfer:\r
341 .P816\r
342 .A8\r
343 .I8\r
344         sei\r
345         pha\r
346         phx\r
347         phy\r
348         ldx     tmp1                    ; load srcbank\r
349         stx     @move+1                 ; store srcbank in move + 1\r
350         ldy     tmp2                    ; load dstbank\r
351         sty     @move+2                 ; store dstbank in move + 2\r
352         clc                             ; switch to native mode\r
353         xce\r
354         php                             ; save status bits\r
355         rep     #%00110000              ; set A and index to 16bit\r
356 .A16\r
357 .I16\r
358         ldy     ptr1\r
359         ldx     ptr2\r
360         lda     ptr3\r
361 @move:\r
362         mvn 0,0\r
363         plp                             ; restore status bits\r
364 .A8\r
365 .I8\r
366         lda     #$00\r
367         pha\r
368         plb                             ; restore dbr\r
369         sec\r
370         xce                             ; switch to emul mode\r
371         ply\r
372         plx\r
373         pla\r
374         cli\r
375         rts\r
376 .P02\r