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