8689c962 |
1 | ############################################################################### |
2 | # |
3 | # Copyright (c) 2011, GraÅžvydas Ignotas |
4 | # All rights reserved. |
5 | # |
6 | # Redistribution and use in source and binary forms, with or without |
7 | # modification, are permitted provided that the following conditions are met: |
8 | # * Redistributions of source code must retain the above copyright |
9 | # notice, this list of conditions and the following disclaimer. |
10 | # * Redistributions in binary form must reproduce the above copyright |
11 | # notice, this list of conditions and the following disclaimer in the |
12 | # documentation and/or other materials provided with the distribution. |
13 | # * Neither the name of the organization nor the |
14 | # names of its contributors may be used to endorse or promote products |
15 | # derived from this software without specific prior written permission. |
16 | # |
f28eaaad |
17 | # THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND ANY |
8689c962 |
18 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
19 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
f28eaaad |
20 | # DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY |
8689c962 |
21 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
22 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
23 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
24 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
26 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | # |
28 | # Assemble with gas |
29 | # --register-prefix-optional --bitwise-or |
30 | # |
31 | |
32 | #include "transfer.h" |
33 | |
34 | .text |
35 | .globl do_transfer |
36 | |
37 | |
38 | # receive 1 byte to d0 |
39 | # in: a1 - data port |
40 | # trash: d1 |
41 | .macro recv_one_byte is_last=0 |
42 | move.b #0,(a1) /* clear TH */ |
43 | |
44 | 0: /*L_wait_tl_low*/ |
45 | move.b (a1),d1 |
46 | btst.b #4,d1 |
47 | bne 0b /*L_wait_tl_low*/ |
48 | |
49 | move.b #0x40,(a1) /* set TH */ |
50 | and.b #0x0f,d1 |
51 | |
52 | 0: /*L_wait_tl_hi*/ |
53 | move.b (a1),d0 |
54 | btst.b #4,d0 |
55 | beq 0b /*L_wait_tl_hi*/ |
56 | |
57 | .if !\is_last |
58 | move.b #0,(a1) /* clear TH - ready for next */ |
59 | .endif |
60 | lsl.b #4,d0 |
61 | or.b d1,d0 |
62 | .endm |
63 | |
64 | # send 1 byte in d0 |
65 | # in: a1 - data port |
66 | # trash: d1,d2 |
67 | .macro send_one_byte |
68 | move.b d0,d2 |
69 | and.b #0x0f,d2 |
70 | |
71 | 0: /*Lwait_tl_low:*/ |
72 | move.b (a1),d1 |
73 | btst.b #4,d1 |
74 | bne 0b /*Lwait_tl_low*/ |
75 | |
76 | move.b d2,(a1) /* clears TH and writes data */ |
77 | |
78 | move.b d0,d2 |
79 | lsr.b #4,d2 |
80 | bset.b #6,d2 /* prepare TH */ |
81 | |
82 | 0: /*wait_tl_hi*/ |
83 | move.b (a1),d1 |
84 | btst.b #4,d1 |
85 | beq 0b /*wait_tl_hi1*/ |
86 | |
87 | move.b d2,(a1) |
88 | .endm |
89 | |
90 | recv_byte: |
272bd2ec |
91 | moveq.l #0,d0 |
8689c962 |
92 | recv_one_byte 1 |
93 | rts |
94 | |
4e6ba16d |
95 | # receive 1 16bit word to d0 |
96 | # in: a1 - data port |
97 | # trash: d1,d2 |
98 | recv_word: |
99 | recv_one_byte |
100 | move.b d0,d2 |
101 | recv_one_byte |
102 | lsl.w #8,d2 |
103 | move.b d0,d2 |
104 | move.w d2,d0 |
105 | rts |
106 | |
8689c962 |
107 | # receive address/size to d0 (3 bytes BE) |
108 | # in: a1 - data port |
109 | # trash: d1,d2 |
110 | recv_ad: |
111 | moveq.l #0,d2 |
112 | bsr recv_byte |
113 | move.b d0,d2 |
114 | bsr recv_byte |
115 | lsl.l #8,d2 |
116 | move.b d0,d2 |
117 | bsr recv_byte |
118 | lsl.l #8,d2 |
119 | move.b d0,d2 |
120 | move.l d2,d0 |
121 | rts |
122 | |
93c5aa8a |
123 | send_byte: |
124 | send_one_byte |
125 | rts |
126 | |
4e6ba16d |
127 | .equ sat_maxsize, (80*8+0x200) /* sprites+max_align */ |
128 | |
129 | # make sure cache is invalidated |
130 | # note: VRAM copy doesn't seem to help here |
131 | # note2: cache is updated as data is written |
132 | # in: d0 - vdp reg5, a0 = 0xc00000 |
133 | # trash: d1,d2,a2 |
134 | invalidate_sprite_cache: |
135 | move.w #0x8f02,4(a0) /* auto increment 2 */ |
136 | lsl.b #1,d0 /* upper byte of sat address */ |
137 | move.b d0,d1 |
138 | lsr.b #6,d1 /* 15:14 dst addr */ |
139 | and.b #0x3f,d0 /* assemble cmd */ |
140 | lsl.w #8,d0 |
141 | swap d0 |
142 | move.b d1,d0 |
143 | move.l d0,4(a0) |
144 | |
145 | move.l #0xffe000,a2 |
146 | move.l #sat_maxsize/2-1,d2 |
147 | 0: |
148 | move.w (a0),(a2)+ |
149 | dbra d2,0b |
150 | |
151 | bset #30,d0 /* VRAM write */ |
152 | move.l d0,4(a0) |
153 | |
154 | move.l #0xffe000,a2 |
155 | move.l #sat_maxsize/2-1,d2 |
156 | 0: |
157 | move.w (a2)+,(a0) |
158 | dbra d2,0b |
159 | rts |
160 | |
161 | |
8689c962 |
162 | |
163 | do_transfer: |
164 | lea 0xa10005,a1 |
165 | move.b #0x40,(0xa1000b).l /* ctrl - all inputs except TH */ |
166 | move.b #0x00,(a1) |
167 | |
168 | bsr recv_byte |
169 | cmp.b #CMD_PREFIX,d0 |
170 | bne return |
171 | |
172 | bsr recv_byte |
272bd2ec |
173 | cmp.b #CMD_FIRST,d0 |
174 | bcs return |
175 | cmp.b #CMD_LAST+1,d0 |
176 | bcc return |
177 | sub.b #CMD_FIRST,d0 |
178 | |
179 | lsl.w #2,d0 |
180 | lea (jumptab,pc,d0),a0 |
181 | jmp (a0) |
182 | jumptab: |
183 | bra pcc_transfer_recv /* sent to us */ |
184 | bra pcc_transfer_send /* recv from us */ |
185 | bra pcc_jump |
93c5aa8a |
186 | bra pcc_io |
4e6ba16d |
187 | bra pcc_loadstate |
272bd2ec |
188 | bra pcc_test_code |
189 | |
190 | |
93c5aa8a |
191 | /* receive data from PC */ |
272bd2ec |
192 | pcc_transfer_recv: |
8689c962 |
193 | bsr recv_ad |
194 | move.l d0,a0 |
195 | bsr recv_ad |
196 | move.l d0,d3 |
197 | |
198 | tr_recv_loop: |
199 | recv_one_byte |
200 | move.b d0,(a0)+ |
201 | subq.l #1,d3 |
272bd2ec |
202 | bgt tr_recv_loop |
8689c962 |
203 | bra return |
204 | |
272bd2ec |
205 | |
93c5aa8a |
206 | /* send data to PC */ |
272bd2ec |
207 | pcc_transfer_send: |
8689c962 |
208 | bsr recv_ad |
209 | move.l d0,a0 |
210 | bsr recv_ad |
211 | move.l d0,d3 |
212 | |
93c5aa8a |
213 | 0: /*Lwait_tl_low: it should switch to rx mode before lowering tl */ |
8689c962 |
214 | move.b (a1),d0 |
215 | btst.b #4,d0 |
216 | bne 0b /*Lwait_tl_low*/ |
217 | |
218 | move.b #0x4f,(0xa1000b).l |
219 | move.b #0x40,(a1) |
220 | |
221 | tr_send_loop: |
222 | move.b (a0)+,d0 |
223 | send_one_byte |
224 | subq.l #1,d3 |
272bd2ec |
225 | bgt tr_send_loop |
226 | bra return |
227 | |
228 | |
93c5aa8a |
229 | /* call specified location */ |
272bd2ec |
230 | pcc_jump: |
231 | bsr recv_ad |
232 | move.l d0,a0 |
93c5aa8a |
233 | jsr (a0) |
234 | bra return |
235 | |
236 | |
237 | /* do simple i/o commands */ |
238 | pcc_io: |
239 | moveq.l #0,d4 |
240 | bsr recv_byte |
241 | move.b d0,d4 |
242 | bsr recv_byte |
243 | lsl.l #8,d4 |
244 | move.b d0,d4 |
272bd2ec |
245 | |
93c5aa8a |
246 | pcc_io_loop: |
247 | move.b #0x40,(0xa1000b).l /* input mode */ |
272bd2ec |
248 | |
93c5aa8a |
249 | sub.w #1,d4 |
250 | bmi return |
251 | |
252 | bsr recv_byte |
253 | move.b d0,d3 /* cmd */ |
254 | |
255 | bsr recv_ad |
256 | move.l d0,a2 /* addr */ |
257 | |
258 | cmp.b #IOSEQ_W32, d3 |
259 | beq pcc_io_w32 |
260 | cmp.b #IOSEQ_W16, d3 |
261 | beq pcc_io_w16 |
262 | cmp.b #IOSEQ_W8, d3 |
263 | bne pcc_io_rx |
264 | |
265 | pcc_io_w8: |
266 | bsr recv_byte |
267 | move.b d0,(a2) |
268 | bra pcc_io_loop |
269 | |
270 | pcc_io_w16: |
271 | bsr recv_byte |
272 | move.b d0,d3 |
273 | bsr recv_byte |
274 | lsl.w #8,d3 |
275 | move.b d0,d3 |
276 | move.w d3,(a2) |
277 | bra pcc_io_loop |
278 | |
279 | pcc_io_w32: |
280 | bsr recv_byte |
281 | move.b d0,d3 |
282 | bsr recv_byte |
283 | lsl.w #8,d3 |
284 | move.b d0,d3 |
285 | bsr recv_byte |
286 | lsl.l #8,d3 |
287 | move.b d0,d3 |
288 | bsr recv_byte |
289 | lsl.l #8,d3 |
290 | move.b d0,d3 |
291 | move.l d3,(a2) |
292 | bra pcc_io_loop |
293 | |
294 | pcc_io_rx: |
295 | 0: /*Lwait_tl_low:*/ |
296 | move.b (a1),d0 |
297 | btst.b #4,d0 |
298 | bne 0b /*Lwait_tl_low*/ |
299 | |
300 | move.b #0x4f,(0xa1000b).l |
301 | move.b #0x40,(a1) |
302 | |
303 | cmp.b #IOSEQ_R32, d3 |
304 | beq pcc_io_r32 |
305 | cmp.b #IOSEQ_R16, d3 |
306 | beq pcc_io_r16 |
307 | cmp.b #IOSEQ_R8, d3 |
308 | bne return |
309 | |
310 | pcc_io_r8: |
311 | move.b (a2),d0 |
312 | bsr send_byte |
313 | bra pcc_io_loop |
314 | |
315 | pcc_io_r16: |
316 | move.w (a2),d3 |
317 | move.w d3,d0 |
318 | lsr.w #8,d0 |
319 | bsr send_byte |
320 | move.b d3,d0 |
321 | bsr send_byte |
322 | bra pcc_io_loop |
323 | |
324 | pcc_io_r32: |
325 | move.l (a2),d3 |
326 | move.l d3,d0 |
327 | swap d0 |
328 | lsr.l #8,d0 |
329 | bsr send_byte |
330 | move.l d3,d0 |
331 | swap d0 |
332 | bsr send_byte |
333 | move.w d3,d0 |
334 | lsr.w #8,d0 |
335 | bsr send_byte |
336 | move.b d3,d0 |
337 | bsr send_byte |
338 | bra pcc_io_loop |
339 | |
340 | |
4e6ba16d |
341 | /* PicoDrive savestate load */ |
342 | pcc_loadstate: |
343 | /* write VRAM */ |
344 | move.l #0xc00000,a0 |
345 | move.w #0x8f02,4(a0) /* auto increment 2 */ |
346 | |
347 | move.l #0x40000000,4(a0) |
348 | move.l #0x10000/2-1,d3 |
349 | tr_do_vram_loop: |
350 | bsr recv_word |
351 | move.w d0,(a0) |
352 | dbra d3, tr_do_vram_loop |
353 | |
354 | /* write cram */ |
355 | move.l #0xc0000000,4(a0) |
356 | move.l #0x80/2-1,d3 |
357 | tr_do_cram_loop: |
358 | bsr recv_word |
359 | move.w d0,(a0) |
360 | dbra d3, tr_do_cram_loop |
361 | |
362 | /* write vsram */ |
363 | move.l #0x40000010,4(a0) |
364 | move.l #0x80/2-1,d3 |
365 | tr_do_vsram_loop: |
366 | bsr recv_word |
367 | move.w d0,(a0) |
368 | dbra d3, tr_do_vsram_loop |
369 | |
370 | /* recv and write regs */ |
371 | lea 0xffe000,a3 |
372 | move.l a3,a2 |
373 | moveq.l #0x20-1,d3 |
374 | tr_do_vdpreg_recv_loop: |
375 | bsr recv_byte |
376 | move.b d0,(a2)+ |
377 | dbra d3, tr_do_vdpreg_recv_loop |
378 | |
379 | move.l a3,a2 |
380 | moveq.l #0,d3 |
381 | tr_do_vdpreg_loop: |
382 | move.b d3,d1 |
383 | or.b #0x80,d1 |
384 | lsl.w #8,d1 |
385 | move.b (d3,a2),d1 |
386 | move.w d1,4(a0) |
387 | addq.l #1,d3 |
388 | cmp.b #0x17,d3 /* FIXME: r23 might cause DMA or.. */ |
389 | bne 0f /* ..something and hang VDP.. */ |
390 | add.b #1,d3 /* ..so we skip it */ |
391 | 0: |
392 | cmp.b #0x20,d3 |
393 | blt tr_do_vdpreg_loop |
394 | |
395 | moveq.l #0,d0 |
396 | move.b 5(a3),d0 |
397 | bsr invalidate_sprite_cache |
398 | |
399 | |
400 | 0: bra 0b |
401 | |
402 | bra return |
403 | |
404 | |
405 | |
406 | |
93c5aa8a |
407 | /* some random code */ |
272bd2ec |
408 | pcc_test_code: |
8689c962 |
409 | bra return |
410 | |
411 | |
93c5aa8a |
412 | |
8689c962 |
413 | return: |
414 | move.b #0,(0xa1000b).l /* all inputs */ |
415 | move.l #0xffe000,a1 |
416 | move.l d0,(a1)+ /* last state for debug */ |
417 | move.l d1,(a1)+ |
418 | move.l d2,(a1)+ |
419 | move.l d3,(a1)+ |
420 | move.l a0,(a1)+ |
421 | bra return_to_main |
422 | |
423 | |
424 | # vim:filetype=asmM68k |