1!   Copyright 2008 Lawrence Sebald
2!
3!   This file is part of Yabause.
4!
5!   Yabause is free software; you can redistribute it and/or modify
6!   it under the terms of the GNU General Public License as published by
7!   the Free Software Foundation; either version 2 of the License, or
8!   (at your option) any later version.
9!
10!   Yabause is distributed in the hope that it will be useful,
11!   but WITHOUT ANY WARRANTY; without even the implied warranty of
12!   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13!   GNU General Public License for more details.
14!
15!   You should have received a copy of the GNU General Public License
16!   along with Yabause; if not, write to the Free Software
17!   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
18
19!   Ok, so this is the start of me assemblerizing different parts of the core
20!   of the Dreamcast port of Yabause. I picked the CD core since its one of the
21!   parts of the emulator that is least likely to change in the future
22!   (hopefully anyway), and its somewhat simple to start with.
23
24    .file       "cd.s"
25    .little
26    .text
27    .align      2
28
29!   static int DCCDInit(const char *cdrom_name)
30!       Initialize the GD drive to read 2352 byte sectors.
31DCCDInit:
32    sts.l       pr, @-r15
33.do_reinit:
34    mov.l       .cdrom_exec_cmd, r0
35    mov         #0, r5
36    jsr         @r0
37    mov         #24, r4                 ! CMD_INIT
38    cmp/eq      #1, r0                  ! ERR_NO_DISC
39    bt          .init_return_success
40    cmp/eq      #3, r0                  ! ERR_SYS
41    bt          .init_return_error
42    mov.l       .gdc_syscall_vector, r1
43    mova        .DCCDInitParams, r0
44    mov         #10, r7
45    mov.l       @r1, r1
46    mov         r0, r4
47    mov         #0, r6
48    jsr         @r1
49    mov         #0, r5
50    lds.l       @r15+, pr
51    rts
52    nop
53.init_return_success:
54    lds.l       @r15+, pr
55    rts
56    mov         #0, r0
57.init_return_error:
58    lds.l       @r15+, pr
59    rts
60    mov         #-1, r0
61    .align 4
62.cdrom_exec_cmd:
63    .long       _cdrom_exec_cmd
64.DCCDInitParams:
65    .long       0       ! 0 = set
66    .long       4096    ! Magic value for RAW sector reads
67    .long       0x0400  ! Ditto
68    .long       2352    ! Sector Size? (Maybe not for RAW though?)
69
70!   static int DCCDGetStatus(void)
71!       Execute the BIOS syscall of the Dreamcast to get the GD drive status,
72!       translating that into the format expected by the core of Yabause.
73DCCDGetStatus:
74    sts.l       pr, @-r15
75.status_startgame:
76    mov.l       .gdc_syscall_vector, r1
77    mova        .get_status_scratchpad, r0
78    mov         #4, r7
79    mov.l       @r1, r1
80    mov         #0, r5
81    mov         r0, r4
82    jsr         @r1
83    mov         #0, r6
84    cmp/eq      #2, r0                      ! 2 = Disc change error
85    bt          .status_reinit
86    cmp/eq      #0, r0
87    bf          .status_error
88.status_endgame:                            ! status in 1st entry in scratchpad
89    mova        .get_status_scratchpad, r0
90    mov         #0x07, r2
91    mov.l       @r0, r1
92    mova        .get_status_return_value, r0
93    and         r2, r1
94    add         r1, r0
95    lds.l       @r15+, pr
96    rts
97    mov.b       @r0, r0
98.status_reinit:
99    mov.l       .get_status_init_func, r0
100    jsr         @r0
101    mov         #0, r4
102    cmp/eq      #0, r0
103    bt          .status_startgame
104.status_error:
105    lds.l       @r15+, pr
106    rts
107    mov         #2, r0
108
109    .align      4
110.gdc_syscall_vector:
111    .long       0x8c0000bc
112.get_status_scratchpad:
113    .long       0
114    .long       0
115.get_status_return_value:
116    .byte       0, 1, 1, 0, 0, 0, 3, 2
117.get_status_init_func:
118    .long       DCCDInit
119
120!   static int DCCDDeInit(void)
121!       Deinitialize the CD Drive of the Dreamcast (i.e., undo the odd
122!       initialization stuff that the code does for Yabause).
123DCCDDeInit:
124    mov.l       .cdrom_reinit, r0
125    sts.l       pr, @-r15
126    jsr         @r0
127    nop
128    lds.l       @r15+, pr
129    rts
130    nop         ! Leave the return value from cdrom_reinit as the return here.
131
132!   static int DCCDReadSectorFAD(u32 FAD, void *buffer)
133!       Read a single 2352 byte sector from the given position on the disc.
134DCCDReadSectorFAD:
135    sts.l       pr, @-r15
136    mov         r4, r2
137    mov.l       r4, @-r15
138    mov         r5, r4
139    mov.l       .cdrom_read_sectors, r0
140    mov.l       r5, @-r15
141    mov         r2, r5
142.read_sector_start:
143    jsr         @r0
144    mov         #1, r6
145    cmp/eq      #2, r0
146    bt          .read_reinit
147    cmp/eq      #0, r0
148    add         #8, r15
149    bf/s        .read_error
150    lds.l       @r15+, pr
151    rts
152    mov         #1, r0
153.read_reinit:
154    mov.l       .DCCDInit, r0
155    jsr         @r0
156    mov         #0, r4
157    cmp/eq      #0, r0
158    mov.l       @r15, r4
159    mov.l       .cdrom_read_sectors, r0
160    bt/s        .read_sector_start
161    mov.l       @(4, r15), r5
162    add         #8, r15
163.read_error:
164    rts
165    mov         #0, r0
166
167!   static int DCCDReadAheadFAD(u32 FAD)
168!       No-op (for the moment).
169DCCDReadAheadFAD:
170    rts
171    nop
172
173!   static s32 DCCDReadTOC(u32 *TOC);
174!       Read the TOC of the CD inserted in the drive.
175!       Amusingly enough, I just realized that the format that Yabause expects
176!       and what the Dreamcast spews out are exactly the same. Go figure!
177DCCDReadTOC:
178    sts.l       pr, @-r15
179    mov.l       .cdrom_read_toc, r0
180    mov.l       r4, @-r15
181.readtoc_start:
182    jsr         @r0
183    mov         #0, r5
184    cmp/eq      #2, r0
185    bt          .readtoc_reinit
186    cmp/eq      #0, r0
187    add         #4, r15
188    bf/s        .readtoc_error
189    mov         #0xCC, r0
190    lds.l       @r15+, pr
191    extu.b      r0, r0
192    rts
193    shll        r0
194.readtoc_reinit:
195    mov.l       .DCCDInit, r0
196    jsr         @r0
197    mov         #0, r4
198    cmp/eq      #0, r0
199    mov.l       @r15, r4
200    bt/s        .readtoc_start
201    mov.l       .cdrom_read_toc, r0
202    add         #4, r15
203.readtoc_error:
204    rts
205    mov         #0, r0
206
207    .align      4
208.cdrom_reinit:
209    .long       _cdrom_reinit
210.cdrom_read_sectors:
211    .long       _cdrom_read_sectors
212.DCCDInit:
213    .long       DCCDInit
214.cdrom_read_toc:
215    .long       _cdrom_read_toc
216
217    .section    .rodata
218    .align      2
219.CDInterfaceName:
220    .string     "Dreamcast CD Drive"
221
222    .data
223    .align      4
224    .globl      _ArchCD
225    .size       _ArchCD, 32
226_ArchCD:
227    .long       2
228    .long       .CDInterfaceName
229    .long       DCCDInit
230    .long       DCCDDeInit
231    .long       DCCDGetStatus
232    .long       DCCDReadTOC
233    .long       DCCDReadSectorFAD
234    .long       DCCDReadAheadFAD
235