]> git.sur5r.net Git - cc65/blob - libsrc/c16/c16-ram.s
New EM driver for the C16
[cc65] / libsrc / c16 / c16-ram.s
1 ;
2 ; Extended memory driver for the C16 hidden RAM. Driver works without
3 ; problems when statically linked.
4 ;
5 ; Ullrich von Bassewitz, 2003-12-15
6 ;
7
8         .include        "zeropage.inc"
9
10         .include        "em-kernel.inc"
11         .include        "em-error.inc"
12         .include        "../plus4/plus4.inc"
13
14         .macpack        generic
15
16
17 ; ------------------------------------------------------------------------
18 ; Header. Includes jump table
19
20 .segment        "JUMPTABLE"
21
22 ; Driver signature
23
24         .byte   $65, $6d, $64           ; "emd"
25         .byte   $00                     ; EM API version number
26
27 ; Jump table.
28
29         .word   INSTALL
30         .word   UNINSTALL
31         .word   PAGECOUNT
32         .word   MAP
33         .word   USE
34         .word   COMMIT
35         .word   COPYFROM
36         .word   COPYTO
37
38 ; ------------------------------------------------------------------------
39 ; Constants
40
41 BASE    = $8000
42
43 ; ------------------------------------------------------------------------
44 ; Data.
45
46 .bss
47 pages:          .res    1               ; Number of pages
48 curpage:        .res    1               ; Current page number
49 window:         .res    256             ; Memory "window"
50
51 .code
52
53 ; ------------------------------------------------------------------------
54 ; INSTALL routine. Is called after the driver is loaded into memory. If
55 ; possible, check if the hardware is present and determine the amount of
56 ; memory available.
57 ; Must return an EM_ERR_xx code in a/x.
58 ;
59
60 INSTALL:
61
62 ; Determine how much memory is available. We will use all memory above
63 ; $8000 up to MEMTOP
64
65         sec
66         jsr     $FF99                   ; MEMTOP: Get top memory into Y/X
67         tya
68         sub     #>BASE                  ; Low 32 K are used
69         bcc     nomem
70         beq     nomem                   ; Offering zero pages is a bad idea
71         sta     pages
72
73         ldx     #$FF
74         stx     curpage                 ; Invalidate the current page
75         inx                             ; X = 0
76         txa                             ; A = X = EM_ERR_OK
77         rts
78
79 nomem:  ldx     #>EM_ERR_NO_DEVICE
80         lda     #<EM_ERR_NO_DEVICE
81 ;       rts                             ; Run into UNINSTALL instead
82
83 ; ------------------------------------------------------------------------
84 ; UNINSTALL routine. Is called before the driver is removed from memory.
85 ; Can do cleanup or whatever. Must not return anything.
86 ;
87
88 UNINSTALL:
89         rts
90
91
92 ; ------------------------------------------------------------------------
93 ; PAGECOUNT: Return the total number of available pages in a/x.
94 ;
95
96 PAGECOUNT:
97         lda     pages
98         ldx     #$00                    ; 128 pages max
99         rts
100
101 ; ------------------------------------------------------------------------
102 ; MAP: Map the page in a/x into memory and return a pointer to the page in
103 ; a/x. The contents of the currently mapped page (if any) may be discarded
104 ; by the driver.
105 ;
106
107 MAP:    sta     curpage                 ; Remember the new page
108
109         add     #>BASE
110         sta     ptr1+1
111         ldy     #$00
112         sty     ptr1
113
114         lda     #<window
115         sta     ptr2
116         lda     #>window
117         sta     ptr2+1
118
119 ; Transfer one page
120
121         jsr     transfer                ; Transfer one page
122
123 ; Return the memory window
124
125         lda     #<window
126         ldx     #>window                ; Return the window address
127         rts
128
129 ; ------------------------------------------------------------------------
130 ; USE: Tell the driver that the window is now associated with a given page.
131
132 USE:    sta     curpage                 ; Remember the page
133         lda     #<window
134         ldx     #>window                ; Return the window
135         rts
136
137 ; ------------------------------------------------------------------------
138 ; COMMIT: Commit changes in the memory window to extended storage.
139
140 COMMIT: lda     curpage                 ; Get the current page
141         bmi     done                    ; Jump if no page mapped
142
143         add     #>BASE
144         sta     ptr2+1
145         ldy     #$00
146         sty     ptr2
147
148         lda     #<window
149         sta     ptr1
150         lda     #>window
151         sta     ptr1+1
152
153 ; Transfer one page. Y must be zero on entry. Because we bank out the
154 ; kernal, we will run the routine with interrupts disabled but leave
155 ; short breath times. Unroll the following loop to make it somewhat faster.
156
157 transfer:
158         sei
159         sta     ENABLE_RAM
160
161         lda     (ptr1),y
162         sta     (ptr2),y
163         iny
164
165         lda     (ptr1),y
166         sta     (ptr2),y
167         iny
168
169         lda     (ptr1),y
170         sta     (ptr2),y
171         iny
172
173         lda     (ptr1),y
174         sta     (ptr2),y
175         iny
176
177         lda     (ptr1),y
178         sta     (ptr2),y
179         iny
180
181         lda     (ptr1),y
182         sta     (ptr2),y
183         iny
184
185         lda     (ptr1),y
186         sta     (ptr2),y
187         iny
188
189         lda     (ptr1),y
190         sta     (ptr2),y
191         iny
192
193         sta     ENABLE_ROM
194         cli
195
196         bne     transfer
197
198 ; Done
199
200 done:   rts
201
202 ; ------------------------------------------------------------------------
203 ; COPYFROM: Copy from extended into linear 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 COPYFROM:
209         sta     ptr3
210         stx     ptr3+1                  ; Save the passed em_copy pointer
211
212         ldy     #EM_COPY_OFFS
213         lda     (ptr3),y
214         sta     ptr1
215         ldy     #EM_COPY_PAGE
216         lda     (ptr3),y
217         add     #>BASE
218         sta     ptr1+1                  ; From
219
220         ldy     #EM_COPY_BUF
221         lda     (ptr3),y
222         sta     ptr2
223         iny
224         lda     (ptr3),y
225         sta     ptr2+1                  ; To
226
227 common: ldy     #EM_COPY_COUNT+1
228         lda     (ptr3),y                ; Get number of pages
229         beq     @L2                     ; Skip if no full pages
230         sta     tmp1
231
232 ; Copy full pages allowing interrupts after each page copied
233
234         ldy     #$00
235 @L1:    jsr     transfer
236         inc     ptr1+1
237         inc     ptr2+1
238         dec     tmp1
239         bne     @L1
240
241 ; Copy the remainder of the page
242
243 @L2:    ldy     #EM_COPY_COUNT
244         lda     (ptr3),y                ; Get bytes in last page
245         beq     @L4
246         tax
247
248         sei                             ; Disable ints
249         sta     ENABLE_RAM              ; Bank out the ROM
250
251 ; Transfer the bytes in the last page
252
253         ldy     #$00
254 @L3:    lda     (ptr1),y
255         sta     (ptr2),y
256         iny
257         dex
258         bne     @L3
259
260 ; Restore the old memory configuration, allow interrupts
261
262         sta     ENABLE_ROM
263         cli
264
265 ; Done
266
267 @L4:    rts
268
269 ; ------------------------------------------------------------------------
270 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
271 ; describing the request is passed in a/x.
272 ; The function must not return anything.
273 ;
274
275 COPYTO: sta     ptr3
276         stx     ptr3+1                  ; Save the passed em_copy pointer
277
278         ldy     #EM_COPY_OFFS
279         lda     (ptr3),y
280         sta     ptr2
281         ldy     #EM_COPY_PAGE
282         lda     (ptr3),y
283         add     #>BASE
284         sta     ptr2+1                  ; To
285
286         ldy     #EM_COPY_BUF
287         lda     (ptr3),y
288         sta     ptr1
289         iny
290         lda     (ptr3),y
291         sta     ptr1+1                  ; From
292
293         jmp     common
294
295