-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdma.asm
201 lines (159 loc) · 3.72 KB
/
dma.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
; DMA queue code adapted from https://github.com/flamewing/ultra-dma-queue
; CD2 CD1 CD0
; 0 0 1 VRAM = %001
; 0 1 1 CRAM = %011
; 1 0 1 VSRAM = %101
; input:
; d5 source
; d6 destination
; d7 length in words
; trashes:
; d4, d5, d6, d7, a6
startDMATransfer MODULE
lea vdp_ctrl, a6
haltZ80
dmaOn (a6)
; length
move.w #$93FF, d4
move.b d7, d4
move.w d4, (a6)
lsr.w #8, d7
move.w #$94FF, d4
move.b d7, d4
move.w d4, (a6)
; source
lsr.l d5 ; Source address >> 1 (even address)
move.w #$95FF, d4
move.b d5, d4
move.w d4, (a6)
lsr.l #8, d5
move.w #$96FF, d4
move.b d5, d4
move.w d4, (a6)
lsr.l #8, d5
move.w #$977F, d4
and.b d5, d4
move.w d4, (a6)
; Build DMA command
lsl.l #2, d6 ; Shift left. 2 bits goes to upper word
addq.w #%01, d6 ; Set two lowest bits to VRAM write
ror.w #2, d6 ; Rotate right. Moves two added bits to highest bits.
swap d6
ori.b #%10000000, d6
move.l d6, (a6)
dmaOff (a6)
resumeZ80
rts
MODEND
; input:
; d6 destination
; d7 length in words
; trashes:
; d4, d6, d7, a6
startDMAFill MODULE
lea vdp_ctrl, a6
haltZ80
dmaOn (a6)
; length
move.w #$93FF, d4
move.b d7, d4
move.w d4, (a6)
lsr.w #8, d7
move.w #$94FF, d4
move.b d7, d4
move.w d4, (a6)
move.w #$9780, (a6)
; Build DMA command
lsl.l #2, d6 ; Shift left. 2 bits goes to upper word
addq.w #%01, d6 ; Set two lowest bits to VRAM write
ror.w #2, d6 ; Rotate right. Moves two added bits to highest bits.
swap d6
ori.b #%10000000, d6
move.l d6, (a6)
move.w #$0, vdp_data
dmaOff (a6)
resumeZ80
rts
MODEND
queueDMATransfer MACRO sourceMem, destVRAM, lenWords
move.l \sourceMem, d5
move.l \destVRAM, d6
move.w \lenWords, d7
jsr _queueDMATransfer
ENDM
; input:
; d5 source
; d6 destination
; d7 length in words
; trashes:
; a6, d4, d5, d6
_queueDMATransfer MODULE
movea.w (dma_queue_pointer).w, a6 ; Move current pointer to a6
cmpa.w #dma_queue_pointer, a6 ; Compare dma_queue_pointer RAM address to current pointer
beq.s @done ; If they are the same, queue is full. (dma_queue_pointer is after dma_queue)
lsr.l d5 ; Source address >> 1 (even address)
swap d5 ; Swap high and low word (low word contains SA23-SA17)
move.w #$977F, d4 ; vdp_w_reg+(23<<8) & $7F where 7F is mask for upper bits (SA23-SA17)
and.b d5, d4 ; AND d4 with d5 lower 8 bits
move.w d4, (a6)+ ; Save reg 23 command+data to DMA queue
move.w d7, d5 ; Move length to d5 lower word
movep.l d5, 1(a6) ; Move each byte to its own word
lea 8(a6), a6 ; Add 8 to queue (the four words written with movep)
; Build DMA command
lsl.l #2, d6 ; Shift left. 2 bits goes to upper word
addq.w #%01, d6 ; Set two lowest bits to VRAM write
ror.w #2, d6 ; Rotate right. Moves two added bits to highest bits.
swap d6
ori.b #%10000000, d6
move.l d6, (a6)+
move.w a6, (dma_queue_pointer).w
@done
rts
MODEND
initDMAQueue MODULE
lea dma_queue, a6
move.w a6, (dma_queue_pointer).w ; Set current pointer to beginning of dma queue
move.l #$96959493, d7 ; vdp_w_reg+(22<<8), vdp_w_reg+(21<<8), vdp_w_reg+(20<<8), vdp_w_reg+(19<<8)
lc = 0
REPT SlotCount
movep.l d7, 2+lc(a6)
lc = lc+14
ENDR
rts
MODEND
;
processDMAQueue MODULE
movea.w (dma_queue_pointer).w, a6
suba #dma_queue, a6
lea vdp_ctrl, a5
haltZ80
dmaOn (a5)
setVDPAutoIncrement 2, (a5)
jmp @jumpTable(a6)
@jumpTable
jmp @done
nop
nop
nop
nop
lc = 1
REPT SlotCount
lea vdp_ctrl, a5
lea dma_queue.w, a6
IF lc<>SlotCount
bra.w @done-lc*8
ENDIF
lc = lc+1
ENDR
REPT SlotCount
move.l (a6)+, (a5) ; reg 23, reg 22
move.l (a6)+, (a5) ; reg 21, reg 20
move.l (a6)+, (a5) ; reg 19, dma first hlf
move.w (a6)+, (a5) ; dma command second half
ENDR
@done
dmaOff (a5)
resumeZ80
move.w #dma_queue, (dma_queue_pointer).w ; Reset dma_queue_pointer
rts
MODEND