testpico: more on timer reload
[megadrive.git] / hexed / transfer.S
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 #
17 # THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND ANY
18 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 # DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
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:
91         moveq.l         #0,d0
92         recv_one_byte 1
93         rts
94
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
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
123 # send 1 byte in d0
124 #  in: a1 - data port
125 #  trash: d1,d2
126 send_byte:
127         send_one_byte
128         rts
129
130 .macro switch_to_output
131 0: /*Lwait_tl_low: PC should switch to rx mode before lowering tl */
132         move.b          (a1),d0
133         btst.b          #4,d0
134         bne             0b /*Lwait_tl_low*/
135
136         move.b          #0x4f,(0xa1000b).l
137         move.b          #0x40,(a1)
138 .endm
139
140 .equ sat_maxsize, (80*8+0x200) /* sprites+max_align */
141
142 # make sure cache is invalidated
143 # note: VRAM copy doesn't seem to help here
144 # note2: cache is updated as data is written
145 #  in: d0 - vdp reg5, a0 = 0xc00000
146 #  trash: d1,d2,a2
147 invalidate_sprite_cache:
148         move.w          #0x8f02,4(a0)           /* auto increment 2 */
149         lsl.b           #1,d0                   /* upper byte of sat address */
150         move.b          d0,d1
151         lsr.b           #6,d1                   /* 15:14 dst addr */
152         and.b           #0x3f,d0                /* assemble cmd */
153         lsl.w           #8,d0
154         swap            d0
155         move.b          d1,d0
156         move.l          d0,4(a0)
157
158         move.l          #0xffe000,a2
159         move.l          #sat_maxsize/2-1,d2
160 0:
161         move.w          (a0),(a2)+
162         dbra            d2,0b
163
164         bset            #30,d0                  /* VRAM write */
165         move.l          d0,4(a0)
166
167         move.l          #0xffe000,a2
168         move.l          #sat_maxsize/2-1,d2
169 0:
170         move.w          (a2)+,(a0)
171         dbra            d2,0b
172         rts
173
174
175
176 do_transfer:
177         lea             0xa10005,a1
178         move.b          #0x40,(0xa1000b).l      /* ctrl - all inputs except TH */
179         move.b          #0x00,(a1)
180
181         bsr             recv_byte
182         cmp.b           #CMD_PREFIX,d0
183         bne             return
184
185         bsr             recv_byte
186         cmp.b           #CMD_FIRST,d0
187         bcs             return
188         cmp.b           #CMD_LAST+1,d0
189         bcc             return
190         sub.b           #CMD_FIRST,d0
191
192         lsl.w           #2,d0
193         lea             (jumptab,pc,d0),a0
194         jmp             (a0)
195 jumptab:
196         bra             pcc_transfer_recv       /* sent to us */
197         bra             pcc_transfer_send       /* recv from us */
198         bra             pcc_jump
199         bra             pcc_io
200         bra             pcc_loadstate
201         bra             pcc_vram_send
202         bra             pcc_test_code
203
204
205 /* receive data from PC */
206 pcc_transfer_recv:
207         bsr             recv_ad
208         move.l          d0,a0
209         bsr             recv_ad
210         move.l          d0,d3
211
212 tr_recv_loop:
213         recv_one_byte
214         move.b          d0,(a0)+
215         subq.l          #1,d3
216         bgt             tr_recv_loop
217         bra             return
218
219
220 /* send data to PC */
221 pcc_transfer_send:
222         bsr             recv_ad
223         move.l          d0,a0
224         bsr             recv_ad
225         move.l          d0,d3
226
227         switch_to_output
228
229 tr_send_loop:
230         move.b          (a0)+,d0
231         send_one_byte
232         subq.l          #1,d3
233         bgt             tr_send_loop
234         bra             return
235
236
237 /* call specified location */
238 pcc_jump:
239         bsr             recv_ad
240         move.l          d0,a0
241         jsr             (a0)
242         bra             return
243
244
245 /* do simple i/o commands */
246 pcc_io:
247         moveq.l         #0,d4
248         bsr             recv_byte
249         move.b          d0,d4
250         bsr             recv_byte
251         lsl.l           #8,d4
252         move.b          d0,d4
253
254 pcc_io_loop:
255         move.b          #0x40,(0xa1000b).l      /* input mode */
256
257         sub.w           #1,d4
258         bmi             return
259
260         bsr             recv_byte
261         move.b          d0,d3                   /* cmd */
262
263         bsr             recv_ad
264         move.l          d0,a2                   /* addr */
265
266         cmp.b           #IOSEQ_W32, d3
267         beq             pcc_io_w32
268         cmp.b           #IOSEQ_W16, d3
269         beq             pcc_io_w16
270         cmp.b           #IOSEQ_W8, d3
271         bne             pcc_io_rx
272
273 pcc_io_w8:
274         bsr             recv_byte
275         move.b          d0,(a2)
276         bra             pcc_io_loop
277
278 pcc_io_w16:
279         bsr             recv_byte
280         move.b          d0,d3
281         bsr             recv_byte
282         lsl.w           #8,d3
283         move.b          d0,d3
284         move.w          d3,(a2)
285         bra             pcc_io_loop
286
287 pcc_io_w32:
288         bsr             recv_byte
289         move.b          d0,d3
290         bsr             recv_byte
291         lsl.w           #8,d3
292         move.b          d0,d3
293         bsr             recv_byte
294         lsl.l           #8,d3
295         move.b          d0,d3
296         bsr             recv_byte
297         lsl.l           #8,d3
298         move.b          d0,d3
299         move.l          d3,(a2)
300         bra             pcc_io_loop
301
302 pcc_io_rx:
303         switch_to_output
304
305         cmp.b           #IOSEQ_R32, d3
306         beq             pcc_io_r32
307         cmp.b           #IOSEQ_R16, d3
308         beq             pcc_io_r16
309         cmp.b           #IOSEQ_R8, d3
310         bne             return
311
312 pcc_io_r8:
313         move.b          (a2),d0
314         bsr             send_byte
315         bra             pcc_io_loop
316
317 pcc_io_r16:
318         move.w          (a2),d3
319         move.w          d3,d0
320         lsr.w           #8,d0
321         bsr             send_byte
322         move.b          d3,d0
323         bsr             send_byte
324         bra             pcc_io_loop
325
326 pcc_io_r32:
327         move.l          (a2),d3
328         move.l          d3,d0
329         swap            d0
330         lsr.l           #8,d0
331         bsr             send_byte
332         move.l          d3,d0
333         swap            d0
334         bsr             send_byte
335         move.w          d3,d0
336         lsr.w           #8,d0
337         bsr             send_byte
338         move.b          d3,d0
339         bsr             send_byte
340         bra             pcc_io_loop
341
342
343 /* PicoDrive savestate load */
344 pcc_loadstate:
345         /* write VRAM */
346         move.l          #0xc00000,a0
347         move.w          #0x8f02,4(a0)           /* auto increment 2 */
348
349         move.l          #0x40000000,4(a0)
350         move.l          #0x10000/2-1,d3
351 tr_do_vram_loop:
352         bsr             recv_word
353         move.w          d0,(a0)
354         dbra            d3, tr_do_vram_loop
355
356         /* write cram */
357         move.l          #0xc0000000,4(a0)
358         move.l          #0x80/2-1,d3
359 tr_do_cram_loop:
360         bsr             recv_word
361         move.w          d0,(a0)
362         dbra            d3, tr_do_cram_loop
363
364         /* write vsram */
365         move.l          #0x40000010,4(a0)
366         move.l          #0x80/2-1,d3
367 tr_do_vsram_loop:
368         bsr             recv_word
369         move.w          d0,(a0)
370         dbra            d3, tr_do_vsram_loop
371
372         /* recv and write regs */
373         lea             0xffe000,a3
374         move.l          a3,a2
375         moveq.l         #0x20-1,d3
376 tr_do_vdpreg_recv_loop:
377         bsr             recv_byte
378         move.b          d0,(a2)+
379         dbra            d3, tr_do_vdpreg_recv_loop
380
381         move.l          a3,a2
382         moveq.l         #0,d3
383 tr_do_vdpreg_loop:
384         move.b          d3,d1
385         or.b            #0x80,d1
386         lsl.w           #8,d1
387         move.b          (d3,a2),d1
388         move.w          d1,4(a0)
389         addq.l          #1,d3
390         cmp.b           #0x17,d3        /* FIXME: r23 might cause DMA or.. */
391         bne             0f              /* ..something and hang VDP.. */
392         add.b           #1,d3           /* ..so we skip it */
393 0:
394         cmp.b           #0x20,d3
395         blt             tr_do_vdpreg_loop
396
397         moveq.l         #0,d0
398         move.b          5(a3),d0
399         bsr             invalidate_sprite_cache
400
401
402 0:      bra             0b
403
404         bra             return
405
406
407 pcc_vram_send:
408         /* write VRAM */
409         move.l          #0xc00000,a0
410         move.w          #0x8f02,4(a0)           /* auto increment 2 */
411         move.l          #0,4(a0)                /* VRAM read, addr 0 */
412         move.l          #0x10000/2-1,d4
413
414         switch_to_output
415
416 tr_vram_send_loop:
417         move.w          (a0),d3
418         move.w          d3,d0
419         lsr.w           #8,d0
420         bsr             send_byte
421         move.b          d3,d0
422         bsr             send_byte
423         dbra            d4,tr_vram_send_loop
424
425         bra             return
426
427
428
429 /* some random code */
430 pcc_test_code:
431         bra             return
432
433
434
435 return:
436         move.b          #0,(0xa1000b).l /* all inputs */
437         move.l          #0xffe000,a1
438         move.l          d0,(a1)+        /* last state for debug */
439         move.l          d1,(a1)+
440         move.l          d2,(a1)+
441         move.l          d3,(a1)+
442         move.l          a0,(a1)+
443         rts
444 #       bra             return_to_main
445
446
447 # vim:filetype=asmM68k