]> git.sur5r.net Git - cc65/blob - libsrc/c64/emd/dtv-himem.s
62bc2007b65753eac17d9a28632f4e42ea3a75b3
[cc65] / libsrc / c64 / emd / dtv-himem.s
1 ;
2 ; Extended memory driver for the C64 D2TV (the second or PAL version).
3 ; Driver works without problems when statically linked.
4 ;
5 ; Ullrich von Bassewitz, 2005-11-27
6 ;
7
8
9         .include        "zeropage.inc"
10
11         .include        "em-kernel.inc"
12         .include        "em-error.inc"
13         .import _get_ostype
14
15
16         .macpack        generic
17
18
19 ; ------------------------------------------------------------------------
20 ; Header. Includes jump table
21
22 .segment        "JUMPTABLE"
23
24 ; Driver signature
25
26         .byte   $65, $6d, $64           ; "emd"
27         .byte   EMD_API_VERSION         ; EM API version number
28
29 ; Library reference
30
31         .addr   $0000
32
33 ; Jump table
34
35         .addr   INSTALL
36         .addr   UNINSTALL
37         .addr   PAGECOUNT
38         .addr   MAP
39         .addr   USE
40         .addr   COMMIT
41         .addr   COPYFROM
42         .addr   COPYTO
43
44 ; ------------------------------------------------------------------------
45 ; Constants
46
47 OP_COPYFROM     = %00001101
48 OP_COPYTO       = %00001111
49
50 START_BANK      = 2                     ; Start at $20000
51 PAGES           = (2048 - 128) * 4
52
53
54 ; ------------------------------------------------------------------------
55 ; Data.
56
57 .bss
58 window:         .res    256             ; Memory "window"
59
60 .data
61
62 ; The MAP and COMMIT entries will actually call COPYFROM/COPYTO with
63 ; a pointer to the following data structure:
64
65 dma_params:     .word   window          ; Host address
66                 .byte   0               ; Offset in page
67 curpage:        .word   $0000           ; Page
68                 .word   .sizeof (window); # bytes to move, lo, hi
69
70 .code
71
72 ; ------------------------------------------------------------------------
73 ; INSTALL routine. Is called after the driver is loaded into memory. If
74 ; possible, check if the hardware is present and determine the amount of
75 ; memory available.
76 ; Must return an EM_ERR_xx code in a/x.
77 ;
78
79 INSTALL:
80
81 ; Check for a DTV
82
83         ldx     #1
84         stx     $d03f
85         ldx     $d040
86         cpx     $d000
87         bne     @present
88         inc     $d000
89         cpx     $d040
90         beq     @present
91         dec     $d000
92
93 ; DTV not found
94
95         lda     #<EM_ERR_NO_DEVICE
96         ldx     #>EM_ERR_NO_DEVICE
97         rts
98
99 @present:
100         ldx     #$FF
101         stx     curpage+1               ; Invalidate curpage
102         inx                             ; X = 0
103         txa                             ; A/X = EM_ERR_OK
104
105 ;       rts                             ; Run into UNINSTALL instead
106
107 ; ------------------------------------------------------------------------
108 ; UNINSTALL routine. Is called before the driver is removed from memory.
109 ; Can do cleanup or whatever. Must not return anything.
110 ;
111
112 UNINSTALL:
113         rts
114
115 ; ------------------------------------------------------------------------
116 ; PAGECOUNT: Return the total number of available pages in a/x.
117 ;
118
119 PAGECOUNT:
120         lda     #<PAGES
121         ldx     #>PAGES
122         rts
123
124 ; ------------------------------------------------------------------------
125 ; MAP: Map the page in a/x into memory and return a pointer to the page in
126 ; a/x.  The contents of the currently mapped page (if any) may be discarded
127 ; by the driver.
128 ;
129
130 MAP:    sta     curpage
131         stx     curpage+1               ; Remember the new page
132
133         lda     #<dma_params
134         ldx     #>dma_params
135         jsr     COPYFROM                ; Copy data into the window
136
137         lda     #<window
138         ldx     #>window                ; Return the window address
139 done:   rts
140
141 ; ------------------------------------------------------------------------
142 ; USE: Tell the driver that the window is now associated with a given page.
143
144 USE:    sta     curpage
145         stx     curpage+1               ; Remember the page
146         lda     #<window
147         ldx     #>window                ; Return the window
148         rts
149
150 ; ------------------------------------------------------------------------
151 ; COMMIT: Commit changes in the memory window to extended storage.
152
153 COMMIT: lda     curpage+1               ; Do we have a page mapped?
154         bmi     done                    ; Jump if no page mapped
155
156         lda     #<dma_params
157         ldx     #>dma_params
158
159 ; Run into COPYTO
160
161 ; ------------------------------------------------------------------------
162 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
163 ; describing the request is passed in a/x.
164 ; The function must not return anything.
165 ;
166
167 COPYTO: sta     ptr1
168         stx     ptr1+1                  ; Save the pointer
169
170         ldx     #OP_COPYTO              ; Load the command
171         bne     transfer
172
173 ; ------------------------------------------------------------------------
174 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
175 ; describing the request is passed in a/x.
176 ; The function must not return anything.
177 ;
178
179 COPYFROM:
180         sta     ptr1
181         stx     ptr1+1                  ; Save the pointer
182
183         ldx     #OP_COPYFROM
184
185 ; DTV DMA transfer routine. Expects the command in X.
186 ; NOTE: We're using knowledge about field order in the EM_COPY struct here!
187
188 transfer:
189         jsr     WAIT                    ; Wait until DMA is finished
190
191 ; Modulo disable
192
193         ldy     #$00
194         sty     $d31e
195
196 ; Setup the target address and the source and target steps. Y contains zero,
197 ; which is EM_COPY::BUF.
198
199         sty     $d307                   ; Source step high = 0
200         sty     $d309                   ; Dest step high = 0
201         lda     (ptr1),y
202         sta     $d303                   ; Dest address low
203         iny                             ; Y = 1
204         sty     $d306                   ; Source step low = 1
205         sty     $d308                   ; Dest step low = 1
206         lda     (ptr1),y
207         sta     $d304
208         lda     #$40                    ; Dest is always RAM, start at $00000
209         sta     $d305
210
211 ; Setup the source address. Incrementing Y will make it point to EM_COPY::OFFS.
212 ; We will allow page numbers higher than PAGES and map them to ROM. This will
213 ; allow reading the ROM by specifying a page starting with PAGES.
214
215         iny                             ; EM_COPY::OFFS
216         lda     (ptr1),y
217         sta     $d300
218         iny                             ; EM_COPY::PAGE
219         lda     (ptr1),y
220         sta     $d301
221         iny
222         lda     (ptr1),y
223         adc     #START_BANK             ; Carry clear here from WAIT
224         and     #$3f
225         cmp     #>PAGES+START_BANK      ; Valid range?
226         bcs     @L1                     ; Jump if no
227         ora     #$40                    ; Address RAM
228 @L1:    sta     $d302
229
230 ; Length
231
232         iny                             ; EM_COPY::COUNT
233         lda     (ptr1),y
234         sta     $d30a
235         iny
236         lda     (ptr1),y
237         sta     $d30b
238
239 ; Start DMA
240
241         stx     $d31f
242
243 ; Wait until DMA is done
244
245 WAIT:   lda     $d31f
246         lsr     a
247         bcs     WAIT
248         rts
249