; This is designed to be serial-line downloaded to cdcode. ; ; Our memory map: ; ; [8c000000,8c010000) Stack (r15 set by cdcode) ; [8c010000,8c01????) cdcode ; [8c020000,8c02????) Us ; ; This program constantly watches the Maple bus, printing the ; configuration whenever it changes. Output looks like ; ; 0001 000e 0000 0000 0000 0000 ; 0001 000e 0100 0000 0000 0000 ; 0000 0000 0000 0000 0000 0000 ; 0040 0000 0000 0000 0000 0000 ; A: Main=Controller Sub1=Clock/LCD/Memory ; B: Main=Controller Sub1=Clock/LCD/Memory Sub2=Puru-puru ; C: Nothing there ; D: Main=Keyboard ; ; (which is real output from a system with a controller with a memory ; card in A and B, with a rumble pack in the B controller's lower ; slot, and a keyboard in port D). .include "regs.s" .include "maple-bits.s" DELAY_TIME = 10000000 . = 0x8c020000 .entry . .sz any .pr any SETS.L #main,r0 jmp @r0 nop SETCONST ; Our "data segment". bss: .align 32 cmd: .space 64 .align 32 resp: .space 1024 cur: ; port A .space 2 ; Function code(s), main .space 2 ; Function code(s), sub 1 .space 2 ; Function code(s), sub 2 .space 2 ; Function code(s), sub 3 .space 2 ; Function code(s), sub 4 .space 2 ; Function code(s), sub 5 ; ports B, C, and D .space [. - cur] * 3 endcur: prev: .space endcur - cur endbss: clear_bss: SETS.L #bss,r0 SETS.L #endbss,r1 xor r2,r2 1: cmp/hi r0,r1 bf 1f bra 1b mov.b r2,@-r1 1: rts nop hex8s: mov.l r1,@-r15 SETS.L #putspace,r1 bra hex8merge nop hex8n: mov.l r1,@-r15 SETS.L #crlf,r1 hex8merge: sts.l pr,@-r15 mov.l r0,@-r15 mov.l r1,@-r15 bsr printhex8 mov.l @(12,r15),r1 mov.l @r15+,r1 jsr @r1 nop mov.l @r15+,r0 lds.l @r15+,pr mov.l @r15+,r1 rts add #4,r15 build_cur_addrs: .byte ADDR_MAIN .byte ADDR_SUB1 .byte ADDR_SUB2 .byte ADDR_SUB3 .byte ADDR_SUB4 .byte ADDR_SUB5 build_cur: sts.l pr,@-r15 SETS.L #build_cur_addrs,r6 SETS.L #cur,r5 SETS.L #3,r9 ; Maple port # 4: SETS.L #0,r8 ; subunit index SETS.L #6,r7 ; subunit loop count 3: SETS.L #cmd,r1 ; First longword: XDESC_LAST | [r9 << XDESC_PORTSHIFT] | [0 << XDESC_LENSHIFT] SETS.L #XDESC_LAST,r0 mov r9,r2 SHLL #XDESC_PORTSHIFT,r2/r3 or r2,r0 mov.l r0,@r1 ; Second longword: resp & DMA_ADDRMASK SETS.L #[resp&DMA_ADDRMASK],r0 mov.l r0,@(4,r1) ; Third longword: MapleFrame CMD_DEVINFO, r9, build_cur_addrs[r8], r9, 0, 0 ; which means, because of the byteswapping, ; [r9 << ADDR_PORTSHIFT] << [24-FRAME_SSHIFT] | ; [[r9 << ADDR_PORTSHIFT] | build_cur_addrs[r8]] << [24-FRAME_RSHIFT] | ; CMD_DEVINFO mov r9,r0 SHLL #ADDR_PORTSHIFT,r0/r2 mov r0,r2 SHLL #[24-FRAME_SSHIFT],r0/r3 mov r6,r3 add r8,r3 mov.b @r3,r4 or r4,r2 SHLL #[24-FRAME_RSHIFT],r2/r3 or r2,r0 .if @IS_UB[CMD_DEVINFO] or #CMD_DEVINFO,r0 .else SETS.L #CMD_DEVINFO,r3 or r3,r0 .endif mov.l r0,@(8,r1) ; Command frame now complete. Send it and wait for completion. ocbp @r1 SETS.L #BUS_DMAADDR,r0 SETS.L #DMA_ADDRMASK,r2 and r2,r1 mov.l r1,@r0 SETS.L #BUS_STATE,r3 SETS.L #BUS_STATE_GO,r0 mov.l r0,@r3 1: mov.l @r3,r0 tst #BUS_STATE_RUNNING,r0 bf 1b ; See what we got. SETS.L #resp,r1 ocbi @r1 mov.l @r1,r0 not r0,r0 tst r0,r0 bt 1f ; Response isn't ffffffff not r0,r2 SHLR #24,r2/r3 cmp/pl r2 bf 5f mov.l @(4,r1),r0 swap.w r0,r0 bra 2f swap.b r0,r1 5: ; Not ffffffff, but response too short (can this happen?) SETS.L #0xffff,r1 bra 2f nop 1: ; Response is ffffffff xor r1,r1 2: mov r9,r0 SETS.L #6,r2 mul.l r2,r0 sts macl,r0 add r8,r0 add r0,r0 mov.w r1,@(r0,r5) dt r7 bf/s 3b add #1,r8 add #-1,r9 cmp/pz r9 bt 4b lds.l @r15+,pr rts nop .align 4 substrs: .long str_main .long str_sub1 .long str_sub2 .long str_sub3 .long str_sub4 .long str_sub5 funcstrs: .long func_001 .long func_002 .long func_004 .long func_008 .long func_010 .long func_020 .long func_040 .long func_080 .long func_100 .long func_200 str_main: .asciz "Main" str_sub1: .asciz "Sub1" str_sub2: .asciz "Sub2" str_sub3: .asciz "Sub3" str_sub4: .asciz "Sub4" str_sub5: .asciz "Sub5" func_001: .asciz "Controller" func_002: .asciz "Memory" func_004: .asciz "LCD" func_008: .asciz "Clock" func_010: .asciz "Microphone" func_020: .asciz "AR-gun" func_040: .asciz "Keyboard" func_080: .asciz "Light-gun" func_100: .asciz "Puru-puru" func_200: .asciz "Mouse" connletters: .ascii "ABCD" str_nothing: .asciz "Nothing" str_nothing_there: .asciz "Nothing there" str_weird: .asciz "Weird" .align 2 dump_cur: sts.l pr,@-r15 SETS.L #cur,r7 SETS.L #4,r9 2: SETS.L #6,r8 1: mov.w @r7,r1 bsr printhexN mov #4,r0 dt r8 bt 1f bsr putchar mov #' ,r1 bra 1b add #2,r7 1: bsr crlf nop dt r9 add #2,r7 bf 2b SETS.L #cur,r7 SETS.L #0,r9 ; port # dc_port_loop: SETS.L #connletters,r0 bsr putchar mov.b @(r0,r9),r1 bsr putchar mov #':,r1 bsr putchar mov #' ,r1 mov r9,r0 SETS.L #6*2,r1 mul.l r1,r0 sts macl,r0 mov.w @(r0,r7),r6 tst r6,r6 bt dc_nothing_line not r6,r6 tst r6,r6 bf dc_something_line ; Weird error SETS.L #str_weird,r0 bsr putz nop bra dc_line_done nop dc_nothing_line: ; Nothing there SETS.L #str_nothing_there,r0 bsr putz nop bra dc_line_done nop dc_something_line: ; Something there mov.l r7,@-r15 mov.l r9,@-r15 SETS.L #0,r9 ; printed-anything-p SETS.L #0,r8 ; subunit index add r0,r7 dc_unit_loop: mov.w @r7,r6 tst r6,r6 bt dc_unit_done not r6,r6 tst r6,r6 bf dc_unit_present ; Weird error bsr print_r8_sub nop bsr putchar mov #'=,r1 SETS.L #str_weird,r0 bsr putz nop bra dc_unit_done dc_unit_present: tst r9,r9 bt 1f bsr putchar mov #' ,r1 1: SETS.L #1,r9 bsr print_r8_sub not r6,r6 SETS.L #0x200,r5 SETS.L #9*4,r4 SETS.L #'=,r3 dc_func_loop: tst r5,r6 bt 1f bsr putchar mov r3,r1 SETS.L #'/,r3 SETS.L #funcstrs,r0 mov.l @(r0,r4),r0 bsr putz nop 1: add #-4,r4 SHLR #1,r5/r0 tst r5,r5 bf dc_func_loop add #-'=,r3 tst r3,r3 bf dc_unit_done SETS.L #str_weird,r0 bsr putz nop bsr putchar mov #'(,r1 mov r6,r1 bsr printhexN mov #4,r0 bsr putchar mov #'),r1 dc_unit_done: add #2,r7 add #1,r8 SETS.L #6,r0 cmp/gt r8,r0 bt dc_unit_loop mov.l @r15+,r9 mov.l @r15+,r7 dc_line_done: bsr crlf add #1,r9 SETS.L #4,r0 cmp/gt r9,r0 bt dc_port_loop lds.l @r15+,pr rts nop print_r8_sub: sts.l pr,@-r15 SETS.L #substrs,r1 mov r8,r0 add r0,r0 add r0,r0 bsr putz mov.l @(r0,r1),r0 lds.l @r15+,pr rts nop maybe_dump_cur: SETS.L #cur,r9 SETS.L #prev,r8 SETS.L #endcur-cur,r7 1: mov.b @r8+,r1 mov.b @r9+,r0 cmp/eq r1,r0 bf 1f dt r7 bf 1b rts nop 1: bra 1f add #-1,r8 2: mov.b @r9+,r0 1: mov.b r0,@r8 dt r7 bf/s 2b add #1,r8 bra dump_cur nop ; The only things startup.s sets up that cdcode hasn't already done for ; us are (1) fpscr and (2) clearing bss. We don't have bss because we ; aren't linked by a conventional linker, and we don't use floating ; point so we don't care about fpscr. So we have nothing to do here. ; Just dive straight into the code. .align 2 main: bsr init_hw nop bsr clear_bss nop 1: bsr build_cur nop bsr maybe_dump_cur nop bsr nbgetchar nop cmp/pz r0 bf 1b bsr crlf nop lds r11,pr rts nop init_hw: mova 9f,r0 1: mov.l @r0+,r1 tst r1,r1 bt 1f mov.l @r0+,r2 bra 1b mov.l r2,@r1 1: rts nop .align 4 9: .long BUS_RESET, BUS_RESET_VALUE .long BUS_RESET2, BUS_RESET2_VALUE .long BUS_SPEED, SPEED_2MBPS|[50000< 2 no < 2 no v 2 no ^ 2 no D no X yes Y yes Z no > yes < yes v yes ^ yes START yes A yes B yes C no CMD_EXTINFO on ADDR_MAIN on a controller on port A with a VMU in the top socket returns: 06 - RESP_EXTINFO 00 - receiving ID (port 0, Dreamcast) 21 - sending ID (port 0, ADDR_MAIN | ADDR_SUB1) 30 - count of following words 01000000 - func (controller) 00003021 - controller info 00000000 - unused 00000000 - unused ff - area code 00 - connector direction 7244 - product name ("Dreamcast Controller ") 636d6165 20747361 746e6f43 6c6c6f72 20207265 20202020 20202020 646f7250 - product license ("Produced By or Under License From SEGA ENTERPRISES,LTD. ") 64656375 20794220 5520726f 7265646e 63694c20 65736e65 6f724620 4553206d 45204147 5245544e 53495250 4c2c5345 202e4454 20202020 01ae - standby power (430) 01f4 - max power (500) 73726556 - versionstring ("Version 1.000,1998/05/11,315-6125-AB ,Analog Module : The 4th Edition. 05/08 ") 206e6f69 30302e31 39312c30 302f3839 31312f35 3531332c 3231362d 42412d35 2c202020 6c616e41 4d20676f 6c75646f 203a2065 20656854 20687434 74696445 2e6e6f69 2f353020 20203830 CMD_EXTINFO on ADDR_SUB1 on a controller on port A with a VMU in the top socket returns: 06 - RESP_EXTINFO 00 - receiving ID (port 0, Dreamcast) 01 - sending ID (port 0, ADDR_SUB1) 30 - count of following words 0e000000 - func (clock, LCD, memory) 403f7e7e - clock info 00100500 - LCD info 00410f00 - memory card info ff - region code 00 - connector direction 6956 - product name ("Visual Memory ") 6c617573 6d654d20 2079726f 20202020 20202020 20202020 20202020 646f7250 - product license ("Produced By or Under License From SEGA ENTERPRISES,LTD. ") 64656375 20794220 5520726f 7265646e 63694c20 65736e65 6f724620 4553206d 45204147 5245544e 53495250 4c2c5345 202e4454 20202020 007c - standby power (124) 0082 - max power (130) 73726556 - versionstring ("Version 1.005,1999/10/26,315-6208-05,SEGA Visual Memory System BIOS Produced by ") 206e6f69 30302e31 39312c35 312f3939 36322f30 3531332c 3032362d 35302d38 4745532c 69562041 6c617573 6d654d20 2079726f 74737953 42206d65 20534f49 646f7250 64656375 20796220 CMD_DEVINFO on ADDR_SUB2 on a controller on port A with a rumble pack in slot 2: 05 - RESP_DEVINFO 00 - receiving ID (port 0, Dreamcast) 02 - sending ID (port 0, ADDR_SUB2) 1c - count of following words 00010000 - func (Puru-Puru pack) 00000101 - Puru-Puru pack info 00000000 - unused 00000000 - unused ff - region code 00 - connector direction 7550 - product name ("Puru Puru Pack ") 50207572 20757275 6b636150 20202020 20202020 20202020 20202020 646f7250 - product license ("Produced By or Under License From SEGA ENTERPRISES,LTD. ") 64656375 20794220 5520726f 7265646e 63694c20 65736e65 6f724620 4553206d 45204147 5245544e 53495250 4c2c5345 202e4454 20202020 00c8 - standby power (200) 0640 - max power (1600) CMD_DEVINFO on ADDR_MAIN on a keyboard on port B: 05 - RESP_DEVINFO 40 - receiving ID (port 1, Dreamcast) 60 - sending ID (port 1, ADDR_MAIN) 1c - count of following words 40000000 - func (keyboard) 80000502 - keyboard info (02 - US keyboard) 00000000 - unused 00000000 - unused 01 - region code 00 - connector direction 654b - product name ("Keyboard ") 616f6279 20206472 20202020 20202020 20202020 20202020 20202020 646f7250 - product license ("Produced By or Under License From SEGA ENTERPRISES,LTD. ") 64656375 20794220 5520726f 7265646e 63694c20 65736e65 6f724620 4553206d 45204147 5245544e 53495250 4c2c5345 202e4454 20202020 012c - standby power (300) 0190 - max power (400) CMD_GETCOND on ADDR_MAIN on a keyboard on port B: 08 - RESP_DATA 40 - receiving ID (port 1, Dreamcast) 60 - sending ID (port 1, ADDR_MAIN) 03 - count 40000000 - func (keyboard) 00 - shift state 0x01 - left Ctrl 0x02 - left Shift 0x04 - left Alt 0x08 - (left) S1 0x10 - right Ctrl 0x20 - right Shift 0x40 - right Alt 0x80 - (right) S2 00 - LED state (?) 0000 - up to 6 keys down; any value < 4 terminates the list 00000000 04 A 05 B 06 C 07 D 08 E 09 F 0a G 0b H 0c I 0d J 0e K 0f L 10 M 11 N 12 O 13 P 14 Q 15 R 16 S 17 T 18 U 19 V 1a W 1b X 1c Y 1d Z 1e 1 ! 1f 2 @ 20 3 # 21 4 $ 22 5 % 23 6 ^ 24 7 & 25 8 * 26 9 ( 27 0 ) 28 Enter 29 Esc 2a Backspace 2b Tab 2c space 2d - _ 2e = + 2f [ { 30 ] } 31 \ | 33 ; : 34 ' " 35 ` ~ 36 , < 37 . > 38 / ? 39 CapsLock 3a F1 3b F2 3c F3 3d F4 3e F5 3f F6 40 F7 41 F8 42 F9 43 F10 44 F11 45 F12 46 PrtScr/SysRq 47 ScrollLock 48 Pause/Break 49 Insert 4a Home 4b PageUp 4c Delete 4d End 4e PageDown 4f rightarrow 50 leftarrow 51 downarrow 52 uparrow 53 NumLock 54 (keypad) / 55 (keypad) * 56 (keypad) - 57 (keypad) + 58 (keypad) Enter 59 (keypad) 1 5a (keypad) 2 5b (keypad) 3 5c (keypad) 4 5d (keypad) 5 5e (keypad) 6 5f (keypad) 7 60 (keypad) 8 61 (keypad) 9 62 (keypad) 0 63 (keypad) . 65 S3 .endif