]> git.sur5r.net Git - cc65/blob - libsrc/c64/emd/c64-ram.s
Make NMI ready
[cc65] / libsrc / c64 / emd / c64-ram.s
1 ;
2 ; Extended memory driver for the C64 hidden RAM. Driver works without
3 ; problems when statically linked.
4 ;
5 ; Ullrich von Bassewitz, 2002-12-02
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_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    = $D000
47 PAGES   = ($FF00 - BASE) / 256
48
49 ; ------------------------------------------------------------------------
50 ; Data.
51
52 .bss
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         ldx     #$FF
67         stx     curpage                 ; Invalidate the current page
68         inx                             ; X = 0
69         txa                             ; A = X = EM_ERR_OK
70 ;       rts                             ; Run into UNINSTALL instead
71
72 ; ------------------------------------------------------------------------
73 ; UNINSTALL routine. Is called before the driver is removed from memory.
74 ; Can do cleanup or whatever. Must not return anything.
75 ;
76
77 UNINSTALL:
78         rts
79
80
81 ; ------------------------------------------------------------------------
82 ; PAGECOUNT: Return the total number of available pages in a/x.
83 ;
84
85 PAGECOUNT:
86         lda     #<PAGES
87         ldx     #>PAGES
88         rts
89
90 ; ------------------------------------------------------------------------
91 ; MAP: Map the page in a/x into memory and return a pointer to the page in
92 ; a/x. The contents of the currently mapped page (if any) may be discarded
93 ; by the driver.
94 ;
95
96 MAP:    sta     curpage                 ; Remember the new page
97
98         clc
99         adc     #>BASE
100         sta     ptr1+1
101         ldy     #$00
102         sty     ptr1
103
104         lda     #<window
105         sta     ptr2
106         lda     #>window
107         sta     ptr2+1
108
109 ; Transfer one page
110
111         jsr     transfer                ; Transfer one page
112
113 ; Return the memory window
114
115         lda     #<window
116         ldx     #>window                ; Return the window address
117         rts
118
119 ; ------------------------------------------------------------------------
120 ; USE: Tell the driver that the window is now associated with a given page.
121
122 USE:    sta     curpage                 ; Remember the page
123         lda     #<window
124         ldx     #>window                ; Return the window
125         rts
126
127 ; ------------------------------------------------------------------------
128 ; COMMIT: Commit changes in the memory window to extended storage.
129
130 COMMIT: lda     curpage                 ; Get the current page
131         bmi     done                    ; Jump if no page mapped
132
133         clc
134         adc     #>BASE
135         sta     ptr2+1
136         ldy     #$00
137         sty     ptr2
138
139         lda     #<window
140         sta     ptr1
141         lda     #>window
142         sta     ptr1+1
143
144 ; Transfer one page. Y must be zero on entry
145
146 transfer:
147         ldx     $01                     ; Remember c64 control port
148         txa
149         and     #$F8                    ; Bank out ROMs, I/O
150         sei
151         sta     $01
152
153 ; Unroll the following loop
154
155 loop:   .repeat 8
156         lda     (ptr1),y
157         sta     (ptr2),y
158         iny
159         .endrepeat
160
161         bne     loop
162
163 ; Restore the old memory configuration, allow interrupts
164
165         stx     $01                     ; Restore the old configuration
166         cli
167
168 ; Done
169
170 done:   rts               
171
172 ; ------------------------------------------------------------------------
173 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
174 ; describing the request is passed in a/x.
175 ; The function must not return anything.
176 ;
177
178 COPYFROM:
179         sta     ptr3
180         stx     ptr3+1                  ; Save the passed em_copy pointer
181                        
182         ldy     #EM_COPY::OFFS
183         lda     (ptr3),y
184         sta     ptr1
185         ldy     #EM_COPY::PAGE
186         lda     (ptr3),y
187         clc
188         adc     #>BASE
189         sta     ptr1+1                  ; From
190
191         ldy     #EM_COPY::BUF
192         lda     (ptr3),y
193         sta     ptr2
194         iny
195         lda     (ptr3),y
196         sta     ptr2+1                  ; To
197
198 common: ldy     #EM_COPY::COUNT+1
199         lda     (ptr3),y                ; Get number of pages
200         beq     @L2                     ; Skip if no full pages
201         sta     tmp1
202
203 ; Copy full pages allowing interrupts after each page copied
204
205         ldy     #$00
206 @L1:    jsr     transfer
207         inc     ptr1+1
208         inc     ptr2+1
209         dec     tmp1
210         bne     @L1
211
212 ; Copy the remainder of the page
213
214 @L2:    ldy     #EM_COPY::COUNT
215         lda     (ptr3),y                ; Get bytes in last page
216         beq     @L4
217         tax
218
219         lda     $01                     ; Remember c64 control port
220         pha
221         and     #$F8                    ; Bank out ROMs, I/O
222         sei
223         sta     $01
224
225 ; Transfer the bytes in the last page
226
227         ldy     #$00
228 @L3:    lda     (ptr1),y
229         sta     (ptr2),y
230         iny
231         dex
232         bne     @L3
233
234 ; Restore the old memory configuration, allow interrupts
235
236         pla
237         sta     $01                     ; Restore the old configuration
238         cli
239
240 ; Done
241
242 @L4:    rts
243
244 ; ------------------------------------------------------------------------
245 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
246 ; describing the request is passed in a/x.
247 ; The function must not return anything.
248 ;
249
250 COPYTO: sta     ptr3
251         stx     ptr3+1                  ; Save the passed em_copy pointer
252
253         ldy     #EM_COPY::OFFS
254         lda     (ptr3),y
255         sta     ptr2
256         ldy     #EM_COPY::PAGE
257         lda     (ptr3),y
258         clc
259         adc     #>BASE
260         sta     ptr2+1                  ; To
261
262         ldy     #EM_COPY::BUF
263         lda     (ptr3),y
264         sta     ptr1
265         iny
266         lda     (ptr3),y
267         sta     ptr1+1                  ; From
268
269         jmp     common