Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/cs2.c
2 views
1
/* Copyright 2003 Guillaume Duhamel
2
Copyright 2004-2006 Theo Berkau
3
4
This file is part of Yabause.
5
6
Yabause is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
11
Yabause is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
15
16
You should have received a copy of the GNU General Public License
17
along with Yabause; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
*/
20
21
#include <stdlib.h>
22
#include <ctype.h>
23
#include "cs2.h"
24
#include "debug.h"
25
#include "error.h"
26
#include "netlink.h"
27
#include "scsp.h"
28
#include "scu.h"
29
#include "smpc.h"
30
#include "yui.h"
31
32
#define CDB_HIRQ_CMOK 0x0001
33
#define CDB_HIRQ_DRDY 0x0002
34
#define CDB_HIRQ_CSCT 0x0004
35
#define CDB_HIRQ_BFUL 0x0008
36
#define CDB_HIRQ_PEND 0x0010
37
#define CDB_HIRQ_DCHG 0x0020
38
#define CDB_HIRQ_ESEL 0x0040
39
#define CDB_HIRQ_EHST 0x0080
40
#define CDB_HIRQ_ECPY 0x0100
41
#define CDB_HIRQ_EFLS 0x0200
42
#define CDB_HIRQ_SCDQ 0x0400
43
#define CDB_HIRQ_MPED 0x0800
44
#define CDB_HIRQ_MPCM 0x1000
45
#define CDB_HIRQ_MPST 0x2000
46
47
#define CDB_STAT_BUSY 0x00
48
#define CDB_STAT_PAUSE 0x01
49
#define CDB_STAT_STANDBY 0x02
50
#define CDB_STAT_PLAY 0x03
51
#define CDB_STAT_SEEK 0x04
52
#define CDB_STAT_SCAN 0x05
53
#define CDB_STAT_OPEN 0x06
54
#define CDB_STAT_NODISC 0x07
55
#define CDB_STAT_RETRY 0x08
56
#define CDB_STAT_ERROR 0x09
57
#define CDB_STAT_FATAL 0x0A
58
#define CDB_STAT_PERI 0x20
59
#define CDB_STAT_TRNS 0x40
60
#define CDB_STAT_WAIT 0x80
61
#define CDB_STAT_REJECT 0xFF
62
63
#define CDB_PLAYTYPE_SECTOR 0x01
64
#define CDB_PLAYTYPE_FILE 0x02
65
66
Cs2 * Cs2Area = NULL;
67
ip_struct *cdip = NULL;
68
69
extern CDInterface *CDCoreList[];
70
71
//////////////////////////////////////////////////////////////////////////////
72
73
static INLINE void doCDReport(u8 status)
74
{
75
Cs2Area->reg.CR1 = (status << 8) | ((Cs2Area->options & 0xF) << 4) | (Cs2Area->repcnt & 0xF);
76
Cs2Area->reg.CR2 = (Cs2Area->ctrladdr << 8) | Cs2Area->track;
77
Cs2Area->reg.CR3 = (u16)((Cs2Area->index << 8) | ((Cs2Area->FAD >> 16) & 0xFF));
78
Cs2Area->reg.CR4 = (u16) Cs2Area->FAD;
79
}
80
81
//////////////////////////////////////////////////////////////////////////////
82
83
static INLINE void doMPEGReport(u8 status)
84
{
85
Cs2Area->reg.CR1 = (status << 8) | Cs2Area->actionstatus;
86
Cs2Area->reg.CR2 = Cs2Area->vcounter;
87
Cs2Area->reg.CR3 = (Cs2Area->pictureinfo << 8) | Cs2Area->mpegaudiostatus;
88
Cs2Area->reg.CR4 = Cs2Area->mpegvideostatus;
89
}
90
91
//////////////////////////////////////////////////////////////////////////////
92
93
u8 FASTCALL Cs2ReadByte(u32 addr)
94
{
95
addr &= 0xFFFFF; // fix me(I should really have proper mapping)
96
97
if(Cs2Area->carttype == CART_NETLINK)
98
return NetlinkReadByte(addr);
99
else
100
{
101
// only netlink seems to use byte-access
102
switch (addr)
103
{
104
case 0x95001:
105
case 0x95005:
106
case 0x95009:
107
case 0x9500D:
108
case 0x95011:
109
case 0x95015:
110
case 0x95019:
111
case 0x9501D:
112
return 0xFF;
113
default:
114
break;
115
}
116
}
117
118
LOG("Unimplemented cs2 byte read: %08X\n", addr);
119
return 0xFF;
120
}
121
122
//////////////////////////////////////////////////////////////////////////////
123
124
void FASTCALL Cs2WriteByte(u32 addr, u8 val)
125
{
126
addr &= 0xFFFFF; // fix me(I should really have proper mapping)
127
128
if(Cs2Area->carttype == CART_NETLINK)
129
{
130
NetlinkWriteByte(addr, val);
131
return;
132
}
133
else
134
{
135
// only netlink seems to use byte-access
136
switch (addr)
137
{
138
case 0x2503D:
139
case 0x95011:
140
case 0x9501D:
141
return;
142
default:
143
break;
144
}
145
}
146
147
LOG("Unimplemented cs2 byte write: %08X\n", addr);
148
}
149
150
//////////////////////////////////////////////////////////////////////////////
151
152
u16 FASTCALL Cs2ReadWord(u32 addr) {
153
u16 val = 0;
154
addr &= 0xFFFFF; // fix me(I should really have proper mapping)
155
156
switch(addr) {
157
case 0x90008:
158
case 0x9000A:
159
val = Cs2Area->reg.HIRQ;
160
161
if (Cs2Area->isbufferfull)
162
val |= CDB_HIRQ_BFUL;
163
else
164
val &= ~CDB_HIRQ_BFUL;
165
166
if (Cs2Area->isdiskchanged)
167
val |= CDB_HIRQ_DCHG;
168
else
169
val &= ~CDB_HIRQ_DCHG;
170
171
if (Cs2Area->isonesectorstored)
172
val |= CDB_HIRQ_CSCT;
173
else
174
val &= ~CDB_HIRQ_CSCT;
175
176
Cs2Area->reg.HIRQ = val;
177
178
// CDLOG("cs2\t: Hirq read, Hirq mask = %x - ret: %x\n", Memory::getWord(0x9000C), val);
179
return val;
180
case 0x9000C:
181
case 0x9000E: return Cs2Area->reg.HIRQMASK;
182
case 0x90018:
183
case 0x9001A: return Cs2Area->reg.CR1;
184
case 0x9001C:
185
case 0x9001E: return Cs2Area->reg.CR2;
186
case 0x90020:
187
case 0x90022: return Cs2Area->reg.CR3;
188
case 0x90024:
189
case 0x90026: Cs2Area->_command = 0;
190
return Cs2Area->reg.CR4;
191
case 0x90028:
192
case 0x9002A: return Cs2Area->reg.MPEGRGB;
193
case 0x98000:
194
// transfer info
195
switch (Cs2Area->infotranstype) {
196
case 0:
197
// Get Toc Data
198
if (Cs2Area->transfercount % 4 == 0)
199
val = (u16)((Cs2Area->TOC[Cs2Area->transfercount >> 2] & 0xFFFF0000) >> 16);
200
else
201
val = (u16)Cs2Area->TOC[Cs2Area->transfercount >> 2];
202
203
Cs2Area->transfercount += 2;
204
Cs2Area->cdwnum += 2;
205
206
if (Cs2Area->transfercount > (0xCC * 2))
207
{
208
Cs2Area->transfercount = 0;
209
Cs2Area->infotranstype = -1;
210
}
211
break;
212
case 1:
213
// Get File Info(1 file info)
214
val = (Cs2Area->transfileinfo[Cs2Area->transfercount] << 8) |
215
Cs2Area->transfileinfo[Cs2Area->transfercount + 1];
216
Cs2Area->transfercount += 2;
217
Cs2Area->cdwnum += 2;
218
219
if (Cs2Area->transfercount > (0x6 * 2))
220
{
221
Cs2Area->transfercount = 0;
222
Cs2Area->infotranstype = -1;
223
}
224
225
break;
226
case 2:
227
// Get File Info(254 file info)
228
229
// Do we need to retrieve the next file info?
230
if (Cs2Area->transfercount % (0x6 * 2) == 0) {
231
// yes we do
232
Cs2SetupFileInfoTransfer(2 + (Cs2Area->transfercount / (0x6 * 2)));
233
}
234
235
val = (Cs2Area->transfileinfo[Cs2Area->transfercount % (0x6 * 2)] << 8) |
236
Cs2Area->transfileinfo[Cs2Area->transfercount % (0x6 * 2) + 1];
237
238
Cs2Area->transfercount += 2;
239
Cs2Area->cdwnum += 2;
240
241
if (Cs2Area->transfercount > (254 * (0x6 * 2)))
242
{
243
Cs2Area->transfercount = 0;
244
Cs2Area->infotranstype = -1;
245
}
246
247
break;
248
default: break;
249
}
250
break;
251
default:
252
LOG("cs2\t: Undocumented register read %08X\n", addr);
253
// val = T3ReadWord(Cs2Area->mem, addr);
254
break;
255
}
256
257
return val;
258
}
259
260
//////////////////////////////////////////////////////////////////////////////
261
262
void FASTCALL Cs2WriteWord(u32 addr, u16 val) {
263
addr &= 0xFFFFF; // fix me(I should really have proper mapping)
264
265
switch(addr) {
266
case 0x90008:
267
case 0x9000A:
268
Cs2Area->reg.HIRQ &= val;
269
return;
270
case 0x9000C:
271
case 0x9000E: Cs2Area->reg.HIRQMASK = val;
272
return;
273
case 0x90018:
274
case 0x9001A: Cs2Area->status &= ~CDB_STAT_PERI;
275
Cs2Area->_command = 1;
276
Cs2Area->reg.CR1 = val;
277
return;
278
case 0x9001C:
279
case 0x9001E: Cs2Area->reg.CR2 = val;
280
return;
281
case 0x90020:
282
case 0x90022: Cs2Area->reg.CR3 = val;
283
return;
284
case 0x90024:
285
case 0x90026: Cs2Area->reg.CR4 = val;
286
Cs2SetCommandTiming(Cs2Area->reg.CR1 >> 8);
287
return;
288
case 0x90028:
289
case 0x9002A: Cs2Area->reg.MPEGRGB = val;
290
return;
291
default:
292
LOG("cs2\t:Undocumented register write %08X\n", addr);
293
// T3WriteWord(Cs2Area->mem, addr, val);
294
break;
295
}
296
}
297
298
//////////////////////////////////////////////////////////////////////////////
299
300
u32 FASTCALL Cs2ReadLong(u32 addr) {
301
s32 i;
302
u32 val = 0;
303
addr &= 0xFFFFF; // fix me(I should really have proper mapping)
304
305
switch(addr) {
306
case 0x90008:
307
val = Cs2Area->reg.HIRQ;
308
309
if (Cs2Area->isbufferfull)
310
val |= CDB_HIRQ_BFUL;
311
else
312
val &= ~CDB_HIRQ_BFUL;
313
314
if (Cs2Area->isdiskchanged)
315
val |= CDB_HIRQ_DCHG;
316
else
317
val &= ~CDB_HIRQ_DCHG;
318
319
if (Cs2Area->isonesectorstored)
320
val |= CDB_HIRQ_CSCT;
321
else
322
val &= ~CDB_HIRQ_CSCT;
323
324
Cs2Area->reg.HIRQ = (u16)val;
325
326
val |= (val << 16);
327
return val;
328
case 0x9000C: return ((Cs2Area->reg.HIRQMASK << 16) | Cs2Area->reg.HIRQMASK);
329
case 0x90018: return ((Cs2Area->reg.CR1 << 16) | Cs2Area->reg.CR1);
330
case 0x9001C: return ((Cs2Area->reg.CR2 << 16) | Cs2Area->reg.CR2);
331
case 0x90020: return ((Cs2Area->reg.CR3 << 16) | Cs2Area->reg.CR3);
332
case 0x90024: Cs2Area->_command = 0;
333
return ((Cs2Area->reg.CR4 << 16) | Cs2Area->reg.CR4);
334
case 0x90028: return ((Cs2Area->reg.MPEGRGB << 16) | Cs2Area->reg.MPEGRGB);
335
case 0x18000:
336
// transfer data
337
if (Cs2Area->datatranstype != -1)
338
{
339
// get sector
340
341
// Make sure we still have sectors to transfer
342
if (Cs2Area->datanumsecttrans < Cs2Area->datasectstotrans)
343
{
344
// Transfer Data
345
const u8 *ptr = &Cs2Area->datatranspartition->block[Cs2Area->datanumsecttrans]->data[Cs2Area->datatransoffset];
346
#ifdef WORDS_BIGENDIAN
347
val = *((const u32 *) ptr);
348
#else
349
val = BSWAP32(*((const u32 *) ptr));
350
#endif
351
352
// increment datatransoffset/cdwnum
353
Cs2Area->cdwnum += 4;
354
Cs2Area->datatransoffset += 4;
355
356
// Make sure we're not beyond the sector size boundry
357
if (Cs2Area->datatransoffset >= Cs2Area->datatranspartition->block[Cs2Area->datanumsecttrans]->size)
358
{
359
Cs2Area->datatransoffset = 0;
360
Cs2Area->datanumsecttrans++;
361
}
362
}
363
else
364
{
365
if (Cs2Area->datatranstype == 2)
366
{
367
// Ok, so we don't have any more sectors to
368
// transfer, might as well delete them all.
369
370
Cs2Area->datatranstype = -1;
371
372
// free blocks
373
for (i = Cs2Area->datatranssectpos; i < (Cs2Area->datatranssectpos+Cs2Area->datasectstotrans); i++)
374
{
375
Cs2FreeBlock(Cs2Area->datatranspartition->block[i]);
376
Cs2Area->datatranspartition->block[i] = NULL;
377
Cs2Area->datatranspartition->blocknum[i] = 0xFF;
378
}
379
380
// sort remaining blocks
381
Cs2SortBlocks(Cs2Area->datatranspartition);
382
383
Cs2Area->datatranspartition->size -= Cs2Area->cdwnum;
384
Cs2Area->datatranspartition->numblocks -= Cs2Area->datasectstotrans;
385
386
CDLOG("cs2\t: datatranspartition->size = %x\n", Cs2Area->datatranspartition->size);
387
}
388
}
389
}
390
break;
391
default:
392
LOG("cs2\t: Undocumented register read %08X\n", addr);
393
// val = T3ReadLong(Cs2Area->mem, addr);
394
break;
395
}
396
397
return val;
398
}
399
400
//////////////////////////////////////////////////////////////////////////////
401
402
void FASTCALL Cs2WriteLong(UNUSED u32 addr, UNUSED u32 val) {
403
LOG("cs2\t: Long writing isn't implemented\n");
404
// T3WriteLong(Cs2Area->mem, addr, val);
405
}
406
407
//////////////////////////////////////////////////////////////////////////////
408
409
/* Copy "count" 32-bit words from the CD buffer to type-1 memory "dest" (a
410
* native pointer), as though 0x25818000 had been read that many times */
411
412
void FASTCALL Cs2RapidCopyT1(void *dest, u32 count)
413
{
414
u8 *dest8 = (u8 *) dest;
415
416
if (Cs2Area->datatranstype != -1)
417
{
418
// Copy as many sectors as we have left, one sector at a time
419
420
while (count > 0 && Cs2Area->datanumsecttrans < Cs2Area->datasectstotrans)
421
{
422
const u8 *src = &Cs2Area->datatranspartition->block[Cs2Area->datanumsecttrans]->data[Cs2Area->datatransoffset];
423
const u32 size = Cs2Area->datatranspartition->block[Cs2Area->datanumsecttrans]->size;
424
const u32 max = size - Cs2Area->datatransoffset;
425
const u32 copy = (max < count*4) ? max : count*4;
426
memcpy(dest8, src, copy);
427
dest8 += copy;
428
count -= copy/4;
429
Cs2Area->datatransoffset += copy;
430
Cs2Area->cdwnum += copy;
431
432
// Update the sector index if we reached the end of the sector
433
if (Cs2Area->datatransoffset >= size)
434
{
435
Cs2Area->datatransoffset = 0;
436
Cs2Area->datanumsecttrans++;
437
}
438
}
439
440
// If we're in delete mode and we read through everything in memory,
441
// delete the sectors
442
if (Cs2Area->datatranstype == 2
443
&& Cs2Area->datanumsecttrans >= Cs2Area->datasectstotrans)
444
{
445
u32 i;
446
447
Cs2Area->datatranstype = -1;
448
449
for (i = Cs2Area->datatranssectpos; i < (Cs2Area->datatranssectpos+Cs2Area->datasectstotrans); i++)
450
{
451
Cs2FreeBlock(Cs2Area->datatranspartition->block[i]);
452
Cs2Area->datatranspartition->block[i] = NULL;
453
Cs2Area->datatranspartition->blocknum[i] = 0xFF;
454
}
455
456
Cs2SortBlocks(Cs2Area->datatranspartition);
457
458
Cs2Area->datatranspartition->size -= Cs2Area->cdwnum;
459
Cs2Area->datatranspartition->numblocks -= Cs2Area->datasectstotrans;
460
461
CDLOG("cs2\t: datatranspartition->size = %x\n", Cs2Area->datatranspartition->size);
462
}
463
}
464
465
if (count > 0)
466
{
467
// We tried to copy more data than was stored, so fill the rest of
468
// the buffer with dummy data
469
memset(dest8, 0xCD, count*4);
470
}
471
}
472
473
//////////////////////////////////////////////////////////////////////////////
474
475
/* Copy "count" 32-bit words from the CD buffer to type-2 memory "dest" (a
476
* native pointer), as though 0x25818000 had been read that many times */
477
478
void FASTCALL Cs2RapidCopyT2(void *dest, u32 count)
479
{
480
u32 *dest32 = (u32 *) dest;
481
482
if (Cs2Area->datatranstype != -1)
483
{
484
// Copy as many sectors as we have left, one sector at a time; copy
485
// four words at a time where possible to improve data parallelism
486
487
while (count > 0 && Cs2Area->datanumsecttrans < Cs2Area->datasectstotrans)
488
{
489
const u8 *src = &Cs2Area->datatranspartition->block[Cs2Area->datanumsecttrans]->data[Cs2Area->datatransoffset];
490
const u32 size = Cs2Area->datatranspartition->block[Cs2Area->datanumsecttrans]->size;
491
const u32 max = size - Cs2Area->datatransoffset;
492
const u32 copy = (max < count*4) ? max : count*4;
493
u32 i = 0;
494
if (copy >= 16) {
495
for (; i < copy-12; i += 16, src += 16, dest32 += 4)
496
{
497
u32 word0, word1, word2, word3;
498
#ifdef WORDS_BIGENDIAN
499
word0 = ((u32 *)src)[0];
500
word1 = ((u32 *)src)[1];
501
word2 = ((u32 *)src)[2];
502
word3 = ((u32 *)src)[3];
503
#else
504
word0 = BSWAP16(((u32 *)src)[0]);
505
word1 = BSWAP16(((u32 *)src)[1]);
506
word2 = BSWAP16(((u32 *)src)[2]);
507
word3 = BSWAP16(((u32 *)src)[3]);
508
#endif
509
dest32[0] = word0;
510
dest32[1] = word1;
511
dest32[2] = word2;
512
dest32[3] = word3;
513
}
514
}
515
for (; i < copy; i += 4, src += 4, dest32++)
516
{
517
#ifdef WORDS_BIGENDIAN
518
*dest32 = *(u32 *)src;
519
#else
520
*dest32 = BSWAP16(*(u32 *)src);
521
#endif
522
}
523
count -= copy/4;
524
Cs2Area->datatransoffset += copy;
525
Cs2Area->cdwnum += copy;
526
527
if (Cs2Area->datatransoffset >= size)
528
{
529
Cs2Area->datatransoffset = 0;
530
Cs2Area->datanumsecttrans++;
531
}
532
}
533
534
if (Cs2Area->datatranstype == 2
535
&& Cs2Area->datanumsecttrans >= Cs2Area->datasectstotrans)
536
{
537
u32 i;
538
539
Cs2Area->datatranstype = -1;
540
541
for (i = Cs2Area->datatranssectpos; i < (Cs2Area->datatranssectpos+Cs2Area->datasectstotrans); i++)
542
{
543
Cs2FreeBlock(Cs2Area->datatranspartition->block[i]);
544
Cs2Area->datatranspartition->block[i] = NULL;
545
Cs2Area->datatranspartition->blocknum[i] = 0xFF;
546
}
547
548
Cs2SortBlocks(Cs2Area->datatranspartition);
549
550
Cs2Area->datatranspartition->size -= Cs2Area->cdwnum;
551
Cs2Area->datatranspartition->numblocks -= Cs2Area->datasectstotrans;
552
553
CDLOG("cs2\t: datatranspartition->size = %x\n", Cs2Area->datatranspartition->size);
554
}
555
}
556
557
if (count > 0)
558
{
559
memset(dest32, 0xCD, count*4);
560
}
561
}
562
563
//////////////////////////////////////////////////////////////////////////////
564
565
int Cs2Init(int carttype, int coreid, const char *cdpath, const char *mpegpath, const char *netlinksetting) {
566
int ret;
567
568
if ((Cs2Area = (Cs2 *) malloc(sizeof(Cs2))) == NULL)
569
return -1;
570
memset(Cs2Area, 0, sizeof(*Cs2Area));
571
572
Cs2Area->carttype = carttype;
573
Cs2Area->mpegpath = mpegpath;
574
Cs2Area->cdi=NULL;
575
576
if ((ret = Cs2ChangeCDCore(coreid, cdpath)) != 0)
577
return ret;
578
579
Cs2Reset();
580
581
// If Modem is connected, set the registers
582
if(Cs2Area->carttype == CART_NETLINK)
583
{
584
if ((ret = NetlinkInit(netlinksetting)) != 0)
585
return ret;
586
}
587
588
if ((cdip = (ip_struct *) calloc(sizeof(ip_struct), 1)) == NULL)
589
return -1;
590
591
return 0;
592
}
593
594
//////////////////////////////////////////////////////////////////////////////
595
596
int Cs2ChangeCDCore(int coreid, const char *cdpath)
597
{
598
int i;
599
600
// Make sure the old core is freed
601
if (Cs2Area->cdi != NULL)
602
Cs2Area->cdi->DeInit();
603
604
// So which core do we want?
605
if (coreid == CDCORE_DEFAULT)
606
coreid = 0; // Assume we want the first one
607
608
// Go through core list and find the id
609
for (i = 0; CDCoreList[i] != NULL; i++)
610
{
611
if (CDCoreList[i]->id == coreid)
612
{
613
// Set to current core
614
Cs2Area->cdi = CDCoreList[i];
615
break;
616
}
617
}
618
619
if (Cs2Area->cdi == NULL)
620
{
621
Cs2Area->cdi = &DummyCD;
622
return -1;
623
}
624
625
if (Cs2Area->cdi->Init(cdpath) != 0)
626
{
627
// This might be helpful.
628
YabSetError(YAB_ERR_CANNOTINIT, (void *)Cs2Area->cdi->Name);
629
630
// Since it failed, instead of it being fatal, we'll just use the dummy
631
// core instead
632
Cs2Area->cdi = &DummyCD;
633
}
634
635
Cs2Area->isdiskchanged = 1;
636
Cs2Area->status = CDB_STAT_PAUSE;
637
SmpcRecheckRegion();
638
639
return 0;
640
}
641
642
//////////////////////////////////////////////////////////////////////////////
643
644
void Cs2DeInit(void) {
645
if(Cs2Area != NULL) {
646
if (Cs2Area->cdi != NULL) {
647
Cs2Area->cdi->DeInit();
648
}
649
650
if(Cs2Area->carttype == CART_NETLINK)
651
NetlinkDeInit();
652
653
free(Cs2Area);
654
}
655
Cs2Area = NULL;
656
657
if (cdip)
658
free(cdip);
659
cdip = NULL;
660
}
661
662
//////////////////////////////////////////////////////////////////////////////
663
664
void Cs2Reset(void) {
665
u32 i, i2;
666
667
switch (Cs2Area->cdi->GetStatus())
668
{
669
case 0:
670
case 1:
671
Cs2Area->status = CDB_STAT_PAUSE;
672
Cs2Area->FAD = 150;
673
Cs2Area->options = 0;
674
Cs2Area->repcnt = 0;
675
Cs2Area->ctrladdr = 0x41;
676
Cs2Area->track = 1;
677
Cs2Area->index = 1;
678
break;
679
case 2:
680
Cs2Area->status = CDB_STAT_NODISC;
681
682
Cs2Area->FAD = 0xFFFFFFFF;
683
Cs2Area->options = 0xFF;
684
Cs2Area->repcnt = 0xFF;
685
Cs2Area->ctrladdr = 0xFF;
686
Cs2Area->track = 0xFF;
687
Cs2Area->index = 0xFF;
688
break;
689
case 3:
690
Cs2Area->status = CDB_STAT_OPEN;
691
692
Cs2Area->FAD = 0xFFFFFFFF;
693
Cs2Area->options = 0xFF;
694
Cs2Area->repcnt = 0xFF;
695
Cs2Area->ctrladdr = 0xFF;
696
Cs2Area->track = 0xFF;
697
Cs2Area->index = 0xFF;
698
break;
699
default: break;
700
}
701
702
Cs2Area->infotranstype = -1;
703
Cs2Area->datatranstype = -1;
704
Cs2Area->transfercount = 0;
705
Cs2Area->cdwnum = 0;
706
Cs2Area->getsectsize = Cs2Area->putsectsize = 2048;
707
Cs2Area->isdiskchanged = 1;
708
Cs2Area->isbufferfull = 0;
709
Cs2Area->isonesectorstored = 0;
710
Cs2Area->isaudio = 0;
711
712
Cs2Area->reg.CR1 = ( 0 <<8) | 'C';
713
Cs2Area->reg.CR2 = ('D'<<8) | 'B';
714
Cs2Area->reg.CR3 = ('L'<<8) | 'O';
715
Cs2Area->reg.CR4 = ('C'<<8) | 'K';
716
Cs2Area->reg.HIRQ = 0xFFFF;
717
Cs2Area->reg.HIRQMASK = 0xFFFF;
718
719
Cs2Area->playFAD = 0xFFFFFFFF;
720
Cs2Area->playendFAD = 0xFFFFFFFF;
721
Cs2Area->playtype = 0;
722
Cs2Area->maxrepeat = 0;
723
724
// set authentication variables to 0(not authenticated)
725
Cs2Area->satauth = 0;
726
Cs2Area->mpgauth = 0;
727
728
// clear filter conditions
729
for (i = 0; i < MAX_SELECTORS; i++)
730
{
731
Cs2Area->filter[i].FAD = 0;
732
Cs2Area->filter[i].range = 0xFFFFFFFF;
733
Cs2Area->filter[i].mode = 0;
734
Cs2Area->filter[i].chan = 0;
735
Cs2Area->filter[i].smmask = 0;
736
Cs2Area->filter[i].cimask = 0;
737
Cs2Area->filter[i].fid = 0;
738
Cs2Area->filter[i].smval = 0;
739
Cs2Area->filter[i].cival = 0;
740
Cs2Area->filter[i].condtrue = 0;
741
Cs2Area->filter[i].condfalse = 0xFF;
742
}
743
744
// clear partitions
745
for (i = 0; i < MAX_SELECTORS; i++)
746
{
747
Cs2Area->partition[i].size = -1;
748
Cs2Area->partition[i].numblocks = 0;
749
750
for (i2 = 0; i2 < MAX_BLOCKS; i2++)
751
{
752
Cs2Area->partition[i].block[i2] = NULL;
753
Cs2Area->partition[i].blocknum[i2] = 0xFF;
754
}
755
}
756
757
// clear blocks
758
for (i = 0; i < MAX_BLOCKS; i++)
759
{
760
Cs2Area->block[i].size = -1;
761
memset(Cs2Area->block[i].data, 0, 2352);
762
}
763
764
Cs2Area->blockfreespace = 200;
765
766
// initialize TOC
767
memset(Cs2Area->TOC, 0xFF, sizeof(Cs2Area->TOC));
768
769
// clear filesystem stuff
770
Cs2Area->curdirsect = 0;
771
Cs2Area->curdirsize = 0;
772
Cs2Area->curdirfidoffset = 0;
773
memset(&Cs2Area->fileinfo, 0, sizeof(Cs2Area->fileinfo));
774
Cs2Area->numfiles = 0;
775
776
Cs2Area->lastbuffer = 0xFF;
777
778
Cs2Area->_command = 0;
779
Cs2Area->_periodiccycles = 0;
780
Cs2Area->_commandtiming = 0;
781
Cs2SetTiming(0);
782
783
// MPEG specific stuff
784
Cs2Area->mpegcon[0].audcon = Cs2Area->mpegcon[0].vidcon = 0x00;
785
Cs2Area->mpegcon[0].audlay = Cs2Area->mpegcon[0].vidlay = 0x00;
786
Cs2Area->mpegcon[0].audbufdivnum = Cs2Area->mpegcon[0].vidbufdivnum = 0xFF;
787
Cs2Area->mpegcon[1].audcon = Cs2Area->mpegcon[1].vidcon = 0x00;
788
Cs2Area->mpegcon[1].audlay = Cs2Area->mpegcon[1].vidlay = 0x00;
789
Cs2Area->mpegcon[1].audbufdivnum = Cs2Area->mpegcon[1].vidbufdivnum = 0xFF;
790
791
// should verify the following
792
Cs2Area->mpegstm[0].audstm = Cs2Area->mpegstm[0].vidstm = 0x00;
793
Cs2Area->mpegstm[0].audstmid = Cs2Area->mpegstm[0].vidstmid = 0x00;
794
Cs2Area->mpegstm[0].audchannum = Cs2Area->mpegstm[0].vidchannum = 0x00;
795
Cs2Area->mpegstm[1].audstm = Cs2Area->mpegstm[1].vidstm = 0x00;
796
Cs2Area->mpegstm[1].audstmid = Cs2Area->mpegstm[1].vidstmid = 0x00;
797
Cs2Area->mpegstm[1].audchannum = Cs2Area->mpegstm[1].vidchannum = 0x00;
798
}
799
800
//////////////////////////////////////////////////////////////////////////////
801
802
void Cs2Exec(u32 timing) {
803
Cs2Area->_periodiccycles += timing * 3;
804
805
if (Cs2Area->_commandtiming > 0)
806
{
807
if (Cs2Area->_commandtiming < timing)
808
{
809
Cs2Execute();
810
Cs2Area->_commandtiming = 0;
811
}
812
else
813
Cs2Area->_commandtiming -= timing;
814
}
815
816
if (Cs2Area->_periodiccycles >= Cs2Area->_periodictiming)
817
{
818
Cs2Area->_periodiccycles -= Cs2Area->_periodictiming;
819
820
// Get Drive's current status and compare with old status
821
// switch(cd->getStatus()) // this shouldn't be called every periodic response
822
switch(0)
823
{
824
case 0:
825
case 1:
826
if ((Cs2Area->status & 0xF) == CDB_STAT_NODISC ||
827
(Cs2Area->status & 0xF) == CDB_STAT_OPEN)
828
{
829
Cs2Area->status = CDB_STAT_PAUSE;
830
Cs2Area->isdiskchanged = 1;
831
}
832
break;
833
case 2:
834
// may need to change this
835
if ((Cs2Area->status & 0xF) != CDB_STAT_NODISC)
836
Cs2Area->status = CDB_STAT_NODISC;
837
break;
838
case 3:
839
// may need to change this
840
if ((Cs2Area->status & 0xF) != CDB_STAT_OPEN)
841
Cs2Area->status = CDB_STAT_OPEN;
842
break;
843
default: break;
844
}
845
846
switch (Cs2Area->status & 0xF) {
847
case CDB_STAT_PAUSE:
848
{
849
// if (FAD >= playFAD && FAD < playendFAD)
850
// status = CDB_STAT_PLAY;
851
// else
852
break;
853
}
854
case CDB_STAT_PLAY:
855
{
856
partition_struct * playpartition;
857
int ret = Cs2ReadFilteredSector(Cs2Area->FAD, &playpartition);
858
859
switch (ret)
860
{
861
case 0:
862
// Sector Read OK
863
Cs2Area->FAD++;
864
Cs2Area->cdi->ReadAheadFAD(Cs2Area->FAD);
865
866
if (playpartition != NULL)
867
{
868
// We can use this sector
869
CDLOG("partition number = %d blocks = %d blockfreespace = %d fad = %x playpartition->size = %x isbufferfull = %x\n", (playpartition - Cs2Area->partition), playpartition->numblocks, Cs2Area->blockfreespace, Cs2Area->FAD, playpartition->size, Cs2Area->isbufferfull);
870
871
Cs2Area->reg.HIRQ |= CDB_HIRQ_CSCT;
872
Cs2Area->isonesectorstored = 1;
873
874
if (Cs2Area->FAD >= Cs2Area->playendFAD) {
875
// Make sure we don't have to do a repeat
876
if (Cs2Area->repcnt >= Cs2Area->maxrepeat) {
877
// we're done
878
Cs2Area->status = CDB_STAT_PAUSE;
879
Cs2SetTiming(0);
880
Cs2Area->reg.HIRQ |= CDB_HIRQ_PEND;
881
882
if (Cs2Area->playtype == CDB_PLAYTYPE_FILE)
883
Cs2Area->reg.HIRQ |= CDB_HIRQ_EFLS;
884
885
CDLOG("PLAY HAS ENDED\n");
886
}
887
else {
888
889
Cs2Area->FAD = Cs2Area->playFAD;
890
if (Cs2Area->repcnt < 0xE)
891
Cs2Area->repcnt++;
892
Cs2Area->track = Cs2FADToTrack(Cs2Area->FAD);
893
894
CDLOG("PLAY HAS REPEATED\n");
895
}
896
}
897
if (Cs2Area->isbufferfull) {
898
CDLOG("BUFFER IS FULL\n");
899
// status = CDB_STAT_PAUSE;
900
}
901
}
902
else
903
{
904
CDLOG("Sector filtered out\n");
905
if (Cs2Area->FAD >= Cs2Area->playendFAD) {
906
// Make sure we don't have to do a repeat
907
if (Cs2Area->repcnt >= Cs2Area->maxrepeat) {
908
// we're done
909
Cs2Area->status = CDB_STAT_PAUSE;
910
Cs2SetTiming(0);
911
Cs2Area->reg.HIRQ |= CDB_HIRQ_PEND;
912
913
if (Cs2Area->playtype == CDB_PLAYTYPE_FILE)
914
Cs2Area->reg.HIRQ |= CDB_HIRQ_EFLS;
915
916
CDLOG("PLAY HAS ENDED\n");
917
}
918
else {
919
Cs2Area->FAD = Cs2Area->playFAD;
920
if (Cs2Area->repcnt < 0xE)
921
Cs2Area->repcnt++;
922
Cs2Area->track = Cs2FADToTrack(Cs2Area->FAD);
923
924
CDLOG("PLAY HAS REPEATED\n");
925
}
926
}
927
}
928
break;
929
case -1:
930
// Things weren't setup correctly
931
break;
932
case -2:
933
// Do a read retry
934
break;
935
}
936
937
break;
938
}
939
case CDB_STAT_SEEK:
940
break;
941
case CDB_STAT_SCAN:
942
break;
943
case CDB_STAT_RETRY:
944
break;
945
default: break;
946
}
947
948
if (Cs2Area->_command)
949
return;
950
951
Cs2Area->status |= CDB_STAT_PERI;
952
953
// adjust registers appropriately here(fix me)
954
doCDReport(Cs2Area->status);
955
956
Cs2Area->reg.HIRQ |= CDB_HIRQ_SCDQ;
957
}
958
959
if(Cs2Area->carttype == CART_NETLINK)
960
NetlinkExec(timing);
961
}
962
963
//////////////////////////////////////////////////////////////////////////////
964
965
/* Returns the number of (emulated) microseconds before the next sector
966
* will have been completely read in */
967
int Cs2GetTimeToNextSector(void) {
968
if ((Cs2Area->status & 0xF) != CDB_STAT_PLAY) {
969
return 0;
970
} else {
971
// Round up, since the caller wants to know when it'll be safe to check
972
int time = (Cs2Area->_periodictiming - Cs2Area->_periodiccycles + 2) / 3;
973
return time<0 ? 0 : time;
974
}
975
}
976
977
//////////////////////////////////////////////////////////////////////////////
978
979
void Cs2Command(void) {
980
Cs2Area->_command = 1;
981
}
982
983
//////////////////////////////////////////////////////////////////////////////
984
985
void Cs2SetTiming(int playing) {
986
if (playing) {
987
if (Cs2Area->isaudio || Cs2Area->speed1x == 1)
988
Cs2Area->_periodictiming = 40000; // 13333.333... * 3
989
else
990
Cs2Area->_periodictiming = 20000; // 6666.666... * 3
991
}
992
else {
993
Cs2Area->_periodictiming = 50000; // 16666.666... * 3
994
}
995
}
996
997
//////////////////////////////////////////////////////////////////////////////
998
999
void Cs2SetCommandTiming(u8 cmd) {
1000
switch(cmd) {
1001
default:
1002
Cs2Area->_commandtiming = 1;
1003
break;
1004
}
1005
}
1006
1007
//////////////////////////////////////////////////////////////////////////////
1008
1009
void Cs2Execute(void) {
1010
u16 instruction = Cs2Area->reg.CR1 >> 8;
1011
1012
Cs2Area->reg.HIRQ &= ~CDB_HIRQ_CMOK;
1013
1014
switch (instruction) {
1015
case 0x00:
1016
CDLOG("cs2\t: Command: getStatus\n");
1017
Cs2GetStatus();
1018
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1019
break;
1020
case 0x01:
1021
CDLOG("cs2\t: Command: getHardwareInfo\n");
1022
Cs2GetHardwareInfo();
1023
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1024
break;
1025
case 0x02:
1026
CDLOG("cs2\t: Command: getToc\n");
1027
Cs2GetToc();
1028
break;
1029
case 0x03:
1030
CDLOG("cs2\t: Command: getSessionInfo\n");
1031
Cs2GetSessionInfo();
1032
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1033
break;
1034
case 0x04:
1035
CDLOG("cs2\t: Command: initializeCDSystem %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1036
Cs2InitializeCDSystem();
1037
break;
1038
case 0x06:
1039
CDLOG("cs2\t: Command: endDataTransfer %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1040
Cs2EndDataTransfer();
1041
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1042
break;
1043
case 0x10:
1044
CDLOG("cs2\t: Command: playDisc %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1045
Cs2PlayDisc();
1046
break;
1047
case 0x11:
1048
CDLOG("cs2\t: Command: seekDisc %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1049
Cs2SeekDisc();
1050
break;
1051
case 0x20:
1052
CDLOG("cs2\t: Command: getSubcodeQRW %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1053
Cs2GetSubcodeQRW();
1054
break;
1055
case 0x30:
1056
CDLOG("cs2\t: Command: setCDDeviceConnection %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1057
Cs2SetCDDeviceConnection();
1058
break;
1059
case 0x32:
1060
CDLOG("cs2\t: Command: getLastBufferDestination %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1061
Cs2GetLastBufferDestination();
1062
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1063
break;
1064
case 0x40:
1065
CDLOG("cs2\t: Command: setFilterRange\n");
1066
Cs2SetFilterRange();
1067
break;
1068
case 0x42:
1069
CDLOG("cs2\t: Command: setFilterSubheaderConditions\n");
1070
Cs2SetFilterSubheaderConditions();
1071
break;
1072
case 0x43:
1073
CDLOG("cs2\t: Command: getFilterSubheaderConditions\n");
1074
Cs2GetFilterSubheaderConditions();
1075
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1076
break;
1077
case 0x44:
1078
CDLOG("cs2\t: Command: setFilterMode\n");
1079
Cs2SetFilterMode();
1080
break;
1081
case 0x45:
1082
CDLOG("cs2\t: Command: getFilterMode\n");
1083
Cs2GetFilterMode();
1084
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1085
break;
1086
case 0x46:
1087
CDLOG("cs2\t: Command: setFilterConnection\n");
1088
Cs2SetFilterConnection();
1089
break;
1090
case 0x48:
1091
CDLOG("cs2\t: Command: resetSelector %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1092
Cs2ResetSelector();
1093
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1094
break;
1095
case 0x50:
1096
CDLOG("cs2\t: Command: getBufferSize\n");
1097
Cs2GetBufferSize();
1098
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1099
break;
1100
case 0x51:
1101
// CDLOG("cs2\t: Command: getSectorNumber %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1102
Cs2GetSectorNumber();
1103
// CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1104
break;
1105
case 0x52:
1106
CDLOG("cs2\t: Command: calculateActualSize %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1107
Cs2CalculateActualSize();
1108
break;
1109
case 0x53:
1110
CDLOG("cs2\t: Command: getActualSize\n");
1111
Cs2GetActualSize();
1112
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1113
break;
1114
case 0x54:
1115
CDLOG("cs2\t: Command: getSectorInfo %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1116
Cs2GetSectorInfo();
1117
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1118
break;
1119
case 0x60:
1120
CDLOG("cs2\t: Command: setSectorLength %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1121
Cs2SetSectorLength();
1122
break;
1123
case 0x61:
1124
CDLOG("cs2\t: Command: getSectorData %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1125
Cs2GetSectorData();
1126
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1127
break;
1128
case 0x62:
1129
CDLOG("cs2\t: Command: deleteSectorData %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1130
Cs2DeleteSectorData();
1131
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1132
break;
1133
case 0x63:
1134
CDLOG("cs2\t: Command: getThenDeleteSectorData %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1135
Cs2GetThenDeleteSectorData();
1136
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1137
break;
1138
case 0x64:
1139
CDLOG("cs2\t: Command: putSectorData %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1140
Cs2PutSectorData();
1141
break;
1142
case 0x67:
1143
CDLOG("cs2\t: Command: getCopyError\n");
1144
Cs2GetCopyError();
1145
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1146
break;
1147
case 0x70:
1148
CDLOG("cs2\t: Command: changeDirectory %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1149
Cs2ChangeDirectory();
1150
break;
1151
case 0x71:
1152
CDLOG("cs2\t: Command: readDirectory %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1153
Cs2ReadDirectory();
1154
break;
1155
case 0x72:
1156
CDLOG("cs2\t: Command: getFileSystemScope\n");
1157
Cs2GetFileSystemScope();
1158
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1159
break;
1160
case 0x73:
1161
CDLOG("cs2\t: Command: getFileInfo %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1162
Cs2GetFileInfo();
1163
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1164
break;
1165
case 0x74:
1166
CDLOG("cs2\t: Command: readFile %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1167
Cs2ReadFile();
1168
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1169
break;
1170
case 0x75:
1171
CDLOG("cs2\t: Command: abortFile\n");
1172
Cs2AbortFile();
1173
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1174
break;
1175
case 0x90:
1176
CDLOG("cs2\t: Command: mpegGetStatus\n");
1177
Cs2MpegGetStatus();
1178
break;
1179
case 0x91:
1180
CDLOG("cs2\t: Command: mpegGetInterrupt\n");
1181
Cs2MpegGetInterrupt();
1182
CDLOG("cs2\t: ret: %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1183
break;
1184
case 0x92:
1185
CDLOG("cs2\t: Command: mpegSetInterruptMask\n");
1186
Cs2MpegSetInterruptMask();
1187
break;
1188
case 0x93:
1189
CDLOG("cs2\t: Command: mpegInit\n");
1190
Cs2MpegInit();
1191
break;
1192
case 0x94:
1193
CDLOG("cs2\t: Command: mpegSetMode\n");
1194
Cs2MpegSetMode();
1195
break;
1196
case 0x95:
1197
CDLOG("cs2\t: Command: mpegPlay\n");
1198
Cs2MpegPlay();
1199
break;
1200
case 0x96:
1201
CDLOG("cs2\t: Command: mpegSetDecodingMethod\n");
1202
Cs2MpegSetDecodingMethod();
1203
break;
1204
case 0x9A:
1205
CDLOG("cs2\t: Command: mpegSetConnection\n");
1206
Cs2MpegSetConnection();
1207
break;
1208
case 0x9B:
1209
CDLOG("cs2\t: Command: mpegGetConnection\n");
1210
Cs2MpegGetConnection();
1211
break;
1212
case 0x9D:
1213
CDLOG("cs2\t: Command: mpegSetStream\n");
1214
Cs2MpegSetStream();
1215
break;
1216
case 0x9E:
1217
CDLOG("cs2\t: Command: mpegGetStream\n");
1218
Cs2MpegGetStream();
1219
break;
1220
case 0xA0:
1221
CDLOG("cs2\t: Command: mpegDisplay\n");
1222
Cs2MpegDisplay();
1223
break;
1224
case 0xA1:
1225
CDLOG("cs2\t: Command: mpegSetWindow\n");
1226
Cs2MpegSetWindow();
1227
break;
1228
case 0xA2:
1229
CDLOG("cs2\t: Command: mpegSetBorderColor\n");
1230
Cs2MpegSetBorderColor();
1231
break;
1232
case 0xA3:
1233
CDLOG("cs2\t: Command: mpegSetFade\n");
1234
Cs2MpegSetFade();
1235
break;
1236
case 0xA4:
1237
CDLOG("cs2\t: Command: mpegSetVideoEffects\n");
1238
Cs2MpegSetVideoEffects();
1239
break;
1240
case 0xAF:
1241
CDLOG("cs2\t: Command: mpegSetLSI\n");
1242
Cs2MpegSetLSI();
1243
break;
1244
case 0xE0:
1245
CDLOG("cs2\t: Command: cmdE0 %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1246
Cs2CmdE0();
1247
break;
1248
case 0xE1:
1249
CDLOG("cs2\t: Command: cmdE1 %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1250
Cs2CmdE1();
1251
break;
1252
case 0xE2:
1253
CDLOG("cs2\t: Command: cmdE2 %04x %04x %04x %04x %04x\n", Cs2Area->reg.HIRQ, Cs2Area->reg.CR1, Cs2Area->reg.CR2, Cs2Area->reg.CR3, Cs2Area->reg.CR4);
1254
Cs2CmdE2();
1255
break;
1256
default:
1257
CDLOG("cs2\t: Command %02x not implemented\n", instruction);
1258
break;
1259
}
1260
}
1261
1262
//////////////////////////////////////////////////////////////////////////////
1263
1264
void Cs2GetStatus(void) {
1265
doCDReport(Cs2Area->status);
1266
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
1267
}
1268
1269
//////////////////////////////////////////////////////////////////////////////
1270
1271
void Cs2GetHardwareInfo(void) {
1272
if ((Cs2Area->status & 0xF) != CDB_STAT_OPEN && (Cs2Area->status & 0xF) != CDB_STAT_NODISC)
1273
Cs2Area->isdiskchanged = 0;
1274
1275
Cs2Area->reg.CR1 = Cs2Area->status << 8;
1276
// hardware flags/CD Version
1277
Cs2Area->reg.CR2 = 0x0201; // mpeg card exists
1278
// mpeg version, it actually is required(at least by the bios)
1279
1280
if (Cs2Area->mpgauth)
1281
Cs2Area->reg.CR3 = 0x1;
1282
else
1283
Cs2Area->reg.CR3 = 0;
1284
1285
// drive info/revision
1286
Cs2Area->reg.CR4 = 0x0400;
1287
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
1288
}
1289
1290
//////////////////////////////////////////////////////////////////////////////
1291
1292
void Cs2GetToc(void) {
1293
Cs2Area->cdi->ReadTOC(Cs2Area->TOC);
1294
1295
Cs2Area->transfercount = 0;
1296
Cs2Area->infotranstype = 0;
1297
1298
Cs2Area->reg.CR1 = Cs2Area->status << 8;
1299
Cs2Area->reg.CR2 = 0xCC;
1300
Cs2Area->reg.CR3 = 0x0;
1301
Cs2Area->reg.CR4 = 0x0;
1302
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_DRDY;
1303
Cs2Area->status = CDB_STAT_PAUSE;
1304
}
1305
1306
//////////////////////////////////////////////////////////////////////////////
1307
1308
void Cs2GetSessionInfo(void) {
1309
1310
switch (Cs2Area->reg.CR1 & 0xFF) {
1311
case 0:
1312
Cs2Area->reg.CR3 = (u16)(0x0100 | ((Cs2Area->TOC[101] & 0xFF0000) >> 16));
1313
Cs2Area->reg.CR4 = (u16)Cs2Area->TOC[101];
1314
break;
1315
case 1:
1316
Cs2Area->reg.CR3 = 0x0100; // return Session number(high byte)/and first byte of Session lba
1317
Cs2Area->reg.CR4 = 0; // lower word of Session lba
1318
break;
1319
default:
1320
Cs2Area->reg.CR3 = 0xFFFF;
1321
Cs2Area->reg.CR4 = 0xFFFF;
1322
break;
1323
}
1324
1325
Cs2Area->status = CDB_STAT_PAUSE;
1326
Cs2Area->reg.CR1 = Cs2Area->status << 8;
1327
Cs2Area->reg.CR2 = 0;
1328
1329
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
1330
}
1331
1332
//////////////////////////////////////////////////////////////////////////////
1333
1334
void Cs2InitializeCDSystem(void) {
1335
u16 val = 0;
1336
u8 initflag = Cs2Area->reg.CR1 & 0xFF;
1337
1338
if ((Cs2Area->status & 0xF) != CDB_STAT_OPEN && (Cs2Area->status & 0xF) != CDB_STAT_NODISC)
1339
{
1340
Cs2Area->status = CDB_STAT_PAUSE;
1341
Cs2Area->FAD = 150;
1342
}
1343
1344
if (initflag & 0x1)
1345
{
1346
// Reset CD block software
1347
}
1348
1349
if (initflag & 0x2)
1350
{
1351
// Decode RW subcode
1352
}
1353
1354
if (initflag & 0x4)
1355
{
1356
// Don't confirm Mode 2 subheader
1357
}
1358
1359
if (initflag & 0x8)
1360
{
1361
// Retry reading Form 2 sectors
1362
}
1363
1364
if (initflag & 0x10)
1365
Cs2Area->speed1x = 1;
1366
else
1367
Cs2Area->speed1x = 0;
1368
1369
val = Cs2Area->reg.HIRQ & 0xFFE5;
1370
Cs2Area->isbufferfull = 0;
1371
1372
if (Cs2Area->isdiskchanged)
1373
val |= CDB_HIRQ_DCHG;
1374
else
1375
val &= ~CDB_HIRQ_DCHG;
1376
1377
doCDReport(Cs2Area->status);
1378
Cs2Area->reg.HIRQ = val | CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1379
}
1380
1381
//////////////////////////////////////////////////////////////////////////////
1382
1383
void Cs2EndDataTransfer(void) {
1384
s32 i;
1385
if (Cs2Area->cdwnum)
1386
{
1387
Cs2Area->reg.CR1 = (u16)((Cs2Area->status << 8) | ((Cs2Area->cdwnum >> 17) & 0xFF));
1388
Cs2Area->reg.CR2 = (u16)(Cs2Area->cdwnum >> 1);
1389
Cs2Area->reg.CR3 = 0;
1390
Cs2Area->reg.CR4 = 0;
1391
}
1392
else
1393
{
1394
Cs2Area->reg.CR1 = (Cs2Area->status << 8) | 0xFF; // FIXME
1395
Cs2Area->reg.CR2 = 0xFFFF;
1396
Cs2Area->reg.CR3 = 0;
1397
Cs2Area->reg.CR4 = 0;
1398
}
1399
1400
// stop any transfers that may be going(this is still probably wrong), and
1401
// set/clear the appropriate flags
1402
1403
switch (Cs2Area->datatranstype)
1404
{
1405
case 0:
1406
// Get Sector Data
1407
Cs2Area->reg.HIRQ |= CDB_HIRQ_EHST;
1408
break;
1409
case 2:
1410
{
1411
// Get Then Delete Sector
1412
1413
// Make sure we actually have to free something
1414
if (Cs2Area->datatranspartition->size <= 0) break;
1415
1416
Cs2Area->datatranstype = -1;
1417
1418
// free blocks
1419
for (i = Cs2Area->datatranssectpos; i < (Cs2Area->datatranssectpos + Cs2Area->datasectstotrans); i++)
1420
{
1421
Cs2FreeBlock(Cs2Area->datatranspartition->block[i]);
1422
Cs2Area->datatranspartition->block[i] = NULL;
1423
Cs2Area->datatranspartition->blocknum[i] = 0xFF;
1424
}
1425
1426
// sort remaining blocks
1427
Cs2SortBlocks(Cs2Area->datatranspartition);
1428
1429
Cs2Area->datatranspartition->size -= Cs2Area->cdwnum;
1430
Cs2Area->datatranspartition->numblocks -= Cs2Area->datasectstotrans;
1431
1432
if (Cs2Area->blockfreespace == 200) Cs2Area->isonesectorstored = 0;
1433
1434
Cs2Area->reg.HIRQ |= CDB_HIRQ_EHST;
1435
break;
1436
}
1437
default: break;
1438
}
1439
1440
Cs2Area->cdwnum = 0;
1441
1442
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
1443
}
1444
1445
//////////////////////////////////////////////////////////////////////////////
1446
1447
void Cs2PlayDisc(void) {
1448
u32 pdspos;
1449
u32 pdepos;
1450
u32 pdpmode;
1451
1452
// Get all the arguments
1453
pdspos = ((Cs2Area->reg.CR1 & 0xFF) << 16) | Cs2Area->reg.CR2;
1454
pdepos = ((Cs2Area->reg.CR3 & 0xFF) << 16) | Cs2Area->reg.CR4;
1455
pdpmode = Cs2Area->reg.CR3 >> 8;
1456
1457
// Convert Start Position to playFAD
1458
if (pdspos == 0xFFFFFF || pdpmode == 0xFF) // This still isn't right
1459
{
1460
// No Change
1461
}
1462
else if (pdspos & 0x800000)
1463
{
1464
// FAD Mode
1465
Cs2Area->playFAD = (pdspos & 0xFFFFF);
1466
1467
Cs2SetupDefaultPlayStats(Cs2FADToTrack(Cs2Area->playFAD), 0);
1468
1469
if (!(pdpmode & 0x80))
1470
// Move pickup to start position
1471
Cs2Area->FAD = Cs2Area->playFAD;
1472
}
1473
else
1474
{
1475
// Track Mode
1476
1477
// If track == 0, set it to the first available track, or something like that
1478
if (pdspos == 0)
1479
pdspos = 0x0100;
1480
1481
if (!(pdpmode & 0x80))
1482
{
1483
Cs2SetupDefaultPlayStats((u8)(pdspos >> 8), 1);
1484
Cs2Area->playFAD = Cs2Area->FAD;
1485
Cs2Area->track = (u8)(pdspos >> 8);
1486
Cs2Area->index = (u8)pdspos;
1487
}
1488
else
1489
{
1490
// Preserve Pickup Position
1491
Cs2SetupDefaultPlayStats((u8)(pdspos >> 8), 0);
1492
}
1493
}
1494
1495
pdpmode &= 0x7F;
1496
1497
// Only update max repeat if bits 0-6 aren't all set
1498
if (pdpmode != 0x7F)
1499
Cs2Area->maxrepeat = pdpmode;
1500
1501
// Convert End Position to playendFAD
1502
if (pdepos == 0xFFFFFF)
1503
{
1504
// No Change
1505
}
1506
else if (pdepos & 0x800000)
1507
{
1508
// FAD Mode
1509
Cs2Area->playendFAD = Cs2Area->playFAD+(pdepos & 0xFFFFF);
1510
}
1511
else if (pdepos != 0)
1512
{
1513
// Track Mode
1514
if ((pdepos & 0xFF) == 0)
1515
Cs2Area->playendFAD = Cs2TrackToFAD((u16)(pdepos | 0x0063));
1516
else
1517
Cs2Area->playendFAD = Cs2TrackToFAD((u16)pdepos);
1518
}
1519
else
1520
{
1521
// Default Mode
1522
Cs2Area->playendFAD = Cs2TrackToFAD(0xFFFF);
1523
}
1524
1525
// setup play mode here
1526
#if CDDEBUG
1527
if (pdpmode != 0)
1528
CDLOG("cs2\t: playDisc: Unsupported play mode = %02X\n", pdpmode);
1529
#endif
1530
1531
Cs2SetTiming(1);
1532
1533
Cs2Area->status = CDB_STAT_PLAY;
1534
Cs2Area->playtype = CDB_PLAYTYPE_SECTOR;
1535
Cs2Area->cdi->ReadAheadFAD(Cs2Area->FAD);
1536
1537
doCDReport(Cs2Area->status);
1538
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
1539
}
1540
1541
//////////////////////////////////////////////////////////////////////////////
1542
1543
void Cs2SeekDisc(void) {
1544
if (Cs2Area->reg.CR1 & 0x80)
1545
{
1546
// Seek by FAD
1547
u32 sdFAD;
1548
1549
sdFAD = ((Cs2Area->reg.CR1 & 0xFF) << 16) | Cs2Area->reg.CR2;
1550
1551
if (sdFAD == 0xFFFFFF)
1552
Cs2Area->status = CDB_STAT_PAUSE;
1553
else
1554
{
1555
CDLOG("cs2\t: seekDisc - FAD Mode not supported\n");
1556
}
1557
}
1558
else
1559
{
1560
// Were we given a valid track number?
1561
if (Cs2Area->reg.CR2 >> 8)
1562
{
1563
// Seek by index
1564
Cs2Area->status = CDB_STAT_PAUSE;
1565
Cs2SetupDefaultPlayStats((Cs2Area->reg.CR2 >> 8), 1);
1566
Cs2Area->index = Cs2Area->reg.CR2 & 0xFF;
1567
}
1568
else
1569
{
1570
// Error
1571
Cs2Area->status = CDB_STAT_STANDBY;
1572
Cs2Area->options = 0xFF;
1573
Cs2Area->repcnt = 0xFF;
1574
Cs2Area->ctrladdr = 0xFF;
1575
Cs2Area->track = 0xFF;
1576
Cs2Area->index = 0xFF;
1577
Cs2Area->FAD = 0xFFFFFFFF;
1578
}
1579
}
1580
1581
Cs2SetTiming(0);
1582
1583
doCDReport(Cs2Area->status);
1584
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
1585
}
1586
1587
//////////////////////////////////////////////////////////////////////////////
1588
1589
void Cs2GetSubcodeQRW(void) {
1590
// According to Tyranid's doc, the subcode type is stored in the low byte
1591
// of CR2. However, Sega's CDC library writes the type to the low byte
1592
// of CR1. Somehow I'd sooner believe Sega is right.
1593
switch(Cs2Area->reg.CR1 & 0xFF) {
1594
case 0:
1595
// Get Q Channel
1596
Cs2Area->reg.CR1 = (Cs2Area->status << 8) | 0;
1597
Cs2Area->reg.CR2 = 5;
1598
Cs2Area->reg.CR3 = 0;
1599
Cs2Area->reg.CR4 = 0;
1600
1601
// setup transfer here(fix me)
1602
break;
1603
case 1:
1604
// Get RW Channel
1605
Cs2Area->reg.CR1 = (Cs2Area->status << 8) | 0;
1606
Cs2Area->reg.CR2 = 12;
1607
Cs2Area->reg.CR3 = 0;
1608
Cs2Area->reg.CR4 = 0;
1609
1610
// setup transfer here(fix me)
1611
break;
1612
default: break;
1613
}
1614
1615
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_DRDY;
1616
}
1617
1618
//////////////////////////////////////////////////////////////////////////////
1619
1620
void Cs2SetCDDeviceConnection(void) {
1621
u32 scdcfilternum;
1622
1623
scdcfilternum = (Cs2Area->reg.CR3 >> 8);
1624
1625
if (scdcfilternum == 0xFF)
1626
Cs2Area->outconcddev = NULL;
1627
else if (scdcfilternum < 0x24)
1628
Cs2Area->outconcddev = Cs2Area->filter + scdcfilternum;
1629
1630
Cs2Area->outconcddevnum = (u8)scdcfilternum;
1631
1632
doCDReport(Cs2Area->status);
1633
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1634
}
1635
1636
//////////////////////////////////////////////////////////////////////////////
1637
1638
void Cs2GetLastBufferDestination(void) {
1639
Cs2Area->reg.CR1 = (Cs2Area->status << 8);
1640
Cs2Area->reg.CR2 = 0;
1641
Cs2Area->reg.CR3 = Cs2Area->lastbuffer << 8;
1642
Cs2Area->reg.CR4 = 0;
1643
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
1644
}
1645
1646
//////////////////////////////////////////////////////////////////////////////
1647
1648
void Cs2SetFilterRange(void) {
1649
u8 sfrfilternum;
1650
1651
sfrfilternum = Cs2Area->reg.CR3 >> 8;
1652
1653
Cs2Area->filter[sfrfilternum].FAD = ((Cs2Area->reg.CR1 & 0xFF) << 16) | Cs2Area->reg.CR2;
1654
Cs2Area->filter[sfrfilternum].range = ((Cs2Area->reg.CR3 & 0xFF) << 16) | Cs2Area->reg.CR4;
1655
1656
// return default cd stats
1657
doCDReport(Cs2Area->status);
1658
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1659
}
1660
1661
//////////////////////////////////////////////////////////////////////////////
1662
1663
void Cs2SetFilterSubheaderConditions(void) {
1664
u8 sfscfilternum;
1665
1666
sfscfilternum = Cs2Area->reg.CR3 >> 8;
1667
1668
Cs2Area->filter[sfscfilternum].chan = Cs2Area->reg.CR1 & 0xFF;
1669
Cs2Area->filter[sfscfilternum].smmask = Cs2Area->reg.CR2 >> 8;
1670
Cs2Area->filter[sfscfilternum].cimask = Cs2Area->reg.CR2 & 0xFF;
1671
Cs2Area->filter[sfscfilternum].fid = Cs2Area->reg.CR3 & 0xFF;;
1672
Cs2Area->filter[sfscfilternum].smval = Cs2Area->reg.CR4 >> 8;
1673
Cs2Area->filter[sfscfilternum].cival = Cs2Area->reg.CR4 & 0xFF;
1674
1675
doCDReport(Cs2Area->status);
1676
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1677
}
1678
1679
//////////////////////////////////////////////////////////////////////////////
1680
1681
void Cs2GetFilterSubheaderConditions(void) {
1682
u8 gfscfilternum;
1683
1684
gfscfilternum = Cs2Area->reg.CR3 >> 8;
1685
1686
Cs2Area->reg.CR1 = (Cs2Area->status << 8) | Cs2Area->filter[gfscfilternum].chan;
1687
Cs2Area->reg.CR2 = (Cs2Area->filter[gfscfilternum].smmask << 8) | Cs2Area->filter[gfscfilternum].cimask;
1688
Cs2Area->reg.CR3 = Cs2Area->filter[gfscfilternum].fid;
1689
Cs2Area->reg.CR4 = (Cs2Area->filter[gfscfilternum].smval << 8) | Cs2Area->filter[gfscfilternum].cival;
1690
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1691
}
1692
1693
//////////////////////////////////////////////////////////////////////////////
1694
1695
void Cs2SetFilterMode(void) {
1696
u8 sfmfilternum;
1697
1698
sfmfilternum = Cs2Area->reg.CR3 >> 8;
1699
1700
Cs2Area->filter[sfmfilternum].mode = Cs2Area->reg.CR1 & 0xFF;
1701
1702
if (Cs2Area->filter[sfmfilternum].mode & 0x80)
1703
{
1704
// Initialize filter conditions
1705
Cs2Area->filter[sfmfilternum].mode = 0;
1706
Cs2Area->filter[sfmfilternum].FAD = 0;
1707
Cs2Area->filter[sfmfilternum].range = 0;
1708
Cs2Area->filter[sfmfilternum].chan = 0;
1709
Cs2Area->filter[sfmfilternum].smmask = 0;
1710
Cs2Area->filter[sfmfilternum].cimask = 0;
1711
Cs2Area->filter[sfmfilternum].smval = 0;
1712
Cs2Area->filter[sfmfilternum].cival = 0;
1713
}
1714
1715
doCDReport(Cs2Area->status);
1716
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1717
}
1718
1719
//////////////////////////////////////////////////////////////////////////////
1720
1721
void Cs2GetFilterMode(void) {
1722
u8 gfmfilternum;
1723
1724
gfmfilternum = Cs2Area->reg.CR3 >> 8;
1725
1726
Cs2Area->reg.CR1 = (Cs2Area->status << 8) | Cs2Area->filter[gfmfilternum].mode;
1727
Cs2Area->reg.CR2 = 0;
1728
Cs2Area->reg.CR3 = 0;
1729
Cs2Area->reg.CR4 = 0;
1730
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1731
}
1732
1733
//////////////////////////////////////////////////////////////////////////////
1734
1735
void Cs2SetFilterConnection(void) {
1736
u8 sfcfilternum;
1737
1738
sfcfilternum = Cs2Area->reg.CR3 >> 8;
1739
1740
if (Cs2Area->reg.CR1 & 0x1)
1741
{
1742
// Set connection for true condition
1743
Cs2Area->filter[sfcfilternum].condtrue = Cs2Area->reg.CR2 >> 8;
1744
}
1745
1746
if (Cs2Area->reg.CR1 & 0x2)
1747
{
1748
// Set connection for false condition
1749
Cs2Area->filter[sfcfilternum].condfalse = Cs2Area->reg.CR2 & 0xFF;
1750
}
1751
1752
doCDReport(Cs2Area->status);
1753
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1754
}
1755
1756
//////////////////////////////////////////////////////////////////////////////
1757
1758
void Cs2ResetSelector(void) {
1759
// still needs a bit of work
1760
u32 i, i2;
1761
1762
if ((Cs2Area->reg.CR1 & 0xFF) == 0)
1763
{
1764
// Reset specified partition buffer only
1765
u32 rsbufno = Cs2Area->reg.CR3 >> 8;
1766
1767
// sort remaining blocks
1768
if (rsbufno < MAX_SELECTORS)
1769
{
1770
// clear partition
1771
for (i = 0; i < Cs2Area->partition[rsbufno].numblocks; i++)
1772
{
1773
Cs2FreeBlock(Cs2Area->partition[rsbufno].block[i]);
1774
Cs2Area->partition[rsbufno].block[i] = NULL;
1775
Cs2Area->partition[rsbufno].blocknum[i] = 0xFF;
1776
}
1777
1778
Cs2Area->partition[rsbufno].size = -1;
1779
Cs2Area->partition[rsbufno].numblocks = 0;
1780
}
1781
1782
if (Cs2Area->blockfreespace > 0) Cs2Area->isbufferfull = 0;
1783
if (Cs2Area->blockfreespace == 200) Cs2Area->isonesectorstored = 0;
1784
1785
doCDReport(Cs2Area->status);
1786
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1787
return;
1788
}
1789
1790
// parse flags and reset the specified area(fix me)
1791
if (Cs2Area->reg.CR1 & 0x80)
1792
{
1793
// reset false filter output connections
1794
for (i = 0; i < MAX_SELECTORS; i++)
1795
Cs2Area->filter[i].condfalse = 0xFF;
1796
}
1797
1798
if (Cs2Area->reg.CR1 & 0x40)
1799
{
1800
// reset true filter output connections
1801
for (i = 0; i < MAX_SELECTORS; i++)
1802
Cs2Area->filter[i].condtrue = (u8)i;
1803
}
1804
1805
if (Cs2Area->reg.CR1 & 0x10)
1806
{
1807
// reset filter conditions
1808
for (i = 0; i < MAX_SELECTORS; i++)
1809
{
1810
Cs2Area->filter[i].FAD = 0;
1811
Cs2Area->filter[i].range = 0xFFFFFFFF;
1812
Cs2Area->filter[i].mode = 0;
1813
Cs2Area->filter[i].chan = 0;
1814
Cs2Area->filter[i].smmask = 0;
1815
Cs2Area->filter[i].cimask = 0;
1816
Cs2Area->filter[i].fid = 0;
1817
Cs2Area->filter[i].smval = 0;
1818
Cs2Area->filter[i].cival = 0;
1819
}
1820
}
1821
1822
if (Cs2Area->reg.CR1 & 0x8)
1823
{
1824
// reset partition output connectors
1825
}
1826
1827
if (Cs2Area->reg.CR1 & 0x4)
1828
{
1829
// reset partitions buffer data
1830
Cs2Area->isbufferfull = 0;
1831
1832
// clear partitions
1833
for (i = 0; i < MAX_SELECTORS; i++)
1834
{
1835
Cs2Area->partition[i].size = -1;
1836
Cs2Area->partition[i].numblocks = 0;
1837
1838
for (i2 = 0; i2 < MAX_BLOCKS; i2++)
1839
{
1840
Cs2Area->partition[i].block[i2] = NULL;
1841
Cs2Area->partition[i].blocknum[i2] = 0xFF;
1842
}
1843
}
1844
1845
// clear blocks
1846
for (i = 0; i < MAX_BLOCKS; i++)
1847
{
1848
Cs2Area->block[i].size = -1;
1849
memset(Cs2Area->block[i].data, 0, 2352);
1850
}
1851
1852
Cs2Area->isonesectorstored = 0;
1853
}
1854
1855
doCDReport(Cs2Area->status);
1856
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1857
}
1858
1859
//////////////////////////////////////////////////////////////////////////////
1860
1861
void Cs2GetBufferSize(void) {
1862
Cs2Area->reg.CR1 = Cs2Area->status << 8;
1863
Cs2Area->reg.CR2 = (u16)Cs2Area->blockfreespace;
1864
Cs2Area->reg.CR3 = MAX_SELECTORS << 8;
1865
Cs2Area->reg.CR4 = MAX_BLOCKS;
1866
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
1867
}
1868
1869
//////////////////////////////////////////////////////////////////////////////
1870
1871
void Cs2GetSectorNumber(void) {
1872
u32 gsnbufno;
1873
1874
gsnbufno = Cs2Area->reg.CR3 >> 8;
1875
1876
if (Cs2Area->partition[gsnbufno].size == -1)
1877
Cs2Area->reg.CR4 = 0;
1878
else
1879
Cs2Area->reg.CR4 = Cs2Area->partition[gsnbufno].numblocks;
1880
1881
Cs2Area->reg.CR1 = Cs2Area->status << 8;
1882
Cs2Area->reg.CR2 = 0;
1883
Cs2Area->reg.CR3 = 0;
1884
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_DRDY;
1885
}
1886
1887
//////////////////////////////////////////////////////////////////////////////
1888
1889
void Cs2CalculateActualSize(void) {
1890
u16 i;
1891
u32 casbufno;
1892
u16 cassectoffset;
1893
u16 casnumsect;
1894
1895
cassectoffset = Cs2Area->reg.CR2;
1896
casbufno = Cs2Area->reg.CR3 >> 8;
1897
casnumsect = Cs2Area->reg.CR4;
1898
1899
if (Cs2Area->partition[casbufno].size != 0)
1900
{
1901
Cs2Area->calcsize = 0;
1902
1903
for (i = 0; i < casnumsect; i++)
1904
{
1905
if (Cs2Area->partition[casbufno].block[cassectoffset])
1906
Cs2Area->calcsize += (Cs2Area->partition[casbufno].block[cassectoffset]->size / 2);
1907
}
1908
}
1909
else
1910
Cs2Area->calcsize = 0;
1911
1912
doCDReport(Cs2Area->status);
1913
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1914
}
1915
1916
//////////////////////////////////////////////////////////////////////////////
1917
1918
void Cs2GetActualSize(void) {
1919
Cs2Area->reg.CR1 = (u16)((Cs2Area->status << 8) | ((Cs2Area->calcsize >> 16) & 0xFF));
1920
Cs2Area->reg.CR2 = (u16)Cs2Area->calcsize;
1921
Cs2Area->reg.CR3 = 0;
1922
Cs2Area->reg.CR4 = 0;
1923
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1924
}
1925
1926
//////////////////////////////////////////////////////////////////////////////
1927
1928
void Cs2GetSectorInfo(void) {
1929
u32 gsisctnum;
1930
u32 gsibufno;
1931
1932
gsisctnum = Cs2Area->reg.CR2 & 0xFF;
1933
gsibufno = Cs2Area->reg.CR3 >> 8;
1934
if (gsibufno < MAX_SELECTORS) {
1935
if (gsisctnum < Cs2Area->partition[gsibufno].numblocks) {
1936
Cs2Area->reg.CR1 = (u16)((Cs2Area->status << 8) | ((Cs2Area->partition[gsibufno].block[gsisctnum]->FAD >> 16) & 0xFF));
1937
Cs2Area->reg.CR2 = (u16)Cs2Area->partition[gsibufno].block[gsisctnum]->FAD;
1938
Cs2Area->reg.CR3 = (Cs2Area->partition[gsibufno].block[gsisctnum]->fn << 8) | Cs2Area->partition[gsibufno].block[gsisctnum]->cn;
1939
Cs2Area->reg.CR4 = (Cs2Area->partition[gsibufno].block[gsisctnum]->sm << 8) | Cs2Area->partition[gsibufno].block[gsisctnum]->ci;
1940
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1941
return;
1942
}
1943
else
1944
{
1945
CDLOG("cs2\t: getSectorInfo: Unsupported Partition Number\n");
1946
}
1947
}
1948
1949
Cs2Area->reg.CR1 = (CDB_STAT_REJECT << 8) | (Cs2Area->reg.CR1 & 0xFF);
1950
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1951
}
1952
1953
//////////////////////////////////////////////////////////////////////////////
1954
1955
void Cs2SetSectorLength(void) {
1956
switch (Cs2Area->reg.CR1 & 0xFF) {
1957
case 0:
1958
Cs2Area->getsectsize = 2048;
1959
break;
1960
case 1:
1961
Cs2Area->getsectsize = 2336;
1962
break;
1963
case 2:
1964
Cs2Area->getsectsize = 2340;
1965
break;
1966
case 3:
1967
Cs2Area->getsectsize = 2352;
1968
break;
1969
default: break;
1970
}
1971
1972
switch (Cs2Area->reg.CR2 >> 8) {
1973
case 0:
1974
Cs2Area->putsectsize = 2048;
1975
break;
1976
case 1:
1977
Cs2Area->putsectsize = 2336;
1978
break;
1979
case 2:
1980
Cs2Area->putsectsize = 2340;
1981
break;
1982
case 3:
1983
Cs2Area->putsectsize = 2352;
1984
break;
1985
default: break;
1986
}
1987
1988
doCDReport(Cs2Area->status);
1989
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_ESEL;
1990
}
1991
1992
//////////////////////////////////////////////////////////////////////////////
1993
1994
static INLINE void CalcSectorOffsetNumber(u32 bufno, u32 *sectoffset, u32 *sectnum)
1995
{
1996
if (*sectoffset == 0xFFFF)
1997
{
1998
// Last sector
1999
CDLOG("FIXME - Sector offset of 0xFFFF not supported\n");
2000
}
2001
else if (*sectnum == 0xFFFF)
2002
{
2003
// From sectoffset to last sector in partition
2004
*sectnum = Cs2Area->partition[bufno].numblocks - *sectoffset;
2005
}
2006
}
2007
2008
//////////////////////////////////////////////////////////////////////////////
2009
2010
void Cs2GetSectorData(void)
2011
{
2012
u32 gsdsectoffset;
2013
u32 gsdbufno;
2014
u32 gsdsectnum;
2015
2016
gsdsectoffset = Cs2Area->reg.CR2;
2017
gsdbufno = Cs2Area->reg.CR3 >> 8;
2018
gsdsectnum = Cs2Area->reg.CR4;
2019
2020
if (gsdbufno >= MAX_SELECTORS)
2021
{
2022
doCDReport(CDB_STAT_REJECT);
2023
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EHST;
2024
return;
2025
}
2026
2027
if (Cs2Area->partition[gsdbufno].numblocks == 0)
2028
{
2029
CDLOG("No sectors available\n");
2030
2031
doCDReport(CDB_STAT_REJECT);
2032
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EHST;
2033
return;
2034
}
2035
2036
CalcSectorOffsetNumber(gsdbufno, &gsdsectoffset, &gsdsectnum);
2037
2038
// Setup Data Transfer
2039
Cs2Area->cdwnum = 0;
2040
Cs2Area->datatranstype = 0;
2041
Cs2Area->datatranspartition = Cs2Area->partition + gsdbufno;
2042
Cs2Area->datatranspartitionnum = (u8)gsdbufno;
2043
Cs2Area->datatransoffset = 0;
2044
Cs2Area->datanumsecttrans = 0;
2045
Cs2Area->datatranssectpos = (u16)gsdsectoffset;
2046
Cs2Area->datasectstotrans = (u16)gsdsectnum;
2047
2048
doCDReport(Cs2Area->status);
2049
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_DRDY | CDB_HIRQ_EHST;
2050
}
2051
2052
//////////////////////////////////////////////////////////////////////////////
2053
2054
void Cs2DeleteSectorData(void)
2055
{
2056
u32 dsdsectoffset;
2057
u32 dsdbufno;
2058
u32 dsdsectnum;
2059
u32 i;
2060
2061
dsdsectoffset = Cs2Area->reg.CR2;
2062
dsdbufno = Cs2Area->reg.CR3 >> 8;
2063
dsdsectnum = Cs2Area->reg.CR4;
2064
2065
if (dsdbufno >= MAX_SELECTORS)
2066
{
2067
doCDReport(CDB_STAT_REJECT);
2068
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EHST;
2069
return;
2070
}
2071
2072
if (Cs2Area->partition[dsdbufno].numblocks == 0)
2073
{
2074
CDLOG("No sectors available\n");
2075
2076
doCDReport(CDB_STAT_REJECT);
2077
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EHST;
2078
return;
2079
}
2080
2081
CalcSectorOffsetNumber(dsdbufno, &dsdsectoffset, &dsdsectnum);
2082
2083
for (i = dsdsectoffset; i < (dsdsectoffset+dsdsectnum); i++)
2084
{
2085
Cs2Area->partition[dsdbufno].size -= Cs2Area->partition[dsdbufno].block[i]->size;
2086
Cs2FreeBlock(Cs2Area->partition[dsdbufno].block[i]);
2087
Cs2Area->partition[dsdbufno].block[i] = NULL;
2088
Cs2Area->partition[dsdbufno].blocknum[i] = 0xFF;
2089
}
2090
2091
// sort remaining blocks
2092
Cs2SortBlocks(&Cs2Area->partition[dsdbufno]);
2093
2094
Cs2Area->partition[dsdbufno].numblocks -= (u8)dsdsectnum;
2095
2096
if (Cs2Area->blockfreespace == 200)
2097
Cs2Area->isonesectorstored = 0;
2098
2099
doCDReport(Cs2Area->status);
2100
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EHST;
2101
}
2102
2103
//////////////////////////////////////////////////////////////////////////////
2104
2105
void Cs2GetThenDeleteSectorData(void)
2106
{
2107
u32 gtdsdsectoffset;
2108
u32 gtdsdbufno;
2109
u32 gtdsdsectnum;
2110
2111
gtdsdsectoffset = Cs2Area->reg.CR2;
2112
gtdsdbufno = Cs2Area->reg.CR3 >> 8;
2113
gtdsdsectnum = Cs2Area->reg.CR4;
2114
2115
if (gtdsdbufno >= MAX_SELECTORS)
2116
{
2117
doCDReport(CDB_STAT_REJECT);
2118
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EHST;
2119
return;
2120
}
2121
2122
if (Cs2Area->partition[gtdsdbufno].numblocks == 0)
2123
{
2124
CDLOG("No sectors available\n");
2125
2126
doCDReport(CDB_STAT_REJECT);
2127
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EHST;
2128
return;
2129
}
2130
2131
CalcSectorOffsetNumber(gtdsdbufno, &gtdsdsectoffset, &gtdsdsectnum);
2132
2133
// Setup Data Transfer
2134
Cs2Area->cdwnum = 0;
2135
Cs2Area->datatranstype = 2;
2136
Cs2Area->datatranspartition = Cs2Area->partition + gtdsdbufno;
2137
Cs2Area->datatransoffset = 0;
2138
Cs2Area->datanumsecttrans = 0;
2139
Cs2Area->datatranssectpos = (u16)gtdsdsectoffset;
2140
Cs2Area->datasectstotrans = (u16)gtdsdsectnum;
2141
2142
doCDReport(Cs2Area->status);
2143
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_DRDY | CDB_HIRQ_EHST;
2144
2145
return;
2146
}
2147
2148
//////////////////////////////////////////////////////////////////////////////
2149
2150
void Cs2PutSectorData(void) {
2151
u32 psdfiltno;
2152
2153
psdfiltno = Cs2Area->reg.CR3 >> 8;
2154
2155
if (psdfiltno < MAX_SELECTORS)
2156
{
2157
// I'm not really sure what I'm supposed to really be doing or returning
2158
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EHST;
2159
}
2160
else
2161
{
2162
doCDReport(CDB_STAT_REJECT);
2163
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EHST;
2164
}
2165
}
2166
2167
//////////////////////////////////////////////////////////////////////////////
2168
2169
void Cs2GetCopyError(void) {
2170
Cs2Area->reg.CR1 = Cs2Area->status << 8;
2171
Cs2Area->reg.CR2 = 0;
2172
Cs2Area->reg.CR3 = 0;
2173
Cs2Area->reg.CR4 = 0;
2174
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
2175
}
2176
2177
//////////////////////////////////////////////////////////////////////////////
2178
2179
void Cs2ChangeDirectory(void) {
2180
u32 cdfilternum;
2181
2182
cdfilternum = (Cs2Area->reg.CR3 >> 8);
2183
2184
if (cdfilternum == 0xFF)
2185
{
2186
doCDReport(CDB_STAT_REJECT);
2187
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EFLS;
2188
return;
2189
}
2190
else if (cdfilternum < 0x24)
2191
{
2192
if (Cs2ReadFileSystem(Cs2Area->filter + cdfilternum, ((Cs2Area->reg.CR3 & 0xFF) << 16) | Cs2Area->reg.CR4, 0) != 0)
2193
{
2194
CDLOG("cs2\t: ReadFileSystem failed\n");
2195
doCDReport(CDB_STAT_REJECT);
2196
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EFLS;
2197
return;
2198
}
2199
}
2200
2201
doCDReport(Cs2Area->status);
2202
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EFLS;
2203
}
2204
2205
//////////////////////////////////////////////////////////////////////////////
2206
2207
void Cs2ReadDirectory(void) {
2208
u32 rdfilternum;
2209
2210
rdfilternum = (Cs2Area->reg.CR3 >> 8);
2211
2212
if (rdfilternum == 0xFF)
2213
{
2214
doCDReport(CDB_STAT_REJECT);
2215
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EFLS;
2216
return;
2217
}
2218
else if (rdfilternum < 0x24)
2219
{
2220
if (Cs2ReadFileSystem(Cs2Area->filter + rdfilternum, ((Cs2Area->reg.CR3 & 0xFF) << 8) | Cs2Area->reg.CR4, 1) != 0)
2221
{
2222
CDLOG("cs2\t: ReadFileSystem failed\n");
2223
doCDReport(CDB_STAT_REJECT);
2224
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EFLS;
2225
return;
2226
}
2227
}
2228
2229
doCDReport(Cs2Area->status);
2230
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EFLS;
2231
}
2232
2233
//////////////////////////////////////////////////////////////////////////////
2234
2235
void Cs2GetFileSystemScope(void) {
2236
// may need to fix this
2237
Cs2Area->reg.CR1 = Cs2Area->status << 8;
2238
Cs2Area->reg.CR2 = (u16)(Cs2Area->numfiles - 2);
2239
Cs2Area->reg.CR3 = 0x0100;
2240
Cs2Area->reg.CR4 = 0x0002;
2241
2242
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EFLS;
2243
}
2244
2245
//////////////////////////////////////////////////////////////////////////////
2246
2247
void Cs2GetFileInfo(void) {
2248
u32 gfifid;
2249
2250
gfifid = ((Cs2Area->reg.CR3 & 0xFF) << 16) | Cs2Area->reg.CR4;
2251
2252
if (gfifid == 0xFFFFFF)
2253
{
2254
Cs2Area->transfercount = 0;
2255
Cs2Area->infotranstype = 2;
2256
2257
Cs2Area->reg.CR1 = Cs2Area->status << 8;
2258
Cs2Area->reg.CR2 = 0x05F4;
2259
Cs2Area->reg.CR3 = 0;
2260
Cs2Area->reg.CR4 = 0;
2261
}
2262
else
2263
{
2264
Cs2SetupFileInfoTransfer(gfifid);
2265
2266
Cs2Area->transfercount = 0;
2267
Cs2Area->infotranstype = 1;
2268
2269
Cs2Area->reg.CR1 = Cs2Area->status << 8;
2270
Cs2Area->reg.CR2 = 0x06;
2271
Cs2Area->reg.CR3 = 0;
2272
Cs2Area->reg.CR4 = 0;
2273
}
2274
2275
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_DRDY;
2276
}
2277
2278
//////////////////////////////////////////////////////////////////////////////
2279
2280
void Cs2ReadFile(void) {
2281
u32 rfoffset, rffilternum, rffid, rfsize;
2282
2283
rfoffset = ((Cs2Area->reg.CR1 & 0xFF) << 8) | Cs2Area->reg.CR2;
2284
rffilternum = Cs2Area->reg.CR3 >> 8;
2285
rffid = ((Cs2Area->reg.CR3 & 0xFF) << 8) | Cs2Area->reg.CR4;
2286
rfsize = ((Cs2Area->fileinfo[rffid].size + Cs2Area->getsectsize - 1) /
2287
Cs2Area->getsectsize) - rfoffset;
2288
2289
Cs2SetupDefaultPlayStats(Cs2FADToTrack(Cs2Area->fileinfo[rffid].lba + rfoffset), 0);
2290
Cs2Area->maxrepeat = 0;
2291
2292
Cs2Area->playFAD = Cs2Area->FAD = Cs2Area->fileinfo[rffid].lba + rfoffset;
2293
Cs2Area->playendFAD = Cs2Area->playFAD + rfsize;
2294
2295
Cs2Area->options = 0x8;
2296
2297
Cs2SetTiming(1);
2298
2299
Cs2Area->outconcddev = Cs2Area->filter + rffilternum;
2300
2301
Cs2Area->status = CDB_STAT_PLAY;
2302
Cs2Area->playtype = CDB_PLAYTYPE_FILE;
2303
Cs2Area->cdi->ReadAheadFAD(Cs2Area->FAD);
2304
2305
doCDReport(Cs2Area->status);
2306
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
2307
}
2308
2309
//////////////////////////////////////////////////////////////////////////////
2310
2311
void Cs2AbortFile(void) {
2312
if ((Cs2Area->status & 0xF) != CDB_STAT_OPEN &&
2313
(Cs2Area->status & 0xF) != CDB_STAT_NODISC)
2314
Cs2Area->status = CDB_STAT_PAUSE;
2315
Cs2Area->isonesectorstored = 0;
2316
Cs2Area->datatranstype = -1;
2317
Cs2Area->cdwnum = 0;
2318
doCDReport(Cs2Area->status);
2319
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_EFLS;
2320
}
2321
2322
//////////////////////////////////////////////////////////////////////////////
2323
2324
void Cs2MpegGetStatus(void) {
2325
doMPEGReport(Cs2Area->status);
2326
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2327
}
2328
2329
//////////////////////////////////////////////////////////////////////////////
2330
2331
void Cs2MpegGetInterrupt(void) {
2332
u32 mgiworkinterrupt;
2333
2334
// mpeg interrupt should be retrieved here
2335
mgiworkinterrupt = 0;
2336
2337
// mask interupt
2338
mgiworkinterrupt &= Cs2Area->mpegintmask;
2339
2340
Cs2Area->reg.CR1 = (u16)((Cs2Area->status << 8) | ((mgiworkinterrupt >> 16) & 0xFF));
2341
Cs2Area->reg.CR2 = (u16) mgiworkinterrupt;
2342
Cs2Area->reg.CR3 = 0;
2343
Cs2Area->reg.CR4 = 0;
2344
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2345
}
2346
2347
//////////////////////////////////////////////////////////////////////////////
2348
2349
void Cs2MpegSetInterruptMask(void) {
2350
Cs2Area->mpegintmask = ((Cs2Area->reg.CR1 & 0xFF) << 16) | Cs2Area->reg.CR2;
2351
2352
doMPEGReport(Cs2Area->status);
2353
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2354
}
2355
2356
//////////////////////////////////////////////////////////////////////////////
2357
2358
void Cs2MpegInit(void) {
2359
2360
if (Cs2Area->mpgauth)
2361
Cs2Area->reg.CR1 = Cs2Area->status << 8;
2362
else
2363
Cs2Area->reg.CR1 = 0xFF00;
2364
2365
// double-check this
2366
if (Cs2Area->reg.CR2 == 0x0001) // software timer/reset?
2367
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM | CDB_HIRQ_MPED | CDB_HIRQ_MPST;
2368
else
2369
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPED | CDB_HIRQ_MPST;
2370
2371
Cs2Area->reg.CR2 = 0;
2372
Cs2Area->reg.CR3 = 0;
2373
Cs2Area->reg.CR4 = 0;
2374
2375
// future mpeg-related variables should be initialized here
2376
}
2377
2378
//////////////////////////////////////////////////////////////////////////////
2379
2380
void Cs2MpegSetMode(void) {
2381
// fix me
2382
2383
doMPEGReport(Cs2Area->status);
2384
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2385
}
2386
2387
//////////////////////////////////////////////////////////////////////////////
2388
2389
void Cs2MpegPlay(void) {
2390
// fix me
2391
2392
doMPEGReport(Cs2Area->status);
2393
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2394
}
2395
2396
//////////////////////////////////////////////////////////////////////////////
2397
2398
void Cs2MpegSetDecodingMethod(void) {
2399
// fix me
2400
2401
doMPEGReport(Cs2Area->status);
2402
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2403
}
2404
2405
//////////////////////////////////////////////////////////////////////////////
2406
2407
void Cs2MpegSetConnection(void) {
2408
int mscnext = (Cs2Area->reg.CR3 >> 8);
2409
2410
if (mscnext == 0)
2411
{
2412
// Current
2413
Cs2Area->mpegcon[0].audcon = Cs2Area->reg.CR1 & 0xFF;
2414
Cs2Area->mpegcon[0].audlay = Cs2Area->reg.CR2 >> 8;
2415
Cs2Area->mpegcon[0].audbufdivnum = Cs2Area->reg.CR2 & 0xFF;
2416
Cs2Area->mpegcon[0].vidcon = Cs2Area->reg.CR3 & 0xFF;
2417
Cs2Area->mpegcon[0].vidlay = Cs2Area->reg.CR4 >> 8;
2418
Cs2Area->mpegcon[0].vidbufdivnum = Cs2Area->reg.CR4 & 0xFF;
2419
}
2420
else
2421
{
2422
// Next
2423
Cs2Area->mpegcon[1].audcon = Cs2Area->reg.CR1 & 0xFF;
2424
Cs2Area->mpegcon[1].audlay = Cs2Area->reg.CR2 >> 8;
2425
Cs2Area->mpegcon[1].audbufdivnum = Cs2Area->reg.CR2 & 0xFF;
2426
Cs2Area->mpegcon[1].vidcon = Cs2Area->reg.CR3 & 0xFF;
2427
Cs2Area->mpegcon[1].vidlay = Cs2Area->reg.CR4 >> 8;
2428
Cs2Area->mpegcon[1].vidbufdivnum = Cs2Area->reg.CR4 & 0xFF;
2429
}
2430
2431
doMPEGReport(Cs2Area->status);
2432
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2433
}
2434
2435
//////////////////////////////////////////////////////////////////////////////
2436
2437
void Cs2MpegGetConnection(void) {
2438
int mgcnext = (Cs2Area->reg.CR3 >> 8);
2439
2440
if (mgcnext == 0)
2441
{
2442
// Current
2443
Cs2Area->reg.CR1 = (Cs2Area->status << 8) | Cs2Area->mpegcon[0].audcon;
2444
Cs2Area->reg.CR2 = (Cs2Area->mpegcon[0].audlay << 8) | Cs2Area->mpegcon[0].audbufdivnum;
2445
Cs2Area->reg.CR3 = Cs2Area->mpegcon[0].vidcon;
2446
Cs2Area->reg.CR4 = (Cs2Area->mpegcon[0].vidlay << 8) | Cs2Area->mpegcon[0].vidbufdivnum;
2447
}
2448
else
2449
{
2450
// Next
2451
Cs2Area->reg.CR1 = (Cs2Area->status << 8) | Cs2Area->mpegcon[1].audcon;
2452
Cs2Area->reg.CR2 = (Cs2Area->mpegcon[1].audlay << 8) | Cs2Area->mpegcon[1].audbufdivnum;
2453
Cs2Area->reg.CR3 = Cs2Area->mpegcon[1].vidcon;
2454
Cs2Area->reg.CR4 = (Cs2Area->mpegcon[1].vidlay << 8) | Cs2Area->mpegcon[1].vidbufdivnum;
2455
}
2456
2457
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2458
}
2459
2460
//////////////////////////////////////////////////////////////////////////////
2461
2462
void Cs2MpegSetStream(void) {
2463
int mssnext = (Cs2Area->reg.CR3 >> 8);
2464
2465
if (mssnext == 0)
2466
{
2467
// Current
2468
Cs2Area->mpegstm[0].audstm = Cs2Area->reg.CR1 & 0xFF;
2469
Cs2Area->mpegstm[0].audstmid = Cs2Area->reg.CR2 >> 8;
2470
Cs2Area->mpegstm[0].audchannum = Cs2Area->reg.CR2 & 0xFF;
2471
Cs2Area->mpegstm[0].vidstm = Cs2Area->reg.CR3 & 0xFF;
2472
Cs2Area->mpegstm[0].vidstmid = Cs2Area->reg.CR4 >> 8;
2473
Cs2Area->mpegstm[0].vidchannum = Cs2Area->reg.CR4 & 0xFF;
2474
}
2475
else
2476
{
2477
// Next
2478
Cs2Area->mpegstm[1].audstm = Cs2Area->reg.CR1 & 0xFF;
2479
Cs2Area->mpegstm[1].audstmid = Cs2Area->reg.CR2 >> 8;
2480
Cs2Area->mpegstm[1].audchannum = Cs2Area->reg.CR2 & 0xFF;
2481
Cs2Area->mpegstm[1].vidstm = Cs2Area->reg.CR3 & 0xFF;
2482
Cs2Area->mpegstm[1].vidstmid = Cs2Area->reg.CR4 >> 8;
2483
Cs2Area->mpegstm[1].vidchannum = Cs2Area->reg.CR4 & 0xFF;
2484
}
2485
2486
doMPEGReport(Cs2Area->status);
2487
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2488
}
2489
2490
//////////////////////////////////////////////////////////////////////////////
2491
2492
void Cs2MpegGetStream(void) {
2493
int mgsnext = (Cs2Area->reg.CR3 >> 8);
2494
2495
if (mgsnext == 0)
2496
{
2497
// Current
2498
Cs2Area->reg.CR1 = (Cs2Area->status << 8) | Cs2Area->mpegstm[0].audstm;
2499
Cs2Area->reg.CR2 = (Cs2Area->mpegstm[0].audstmid << 8) | Cs2Area->mpegstm[0].audchannum;
2500
Cs2Area->reg.CR3 = Cs2Area->mpegstm[0].vidstm;
2501
Cs2Area->reg.CR4 = (Cs2Area->mpegstm[0].vidstmid << 8) | Cs2Area->mpegstm[0].vidchannum;
2502
}
2503
else
2504
{
2505
// Next
2506
Cs2Area->reg.CR1 = (Cs2Area->status << 8) | Cs2Area->mpegstm[1].audstm;
2507
Cs2Area->reg.CR2 = (Cs2Area->mpegstm[1].audstmid << 8) | Cs2Area->mpegstm[1].audchannum;
2508
Cs2Area->reg.CR3 = Cs2Area->mpegstm[1].vidstm;
2509
Cs2Area->reg.CR4 = (Cs2Area->mpegstm[1].vidstmid << 8) | Cs2Area->mpegstm[1].vidchannum;
2510
}
2511
2512
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2513
}
2514
2515
//////////////////////////////////////////////////////////////////////////////
2516
2517
void Cs2MpegDisplay(void) {
2518
// fix me(should be setting display setting)
2519
2520
doMPEGReport(Cs2Area->status);
2521
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2522
}
2523
2524
//////////////////////////////////////////////////////////////////////////////
2525
2526
void Cs2MpegSetWindow(void) {
2527
// fix me(should be setting windows settings)
2528
2529
// return default mpeg stats
2530
doMPEGReport(Cs2Area->status);
2531
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2532
}
2533
2534
//////////////////////////////////////////////////////////////////////////////
2535
2536
void Cs2MpegSetBorderColor(void) {
2537
// fix me(should be setting border color)
2538
2539
doMPEGReport(Cs2Area->status);
2540
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2541
}
2542
2543
//////////////////////////////////////////////////////////////////////////////
2544
2545
void Cs2MpegSetFade(void) {
2546
// fix me(should be setting fade setting)
2547
2548
doMPEGReport(Cs2Area->status);
2549
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2550
}
2551
2552
//////////////////////////////////////////////////////////////////////////////
2553
2554
void Cs2MpegSetVideoEffects(void) {
2555
// fix me(should be setting video effects settings)
2556
2557
doMPEGReport(Cs2Area->status);
2558
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2559
}
2560
2561
//////////////////////////////////////////////////////////////////////////////
2562
2563
void Cs2MpegSetLSI(void) {
2564
// fix me(should be setting the LSI, among other things)
2565
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPCM;
2566
}
2567
2568
//////////////////////////////////////////////////////////////////////////////
2569
2570
void Cs2CmdE0(void) {
2571
int mpegauth;
2572
2573
mpegauth = Cs2Area->reg.CR2 & 0xFF;
2574
2575
2576
if ((Cs2Area->status & 0xF) != CDB_STAT_NODISC &&
2577
(Cs2Area->status & 0xF) != CDB_STAT_OPEN)
2578
{
2579
// Set registers all to invalid values(aside from status)
2580
Cs2Area->status = CDB_STAT_BUSY;
2581
2582
Cs2Area->reg.CR1 = (Cs2Area->status << 8) | 0xFF;
2583
Cs2Area->reg.CR2 = 0xFFFF;
2584
Cs2Area->reg.CR3 = 0xFFFF;
2585
Cs2Area->reg.CR4 = 0xFFFF;
2586
2587
if (mpegauth == 1)
2588
{
2589
Cs2Area->reg.HIRQ |= CDB_HIRQ_MPED;
2590
Cs2Area->mpgauth = 2;
2591
}
2592
else
2593
{
2594
// if authentication passes(obviously it always does), CDB_HIRQ_CSCT is set
2595
Cs2Area->isonesectorstored = 1;
2596
Cs2Area->reg.HIRQ |= CDB_HIRQ_EFLS | CDB_HIRQ_CSCT;
2597
Cs2Area->satauth = 4;
2598
}
2599
2600
// Set registers all back to normal values
2601
2602
Cs2Area->status = CDB_STAT_PAUSE;
2603
}
2604
else
2605
{
2606
if (mpegauth == 1)
2607
{
2608
Cs2Area->reg.HIRQ |= CDB_HIRQ_MPED;
2609
Cs2Area->mpgauth = 2;
2610
}
2611
else
2612
Cs2Area->reg.HIRQ |= CDB_HIRQ_EFLS | CDB_HIRQ_CSCT;
2613
}
2614
2615
doCDReport(Cs2Area->status);
2616
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
2617
}
2618
2619
//////////////////////////////////////////////////////////////////////////////
2620
2621
void Cs2CmdE1(void) {
2622
Cs2Area->reg.CR1 = (Cs2Area->status << 8);
2623
if (Cs2Area->reg.CR2)
2624
Cs2Area->reg.CR2 = Cs2Area->mpgauth;
2625
else
2626
Cs2Area->reg.CR2 = Cs2Area->satauth;
2627
Cs2Area->reg.CR3 = 0;
2628
Cs2Area->reg.CR4 = 0;
2629
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK;
2630
}
2631
2632
//////////////////////////////////////////////////////////////////////////////
2633
2634
void Cs2CmdE2(void) {
2635
u16 i;
2636
FILE * mpgfp;
2637
partition_struct * mpgpartition;
2638
2639
// fix me
2640
Cs2Area->mpgauth |= 0x300;
2641
2642
Cs2Area->outconmpegrom = Cs2Area->filter + 0;
2643
Cs2Area->outconmpegromnum = 0;
2644
2645
if (Cs2Area->mpegpath && (mpgfp = fopen(Cs2Area->mpegpath, "rb")) != NULL)
2646
{
2647
u32 readoffset = ((Cs2Area->reg.CR1 & 0xFF) << 8) | Cs2Area->reg.CR2;
2648
u16 readsize = Cs2Area->reg.CR4;
2649
2650
fseek(mpgfp, readoffset * Cs2Area->getsectsize, SEEK_SET);
2651
if ((mpgpartition = Cs2GetPartition(Cs2Area->outconmpegrom)) != NULL && !Cs2Area->isbufferfull)
2652
{
2653
IOCheck_struct check;
2654
mpgpartition->size = 0;
2655
2656
for (i = 0; i < readsize; i++)
2657
{
2658
mpgpartition->block[mpgpartition->numblocks] = Cs2AllocateBlock(&mpgpartition->blocknum[mpgpartition->numblocks]);
2659
2660
if (mpgpartition->block[mpgpartition->numblocks] != NULL) {
2661
// read data
2662
yread(&check, (void *)mpgpartition->block[mpgpartition->numblocks]->data, 1, Cs2Area->getsectsize, mpgfp);
2663
2664
mpgpartition->numblocks++;
2665
mpgpartition->size += Cs2Area->getsectsize;
2666
}
2667
}
2668
2669
Cs2Area->isonesectorstored = 1;
2670
Cs2Area->reg.HIRQ |= CDB_HIRQ_CSCT;
2671
}
2672
2673
fclose(mpgfp);
2674
}
2675
2676
doCDReport(Cs2Area->status);
2677
Cs2Area->reg.HIRQ |= CDB_HIRQ_CMOK | CDB_HIRQ_MPED;
2678
}
2679
2680
//////////////////////////////////////////////////////////////////////////////
2681
2682
u8 Cs2FADToTrack(u32 val) {
2683
int i;
2684
for (i = 0; i < 99; i++)
2685
{
2686
if (Cs2Area->TOC[i] == 0xFFFFFFFF) return 0xFF;
2687
2688
if (val >= (Cs2Area->TOC[i] & 0xFFFFFF) && val < (Cs2Area->TOC[i + 1] & 0xFFFFFF))
2689
return (i + 1);
2690
}
2691
2692
return 0;
2693
}
2694
2695
//////////////////////////////////////////////////////////////////////////////
2696
2697
u32 Cs2TrackToFAD(u16 trackandindex) {
2698
if (trackandindex == 0xFFFF)
2699
// leadout position
2700
return (Cs2Area->TOC[101] & 0x00FFFFFF);
2701
if (trackandindex != 0x0000)
2702
{
2703
// regular track
2704
// (really, we should be fetching subcode q's here)
2705
if ((trackandindex & 0xFF) == 0x01)
2706
// Return Start of Track
2707
return (Cs2Area->TOC[(trackandindex >> 8) - 1] & 0x00FFFFFF);
2708
else if ((trackandindex & 0xFF) == 0x63)
2709
// Return End of Track
2710
return ((Cs2Area->TOC[(trackandindex >> 8)] & 0x00FFFFFF) - 1);
2711
}
2712
2713
// assume it's leadin
2714
return 0;
2715
}
2716
2717
//////////////////////////////////////////////////////////////////////////////
2718
2719
void Cs2SetupDefaultPlayStats(u8 track_number, int writeFAD) {
2720
if (track_number != 0xFF)
2721
{
2722
Cs2Area->options = 0;
2723
Cs2Area->repcnt = 0;
2724
Cs2Area->ctrladdr = (u8)(Cs2Area->TOC[track_number - 1] >> 24);
2725
Cs2Area->index = 1;
2726
Cs2Area->track = track_number;
2727
if (writeFAD)
2728
Cs2Area->FAD = Cs2Area->TOC[track_number - 1] & 0x00FFFFFF;
2729
}
2730
}
2731
2732
//////////////////////////////////////////////////////////////////////////////
2733
2734
block_struct * Cs2AllocateBlock(u8 * blocknum) {
2735
u32 i;
2736
// find a free block
2737
for(i = 0; i < 200; i++)
2738
{
2739
if (Cs2Area->block[i].size == -1)
2740
{
2741
Cs2Area->blockfreespace--;
2742
2743
if (Cs2Area->blockfreespace <= 0) Cs2Area->isbufferfull = 1;
2744
2745
Cs2Area->block[i].size = Cs2Area->getsectsize;
2746
2747
*blocknum = (u8)i;
2748
return (Cs2Area->block + i);
2749
}
2750
}
2751
2752
Cs2Area->isbufferfull = 1;
2753
2754
return NULL;
2755
}
2756
2757
//////////////////////////////////////////////////////////////////////////////
2758
2759
void Cs2FreeBlock(block_struct * blk) {
2760
if (blk == NULL) return;
2761
blk->size = -1;
2762
Cs2Area->blockfreespace++;
2763
Cs2Area->isbufferfull = 0;
2764
Cs2Area->reg.HIRQ &= ~CDB_HIRQ_BFUL;
2765
}
2766
2767
//////////////////////////////////////////////////////////////////////////////
2768
2769
void Cs2SortBlocks(partition_struct * part) {
2770
unsigned int from, to;
2771
2772
for (from = to = 0; from < MAX_BLOCKS; from++)
2773
{
2774
if (part->block[from] != NULL)
2775
{
2776
if (to != from)
2777
{
2778
part->block[to] = part->block[from];
2779
}
2780
to++;
2781
}
2782
}
2783
2784
for (; to < MAX_BLOCKS; to++) {
2785
part->block[to] = NULL;
2786
}
2787
}
2788
2789
//////////////////////////////////////////////////////////////////////////////
2790
2791
partition_struct * Cs2GetPartition(filter_struct * curfilter)
2792
{
2793
// go through various filter conditions here(fix me)
2794
2795
return &Cs2Area->partition[curfilter->condtrue];
2796
}
2797
2798
//////////////////////////////////////////////////////////////////////////////
2799
2800
partition_struct * Cs2FilterData(filter_struct * curfilter, int isaudio)
2801
{
2802
int condresults = 1;
2803
partition_struct * fltpartition = NULL;
2804
2805
// fix me, this is pretty bad. Though I guess it's a start
2806
2807
for (;;)
2808
{
2809
// detect which type of sector we're dealing with
2810
// If it's not mode 2, ignore the subheader conditions
2811
if (Cs2Area->workblock.data[0xF] == 0x02 && !isaudio)
2812
{
2813
// Mode 2
2814
// go through various subheader filter conditions here(fix me)
2815
2816
if (curfilter->mode & 0x01)
2817
{
2818
// File Number Check
2819
if (Cs2Area->workblock.fn != curfilter->fid)
2820
condresults = 0;
2821
}
2822
2823
if (curfilter->mode & 0x02)
2824
{
2825
// Channel Number Check
2826
if (Cs2Area->workblock.cn != curfilter->chan)
2827
condresults = 0;
2828
}
2829
2830
if (curfilter->mode & 0x04)
2831
{
2832
// Sub Mode Check
2833
if ((Cs2Area->workblock.sm & curfilter->smmask) != curfilter->smval)
2834
condresults = 0;
2835
}
2836
2837
if (curfilter->mode & 0x08)
2838
{
2839
// Coding Information Check
2840
CDLOG("cs2\t: FilterData: Coding Information Check. Coding Information = %02X. Filter's Coding Information Mask = %02X, Coding Information Value = %02X\n", Cs2Area->workblock.ci, curfilter->cimask, curfilter->cival);
2841
if ((Cs2Area->workblock.ci & curfilter->cimask) != curfilter->cival)
2842
condresults = 0;
2843
}
2844
2845
if (curfilter->mode & 0x10)
2846
{
2847
// Reverse Subheader Conditions
2848
CDLOG("cs2\t: FilterData: Reverse Subheader Conditions\n");
2849
condresults ^= 1;
2850
}
2851
}
2852
2853
if (curfilter->mode & 0x40)
2854
{
2855
// FAD Range Check
2856
if (Cs2Area->workblock.FAD < curfilter->FAD ||
2857
Cs2Area->workblock.FAD > (curfilter->FAD+curfilter->range))
2858
condresults = 0;
2859
}
2860
2861
if (condresults == 1)
2862
{
2863
Cs2Area->lastbuffer = curfilter->condtrue;
2864
fltpartition = &Cs2Area->partition[curfilter->condtrue];
2865
break;
2866
}
2867
else
2868
{
2869
Cs2Area->lastbuffer = curfilter->condfalse;
2870
2871
if (curfilter->condfalse == 0xFF)
2872
return NULL;
2873
// loop and try filter that was connected to the false connector
2874
curfilter = &Cs2Area->filter[curfilter->condfalse];
2875
}
2876
}
2877
2878
// Allocate block
2879
fltpartition->block[fltpartition->numblocks] = Cs2AllocateBlock(&fltpartition->blocknum[fltpartition->numblocks]);
2880
2881
if (fltpartition->block[fltpartition->numblocks] == NULL)
2882
return NULL;
2883
2884
// Copy workblock settings to allocated block
2885
fltpartition->block[fltpartition->numblocks]->size = Cs2Area->workblock.size;
2886
fltpartition->block[fltpartition->numblocks]->FAD = Cs2Area->workblock.FAD;
2887
fltpartition->block[fltpartition->numblocks]->cn = Cs2Area->workblock.cn;
2888
fltpartition->block[fltpartition->numblocks]->fn = Cs2Area->workblock.fn;
2889
fltpartition->block[fltpartition->numblocks]->sm = Cs2Area->workblock.sm;
2890
fltpartition->block[fltpartition->numblocks]->ci = Cs2Area->workblock.ci;
2891
2892
// convert raw sector to type specified in getsectsize
2893
switch(Cs2Area->workblock.size)
2894
{
2895
case 2048: // user data only
2896
if (Cs2Area->workblock.data[0xF] == 0x02)
2897
// m2f1
2898
memcpy(fltpartition->block[fltpartition->numblocks]->data,
2899
Cs2Area->workblock.data + 24, Cs2Area->workblock.size);
2900
else
2901
// m1
2902
memcpy(fltpartition->block[fltpartition->numblocks]->data,
2903
Cs2Area->workblock.data + 16, Cs2Area->workblock.size);
2904
break;
2905
case 2324: // m2f2 user data only
2906
memcpy(fltpartition->block[fltpartition->numblocks]->data,
2907
Cs2Area->workblock.data + 24, Cs2Area->workblock.size);
2908
break;
2909
case 2336: // m2f2 skip sync+header data
2910
memcpy(fltpartition->block[fltpartition->numblocks]->data,
2911
Cs2Area->workblock.data + 16, Cs2Area->workblock.size);
2912
break;
2913
case 2340: // m2f2 skip sync data
2914
memcpy(fltpartition->block[fltpartition->numblocks]->data,
2915
Cs2Area->workblock.data + 12, Cs2Area->workblock.size);
2916
break;
2917
case 2352: // Copy data as is
2918
memcpy(fltpartition->block[fltpartition->numblocks]->data,
2919
Cs2Area->workblock.data, Cs2Area->workblock.size);
2920
break;
2921
default: break;
2922
}
2923
2924
// Modify Partition values
2925
if (fltpartition->size == -1) fltpartition->size = 0;
2926
fltpartition->size += fltpartition->block[fltpartition->numblocks]->size;
2927
fltpartition->numblocks++;
2928
2929
return fltpartition;
2930
}
2931
2932
//////////////////////////////////////////////////////////////////////////////
2933
2934
int Cs2CopyDirRecord(u8 * buffer, dirrec_struct * dirrec)
2935
{
2936
u8 * temp_pointer;
2937
2938
temp_pointer = buffer;
2939
2940
memcpy(&dirrec->recordsize, buffer, sizeof(dirrec->recordsize));
2941
buffer += sizeof(dirrec->recordsize);
2942
2943
memcpy(&dirrec->xarecordsize, buffer, sizeof(dirrec->xarecordsize));
2944
buffer += sizeof(dirrec->xarecordsize);
2945
2946
#ifdef WORDS_BIGENDIAN
2947
buffer += sizeof(dirrec->lba);
2948
memcpy(&dirrec->lba, buffer, sizeof(dirrec->lba));
2949
buffer += sizeof(dirrec->lba);
2950
#else
2951
memcpy(&dirrec->lba, buffer, sizeof(dirrec->lba));
2952
buffer += (sizeof(dirrec->lba) * 2);
2953
#endif
2954
2955
#ifdef WORDS_BIGENDIAN
2956
buffer += sizeof(dirrec->size);
2957
memcpy(&dirrec->size, buffer, sizeof(dirrec->size));
2958
buffer += sizeof(dirrec->size);
2959
#else
2960
memcpy(&dirrec->size, buffer, sizeof(dirrec->size));
2961
buffer += (sizeof(dirrec->size) * 2);
2962
#endif
2963
2964
dirrec->dateyear = buffer[0];
2965
dirrec->datemonth = buffer[1];
2966
dirrec->dateday = buffer[2];
2967
dirrec->datehour = buffer[3];
2968
dirrec->dateminute = buffer[4];
2969
dirrec->datesecond = buffer[5];
2970
dirrec->gmtoffset = buffer[6];
2971
buffer += 7;
2972
2973
dirrec->flags = buffer[0];
2974
buffer += sizeof(dirrec->flags);
2975
2976
dirrec->fileunitsize = buffer[0];
2977
buffer += sizeof(dirrec->fileunitsize);
2978
2979
dirrec->interleavegapsize = buffer[0];
2980
buffer += sizeof(dirrec->interleavegapsize);
2981
2982
#ifdef WORDS_BIGENDIAN
2983
buffer += sizeof(dirrec->volumesequencenumber);
2984
memcpy(&dirrec->volumesequencenumber, buffer, sizeof(dirrec->volumesequencenumber));
2985
buffer += sizeof(dirrec->volumesequencenumber);
2986
#else
2987
memcpy(&dirrec->volumesequencenumber, buffer, sizeof(dirrec->volumesequencenumber));
2988
buffer += (sizeof(dirrec->volumesequencenumber) * 2);
2989
#endif
2990
2991
dirrec->namelength = buffer[0];
2992
buffer += sizeof(dirrec->namelength);
2993
2994
memset(dirrec->name, 0, sizeof(dirrec->name));
2995
memcpy(dirrec->name, buffer, dirrec->namelength);
2996
buffer += dirrec->namelength;
2997
2998
// handle padding
2999
buffer += (1 - dirrec->namelength % 2);
3000
3001
memset(&dirrec->xarecord, 0, sizeof(dirrec->xarecord));
3002
3003
// sadily, this is the best way I can think of for detecting XA records
3004
3005
if ((dirrec->recordsize - (buffer - temp_pointer)) == 14)
3006
{
3007
memcpy(&dirrec->xarecord.groupid, buffer, sizeof(dirrec->xarecord.groupid));
3008
buffer += sizeof(dirrec->xarecord.groupid);
3009
3010
memcpy(&dirrec->xarecord.userid, buffer, sizeof(dirrec->xarecord.userid));
3011
buffer += sizeof(dirrec->xarecord.userid);
3012
3013
memcpy(&dirrec->xarecord.attributes, buffer, sizeof(dirrec->xarecord.attributes));
3014
buffer += sizeof(dirrec->xarecord.attributes);
3015
3016
#ifndef WORDS_BIGENDIAN
3017
// byte swap it
3018
dirrec->xarecord.attributes = ((dirrec->xarecord.attributes & 0xFF00) >> 8) +
3019
((dirrec->xarecord.attributes & 0x00FF) << 8);
3020
#endif
3021
3022
memcpy(&dirrec->xarecord.signature, buffer, sizeof(dirrec->xarecord.signature));
3023
buffer += sizeof(dirrec->xarecord.signature);
3024
3025
memcpy(&dirrec->xarecord.filenumber, buffer, sizeof(dirrec->xarecord.filenumber));
3026
buffer += sizeof(dirrec->xarecord.filenumber);
3027
3028
memcpy(dirrec->xarecord.reserved, buffer, sizeof(dirrec->xarecord.reserved));
3029
buffer += sizeof(dirrec->xarecord.reserved);
3030
}
3031
3032
return 0;
3033
}
3034
3035
//////////////////////////////////////////////////////////////////////////////
3036
3037
int Cs2ReadFileSystem(filter_struct * curfilter, u32 fid, int isoffset)
3038
{
3039
u8 * workbuffer;
3040
u32 i;
3041
dirrec_struct dirrec;
3042
u8 numsectorsleft = 0;
3043
u32 curdirlba = 0;
3044
partition_struct * rfspartition;
3045
u32 blocksectsize = Cs2Area->getsectsize;
3046
3047
Cs2Area->outconcddev = curfilter;
3048
3049
if (isoffset)
3050
{
3051
// readDirectory operation
3052
3053
// make sure we have a valid current directory
3054
if (Cs2Area->curdirsect == 0)
3055
return -1;
3056
3057
Cs2Area->curdirfidoffset = fid - 2;
3058
curdirlba = Cs2Area->curdirsect;
3059
numsectorsleft = (u8)Cs2Area->curdirsize;
3060
}
3061
else
3062
{
3063
// changeDirectory operation
3064
3065
if (fid == 0xFFFFFF)
3066
{
3067
// Figure out root directory's location
3068
3069
// Read sector 16
3070
if ((rfspartition = Cs2ReadUnFilteredSector(166)) == NULL)
3071
return -2;
3072
3073
blocksectsize = rfspartition->block[rfspartition->numblocks - 1]->size;
3074
3075
// Retrieve directory record's lba
3076
Cs2CopyDirRecord(rfspartition->block[rfspartition->numblocks - 1]->data + 0x9C, &dirrec);
3077
3078
// Free Block
3079
rfspartition->size -= rfspartition->block[rfspartition->numblocks - 1]->size;
3080
Cs2FreeBlock(rfspartition->block[rfspartition->numblocks - 1]);
3081
rfspartition->blocknum[rfspartition->numblocks - 1] = 0xFF;
3082
3083
// Sort remaining blocks
3084
Cs2SortBlocks(rfspartition);
3085
rfspartition->numblocks -= 1;
3086
3087
curdirlba = Cs2Area->curdirsect = dirrec.lba;
3088
Cs2Area->curdirsize = (dirrec.size / blocksectsize) - 1;
3089
numsectorsleft = (u8)Cs2Area->curdirsize;
3090
Cs2Area->curdirfidoffset = 0;
3091
}
3092
else
3093
{
3094
// Read in new directory record of specified directory
3095
3096
// make sure we have a valid current directory
3097
if (Cs2Area->curdirsect == 0)
3098
return -1;
3099
3100
curdirlba = Cs2Area->curdirsect = Cs2Area->fileinfo[fid - Cs2Area->curdirfidoffset].lba - 150;
3101
Cs2Area->curdirsize = (Cs2Area->fileinfo[fid - Cs2Area->curdirfidoffset].size / blocksectsize) - 1;
3102
numsectorsleft = (u8)Cs2Area->curdirsize;
3103
Cs2Area->curdirfidoffset = 0;
3104
}
3105
}
3106
3107
// Make sure any old records are cleared
3108
memset(Cs2Area->fileinfo, 0, sizeof(dirrec_struct) * MAX_FILES);
3109
3110
// now read in first sector of directory record
3111
if ((rfspartition = Cs2ReadUnFilteredSector(curdirlba+150)) == NULL)
3112
return -2;
3113
3114
curdirlba++;
3115
workbuffer = rfspartition->block[rfspartition->numblocks - 1]->data;
3116
3117
// Fill in first two entries of fileinfo
3118
for (i = 0; i < 2; i++)
3119
{
3120
Cs2CopyDirRecord(workbuffer, Cs2Area->fileinfo + i);
3121
Cs2Area->fileinfo[i].lba += 150;
3122
workbuffer += Cs2Area->fileinfo[i].recordsize;
3123
3124
if (workbuffer[0] == 0)
3125
{
3126
Cs2Area->numfiles = i;
3127
break;
3128
}
3129
}
3130
3131
// If doing a ReadDirectory operation, parse sector entries until we've
3132
// found the fid that matches fid
3133
if (isoffset)
3134
{
3135
for (i = 2; i < fid; i++)
3136
{
3137
Cs2CopyDirRecord(workbuffer, Cs2Area->fileinfo + 2);
3138
workbuffer += Cs2Area->fileinfo[2].recordsize;
3139
3140
if (workbuffer[0] == 0)
3141
{
3142
if (numsectorsleft > 0)
3143
{
3144
// Free previous read sector
3145
rfspartition->size -= rfspartition->block[rfspartition->numblocks - 1]->size;
3146
Cs2FreeBlock(rfspartition->block[rfspartition->numblocks - 1]);
3147
rfspartition->blocknum[rfspartition->numblocks - 1] = 0xFF;
3148
3149
// Sort remaining blocks
3150
Cs2SortBlocks(rfspartition);
3151
rfspartition->numblocks -= 1;
3152
3153
// Read in next sector of directory record
3154
if ((rfspartition = Cs2ReadUnFilteredSector(curdirlba+150)) == NULL)
3155
return -2;
3156
3157
curdirlba++;
3158
3159
numsectorsleft--;
3160
workbuffer = rfspartition->block[rfspartition->numblocks - 1]->data;
3161
}
3162
else
3163
{
3164
break;
3165
}
3166
}
3167
}
3168
}
3169
3170
// Now generate the last 254 entries(the first two should've already been
3171
// generated earlier)
3172
for (i = 2; i < MAX_FILES; i++)
3173
{
3174
Cs2CopyDirRecord(workbuffer, Cs2Area->fileinfo + i);
3175
Cs2Area->fileinfo[i].lba += 150;
3176
workbuffer += Cs2Area->fileinfo[i].recordsize;
3177
3178
if (workbuffer[0] == 0)
3179
{
3180
if (numsectorsleft > 0)
3181
{
3182
// Free previous read sector
3183
rfspartition->size -= rfspartition->block[rfspartition->numblocks - 1]->size;
3184
Cs2FreeBlock(rfspartition->block[rfspartition->numblocks - 1]);
3185
rfspartition->blocknum[rfspartition->numblocks - 1] = 0xFF;
3186
3187
// Sort remaining blocks
3188
Cs2SortBlocks(rfspartition);
3189
rfspartition->numblocks -= 1;
3190
3191
// Read in next sector of directory record
3192
if ((rfspartition = Cs2ReadUnFilteredSector(curdirlba+150)) == NULL)
3193
return -2;
3194
3195
curdirlba++;
3196
numsectorsleft--;
3197
workbuffer = rfspartition->block[rfspartition->numblocks - 1]->data;
3198
}
3199
else
3200
{
3201
Cs2Area->numfiles = i;
3202
break;
3203
}
3204
}
3205
}
3206
3207
// Free the remaining sector
3208
rfspartition->size -= rfspartition->block[rfspartition->numblocks - 1]->size;
3209
Cs2FreeBlock(rfspartition->block[rfspartition->numblocks - 1]);
3210
rfspartition->blocknum[rfspartition->numblocks - 1] = 0xFF;
3211
3212
// Sort remaining blocks
3213
Cs2SortBlocks(rfspartition);
3214
rfspartition->numblocks -= 1;
3215
3216
//#if CDDEBUG
3217
// for (i = 0; i < MAX_FILES; i++)
3218
// {
3219
// CDLOG("fileinfo[%d].name = %s\n", i, Cs2Area->fileinfo[i].name);
3220
// }
3221
//#endif
3222
3223
return 0;
3224
}
3225
3226
//////////////////////////////////////////////////////////////////////////////
3227
3228
void Cs2SetupFileInfoTransfer(u32 fid) {
3229
Cs2Area->transfileinfo[0] = (u8)(Cs2Area->fileinfo[fid].lba >> 24);
3230
Cs2Area->transfileinfo[1] = (u8)(Cs2Area->fileinfo[fid].lba >> 16);
3231
Cs2Area->transfileinfo[2] = (u8)(Cs2Area->fileinfo[fid].lba >> 8);
3232
Cs2Area->transfileinfo[3] = (u8)Cs2Area->fileinfo[fid].lba;
3233
3234
Cs2Area->transfileinfo[4] = (u8)(Cs2Area->fileinfo[fid].size >> 24);
3235
Cs2Area->transfileinfo[5] = (u8)(Cs2Area->fileinfo[fid].size >> 16);
3236
Cs2Area->transfileinfo[6] = (u8)(Cs2Area->fileinfo[fid].size >> 8);
3237
Cs2Area->transfileinfo[7] = (u8)Cs2Area->fileinfo[fid].size;
3238
3239
Cs2Area->transfileinfo[8] = Cs2Area->fileinfo[fid].interleavegapsize;
3240
Cs2Area->transfileinfo[9] = Cs2Area->fileinfo[fid].fileunitsize;
3241
Cs2Area->transfileinfo[10] = (u8) fid;
3242
Cs2Area->transfileinfo[11] = Cs2Area->fileinfo[fid].flags;
3243
}
3244
3245
//////////////////////////////////////////////////////////////////////////////
3246
3247
partition_struct * Cs2ReadUnFilteredSector(u32 rufsFAD) {
3248
partition_struct * rufspartition;
3249
char syncheader[12] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
3250
0xFF, 0xFF, 0xFF, 0x00};
3251
3252
if ((rufspartition = Cs2GetPartition(Cs2Area->outconcddev)) != NULL && !Cs2Area->isbufferfull)
3253
{
3254
// Allocate Block
3255
rufspartition->block[rufspartition->numblocks] = Cs2AllocateBlock(&rufspartition->blocknum[rufspartition->numblocks]);
3256
3257
if (rufspartition->block[rufspartition->numblocks] == NULL)
3258
return NULL;
3259
3260
// read a sector using cd interface function
3261
if (!Cs2Area->cdi->ReadSectorFAD(rufsFAD, Cs2Area->workblock.data))
3262
return NULL;
3263
3264
// convert raw sector to type specified in getsectsize
3265
switch(Cs2Area->getsectsize)
3266
{
3267
case 2048: // user data only
3268
if (Cs2Area->workblock.data[0xF] == 0x02)
3269
{
3270
// is it form1/form2 data?
3271
if (!(Cs2Area->workblock.data[0x12] & 0x20))
3272
{
3273
// form 1
3274
memcpy(rufspartition->block[rufspartition->numblocks]->data,
3275
Cs2Area->workblock.data + 24, 2048);
3276
Cs2Area->workblock.size = Cs2Area->getsectsize;
3277
}
3278
else
3279
{
3280
// form 2
3281
memcpy(rufspartition->block[rufspartition->numblocks]->data,
3282
Cs2Area->workblock.data + 24, 2324);
3283
Cs2Area->workblock.size = 2324;
3284
}
3285
}
3286
else
3287
{
3288
memcpy(rufspartition->block[rufspartition->numblocks]->data,
3289
Cs2Area->workblock.data + 16, 2048);
3290
Cs2Area->workblock.size = Cs2Area->getsectsize;
3291
}
3292
break;
3293
case 2336: // skip sync+header data
3294
memcpy(rufspartition->block[rufspartition->numblocks]->data,
3295
Cs2Area->workblock.data + 16, 2336);
3296
Cs2Area->workblock.size = Cs2Area->getsectsize;
3297
break;
3298
case 2340: // skip sync data
3299
memcpy(rufspartition->block[rufspartition->numblocks]->data,
3300
Cs2Area->workblock.data + 12, 2340);
3301
Cs2Area->workblock.size = Cs2Area->getsectsize;
3302
break;
3303
case 2352: // no conversion needed
3304
Cs2Area->workblock.size = Cs2Area->getsectsize;
3305
break;
3306
default: break;
3307
}
3308
3309
// if mode 2 track, setup the subheader values
3310
if (memcmp(syncheader, Cs2Area->workblock.data, 12) == 0 &&
3311
Cs2Area->workblock.data[0xF] == 0x02)
3312
{
3313
rufspartition->block[rufspartition->numblocks]->fn = Cs2Area->workblock.data[0x10];
3314
rufspartition->block[rufspartition->numblocks]->cn = Cs2Area->workblock.data[0x11];
3315
rufspartition->block[rufspartition->numblocks]->sm = Cs2Area->workblock.data[0x12];
3316
rufspartition->block[rufspartition->numblocks]->ci = Cs2Area->workblock.data[0x13];
3317
}
3318
3319
Cs2Area->workblock.FAD = rufsFAD;
3320
3321
// Modify Partition values
3322
if (rufspartition->size == -1) rufspartition->size = 0;
3323
rufspartition->size += rufspartition->block[rufspartition->numblocks]->size;
3324
rufspartition->numblocks++;
3325
3326
return rufspartition;
3327
}
3328
3329
return NULL;
3330
}
3331
3332
//////////////////////////////////////////////////////////////////////////////
3333
3334
int Cs2ReadFilteredSector(u32 rfsFAD, partition_struct **partition) {
3335
char syncheader[12] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
3336
0xFF, 0xFF, 0xFF, 0x00};
3337
int isaudio = 0;
3338
3339
if (Cs2Area->outconcddev != NULL && !Cs2Area->isbufferfull)
3340
{
3341
// read a sector using cd interface function to workblock.data
3342
if (!Cs2Area->cdi->ReadSectorFAD(rfsFAD, Cs2Area->workblock.data))
3343
{
3344
*partition = NULL;
3345
return -2;
3346
}
3347
3348
Cs2Area->workblock.size = Cs2Area->getsectsize;
3349
Cs2Area->workblock.FAD = rfsFAD;
3350
3351
if (memcmp(syncheader, Cs2Area->workblock.data, 12) != 0) isaudio = 1;
3352
3353
// force 1x speed if reading from an audio track
3354
Cs2Area->isaudio = isaudio;
3355
Cs2SetTiming(1);
3356
3357
// if mode 2 track, setup the subheader values
3358
if (isaudio)
3359
{
3360
ScspReceiveCDDA(Cs2Area->workblock.data);
3361
*partition = NULL;
3362
return 0;
3363
}
3364
else if (Cs2Area->workblock.data[0xF] == 0x02)
3365
{
3366
// if it's form 2 data the sector size should be 2324
3367
if (Cs2Area->workblock.data[0x12] & 0x20) Cs2Area->workblock.size = 2324;
3368
3369
Cs2Area->workblock.fn = Cs2Area->workblock.data[0x10];
3370
Cs2Area->workblock.cn = Cs2Area->workblock.data[0x11];
3371
Cs2Area->workblock.sm = Cs2Area->workblock.data[0x12];
3372
Cs2Area->workblock.ci = Cs2Area->workblock.data[0x13];
3373
}
3374
3375
3376
// pass workblock to filter function(after it identifies partition,
3377
// it should allocate the partition block, setup/change the partition
3378
// values, and copy workblock to the allocated block)
3379
*partition = Cs2FilterData(Cs2Area->outconcddev, isaudio);
3380
return 0;
3381
}
3382
3383
*partition = NULL;
3384
return -1;
3385
}
3386
3387
//////////////////////////////////////////////////////////////////////////////
3388
3389
u8 Cs2GetIP(int autoregion) {
3390
partition_struct * gripartition;
3391
u8 ret = 0;
3392
3393
Cs2Area->outconcddev = Cs2Area->filter + 0;
3394
Cs2Area->outconcddevnum = 0;
3395
3396
// read in lba 0/FAD 150
3397
if ((gripartition = Cs2ReadUnFilteredSector(150)) != NULL)
3398
{
3399
char *buf=(char*)gripartition->block[gripartition->numblocks - 1]->data;
3400
3401
// Make sure we're dealing with a saturn game
3402
if (memcmp(buf, "SEGA SEGASATURN", 15) == 0)
3403
{
3404
memcpy(cdip->system, buf, 16);
3405
cdip->system[16]='\0';
3406
memcpy(cdip->company, buf+0x10, 16);
3407
cdip->company[16]='\0';
3408
sscanf(buf+0x20, "%s", cdip->itemnum);
3409
memcpy(cdip->version, buf+0x2A, 6);
3410
cdip->version[6]='\0';
3411
sprintf(cdip->date, "%c%c/%c%c/%c%c%c%c", buf[0x34], buf[0x35], buf[0x36], buf[0x37], buf[0x30], buf[0x31], buf[0x32], buf[0x33]);
3412
sscanf(buf+0x38, "%s", cdip->cdinfo);
3413
sscanf(buf+0x40, "%s", cdip->region);
3414
sscanf(buf+0x50, "%s", cdip->peripheral);
3415
memcpy(cdip->gamename, buf+0x60, 112);
3416
cdip->gamename[112]='\0';
3417
#ifdef WORDS_BIGENDIAN
3418
memcpy(&cdip->ipsize, buf+0xE0, sizeof(u32));
3419
memcpy(&cdip->msh2stack, buf+0xE8, sizeof(u32));
3420
memcpy(&cdip->ssh2stack, buf+0xEC, sizeof(u32));
3421
memcpy(&cdip->firstprogaddr, buf+0xF0, sizeof(u32));
3422
memcpy(&cdip->firstprogsize, buf+0xF4, sizeof(u32));
3423
#else
3424
cdip->ipsize = (buf[0xE0] << 24) | (buf[0xE1] << 16) |
3425
(buf[0xE2] << 8) | buf[0xE3];
3426
cdip->msh2stack = (buf[0xE8] << 24) | (buf[0xE9] << 16) |
3427
(buf[0xEA] << 8) | buf[0xEB];
3428
cdip->ssh2stack = (buf[0xEC] << 24) | (buf[0xED] << 16) |
3429
(buf[0xEE] << 8) | buf[0xEF];
3430
cdip->firstprogaddr = (buf[0xF0] << 24) | (buf[0xF1] << 16) |
3431
(buf[0xF2] << 8) | buf[0xF3];
3432
cdip->firstprogsize = (buf[0xF4] << 24) | (buf[0xF5] << 16) |
3433
(buf[0xF6] << 8) | buf[0xF7];
3434
#endif
3435
3436
if (autoregion)
3437
{
3438
// Read first available region, that'll be what we'll use
3439
switch (cdip->region[0])
3440
{
3441
case 'J':
3442
ret = 1;
3443
break;
3444
case 'T':
3445
ret = 2;
3446
break;
3447
case 'U':
3448
ret = 4;
3449
break;
3450
case 'B':
3451
ret = 5;
3452
break;
3453
case 'K':
3454
ret = 6;
3455
break;
3456
case 'A':
3457
ret = 0xA;
3458
break;
3459
case 'E':
3460
ret = 0xC;
3461
break;
3462
case 'L':
3463
ret = 0xD;
3464
break;
3465
default: break;
3466
}
3467
}
3468
}
3469
3470
// Free Block
3471
gripartition->size -= gripartition->block[gripartition->numblocks - 1]->size;
3472
Cs2FreeBlock(gripartition->block[gripartition->numblocks - 1]);
3473
gripartition->blocknum[gripartition->numblocks - 1] = 0xFF;
3474
3475
// Sort remaining blocks
3476
Cs2SortBlocks(gripartition);
3477
gripartition->numblocks -= 1;
3478
}
3479
3480
return ret;
3481
}
3482
3483
//////////////////////////////////////////////////////////////////////////////
3484
3485
u8 Cs2GetRegionID(void)
3486
{
3487
return Cs2GetIP(1);
3488
}
3489
3490
//////////////////////////////////////////////////////////////////////////////
3491
3492
int Cs2SaveState(FILE * fp) {
3493
int offset, i;
3494
IOCheck_struct check;
3495
3496
// This is mostly kludge, but it will have to do until I have time to rewrite it all
3497
3498
offset = StateWriteHeader(fp, "CS2 ", 2);
3499
3500
// Write cart type
3501
ywrite(&check, (void *) &Cs2Area->carttype, 4, 1, fp);
3502
3503
// Write cd block registers
3504
ywrite(&check, (void *) &Cs2Area->reg, sizeof(blockregs_struct), 1, fp);
3505
3506
// Write current Status variables(needs a rewrite)
3507
ywrite(&check, (void *) &Cs2Area->FAD, 4, 1, fp);
3508
ywrite(&check, (void *) &Cs2Area->status, 1, 1, fp);
3509
ywrite(&check, (void *) &Cs2Area->options, 1, 1, fp);
3510
ywrite(&check, (void *) &Cs2Area->repcnt, 1, 1, fp);
3511
ywrite(&check, (void *) &Cs2Area->ctrladdr, 1, 1, fp);
3512
ywrite(&check, (void *) &Cs2Area->track, 1, 1, fp);
3513
ywrite(&check, (void *) &Cs2Area->index, 1, 1, fp);
3514
3515
// Write other cd block internal variables
3516
ywrite(&check, (void *) &Cs2Area->satauth, 2, 1, fp);
3517
ywrite(&check, (void *) &Cs2Area->mpgauth, 2, 1, fp);
3518
ywrite(&check, (void *) &Cs2Area->transfercount, 4, 1, fp);
3519
ywrite(&check, (void *) &Cs2Area->cdwnum, 4, 1, fp);
3520
ywrite(&check, (void *) Cs2Area->TOC, 4, 102, fp);
3521
ywrite(&check, (void *) &Cs2Area->playFAD, 4, 1, fp);
3522
ywrite(&check, (void *) &Cs2Area->playendFAD, 4, 1, fp);
3523
ywrite(&check, (void *) &Cs2Area->getsectsize, 4, 1, fp);
3524
ywrite(&check, (void *) &Cs2Area->putsectsize, 4, 1, fp);
3525
ywrite(&check, (void *) &Cs2Area->calcsize, 4, 1, fp);
3526
ywrite(&check, (void *) &Cs2Area->infotranstype, 4, 1, fp);
3527
ywrite(&check, (void *) &Cs2Area->datatranstype, 4, 1, fp);
3528
ywrite(&check, (void *) &Cs2Area->isonesectorstored, 1, 1, fp);
3529
ywrite(&check, (void *) &Cs2Area->isdiskchanged, 1, 1, fp);
3530
ywrite(&check, (void *) &Cs2Area->isbufferfull, 1, 1, fp);
3531
ywrite(&check, (void *) &Cs2Area->speed1x, 1, 1, fp);
3532
ywrite(&check, (void *) &Cs2Area->isaudio, 1, 1, fp);
3533
ywrite(&check, (void *) &Cs2Area->transfileinfo, 1, 12, fp);
3534
ywrite(&check, (void *) &Cs2Area->lastbuffer, 1, 1, fp);
3535
ywrite(&check, (void *) &Cs2Area->_command, 1, 1, fp);
3536
{
3537
u32 temp = (Cs2Area->_periodictiming + 3) / 3;
3538
ywrite(&check, (void *) &temp, 4, 1, fp);
3539
}
3540
ywrite(&check, (void *) &Cs2Area->_commandtiming, 4, 1, fp);
3541
ywrite(&check, (void *) &Cs2Area->outconcddevnum, 1, 1, fp);
3542
ywrite(&check, (void *) &Cs2Area->outconmpegfbnum, 1, 1, fp);
3543
ywrite(&check, (void *) &Cs2Area->outconmpegbufnum, 1, 1, fp);
3544
ywrite(&check, (void *) &Cs2Area->outconmpegromnum, 1, 1, fp);
3545
ywrite(&check, (void *) &Cs2Area->outconhostnum, 1, 1, fp);
3546
ywrite(&check, (void *) &Cs2Area->datatranspartitionnum, 1, 1, fp);
3547
ywrite(&check, (void *) &Cs2Area->datatransoffset, 4, 1, fp);
3548
ywrite(&check, (void *) &Cs2Area->datanumsecttrans, 4, 1, fp);
3549
ywrite(&check, (void *) &Cs2Area->datatranssectpos, 2, 1, fp);
3550
ywrite(&check, (void *) &Cs2Area->datasectstotrans, 2, 1, fp);
3551
ywrite(&check, (void *) &Cs2Area->blockfreespace, 4, 1, fp);
3552
ywrite(&check, (void *) &Cs2Area->curdirsect, 4, 1, fp);
3553
3554
// Write CD buffer
3555
ywrite(&check, (void *)Cs2Area->block, sizeof(block_struct), MAX_BLOCKS, fp);
3556
3557
// Write partition data
3558
for (i = 0; i < MAX_SELECTORS; i++)
3559
{
3560
ywrite(&check, (void *)&Cs2Area->partition[i].size, 4, 1, fp);
3561
ywrite(&check, (void *)Cs2Area->partition[i].blocknum, 1, MAX_BLOCKS, fp);
3562
ywrite(&check, (void *)&Cs2Area->partition[i].numblocks, 1, 1, fp);
3563
}
3564
3565
// Write filter data
3566
ywrite(&check, (void *)Cs2Area->filter, sizeof(filter_struct), MAX_SELECTORS, fp);
3567
3568
// Write File Info Table
3569
ywrite(&check, (void *)Cs2Area->fileinfo, sizeof(dirrec_struct), MAX_FILES, fp);
3570
3571
// Write MPEG card registers here
3572
3573
// Write current MPEG card status variables
3574
ywrite(&check, (void *)&Cs2Area->actionstatus, 1, 1, fp);
3575
ywrite(&check, (void *)&Cs2Area->pictureinfo, 1, 1, fp);
3576
ywrite(&check, (void *)&Cs2Area->mpegaudiostatus, 1, 1, fp);
3577
ywrite(&check, (void *)&Cs2Area->mpegvideostatus, 2, 1, fp);
3578
ywrite(&check, (void *)&Cs2Area->vcounter, 2, 1, fp);
3579
3580
// Write other MPEG card internal variables
3581
ywrite(&check, (void *)&Cs2Area->mpegintmask, 4, 1, fp);
3582
ywrite(&check, (void *)Cs2Area->mpegcon, sizeof(mpegcon_struct), 2, fp);
3583
ywrite(&check, (void *)Cs2Area->mpegstm, sizeof(mpegstm_struct), 2, fp);
3584
3585
return StateFinishHeader(fp, offset);
3586
}
3587
3588
//////////////////////////////////////////////////////////////////////////////
3589
3590
int Cs2LoadState(FILE * fp, int version, int size) {
3591
int i, i2;
3592
IOCheck_struct check;
3593
3594
// This is mostly kludge, but it will have to do until I have time to rewrite it all
3595
3596
// Read cart type
3597
yread(&check, (void *)&Cs2Area->carttype, 4, 1, fp);
3598
3599
// Read cd block registers
3600
yread(&check, (void *)&Cs2Area->reg, sizeof(blockregs_struct), 1, fp);
3601
3602
// Read current Status variables(needs a reRead)
3603
yread(&check, (void *)&Cs2Area->FAD, 4, 1, fp);
3604
yread(&check, (void *)&Cs2Area->status, 1, 1, fp);
3605
yread(&check, (void *)&Cs2Area->options, 1, 1, fp);
3606
yread(&check, (void *)&Cs2Area->repcnt, 1, 1, fp);
3607
yread(&check, (void *)&Cs2Area->ctrladdr, 1, 1, fp);
3608
yread(&check, (void *)&Cs2Area->track, 1, 1, fp);
3609
yread(&check, (void *)&Cs2Area->index, 1, 1, fp);
3610
3611
// Read other cd block internal variables
3612
yread(&check, (void *)&Cs2Area->satauth, 2, 1, fp);
3613
yread(&check, (void *)&Cs2Area->mpgauth, 2, 1, fp);
3614
yread(&check, (void *)&Cs2Area->transfercount, 4, 1, fp);
3615
yread(&check, (void *)&Cs2Area->cdwnum, 4, 1, fp);
3616
yread(&check, (void *)Cs2Area->TOC, 4, 102, fp);
3617
yread(&check, (void *)&Cs2Area->playFAD, 4, 1, fp);
3618
yread(&check, (void *)&Cs2Area->playendFAD, 4, 1, fp);
3619
yread(&check, (void *)&Cs2Area->getsectsize, 4, 1, fp);
3620
yread(&check, (void *)&Cs2Area->putsectsize, 4, 1, fp);
3621
yread(&check, (void *)&Cs2Area->calcsize, 4, 1, fp);
3622
yread(&check, (void *)&Cs2Area->infotranstype, 4, 1, fp);
3623
yread(&check, (void *)&Cs2Area->datatranstype, 4, 1, fp);
3624
yread(&check, (void *)&Cs2Area->isonesectorstored, 1, 1, fp);
3625
yread(&check, (void *)&Cs2Area->isdiskchanged, 1, 1, fp);
3626
yread(&check, (void *)&Cs2Area->isbufferfull, 1, 1, fp);
3627
yread(&check, (void *)&Cs2Area->speed1x, 1, 1, fp);
3628
if (version > 1)
3629
yread(&check, (void *)&Cs2Area->isaudio, 1, 1, fp);
3630
yread(&check, (void *)&Cs2Area->transfileinfo, 1, 12, fp);
3631
yread(&check, (void *)&Cs2Area->lastbuffer, 1, 1, fp);
3632
yread(&check, (void *)&Cs2Area->_command, 1, 1, fp);
3633
{
3634
u32 temp;
3635
yread(&check, (void *)&temp, 4, 1, fp);
3636
// Derive the actual, accurate value (always a multiple of 10)
3637
Cs2Area->_periodictiming = ((temp * 3) / 10) * 10;
3638
}
3639
yread(&check, (void *)&Cs2Area->_commandtiming, 4, 1, fp);
3640
yread(&check, (void *)&Cs2Area->outconcddevnum, 1, 1, fp);
3641
if (Cs2Area->outconcddevnum == 0xFF)
3642
Cs2Area->outconcddev = NULL;
3643
else
3644
Cs2Area->outconcddev = Cs2Area->filter + Cs2Area->outconcddevnum;
3645
3646
yread(&check, (void *)&Cs2Area->outconmpegfbnum, 1, 1, fp);
3647
if (Cs2Area->outconmpegfbnum == 0xFF)
3648
Cs2Area->outconmpegfb = NULL;
3649
else
3650
Cs2Area->outconmpegfb = Cs2Area->filter + Cs2Area->outconmpegfbnum;
3651
3652
yread(&check, (void *)&Cs2Area->outconmpegbufnum, 1, 1, fp);
3653
if (Cs2Area->outconmpegbufnum == 0xFF)
3654
Cs2Area->outconmpegbuf = NULL;
3655
else
3656
Cs2Area->outconmpegbuf = Cs2Area->filter + Cs2Area->outconmpegbufnum;
3657
3658
yread(&check, (void *)&Cs2Area->outconmpegromnum, 1, 1, fp);
3659
if (Cs2Area->outconmpegromnum == 0xFF)
3660
Cs2Area->outconmpegrom = NULL;
3661
else
3662
Cs2Area->outconmpegrom = Cs2Area->filter + Cs2Area->outconmpegromnum;
3663
3664
yread(&check, (void *)&Cs2Area->outconhostnum, 1, 1, fp);
3665
if (Cs2Area->outconhostnum == 0xFF)
3666
Cs2Area->outconhost = NULL;
3667
else
3668
Cs2Area->outconhost = Cs2Area->filter + Cs2Area->outconhostnum;
3669
3670
yread(&check, (void *)&Cs2Area->datatranspartitionnum, 1, 1, fp);
3671
yread(&check, (void *)&Cs2Area->datatransoffset, 4, 1, fp);
3672
yread(&check, (void *)&Cs2Area->datanumsecttrans, 4, 1, fp);
3673
yread(&check, (void *)&Cs2Area->datatranssectpos, 2, 1, fp);
3674
yread(&check, (void *)&Cs2Area->datasectstotrans, 2, 1, fp);
3675
yread(&check, (void *)&Cs2Area->blockfreespace, 4, 1, fp);
3676
yread(&check, (void *)&Cs2Area->curdirsect, 4, 1, fp);
3677
3678
// Read CD buffer
3679
yread(&check, (void *)Cs2Area->block, sizeof(block_struct), MAX_BLOCKS, fp);
3680
3681
// Read partition data
3682
for (i = 0; i < MAX_SELECTORS; i++)
3683
{
3684
yread(&check, (void *)&Cs2Area->partition[i].size, 4, 1, fp);
3685
yread(&check, (void *)Cs2Area->partition[i].blocknum, 1, MAX_BLOCKS, fp);
3686
yread(&check, (void *)&Cs2Area->partition[i].numblocks, 1, 1, fp);
3687
3688
for (i2 = 0; i2 < MAX_BLOCKS; i2++)
3689
{
3690
if (Cs2Area->partition[i].blocknum[i2] == 0xFF)
3691
Cs2Area->partition[i].block[i2] = NULL;
3692
else
3693
Cs2Area->partition[i].block[i2] = Cs2Area->block + Cs2Area->partition[i].blocknum[i2];
3694
}
3695
}
3696
3697
// Read filter data
3698
yread(&check, (void *)Cs2Area->filter, sizeof(filter_struct), MAX_SELECTORS, fp);
3699
3700
// Read File Info Table
3701
yread(&check, (void *)Cs2Area->fileinfo, sizeof(dirrec_struct), MAX_FILES, fp);
3702
3703
// Read MPEG card registers here
3704
3705
// Read current MPEG card status variables
3706
yread(&check, (void *)&Cs2Area->actionstatus, 1, 1, fp);
3707
yread(&check, (void *)&Cs2Area->pictureinfo, 1, 1, fp);
3708
yread(&check, (void *)&Cs2Area->mpegaudiostatus, 1, 1, fp);
3709
yread(&check, (void *)&Cs2Area->mpegvideostatus, 2, 1, fp);
3710
yread(&check, (void *)&Cs2Area->vcounter, 2, 1, fp);
3711
3712
// Read other MPEG card internal variables
3713
yread(&check, (void *)&Cs2Area->mpegintmask, 4, 1, fp);
3714
yread(&check, (void *)Cs2Area->mpegcon, sizeof(mpegcon_struct), 2, fp);
3715
yread(&check, (void *)Cs2Area->mpegstm, sizeof(mpegstm_struct), 2, fp);
3716
3717
return size;
3718
}
3719
3720
//////////////////////////////////////////////////////////////////////////////
3721
3722