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