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