]> git.sur5r.net Git - cc65/blob - libsrc/atari/emd/atr130.s
7082609bb55bb5505fba18b41cf94eef5b43bb53
[cc65] / libsrc / atari / emd / atr130.s
1 ;
2 ; Extended memory driver for the Atari 130XE memory standard
3 ; Shawn Jefferson, 2012-08-11
4 ;
5 ; Banking Register $D301:
6 ; Bit 7: Self-Test on/off
7 ; Bit 6: Unused
8 ; Bit 5: Antic sees bank
9 ; Bit 4: CPU sees bank
10 ; Bit 3: bank control
11 ; Bit 2: bank control
12 ; Bit 1: BASIC on/off
13 ; Bit 0: OS RAM on/off
14
15 ; Masks: %11100011  $E3     Bank 0
16 ;        %11100111  $E7     Bank 1
17 ;        %11101011  $EB     Bank 2
18 ;        %11101111  $EF     Bank 3
19 ;        %11111111  $FF     Off
20 ;
21 ; Based on the Extended memory driver for the Apple II auxiliary memory
22 ;  by
23 ; Stefan Haubenthal, 2003-12-12
24 ; Ullrich von Bassewitz, 2002-12-02
25 ;
26
27         .include        "zeropage.inc"
28
29         .include        "em-kernel.inc"
30         .include        "em-error.inc"
31
32
33         .macpack        generic
34
35
36 ; ------------------------------------------------------------------------
37 ; Header. Includes jump table
38
39 .segment        "HEADER"
40
41 ; Driver signature
42
43         .byte   $65, $6d, $64           ; "emd"
44         .byte   EMD_API_VERSION         ; EM API version number
45
46 ; Library reference
47
48         .addr   $0000
49
50 ; Jump table
51
52         .addr   INSTALL
53         .addr   UNINSTALL
54         .addr   PAGECOUNT
55         .addr   MAP
56         .addr   USE
57         .addr   COMMIT
58         .addr   COPYFROM
59         .addr   COPYTO
60
61 ; ------------------------------------------------------------------------
62 ; Constants
63
64 BANK    = $4000                         ; bank window
65 STACK   = $0100                         ; stack location 
66 PAGES   = 256                           ; 4 x 16k banks
67
68
69 ; ------------------------------------------------------------------------
70 ; Data.
71
72 .rodata
73 banks:          .byte $E3,$E7,$EB,$EF   ; 130XE banks for cpu banking
74
75 stacktest:      sei
76                 ldy banks
77                 sty $D301
78                 tax                     ; A is set by caller
79                 inx
80                 stx $4000               ; change $4000
81                 ldy #$FF                ; STACK+13
82                 sty $D301
83                 cmp $4000               ; changed?
84                 beq @1
85                 sec                     ; error
86                 bcs @2
87 @1:             clc
88 @2:             sta $4000               ; restore
89                 cli
90                 rts
91 stacktest_end: 
92
93 stackcopy:      sei                     ; disable interrupts
94 @1:             dex                     ; pre-decrement (full page x=0)
95                 ldy #$FF                ; this will be replaced  STACK+3
96                 sty $D301               ; set bank 
97                 lda $FF00,x             ; address to copy from   STACK+8,+9
98                 ldy #$FF                ; this will be replaced  STACK+11
99                 sty $D301 
100                 sta $FF00,x             ; address to copy to     STACK+16,+17
101                 cpx #0 
102                 bne @1
103                 ldy #$FF                ; portb_save             STACK+23
104                 sty $D301
105                 cli                     ; enable interrupts
106                 rts
107 stackcopy_end:
108
109 stackcopy_byte: sei
110                 ldy #$FF                ; STACK+2
111                 sty $D301
112                 lda $FFFF               ; STACK+7 +8
113                 ldy #$FF                ; STACK+10
114                 sty $D301
115                 sta $FFFF               ; STACK+15 +16
116                 ldy #$FF                ; STACK+18
117                 sty $D301
118                 cli
119                 rts
120 stackcopy_byte_end: 
121
122
123 .data
124 curpage:        .byte   $FF             ; Current page number in bank (invalid)
125 curbank:        .byte   $FF             ; Current bank number
126
127 .bss
128 window:         .res    256             ; Memory "window"
129 portb_save:     .res    1               ; portb state
130
131 .code
132
133 install_transfer:
134                 ldx #stackcopy_end - stackcopy - 1
135 @1:             lda stackcopy,x
136                 sta STACK,x
137                 dex
138                 bpl @1
139                 rts
140
141 install_byte_transfer:
142                 ldx #stackcopy_byte_end - stackcopy_byte - 1
143 @2:             lda stackcopy_byte,x
144                 sta STACK,x
145                 dex
146                 bpl @2
147                 rts
148
149 install_test:
150                 ldx #stacktest_end - stacktest - 1
151 @3:             lda stacktest,x
152                 sta STACK,x
153                 dex
154                 bpl @3
155                 rts
156
157 setpage:
158                 tax                             ; save page
159                 and     #$C0                    ; mask out bank
160                 clc
161                 ror
162                 ror                             ; divide by 64
163                 ror                             ; 64 pages in each bank
164                 ror
165                 ror
166                 ror
167                 sta     curbank                 ; Remember the new bank
168                 txa                             ; bring back page
169                 and     #$3F                    ; mask out page
170                 sta     curpage                 ; curpage in bank
171                 rts
172
173
174 ; ------------------------------------------------------------------------
175 ; INSTALL routine. Is called after the driver is loaded into memory. If
176 ; possible, check if the hardware is present and determine the amount of
177 ; memory available.
178 ; Must return an EM_ERR_xx code in a/x.
179 ;
180
181 INSTALL:
182         lda     $D301                   ; save state of portb
183         sta     portb_save
184         tay 
185
186         jsr     install_test            ; doesn't touch Y
187         sty     STACK+13
188
189         lda     $4000                   ; test for extended memory
190         jsr     STACK
191         bcs     @1 
192         lda     #EM_ERR_OK
193         rts
194 @1:     lda     #EM_ERR_NO_DEVICE
195         rts
196
197 ; ------------------------------------------------------------------------
198 ; UNINSTALL routine. Is called before the driver is removed from memory.
199 ; Can do cleanup or whatever. Must not return anything.
200 ;
201
202 UNINSTALL:
203         rts
204
205
206 ; ------------------------------------------------------------------------
207 ; PAGECOUNT: Return the total number of available pages in a/x.
208 ;
209
210 PAGECOUNT:
211         lda     #<PAGES
212         ldx     #>PAGES
213         rts
214
215 ; ------------------------------------------------------------------------
216 ; MAP: Map the page in a/x into memory and return a pointer to the page in
217 ; a/x. The contents of the currently mapped page (if any) may be discarded
218 ; by the driver.
219 ;
220
221 MAP:    jsr setpage                     ; extract the bank/page
222         add     #>BANK                  ; $4000 + page  (carry is cleared)
223         sta     ptr1+1
224         ;ldy     #$00
225         ;sty     ptr1
226
227         lda     #<window
228         sta     ptr2
229         lda     #>window
230         sta     ptr2+1
231
232 ; Transfer one page
233
234         jsr     install_transfer        ; Transfer one page
235
236         ldx     curbank
237         lda     banks,x
238         sta     STACK+3                 ; set bank to copy from
239 ;        lda     ptr1
240 ;        sta     STACK+8 
241         lda     ptr1+1
242         sta     STACK+9                 ; set copy from address
243         lda     portb_save
244         sta     STACK+11                ; set portb restore
245         sta     STACK+23                ; set final portb restore
246         lda     ptr2
247         sta     STACK+16
248         lda     ptr2+1
249         sta     STACK+17                ; set copy to address 
250
251         ldx     #0                      ; full page copy
252         jsr     STACK                   ; do the copy! 
253
254 ; Return the memory window
255
256         lda     #<window
257         ldx     #>window                ; Return the window address
258
259         rts
260
261 ; ------------------------------------------------------------------------
262 ; USE: Tell the driver that the window is now associated with a given page.
263
264 USE:    ;sta     curpage                 ; Remember the page
265         jsr setpage                     ; extract bank/page
266         lda     #<window
267         ldx     #>window                ; Return the window
268         rts
269
270 ; ------------------------------------------------------------------------
271 ; COMMIT: Commit changes in the memory window to extended storage.
272
273 COMMIT: lda     curpage                 ; Get the current page
274         cmp     #$FF
275         beq     commit_done             ; Jump if no page mapped
276
277         clc
278         add     #>BANK
279         sta     ptr2+1
280         ;ldy     #$00
281         ;sty     ptr2
282
283         lda     #<window
284         sta     ptr1
285         lda     #>window
286         sta     ptr1+1
287
288 ; Transfer one page/all bytes
289
290         jsr     install_transfer        ; Transfer one page
291
292         lda     portb_save
293         sta     STACK+3                 ; set bank to copy from
294         sta     STACK+23                ; set final portb restore
295         lda     ptr1
296         sta     STACK+8 
297         lda     ptr1+1
298         sta     STACK+9                 ; set copy from address
299         ldx     curbank
300         lda     banks,x
301         sta     STACK+11                ; set bank to copy to
302         ;lda     ptr2
303         ;sta     STACK+16
304         lda     ptr2+1
305         sta     STACK+17                ; set copy to address 
306
307         ldx     #0                      ; full page copy
308         jsr     STACK                   ; do the copy! 
309
310 commit_done:
311         rts
312
313
314 ; ------------------------------------------------------------------------
315 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
316 ; describing the request is passed in a/x.
317 ; The function must not return anything.
318 ;
319 COPYFROM:
320         sta     ptr3
321         stx     ptr3+1                  ; Save the passed em_copy pointer
322
323         jsr     install_byte_transfer   ; install the stack copy routine
324
325         ldy     #EM_COPY::OFFS
326         lda     (ptr3),y
327         sta     STACK+7                 ; offset goes into BANK low 
328
329         ldy     #EM_COPY::PAGE
330         lda     (ptr3),y
331         sta     tmp1                    ; save page for later
332         ;add     #>BANK
333         ;sta     STACK+8                 ; BANK + page goes into BANK high
334
335         ldy     #EM_COPY::BUF
336         lda     (ptr3),y
337         sta     STACK+15                ; buffer goes into dest low
338         iny
339         lda     (ptr3),y
340         sta     STACK+16                ; buffer goes into dest high
341
342         ldy     #EM_COPY::COUNT
343         lda     (ptr3),y                ; Get bytes in last page
344         sta     ptr4
345         iny
346         lda     (ptr3),y                ; Get number of pages
347         sta     ptr4+1
348
349         lda     tmp1                    ; extract bank/page
350         jsr     setpage                 ; sets curbank/curpage
351         lda     curpage
352         add     #>BANK                  ; add to BANK address
353         sta     STACK+8                 ; current page in bank
354         ldx     curbank
355         lda     banks,x 
356         sta     STACK+2                 ; set bank in stack 
357         lda     portb_save 
358         sta     STACK+10                ; set bank restore in stack
359         sta     STACK+18                ; set final restore too
360
361 copyfrom_copy:
362         lda     ptr4                    ; check if count is zero
363         bne     @4
364         lda     ptr4+1
365         beq     done
366
367 @4:     jsr     STACK                   ; copy one byte
368
369         sec
370         lda     ptr4
371         sub     #1
372         sta     ptr4
373         bcs     @1
374         lda     ptr4+1
375         beq     @1
376         sub     #1
377         sta     ptr4+1
378
379 @1:     inc     STACK+7                 ; increment address in BANK
380         bne     @2
381         inc     STACK+8
382         lda     STACK+8
383         cmp     #$80                    ; we stepped outside bank
384         bne     @2
385
386         inc     curbank                 ; get next bank
387         ldx     curbank
388         lda     banks,x
389         sta     STACK+2                 ; set new bank
390         lda     #$40                    ; set address back to $4000
391         sta     STACK+8
392
393 @2:     inc     STACK+15                ; increment buffer address
394         bne     @3
395         inc     STACK+16
396
397 @3:     jmp     copyfrom_copy           ; copy another byte 
398
399 done:
400         rts
401
402 ; ------------------------------------------------------------------------
403 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
404 ; describing the request is passed in a/x.
405 ; The function must not return anything.
406 ;
407
408 COPYTO:
409         sta     ptr3
410         stx     ptr3+1                  ; Save the passed em_copy pointer
411
412         jsr     install_byte_transfer   ; install the stack copy routine
413
414         ldy     #EM_COPY::OFFS
415         lda     (ptr3),y
416         sta     STACK+15                 ; offset goes into BANK low 
417
418         ldy     #EM_COPY::PAGE
419         lda     (ptr3),y
420         sta     tmp1                    ; save page for later
421         ;add     #>BANK
422         ;sta     STACK+16                ; BANK + page goes into BANK high
423
424         ldy     #EM_COPY::BUF
425         lda     (ptr3),y
426         sta     STACK+7                ; buffer goes into dest low
427         iny
428         lda     (ptr3),y
429         sta     STACK+8                ; buffer goes into dest high
430
431         ldy     #EM_COPY::COUNT
432         lda     (ptr3),y                ; Get bytes in last page
433         sta     ptr4
434         iny
435         lda     (ptr3),y                ; Get number of pages
436         sta     ptr4+1
437
438         lda     tmp1                    ; extract bank/page
439         jsr     setpage                 ; sets curbank/curpage
440         lda     curpage
441         add     #>BANK                  ; add to BANK address
442         sta     STACK+16                ; current page in bank
443         ldx     curbank
444         lda     banks,x 
445         sta     STACK+10                ; set bank in stack 
446         lda     portb_save 
447         sta     STACK+2                 ; set bank restore in stack
448         sta     STACK+18                ; set final restore too
449
450 copyto_copy:
451         lda     ptr4                    ; check if count is zero
452         bne     @4
453         lda     ptr4+1
454         beq     done
455
456 @4:     jsr     STACK                   ; copy one byte
457
458         sec
459         lda     ptr4
460         sub     #1
461         sta     ptr4
462         bcs     @1
463         lda     ptr4+1
464         beq     @1
465         sub     #1
466         sta     ptr4+1
467
468 @1:     inc     STACK+15               ; increment address in BANK
469         bne     @2
470         inc     STACK+16
471         lda     STACK+16
472         cmp     #$80                    ; we stepped outside bank
473         bne     @2
474
475         inc     curbank                 ; get next bank
476         ldx     curbank
477         lda     banks,x
478         sta     STACK+10                ; set new bank
479         lda     #$40                    ; set address back to $4000
480         sta     STACK+16
481
482 @2:     inc     STACK+7                ; increment buffer address
483         bne     @3
484         inc     STACK+8
485
486 @3:     jmp     copyto_copy           ; copy another byte 
487