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