2 ; Extended memory driver for 65816 based extra RAM. Driver works without
\r
3 ; problems when statically linked.
\r
5 ; Marco van den Heuvel, 2015-12-01
\r
8 .include "zeropage.inc"
\r
10 .include "em-kernel.inc"
\r
11 .include "em-error.inc"
\r
18 ; ------------------------------------------------------------------------
\r
19 ; Header. Includes jump table
\r
21 module_header _c64_65816_emd
\r
25 .byte $65, $6d, $64 ; "emd"
\r
26 .byte EMD_API_VERSION ; EM API version number
\r
43 ; ------------------------------------------------------------------------
\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
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
59 ; Must return an EM_ERR_xx code in a/x.
\r
67 adc #$01 ; on 65C02, 65SC02, 65CE02, 65802 and 65816 sets the zero flag correctly
\r
72 sep #$01 ; nop #$01 on 65C02/65SC02 and lda ($01,s),y on 65CE02
\r
79 pha ; save value incase it was used somewhere else
\r
81 @fillloop: ; fill from top (bank 255) to bottom
\r
92 @compareloop: ; check from bottom to top
\r
128 lda #<EM_ERR_NO_DEVICE
\r
129 ldx #>EM_ERR_NO_DEVICE
\r
130 ; rts ; Run into UNINSTALL instead
\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
142 ; ------------------------------------------------------------------------
\r
143 ; PAGECOUNT: Return the total number of available pages in a/x.
\r
147 lda #$00 ; a whole bank is either usable or not
\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
157 MAP: sta curpage ; Remember the new page
\r
158 stx curbank ; Remember the new bank
\r
160 sta ptr2+1 ; src address low
\r
162 sta ptr2 ; src address high
\r
164 ldy isnotscpu ; check if not scpu
\r
168 stx tmp2 ; src bank
\r
170 sta tmp1 ; dst bank
\r
172 sta ptr3+1 ; length high
\r
174 sta ptr3 ; length low
\r
177 sta ptr1 ; dst address low
\r
179 stx ptr1+1 ; dst address high
\r
185 ; ------------------------------------------------------------------------
\r
186 ; USE: Tell the driver that the window is now associated with a given page.
\r
188 USE: sta curpage ; Remember the page
\r
189 stx curbank ; Remember the bank
\r
191 ldx #>window ; Return the window
\r
194 ; ------------------------------------------------------------------------
\r
195 ; COMMIT: Commit changes in the memory window to extended storage.
\r
197 COMMIT: lda curpage ; Get the current page
\r
198 sta ptr1+1 ; dst high
\r
205 sta ptr2+1 ; src high
\r
207 stx ptr3+1 ; length high
\r
209 sta ptr3 ; length low
\r
211 stx tmp2 ; src bank
\r
212 ldy curbank ; Get the current bank
\r
218 sty tmp1 ; dst bank
\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
232 stx ptr4+1 ; Save the passed em_copy pointer
\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
238 lda (ptr4),y ; get low byte of count
\r
245 sta ptr3 ; length low
\r
246 stx ptr3+1 ; length high
\r
248 lda (ptr4),y ; get bank
\r
258 sta tmp2 ; src bank
\r
260 lda (ptr4),y ; get page
\r
261 sta ptr2+1 ; src high
\r
263 lda (ptr4),y ; get offset in page
\r
266 lda (ptr4),y ; get memory buffer high
\r
267 sta ptr1+1 ; dst high
\r
269 lda (ptr4),y ; get memory buffer low
\r
272 sta tmp1 ; dst bank
\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
285 stx ptr4+1 ; Save the passed em_copy pointer
\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
291 lda (ptr4),y ; get low byte of count
\r
298 sta ptr3 ; length low
\r
300 sta ptr3+1 ; length high
\r
302 lda (ptr4),y ; get bank
\r
312 sta tmp1 ; dst bank
\r
314 lda (ptr4),y ; get page
\r
315 sta ptr1+1 ; dst high
\r
317 lda (ptr4),y ; get page offset
\r
320 lda (ptr4),y ; get memory buffer high
\r
321 sta ptr2+1 ; src low
\r
323 lda (ptr4),y ; get memory buffer low
\r
324 sta ptr2 ; src high
\r
326 sta tmp2 ; src bank
\r
332 ; ------------------------------------------------------------------------
\r
333 ; Helper function for moving a block, the following is used:
\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
354 php ; save status bits
\r
355 rep #%00110000 ; set A and index to 16bit
\r
363 plp ; restore status bits
\r
370 xce ; switch to emul mode
\r