Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/bios.c
2 views
1
/* Copyright 2006-2007 Theo Berkau
2
3
This file is part of Yabause.
4
5
Yabause is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
9
10
Yabause is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with Yabause; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
*/
19
20
#include "memory.h"
21
#include "cs0.h"
22
#include "debug.h"
23
#include "sh2core.h"
24
#include "bios.h"
25
#include "smpc.h"
26
27
static u8 sh2masklist[0x20] = {
28
0xF0, 0xE0, 0xD0, 0xC0, 0xB0, 0xA0, 0x90, 0x80,
29
0x80, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
30
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
31
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70
32
};
33
34
static u32 scumasklist[0x20] = {
35
0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8,
36
0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80,
37
0xFFFFFF80, 0xFFFFFE00, 0xFFFFFE00, 0xFFFFFE00,
38
0xFFFFFE00, 0xFFFFFE00, 0xFFFFFE00, 0xFFFFFE00,
39
0xFFFFFE00, 0xFFFFFE00, 0xFFFFFE00, 0xFFFFFE00,
40
0xFFFFFE00, 0xFFFFFE00, 0xFFFFFE00, 0xFFFFFE00,
41
0xFFFFFE00, 0xFFFFFE00, 0xFFFFFE00, 0xFFFFFE00,
42
0xFFFFFE00, 0xFFFFFE00, 0xFFFFFE00, 0xFFFFFE00
43
};
44
45
u32 interruptlist[2][0x80];
46
47
//////////////////////////////////////////////////////////////////////////////
48
49
void BiosInit(void)
50
{
51
int i;
52
53
// Setup vectors
54
MappedMemoryWriteLong(0x06000600, 0x002B0009); // rte, nop
55
MappedMemoryWriteLong(0x06000604, 0xE0F0600C); // mov #0xF0, r0; extu.b r0, r0
56
MappedMemoryWriteLong(0x06000608, 0x400E8BFE); // ldc r0, sr; bf
57
MappedMemoryWriteLong(0x0600060C, 0x00090009); // nop
58
MappedMemoryWriteLong(0x06000610, 0x000B0009); // rts, nop
59
60
for (i = 0; i < 0x200; i+=4)
61
{
62
MappedMemoryWriteLong(0x06000000+i, 0x06000600);
63
MappedMemoryWriteLong(0x06000400+i, 0x06000600);
64
interruptlist[0][i >> 2] = 0x06000600;
65
interruptlist[1][i >> 2] = 0x06000600;
66
}
67
68
MappedMemoryWriteLong(0x06000010, 0x06000604);
69
MappedMemoryWriteLong(0x06000018, 0x06000604);
70
MappedMemoryWriteLong(0x06000024, 0x06000604);
71
MappedMemoryWriteLong(0x06000028, 0x06000604);
72
interruptlist[0][4] = 0x06000604;
73
interruptlist[0][6] = 0x06000604;
74
interruptlist[0][9] = 0x06000604;
75
interruptlist[0][10] = 0x06000604;
76
77
MappedMemoryWriteLong(0x06000410, 0x06000604);
78
MappedMemoryWriteLong(0x06000418, 0x06000604);
79
MappedMemoryWriteLong(0x06000424, 0x06000604);
80
MappedMemoryWriteLong(0x06000428, 0x06000604);
81
interruptlist[1][4] = 0x06000604;
82
interruptlist[1][6] = 0x06000604;
83
interruptlist[1][9] = 0x06000604;
84
interruptlist[1][10] = 0x06000604;
85
86
// Scu Interrupts
87
for (i = 0; i < 0x38; i+=4)
88
{
89
MappedMemoryWriteLong(0x06000100+i, 0x00000400+i);
90
interruptlist[0][0x40+(i >> 2)] = 0x00000400+i;
91
}
92
93
for (i = 0; i < 0x40; i+=4)
94
{
95
MappedMemoryWriteLong(0x06000140+i, 0x00000440+i);
96
interruptlist[0][0x50+(i >> 2)] = 0x00000440+i;
97
}
98
99
for (i = 0; i < 0x100; i+=4)
100
MappedMemoryWriteLong(0x06000A00+i, 0x06000610);
101
102
// Setup Bios Functions
103
MappedMemoryWriteLong(0x06000210, 0x00000210);
104
MappedMemoryWriteLong(0x0600026C, 0x0000026C);
105
MappedMemoryWriteLong(0x06000274, 0x00000274);
106
MappedMemoryWriteLong(0x06000280, 0x00000280);
107
MappedMemoryWriteLong(0x0600029C, 0x0000029C);
108
MappedMemoryWriteLong(0x060002DC, 0x000002DC);
109
MappedMemoryWriteLong(0x06000300, 0x00000300);
110
MappedMemoryWriteLong(0x06000304, 0x00000304);
111
MappedMemoryWriteLong(0x06000310, 0x00000310);
112
MappedMemoryWriteLong(0x06000314, 0x00000314);
113
MappedMemoryWriteLong(0x06000320, 0x00000320);
114
MappedMemoryWriteLong(0x06000324, 0x00000000);
115
MappedMemoryWriteLong(0x06000330, 0x00000330);
116
MappedMemoryWriteLong(0x06000334, 0x00000334);
117
MappedMemoryWriteLong(0x06000340, 0x00000340);
118
MappedMemoryWriteLong(0x06000344, 0x00000344);
119
MappedMemoryWriteLong(0x06000348, 0xFFFFFFFF);
120
MappedMemoryWriteLong(0x06000354, 0x00000000);
121
MappedMemoryWriteLong(0x06000358, 0x00000358);
122
}
123
124
//////////////////////////////////////////////////////////////////////////////
125
126
static void FASTCALL BiosSetScuInterrupt(SH2_struct * sh)
127
{
128
SH2GetRegisters(sh, &sh->regs);
129
130
// LOG("BiosSetScuInterrupt. vector = %02X, func = %08X\n", sh->regs.R[4], sh->regs.R[5]);
131
132
if (sh->regs.R[5] == 0)
133
{
134
MappedMemoryWriteLong(0x06000900+(sh->regs.R[4] << 2), 0x06000610);
135
sh->cycles += 8;
136
}
137
else
138
{
139
MappedMemoryWriteLong(0x06000900+(sh->regs.R[4] << 2), sh->regs.R[5]);
140
sh->cycles += 9;
141
}
142
143
sh->regs.PC = sh->regs.PR;
144
SH2SetRegisters(sh, &sh->regs);
145
}
146
147
//////////////////////////////////////////////////////////////////////////////
148
149
static void FASTCALL BiosGetScuInterrupt(SH2_struct * sh)
150
{
151
SH2GetRegisters(sh, &sh->regs);
152
153
// check me
154
// LOG("BiosGetScuInterrupt\n");
155
156
sh->regs.R[0] = MappedMemoryReadLong(0x06000900+(sh->regs.R[4] << 2));
157
sh->cycles += 5;
158
159
sh->regs.PC = sh->regs.PR;
160
SH2SetRegisters(sh, &sh->regs);
161
}
162
163
//////////////////////////////////////////////////////////////////////////////
164
165
static void FASTCALL BiosSetSh2Interrupt(SH2_struct * sh)
166
{
167
SH2GetRegisters(sh, &sh->regs);
168
169
// LOG("BiosSetSh2Interrupt\n");
170
171
if (sh->regs.R[5] == 0)
172
{
173
MappedMemoryWriteLong(sh->regs.VBR+(sh->regs.R[4] << 2), interruptlist[sh->isslave][sh->regs.R[4]]);
174
sh->cycles += 8;
175
}
176
else
177
{
178
MappedMemoryWriteLong(sh->regs.VBR+(sh->regs.R[4] << 2), sh->regs.R[5]);
179
sh->cycles += 9;
180
}
181
182
sh->regs.PC = sh->regs.PR;
183
SH2SetRegisters(sh, &sh->regs);
184
}
185
186
//////////////////////////////////////////////////////////////////////////////
187
188
static void FASTCALL BiosGetSh2Interrupt(SH2_struct * sh)
189
{
190
SH2GetRegisters(sh, &sh->regs);
191
192
// check me
193
// LOG("BiosGetSh2Interrupt\n");
194
195
sh->regs.R[0] = MappedMemoryReadLong(sh->regs.VBR+(sh->regs.R[4] << 2));
196
sh->cycles += 5;
197
198
sh->regs.PC = sh->regs.PR;
199
SH2SetRegisters(sh, &sh->regs);
200
}
201
202
//////////////////////////////////////////////////////////////////////////////
203
204
static void FASTCALL BiosSetScuInterruptMask(SH2_struct * sh)
205
{
206
SH2GetRegisters(sh, &sh->regs);
207
208
// check me
209
LOG("BiosSetScuInterruptMask\n");
210
211
MappedMemoryWriteLong(0x06000348, sh->regs.R[4]);
212
MappedMemoryWriteLong(0x25FE00A0, sh->regs.R[4]); // Interrupt Mask Register
213
214
if (!(sh->regs.R[4] & 0x8000)) // double check this
215
MappedMemoryWriteLong(0x25FE00A8, 1); // A-bus Interrupt Acknowledge
216
217
sh->cycles += 17;
218
219
sh->regs.PC = sh->regs.PR;
220
SH2SetRegisters(sh, &sh->regs);
221
}
222
223
//////////////////////////////////////////////////////////////////////////////
224
225
static void FASTCALL BiosChangeScuInterruptMask(SH2_struct * sh)
226
{
227
u32 newmask;
228
229
SH2GetRegisters(sh, &sh->regs);
230
231
// LOG("BiosChangeScuInterruptMask\n");
232
233
// Read Stored Scu Interrupt Mask, AND it by R4, OR it by R5, then put it back
234
newmask = (MappedMemoryReadLong(0x06000348) & sh->regs.R[4]) | sh->regs.R[5];
235
MappedMemoryWriteLong(0x06000348, newmask);
236
MappedMemoryWriteLong(0x25FE00A0, newmask); // Interrupt Mask Register
237
MappedMemoryWriteLong(0x25FE00A4, (u32)(s16)sh->regs.R[4]); // Interrupt Status Register
238
239
if (!(sh->regs.R[4] & 0x8000)) // double check this
240
MappedMemoryWriteLong(0x25FE00A8, 1); // A-bus Interrupt Acknowledge
241
242
sh->cycles += 20;
243
244
sh->regs.PC = sh->regs.PR;
245
SH2SetRegisters(sh, &sh->regs);
246
}
247
248
//////////////////////////////////////////////////////////////////////////////
249
250
static void FASTCALL BiosCDINIT2(SH2_struct * sh)
251
{
252
SH2GetRegisters(sh, &sh->regs);
253
sh->regs.PC = sh->regs.PR;
254
SH2SetRegisters(sh, &sh->regs);
255
}
256
257
//////////////////////////////////////////////////////////////////////////////
258
259
static void FASTCALL BiosCDINIT1(SH2_struct * sh)
260
{
261
SH2GetRegisters(sh, &sh->regs);
262
sh->regs.PC = sh->regs.PR;
263
SH2SetRegisters(sh, &sh->regs);
264
}
265
266
//////////////////////////////////////////////////////////////////////////////
267
268
static void FASTCALL BiosGetSemaphore(SH2_struct * sh)
269
{
270
u8 temp;
271
272
SH2GetRegisters(sh, &sh->regs);
273
274
// check me
275
LOG("BiosGetSemaphore\n");
276
277
if ((temp = MappedMemoryReadByte(0x06000B00 + sh->regs.R[4])) == 0)
278
sh->regs.R[0] = 1;
279
else
280
sh->regs.R[0] = 0;
281
282
temp |= 0x80;
283
MappedMemoryWriteByte(0x06000B00 + sh->regs.R[4], temp);
284
285
sh->cycles += 11;
286
sh->regs.PC = sh->regs.PR;
287
SH2SetRegisters(sh, &sh->regs);
288
}
289
290
//////////////////////////////////////////////////////////////////////////////
291
292
static void FASTCALL BiosClearSemaphore(SH2_struct * sh)
293
{
294
SH2GetRegisters(sh, &sh->regs);
295
296
// check me
297
LOG("BiosClearSemaphore\n");
298
299
MappedMemoryWriteByte(0x06000B00 + sh->regs.R[4], 0);
300
301
sh->cycles += 5;
302
sh->regs.PC = sh->regs.PR;
303
SH2SetRegisters(sh, &sh->regs);
304
}
305
306
//////////////////////////////////////////////////////////////////////////////
307
308
static void FASTCALL BiosChangeSystemClock(SH2_struct * sh)
309
{
310
SH2GetRegisters(sh, &sh->regs);
311
312
LOG("BiosChangeSystemClock\n");
313
314
MappedMemoryWriteLong(0x06000324, sh->regs.R[4]);
315
316
if (sh->regs.R[4] == 0)
317
SmpcCKCHG320();
318
else
319
SmpcCKCHG352();
320
321
sh->regs.PC = sh->regs.PR;
322
SH2SetRegisters(sh, &sh->regs);
323
}
324
325
//////////////////////////////////////////////////////////////////////////////
326
327
static void FASTCALL BiosChangeScuInterruptPriority(SH2_struct * sh)
328
{
329
int i;
330
331
SH2GetRegisters(sh, &sh->regs);
332
333
// check me
334
// LOG("BiosChangeScuInterruptPriority\n");
335
336
for (i = 0; i < 0x20; i++)
337
{
338
scumasklist[i] = MappedMemoryReadLong(sh->regs.R[4]+(i << 2));
339
sh2masklist[i] = (scumasklist[i] >> 16);
340
if (scumasklist[i] & 0x8000)
341
scumasklist[i] |= 0xFFFF0000;
342
else
343
scumasklist[i] &= 0x0000FFFF;
344
}
345
346
sh->cycles += 186;
347
sh->regs.PC = sh->regs.PR;
348
SH2SetRegisters(sh, &sh->regs);
349
}
350
351
//////////////////////////////////////////////////////////////////////////////
352
353
static void FASTCALL BiosExecuteCDPlayer(SH2_struct * sh)
354
{
355
SH2GetRegisters(sh, &sh->regs);
356
357
LOG("BiosExecuteCDPlayer\n");
358
359
sh->regs.PC = sh->regs.PR;
360
SH2SetRegisters(sh, &sh->regs);
361
}
362
363
//////////////////////////////////////////////////////////////////////////////
364
365
static void FASTCALL BiosPowerOnMemoryClear(SH2_struct * sh)
366
{
367
SH2GetRegisters(sh, &sh->regs);
368
369
LOG("BiosPowerOnMemoryClear\n");
370
371
sh->regs.PC = sh->regs.PR;
372
SH2SetRegisters(sh, &sh->regs);
373
}
374
375
//////////////////////////////////////////////////////////////////////////////
376
377
static void FASTCALL BiosCheckMPEGCard(SH2_struct * sh)
378
{
379
SH2GetRegisters(sh, &sh->regs);
380
381
LOG("BiosCheckMPEGCard\n");
382
383
sh->regs.PC = sh->regs.PR;
384
SH2SetRegisters(sh, &sh->regs);
385
}
386
387
//////////////////////////////////////////////////////////////////////////////
388
389
static u32 GetDeviceStats(u32 device, u32 *size, u32 *addr, u32 *blocksize)
390
{
391
switch(device)
392
{
393
case 0:
394
*addr = 0x00180000;
395
*size = 0x8000;
396
*blocksize = 0x40;
397
return 0;
398
case 1:
399
if ((CartridgeArea->cartid & 0xF0) == 0x20)
400
{
401
*addr = 0x04000000;
402
*size = 0x40000 << (CartridgeArea->cartid & 0x0F);
403
if (CartridgeArea->cartid == 0x24)
404
*blocksize = 0x400;
405
else
406
*blocksize = 0x200;
407
408
return 0;
409
}
410
else
411
return 1;
412
default:
413
*addr = 0;
414
*size = 0;
415
*blocksize = 0;
416
return 1;
417
}
418
419
return 1;
420
}
421
422
//////////////////////////////////////////////////////////////////////////////
423
424
static int CheckHeader(UNUSED u32 device)
425
{
426
return 0;
427
}
428
429
//////////////////////////////////////////////////////////////////////////////
430
431
static int CalcSaveSize(u32 tableaddr, int blocksize)
432
{
433
int numblocks=0;
434
435
// Now figure out how many blocks this save is
436
for(;;)
437
{
438
u16 block;
439
block = (MappedMemoryReadByte(tableaddr) << 8) | MappedMemoryReadByte(tableaddr + 2);
440
if (block == 0)
441
break;
442
tableaddr += 4;
443
if (((tableaddr-1) & ((blocksize << 1) - 1)) == 0)
444
tableaddr += 8;
445
numblocks++;
446
}
447
448
return numblocks;
449
}
450
451
//////////////////////////////////////////////////////////////////////////////
452
453
static u32 GetFreeSpace(UNUSED u32 device, u32 size, u32 addr, u32 blocksize)
454
{
455
u32 i;
456
u32 usedblocks=0;
457
458
for (i = ((2 * blocksize) << 1); i < (size << 1); i += (blocksize << 1))
459
{
460
// Find a block with the start of a save
461
if (((s8)MappedMemoryReadByte(addr + i + 1)) < 0)
462
{
463
// Now figure out how many blocks this save is
464
usedblocks += (CalcSaveSize(addr+i+0x45, blocksize) + 1);
465
}
466
}
467
468
return ((size / blocksize) - 2 - usedblocks);
469
}
470
471
//////////////////////////////////////////////////////////////////////////////
472
473
static u32 FindSave(UNUSED u32 device, u32 stringaddr, u32 blockoffset, u32 size, u32 addr, u32 blocksize)
474
{
475
u32 i;
476
477
for (i = ((blockoffset * blocksize) << 1); i < (size << 1); i += (blocksize << 1))
478
{
479
// Find a block with the start of a save
480
if (((s8)MappedMemoryReadByte(addr + i + 1)) < 0)
481
{
482
int i3;
483
484
// See if string matches, or if there's no string to check, just copy
485
// the data over
486
for (i3 = 0; i3 < 11; i3++)
487
{
488
u8 data = MappedMemoryReadByte(stringaddr+i3);
489
490
if (MappedMemoryReadByte(addr+i+0x9+(i3*2)) != data)
491
{
492
if (data == 0)
493
// There's no string to match
494
return ((i / blocksize) >> 1);
495
else
496
// No Match, move onto the next block
497
i3 = 12;
498
}
499
else
500
{
501
// Match
502
if (i3 == 10 || data == 0)
503
return ((i / blocksize) >> 1);
504
}
505
}
506
}
507
}
508
509
return 0;
510
}
511
512
//////////////////////////////////////////////////////////////////////////////
513
514
static u32 FindSave2(UNUSED u32 device, const char *string, u32 blockoffset, u32 size, u32 addr, u32 blocksize)
515
{
516
u32 i;
517
518
for (i = ((blockoffset * blocksize) << 1); i < (size << 1); i += (blocksize << 1))
519
{
520
// Find a block with the start of a save
521
if (((s8)MappedMemoryReadByte(addr + i + 1)) < 0)
522
{
523
int i3;
524
525
// See if string matches, or if there's no string to check, just copy
526
// the data over
527
for (i3 = 0; i3 < 11; i3++)
528
{
529
if (MappedMemoryReadByte(addr+i+0x9+(i3*2)) != string[i3])
530
{
531
if (string[i3] == 0)
532
// There's no string to match
533
return ((i / blocksize) >> 1);
534
else
535
// No Match, move onto the next block
536
i3 = 12;
537
}
538
else
539
{
540
// Match
541
if (i3 == 10 || string[i3] == 0)
542
return ((i / blocksize) >> 1);
543
}
544
}
545
}
546
}
547
548
return 0;
549
}
550
551
//////////////////////////////////////////////////////////////////////////////
552
553
static void DeleteSave(u32 addr, u32 blockoffset, u32 blocksize)
554
{
555
MappedMemoryWriteByte(addr + (blockoffset * blocksize * 2) + 0x1, 0x00);
556
}
557
558
//////////////////////////////////////////////////////////////////////////////
559
560
static u16 *GetFreeBlocks(u32 addr, u32 blocksize, u32 numblocks, u32 size)
561
{
562
u8 *blocktbl;
563
u16 *freetbl;
564
u32 tableaddr;
565
u32 i;
566
u32 blockcount=0;
567
568
// Create a table that tells us which blocks are free and used
569
if ((blocktbl = (u8 *)malloc(sizeof(u8) * (size / blocksize))) == NULL)
570
return NULL;
571
572
memset(blocktbl, 0, (size / blocksize));
573
574
for (i = ((2 * blocksize) << 1); i < (size << 1); i += (blocksize << 1))
575
{
576
// Find a block with the start of a save
577
if (((s8)MappedMemoryReadByte(addr + i + 1)) < 0)
578
{
579
tableaddr = addr+i+0x45;
580
blocktbl[i / (blocksize << 1)] = 1;
581
582
// Now let's figure out which blocks are used
583
for(;;)
584
{
585
u16 block;
586
block = (MappedMemoryReadByte(tableaddr) << 8) | MappedMemoryReadByte(tableaddr + 2);
587
if (block == 0)
588
break;
589
tableaddr += 4;
590
if (((tableaddr-1) & ((blocksize << 1) - 1)) == 0)
591
tableaddr += 8;
592
// block is used
593
blocktbl[block] = 1;
594
}
595
}
596
}
597
598
if ((freetbl = (u16 *)malloc(sizeof(u16) * numblocks)) == NULL)
599
{
600
free(blocktbl);
601
return NULL;
602
}
603
604
// Find some free blocks for us to use
605
for (i = 2; i < (size / blocksize); i++)
606
{
607
if (blocktbl[i] == 0)
608
{
609
freetbl[blockcount] = (u16)i;
610
blockcount++;
611
612
if (blockcount >= numblocks)
613
break;
614
}
615
}
616
617
// Ok, we're all done
618
free(blocktbl);
619
620
return freetbl;
621
}
622
623
//////////////////////////////////////////////////////////////////////////////
624
625
static u16 *ReadBlockTable(u32 addr, u32 *tableaddr, int block, int blocksize, int *numblocks, int *blocksread)
626
{
627
u16 *blocktbl;
628
int i=0;
629
630
tableaddr[0] = addr + (block * blocksize * 2) + 0x45;
631
blocksread[0]=0;
632
633
// First of all figure out how large of buffer we need
634
numblocks[0] = CalcSaveSize(tableaddr[0], blocksize);
635
636
// Allocate buffer
637
if ((blocktbl = (u16 *)malloc(sizeof(u16) * numblocks[0])) == NULL)
638
return NULL;
639
640
// Now read in the table
641
for(i = 0; i < numblocks[0]; i++)
642
{
643
u16 block;
644
block = (MappedMemoryReadByte(tableaddr[0]) << 8) | MappedMemoryReadByte(tableaddr[0] + 2);
645
tableaddr[0] += 4;
646
647
if (((tableaddr[0]-1) & ((blocksize << 1) - 1)) == 0)
648
{
649
tableaddr[0] = addr + (blocktbl[blocksread[0]] * blocksize * 2) + 9;
650
blocksread[0]++;
651
}
652
blocktbl[i] = block;
653
}
654
655
tableaddr[0] += 4;
656
657
return blocktbl;
658
}
659
660
//////////////////////////////////////////////////////////////////////////////
661
662
static void FASTCALL BiosBUPInit(SH2_struct * sh)
663
{
664
SH2GetRegisters(sh, &sh->regs);
665
666
// LOG("BiosBUPInit. arg1 = %08X, arg2 = %08X, arg3 = %08X\n", sh->regs.R[4], sh->regs.R[5], sh->regs.R[6]);
667
668
// Setup Function table
669
MappedMemoryWriteLong(0x06000354, sh->regs.R[5]);
670
MappedMemoryWriteLong(sh->regs.R[5]+0x00, 0x00000380);
671
MappedMemoryWriteLong(sh->regs.R[5]+0x04, 0x00000384);
672
MappedMemoryWriteLong(sh->regs.R[5]+0x08, 0x00000388);
673
MappedMemoryWriteLong(sh->regs.R[5]+0x0C, 0x0000038C);
674
MappedMemoryWriteLong(sh->regs.R[5]+0x10, 0x00000390);
675
MappedMemoryWriteLong(sh->regs.R[5]+0x14, 0x00000394);
676
MappedMemoryWriteLong(sh->regs.R[5]+0x18, 0x00000398);
677
MappedMemoryWriteLong(sh->regs.R[5]+0x1C, 0x0000039C);
678
MappedMemoryWriteLong(sh->regs.R[5]+0x20, 0x000003A0);
679
MappedMemoryWriteLong(sh->regs.R[5]+0x24, 0x000003A4);
680
MappedMemoryWriteLong(sh->regs.R[5]+0x28, 0x000003A8);
681
MappedMemoryWriteLong(sh->regs.R[5]+0x2C, 0x000003AC);
682
683
// Setup Device list
684
685
// First Device
686
MappedMemoryWriteWord(sh->regs.R[6], 1); // ID
687
MappedMemoryWriteWord(sh->regs.R[6]+0x2, 1); // Number of partitions
688
689
// Second Device
690
if ((CartridgeArea->cartid & 0xF0) == 0x20)
691
{
692
MappedMemoryWriteWord(sh->regs.R[6]+0x4, 2); // ID
693
MappedMemoryWriteWord(sh->regs.R[6]+0x6, 1); // Number of partitions
694
}
695
else
696
{
697
MappedMemoryWriteWord(sh->regs.R[6]+0x4, 0); // ID
698
MappedMemoryWriteWord(sh->regs.R[6]+0x6, 0); // Number of partitions
699
}
700
701
// Third Device
702
MappedMemoryWriteWord(sh->regs.R[6]+0x08, 0); // ID
703
MappedMemoryWriteWord(sh->regs.R[6]+0x0A, 0); // Number of partitions
704
705
// cycles need to be incremented
706
707
sh->regs.PC = sh->regs.PR;
708
SH2SetRegisters(sh, &sh->regs);
709
}
710
711
//////////////////////////////////////////////////////////////////////////////
712
713
static void FASTCALL BiosBUPSelectPartition(SH2_struct * sh)
714
{
715
SH2GetRegisters(sh, &sh->regs);
716
717
LOG("BiosBUPSelectPartition. PR = %08X\n", sh->regs.PR);
718
719
sh->regs.R[0] = 0; // returns 0 if there's no error
720
sh->regs.PC = sh->regs.PR;
721
SH2SetRegisters(sh, &sh->regs);
722
}
723
724
//////////////////////////////////////////////////////////////////////////////
725
726
static void FASTCALL BiosBUPFormat(SH2_struct * sh)
727
{
728
SH2GetRegisters(sh, &sh->regs);
729
730
// LOG("BiosBUPFormat. PR = %08X\n", sh->regs.PR);
731
732
BupFormat(sh->regs.R[4]);
733
734
sh->regs.R[0] = 0; // returns 0 if there's no error
735
sh->regs.PC = sh->regs.PR;
736
SH2SetRegisters(sh, &sh->regs);
737
}
738
739
//////////////////////////////////////////////////////////////////////////////
740
741
static void FASTCALL BiosBUPStatus(SH2_struct * sh)
742
{
743
u32 size;
744
u32 addr;
745
u32 blocksize;
746
u32 ret;
747
u32 freeblocks=0;
748
749
SH2GetRegisters(sh, &sh->regs);
750
751
// LOG("BiosBUPStatus. arg1 = %d, arg2 = %d, arg3 = %08X, PR = %08X\n", sh->regs.R[4], sh->regs.R[5], sh->regs.R[6], sh->regs.PR);
752
753
// Fill in status variables
754
ret = GetDeviceStats(sh->regs.R[4], &size, &addr, &blocksize);
755
756
// Make sure there's a proper header, and return if there's any other errors
757
if (ret == 1 || CheckHeader(sh->regs.R[4]) != 0)
758
{
759
// Error
760
sh->regs.R[0] = ret;
761
sh->regs.PC = sh->regs.PR;
762
SH2SetRegisters(sh, &sh->regs);
763
return;
764
}
765
766
freeblocks = GetFreeSpace(sh->regs.R[4], size, addr, blocksize);
767
768
MappedMemoryWriteLong(sh->regs.R[6], size); // Size of Backup Ram (in bytes)
769
MappedMemoryWriteLong(sh->regs.R[6]+0x4, size / blocksize); // Size of Backup Ram (in blocks)
770
MappedMemoryWriteLong(sh->regs.R[6]+0x8, blocksize); // Size of block
771
MappedMemoryWriteLong(sh->regs.R[6]+0xC, ((blocksize - 6) * freeblocks) - 30); // Free space(in bytes)
772
MappedMemoryWriteLong(sh->regs.R[6]+0x10, freeblocks); // Free space(in blocks)
773
MappedMemoryWriteLong(sh->regs.R[6]+0x14, freeblocks); // Not sure, but seems to be the same as Free Space(in blocks)
774
775
// cycles need to be incremented
776
777
sh->regs.R[0] = ret; // returns 0 if there's no error
778
sh->regs.PC = sh->regs.PR;
779
SH2SetRegisters(sh, &sh->regs);
780
}
781
782
//////////////////////////////////////////////////////////////////////////////
783
784
static void FASTCALL BiosBUPWrite(SH2_struct * sh)
785
{
786
u32 size;
787
u32 addr;
788
u32 blocksize;
789
u32 block;
790
u32 ret;
791
u32 savesize;
792
u16 *blocktbl;
793
u32 workaddr;
794
u32 blockswritten=0;
795
u32 datasize;
796
u32 i;
797
798
SH2GetRegisters(sh, &sh->regs);
799
800
LOG("BiosBUPWrite. arg1 = %d, arg2 = %08X, arg3 = %08X, arg4 = %d, PR = %08X\n", sh->regs.R[4], sh->regs.R[5], sh->regs.R[6], sh->regs.R[7], sh->regs.PR);
801
802
// Fill in status variables
803
ret = GetDeviceStats(sh->regs.R[4], &size, &addr, &blocksize);
804
if (ret == 1)
805
{
806
// Error
807
sh->regs.R[0] = ret;
808
sh->regs.PC = sh->regs.PR;
809
SH2SetRegisters(sh, &sh->regs);
810
return;
811
}
812
813
// See if save exists already
814
if ((block = FindSave(sh->regs.R[4], sh->regs.R[5], 2, size, addr, blocksize)) != 0)
815
{
816
// save exists
817
818
// Should we be overwriting it?
819
if (sh->regs.R[7] != 0)
820
{
821
// Nope, let's bail instead
822
sh->regs.R[0] = 6;
823
sh->regs.PC = sh->regs.PR;
824
SH2SetRegisters(sh, &sh->regs);
825
return;
826
}
827
828
// Delete old save
829
DeleteSave(addr, block, blocksize);
830
}
831
832
// Let's figure out how many blocks will be needed for the save
833
datasize = MappedMemoryReadLong(sh->regs.R[5]+0x1C);
834
savesize = (datasize + 0x1D) / (blocksize - 6);
835
if ((datasize + 0x1D) % (blocksize - 6))
836
savesize++;
837
838
// Will it blend? Err... fit
839
if (savesize > GetFreeSpace(sh->regs.R[4], size, addr, blocksize))
840
{
841
// Nope, time to bail
842
sh->regs.R[0] = 4;
843
sh->regs.PC = sh->regs.PR;
844
SH2SetRegisters(sh, &sh->regs);
845
return;
846
}
847
848
// Find free blocks for the save
849
if ((blocktbl = GetFreeBlocks(addr, blocksize, savesize, size)) == NULL)
850
{
851
// Just return an error that might make sense
852
sh->regs.R[0] = 8;
853
sh->regs.PC = sh->regs.PR;
854
SH2SetRegisters(sh, &sh->regs);
855
return;
856
}
857
858
// Create save
859
workaddr = addr + (blocktbl[0] * blocksize * 2);
860
861
MappedMemoryWriteByte(workaddr+0x1, 0x80);
862
863
// Copy over filename
864
for (i = workaddr+0x9; i < ((workaddr+0x9) + (11 * 2)); i+=2)
865
{
866
MappedMemoryWriteByte(i, MappedMemoryReadByte(sh->regs.R[5]));
867
sh->regs.R[5]++;
868
}
869
870
sh->regs.R[5]++;
871
872
// Copy over comment
873
for (i = workaddr+0x21; i < ((workaddr+0x21) + (10 * 2)); i+=2)
874
{
875
MappedMemoryWriteByte(i, MappedMemoryReadByte(sh->regs.R[5]));
876
sh->regs.R[5]++;
877
}
878
879
// Copy over language
880
MappedMemoryWriteByte(workaddr+0x1F, MappedMemoryReadByte(sh->regs.R[5]));
881
sh->regs.R[5]++;
882
883
sh->regs.R[5]++;
884
885
// Copy over date
886
for (i = workaddr+0x35; i < ((workaddr+0x35) + (4 * 2)); i+=2)
887
{
888
MappedMemoryWriteByte(i, MappedMemoryReadByte(sh->regs.R[5]));
889
sh->regs.R[5]++;
890
}
891
892
// Copy over data size
893
for (i = workaddr+0x3D; i < ((workaddr+0x3D) + (4 * 2)); i+=2)
894
{
895
MappedMemoryWriteByte(i, MappedMemoryReadByte(sh->regs.R[5]));
896
sh->regs.R[5]++;
897
}
898
899
// write the block table
900
workaddr += 0x45;
901
902
for (i = 1; i < savesize; i++)
903
{
904
MappedMemoryWriteByte(workaddr, (u8)(blocktbl[i] >> 8));
905
workaddr+=2;
906
MappedMemoryWriteByte(workaddr, (u8)blocktbl[i]);
907
workaddr+=2;
908
909
if (((workaddr-1) & ((blocksize << 1) - 1)) == 0)
910
{
911
// Next block
912
blockswritten++;
913
workaddr = addr + (blocktbl[blockswritten] * blocksize * 2) + 9;
914
}
915
}
916
917
// Write 2 blank bytes so we now how large the table size is next time
918
MappedMemoryWriteByte(workaddr, 0);
919
workaddr+=2;
920
MappedMemoryWriteByte(workaddr, 0);
921
workaddr+=2;
922
923
// Lastly, write the actual save data
924
while (datasize > 0)
925
{
926
MappedMemoryWriteByte(workaddr, MappedMemoryReadByte(sh->regs.R[6]));
927
datasize--;
928
sh->regs.R[6]++;
929
workaddr+=2;
930
931
if (((workaddr-1) & ((blocksize << 1) - 1)) == 0)
932
{
933
// Next block
934
blockswritten++;
935
workaddr = addr + (blocktbl[blockswritten] * blocksize * 2) + 9;
936
}
937
}
938
939
free(blocktbl);
940
941
sh->regs.R[0] = 0; // returns 0 if there's no error
942
sh->regs.PC = sh->regs.PR;
943
SH2SetRegisters(sh, &sh->regs);
944
}
945
946
//////////////////////////////////////////////////////////////////////////////
947
948
static void FASTCALL BiosBUPRead(SH2_struct * sh)
949
{
950
u32 size;
951
u32 addr;
952
u32 blocksize;
953
u32 block;
954
u32 ret;
955
u32 tableaddr;
956
u16 *blocktbl;
957
int numblocks;
958
int blocksread;
959
u32 datasize;
960
961
SH2GetRegisters(sh, &sh->regs);
962
963
LOG("BiosBUPRead\n", sh->regs.PR);
964
965
ret = GetDeviceStats(sh->regs.R[4], &size, &addr, &blocksize);
966
967
if (ret == 1)
968
{
969
// Error
970
sh->regs.R[0] = ret;
971
sh->regs.PC = sh->regs.PR;
972
SH2SetRegisters(sh, &sh->regs);
973
return;
974
}
975
976
// See if save exists
977
if ((block = FindSave(sh->regs.R[4], sh->regs.R[5], 2, size, addr, blocksize)) == 0)
978
{
979
// save doesn't exist
980
sh->regs.R[0] = 5;
981
sh->regs.PC = sh->regs.PR;
982
SH2SetRegisters(sh, &sh->regs);
983
return;
984
}
985
986
tableaddr = addr + (block * blocksize * 2) + 0x3D;
987
datasize = (MappedMemoryReadByte(tableaddr) << 24) | (MappedMemoryReadByte(tableaddr + 2) << 16) |
988
(MappedMemoryReadByte(tableaddr+4) << 8) | MappedMemoryReadByte(tableaddr + 6);
989
990
// Read in Block Table
991
if ((blocktbl = ReadBlockTable(addr, &tableaddr, block, blocksize, &numblocks, &blocksread)) == NULL)
992
{
993
// Just return an error that might make sense
994
sh->regs.R[0] = 8;
995
sh->regs.PC = sh->regs.PR;
996
SH2SetRegisters(sh, &sh->regs);
997
return;
998
}
999
1000
// Now let's read in the data
1001
while (datasize > 0)
1002
{
1003
MappedMemoryWriteByte(sh->regs.R[6], MappedMemoryReadByte(tableaddr));
1004
datasize--;
1005
sh->regs.R[6]++;
1006
tableaddr+=2;
1007
1008
if (((tableaddr-1) & ((blocksize << 1) - 1)) == 0)
1009
{
1010
// Load up the next block
1011
tableaddr = addr + (blocktbl[blocksread] * blocksize * 2) + 9;
1012
blocksread++;
1013
}
1014
}
1015
1016
free(blocktbl);
1017
1018
sh->regs.R[0] = 0; // returns 0 if there's no error
1019
sh->regs.PC = sh->regs.PR;
1020
SH2SetRegisters(sh, &sh->regs);
1021
}
1022
1023
//////////////////////////////////////////////////////////////////////////////
1024
1025
static void FASTCALL BiosBUPDelete(SH2_struct * sh)
1026
{
1027
u32 size;
1028
u32 addr;
1029
u32 blocksize;
1030
u32 block;
1031
u32 ret;
1032
1033
SH2GetRegisters(sh, &sh->regs);
1034
1035
LOG("BiosBUPDelete. PR = %08X\n", sh->regs.PR);
1036
1037
// Fill in status variables
1038
ret = GetDeviceStats(sh->regs.R[4], &size, &addr, &blocksize);
1039
if (ret == 1)
1040
{
1041
// Error
1042
sh->regs.R[0] = ret;
1043
sh->regs.PC = sh->regs.PR;
1044
SH2SetRegisters(sh, &sh->regs);
1045
return;
1046
}
1047
1048
// See if save exists
1049
if ((block = FindSave(sh->regs.R[4], sh->regs.R[5], 2, size, addr, blocksize)) == 0)
1050
{
1051
// Since the save doesn't exist, let's bail with an error
1052
1053
sh->regs.R[0] = 5;
1054
sh->regs.PC = sh->regs.PR;
1055
SH2SetRegisters(sh, &sh->regs);
1056
return;
1057
}
1058
1059
DeleteSave(addr, block, blocksize);
1060
1061
sh->regs.R[0] = 0; // returns 0 if there's no error
1062
sh->regs.PC = sh->regs.PR;
1063
SH2SetRegisters(sh, &sh->regs);
1064
}
1065
1066
//////////////////////////////////////////////////////////////////////////////
1067
1068
static void FASTCALL BiosBUPDirectory(SH2_struct * sh)
1069
{
1070
u32 size;
1071
u32 addr;
1072
u32 blocksize;
1073
u32 ret;
1074
u32 i;
1075
char filename[12];
1076
u32 blockoffset=2;
1077
1078
SH2GetRegisters(sh, &sh->regs);
1079
1080
// int findmatch = MappedMemoryReadByte(sh->regs.R[5]);
1081
1082
for (i = 0; i < 12; i++)
1083
filename[i] = MappedMemoryReadByte(sh->regs.R[5]+i);
1084
1085
LOG("BiosBUPDirectory. arg1 = %d, arg2 = %s, arg3 = %08X, arg4 = %08X, PR = %08X\n", sh->regs.R[4], filename, sh->regs.R[6], sh->regs.R[7], sh->regs.PR);
1086
1087
ret = GetDeviceStats(sh->regs.R[4], &size, &addr, &blocksize);
1088
1089
if (ret == 1)
1090
{
1091
// Error
1092
sh->regs.R[0] = ret;
1093
sh->regs.PC = sh->regs.PR;
1094
SH2SetRegisters(sh, &sh->regs);
1095
return;
1096
}
1097
1098
for (i = 0; i < sh->regs.R[6]; i++)
1099
{
1100
u32 i4;
1101
u32 datasize=0;
1102
u32 block = FindSave(sh->regs.R[4], sh->regs.R[5], blockoffset, size, addr, blocksize);
1103
1104
if (block == 0)
1105
break;
1106
1107
blockoffset = block+1;
1108
1109
// Alright, we found a match :) Time to copy over some data
1110
block = addr + (blocksize * block * 2);
1111
1112
// Copy over filename
1113
for (i4 = block+0x9; i4 < ((block+0x9) + (11 * 2)); i4+=2)
1114
{
1115
MappedMemoryWriteByte(sh->regs.R[7], MappedMemoryReadByte(i4));
1116
sh->regs.R[7]++;
1117
}
1118
MappedMemoryWriteByte(sh->regs.R[7], 0);
1119
sh->regs.R[7]++;
1120
1121
// Copy over comment
1122
for (i4 = block+0x21; i4 < ((block+0x21) + (10 * 2)); i4+=2)
1123
{
1124
MappedMemoryWriteByte(sh->regs.R[7], MappedMemoryReadByte(i4));
1125
sh->regs.R[7]++;
1126
}
1127
1128
// Copy over language
1129
MappedMemoryWriteByte(sh->regs.R[7], MappedMemoryReadByte(block+0x1F));
1130
sh->regs.R[7]++;
1131
1132
MappedMemoryWriteByte(sh->regs.R[7], 0);
1133
sh->regs.R[7]++;
1134
1135
// Copy over date
1136
for (i4 = block+0x35; i4 < ((block+0x35) + (4 * 2)); i4+=2)
1137
{
1138
MappedMemoryWriteByte(sh->regs.R[7], MappedMemoryReadByte(i4));
1139
sh->regs.R[7]++;
1140
}
1141
1142
// Copy over data size
1143
for (i4 = block+0x3D; i4 < ((block+0x3D) + (4 * 2)); i4+=2)
1144
{
1145
u8 data;
1146
datasize <<= 8;
1147
data = MappedMemoryReadByte(i4);
1148
MappedMemoryWriteByte(sh->regs.R[7], data);
1149
datasize |= data;
1150
sh->regs.R[7]++;
1151
}
1152
1153
// Calculate block size from the data size, and then copy it over
1154
MappedMemoryWriteWord(sh->regs.R[7], (u16)(((datasize + 0x1D) / (blocksize - 6)) + 1));
1155
sh->regs.R[7] += 4;
1156
}
1157
1158
sh->regs.R[0] = i; // returns the number of successfully read dir entries
1159
sh->regs.PC = sh->regs.PR;
1160
SH2SetRegisters(sh, &sh->regs);
1161
}
1162
1163
//////////////////////////////////////////////////////////////////////////////
1164
1165
static void FASTCALL BiosBUPVerify(SH2_struct * sh)
1166
{
1167
u32 size;
1168
u32 addr;
1169
u32 blocksize;
1170
u32 block;
1171
u32 ret;
1172
u32 tableaddr;
1173
u32 datasize;
1174
u16 *blocktbl;
1175
int numblocks;
1176
int blocksread;
1177
1178
SH2GetRegisters(sh, &sh->regs);
1179
1180
LOG("BiosBUPVerify. PR = %08X\n", sh->regs.PR);
1181
1182
ret = GetDeviceStats(sh->regs.R[4], &size, &addr, &blocksize);
1183
1184
if (ret == 1)
1185
{
1186
// Error
1187
sh->regs.R[0] = ret;
1188
sh->regs.PC = sh->regs.PR;
1189
SH2SetRegisters(sh, &sh->regs);
1190
return;
1191
}
1192
1193
// See if save exists
1194
if ((block = FindSave(sh->regs.R[4], sh->regs.R[5], 2, size, addr, blocksize)) == 0)
1195
{
1196
// Since the save doesn't exist, let's bail with an error
1197
sh->regs.R[0] = 5; // Not found
1198
sh->regs.PC = sh->regs.PR;
1199
SH2SetRegisters(sh, &sh->regs);
1200
return;
1201
}
1202
1203
tableaddr = addr + (block * blocksize * 2) + 0x3D;
1204
datasize = (MappedMemoryReadByte(tableaddr) << 24) | (MappedMemoryReadByte(tableaddr + 2) << 16) |
1205
(MappedMemoryReadByte(tableaddr+4) << 8) | MappedMemoryReadByte(tableaddr + 6);
1206
1207
// Read in Block Table
1208
if ((blocktbl = ReadBlockTable(addr, &tableaddr, block, blocksize, &numblocks, &blocksread)) == NULL)
1209
{
1210
// Just return an error that might make sense
1211
sh->regs.R[0] = 8; // Broken
1212
sh->regs.PC = sh->regs.PR;
1213
SH2SetRegisters(sh, &sh->regs);
1214
return;
1215
}
1216
1217
// Now let's read in the data, and check to see if it matches
1218
while (datasize > 0)
1219
{
1220
if (MappedMemoryReadByte(sh->regs.R[6]) != MappedMemoryReadByte(tableaddr))
1221
{
1222
free(blocktbl);
1223
// Ok, the data doesn't match
1224
sh->regs.R[0] = 7; // No match
1225
sh->regs.PC = sh->regs.PR;
1226
SH2SetRegisters(sh, &sh->regs);
1227
return;
1228
}
1229
1230
datasize--;
1231
sh->regs.R[6]++;
1232
tableaddr+=2;
1233
1234
if (((tableaddr-1) & ((blocksize << 1) - 1)) == 0)
1235
{
1236
// Load up the next block
1237
tableaddr = addr + (blocktbl[blocksread] * blocksize * 2) + 9;
1238
blocksread++;
1239
}
1240
}
1241
1242
free(blocktbl);
1243
1244
sh->regs.R[0] = 0; // returns 0 if there's no error
1245
sh->regs.PC = sh->regs.PR;
1246
SH2SetRegisters(sh, &sh->regs);
1247
}
1248
1249
//////////////////////////////////////////////////////////////////////////////
1250
1251
static void ConvertMonthAndDay(u32 data, u32 monthaddr, u32 dayaddr, int type)
1252
{
1253
int i;
1254
u16 monthtbl[11] = { 31, 31+28, 31+28+31, 31+28+31+30, 31+28+31+30+31,
1255
31+28+31+30+31+30, 31+28+31+30+31+30+31,
1256
31+28+31+30+31+30+31+31, 31+28+31+30+31+30+31+31+30,
1257
31+28+31+30+31+30+31+31+30+31,
1258
31+28+31+30+31+30+31+31+30+31+30 };
1259
1260
if (data < monthtbl[0])
1261
{
1262
// Month
1263
MappedMemoryWriteByte(monthaddr, 1);
1264
1265
// Day
1266
MappedMemoryWriteByte(dayaddr, (u8)(data + 1));
1267
return;
1268
}
1269
1270
for (i = 1; i < 11; i++)
1271
{
1272
if (data <= monthtbl[i])
1273
break;
1274
}
1275
1276
if (type == 1)
1277
{
1278
// Month
1279
MappedMemoryWriteByte(monthaddr, (u8)(i + 1));
1280
1281
// Day
1282
if ((i + 1) == 2)
1283
MappedMemoryWriteByte(dayaddr, (u8)(data - monthtbl[(i - 1)] + 1));
1284
else
1285
MappedMemoryWriteByte(dayaddr, (u8)(data - monthtbl[(i - 1)]));
1286
}
1287
else
1288
{
1289
// Month
1290
MappedMemoryWriteByte(monthaddr, (u8)(i + 1));
1291
1292
// Day
1293
MappedMemoryWriteByte(dayaddr, (u8)(data - monthtbl[(i - 1)] + 1));
1294
}
1295
}
1296
1297
//////////////////////////////////////////////////////////////////////////////
1298
1299
static void FASTCALL BiosBUPGetDate(SH2_struct * sh)
1300
{
1301
u32 date;
1302
u32 div;
1303
u32 yearoffset;
1304
u32 yearremainder;
1305
1306
SH2GetRegisters(sh, &sh->regs);
1307
1308
LOG("BiosBUPGetDate. PR = %08X\n", sh->regs.PR);
1309
1310
date = sh->regs.R[4];
1311
1312
// Time
1313
MappedMemoryWriteByte(sh->regs.R[5]+3, (u8)((date % 0x5A0) / 0x3C));
1314
1315
// Minute
1316
MappedMemoryWriteByte(sh->regs.R[5]+4, (u8)(date % 0x3C));
1317
1318
div = date / 0x5A0;
1319
1320
// Week
1321
if (div > 0xAB71)
1322
MappedMemoryWriteByte(sh->regs.R[5]+5, (u8)((div + 1) % 7));
1323
else
1324
MappedMemoryWriteByte(sh->regs.R[5]+5, (u8)((div + 2) % 7));
1325
1326
yearremainder = div % 0x5B5;
1327
1328
if (yearremainder > 0x16E)
1329
{
1330
yearoffset = (yearremainder - 1) / 0x16D;
1331
ConvertMonthAndDay((yearremainder - 1) % 0x16D, sh->regs.R[5]+1, sh->regs.R[5]+2, 0);
1332
}
1333
else
1334
{
1335
yearoffset = 0;
1336
ConvertMonthAndDay(0, sh->regs.R[5]+1, sh->regs.R[5]+2, 1);
1337
}
1338
1339
// Year
1340
MappedMemoryWriteByte(sh->regs.R[5], (u8)(((div / 0x5B5) * 4) + yearoffset));
1341
1342
sh->regs.PC = sh->regs.PR;
1343
SH2SetRegisters(sh, &sh->regs);
1344
}
1345
1346
//////////////////////////////////////////////////////////////////////////////
1347
1348
static void FASTCALL BiosBUPSetDate(SH2_struct * sh)
1349
{
1350
u32 date;
1351
u8 data;
1352
u32 remainder;
1353
u16 monthtbl[11] = { 31, 31+28, 31+28+31, 31+28+31+30, 31+28+31+30+31,
1354
31+28+31+30+31+30, 31+28+31+30+31+30+31,
1355
31+28+31+30+31+30+31+31, 31+28+31+30+31+30+31+31+30,
1356
31+28+31+30+31+30+31+31+30+31,
1357
31+28+31+30+31+30+31+31+30+31+30 };
1358
1359
SH2GetRegisters(sh, &sh->regs);
1360
1361
LOG("BiosBUPSetDate. PR = %08X\n", sh->regs.PR);
1362
1363
// Year
1364
data = MappedMemoryReadByte(sh->regs.R[4]);
1365
date = (data / 4) * 0x5B5;
1366
remainder = data % 4;
1367
if (remainder)
1368
date += (remainder * 0x16D) + 1;
1369
1370
// Month
1371
data = MappedMemoryReadByte(sh->regs.R[4]+1);
1372
if (data != 1 && data < 13)
1373
{
1374
date += monthtbl[data - 2];
1375
if (date > 2 && remainder == 0)
1376
date++;
1377
}
1378
1379
// Day
1380
date += MappedMemoryReadByte(sh->regs.R[4]+2) - 1;
1381
date *= 0x5A0;
1382
1383
// Hour
1384
date += (MappedMemoryReadByte(sh->regs.R[4]+3) * 0x3C);
1385
1386
// Minute
1387
date += MappedMemoryReadByte(sh->regs.R[4]+4);
1388
1389
sh->regs.R[0] = date;
1390
sh->regs.PC = sh->regs.PR;
1391
SH2SetRegisters(sh, &sh->regs);
1392
}
1393
1394
//////////////////////////////////////////////////////////////////////////////
1395
1396
static void FASTCALL BiosHandleScuInterrupt(SH2_struct * sh, int vector)
1397
{
1398
SH2GetRegisters(sh, &sh->regs);
1399
1400
// Save R0-R7, PR, GBR, and old Interrupt mask to stack
1401
sh->regs.R[15] -= 4;
1402
MappedMemoryWriteLong(sh->regs.R[15], sh->regs.R[0]);
1403
sh->regs.R[15] -= 4;
1404
MappedMemoryWriteLong(sh->regs.R[15], sh->regs.R[1]);
1405
sh->regs.R[15] -= 4;
1406
MappedMemoryWriteLong(sh->regs.R[15], sh->regs.R[2]);
1407
sh->regs.R[15] -= 4;
1408
MappedMemoryWriteLong(sh->regs.R[15], sh->regs.R[3]);
1409
sh->regs.R[15] -= 4;
1410
MappedMemoryWriteLong(sh->regs.R[15], MappedMemoryReadLong(0x06000348));
1411
sh->regs.R[15] -= 4;
1412
MappedMemoryWriteLong(sh->regs.R[15], sh->regs.R[4]);
1413
sh->regs.R[15] -= 4;
1414
MappedMemoryWriteLong(sh->regs.R[15], sh->regs.R[5]);
1415
sh->regs.R[15] -= 4;
1416
MappedMemoryWriteLong(sh->regs.R[15], sh->regs.R[6]);
1417
sh->regs.R[15] -= 4;
1418
MappedMemoryWriteLong(sh->regs.R[15], sh->regs.R[7]);
1419
sh->regs.R[15] -= 4;
1420
MappedMemoryWriteLong(sh->regs.R[15], sh->regs.PR);
1421
sh->regs.R[15] -= 4;
1422
MappedMemoryWriteLong(sh->regs.R[15], sh->regs.GBR);
1423
1424
// Set SR according to vector
1425
sh->regs.SR.all = (u32)sh2masklist[vector - 0x40];
1426
1427
// Write new Interrupt mask value
1428
MappedMemoryWriteLong(0x06000348, MappedMemoryReadLong(0x06000348) | scumasklist[vector - 0x40]);
1429
MappedMemoryWriteLong(0x25FE00A0, MappedMemoryReadLong(0x06000348) | scumasklist[vector - 0x40]);
1430
1431
// Set PR to our Interrupt Return handler
1432
sh->regs.PR = 0x00000480;
1433
1434
// Now execute the interrupt
1435
sh->regs.PC = MappedMemoryReadLong(0x06000900+(vector << 2));
1436
// LOG("Interrupt PC = %08X. Read from %08X\n", sh->regs.PC, 0x06000900+(vector << 2));
1437
1438
sh->cycles += 33;
1439
SH2SetRegisters(sh, &sh->regs);
1440
}
1441
1442
//////////////////////////////////////////////////////////////////////////////
1443
1444
static void FASTCALL BiosHandleScuInterruptReturn(SH2_struct * sh)
1445
{
1446
u32 oldmask;
1447
1448
SH2GetRegisters(sh, &sh->regs);
1449
1450
// Restore R0-R7, PR, GBR, and old Interrupt mask from stack
1451
sh->regs.GBR = MappedMemoryReadLong(sh->regs.R[15]);
1452
sh->regs.R[15] += 4;
1453
sh->regs.PR = MappedMemoryReadLong(sh->regs.R[15]);
1454
sh->regs.R[15] += 4;
1455
sh->regs.R[7] = MappedMemoryReadLong(sh->regs.R[15]);
1456
sh->regs.R[15] += 4;
1457
sh->regs.R[6] = MappedMemoryReadLong(sh->regs.R[15]);
1458
sh->regs.R[15] += 4;
1459
sh->regs.R[5] = MappedMemoryReadLong(sh->regs.R[15]);
1460
sh->regs.R[15] += 4;
1461
sh->regs.R[4] = MappedMemoryReadLong(sh->regs.R[15]);
1462
sh->regs.R[15] += 4;
1463
// Return SR back to normal
1464
sh->regs.SR.all = 0xF0;
1465
oldmask = MappedMemoryReadLong(sh->regs.R[15]);
1466
MappedMemoryWriteLong(0x06000348, oldmask);
1467
MappedMemoryWriteLong(0x25FE00A0, oldmask);
1468
sh->regs.R[15] += 4;
1469
sh->regs.R[3] = MappedMemoryReadLong(sh->regs.R[15]);
1470
sh->regs.R[15] += 4;
1471
sh->regs.R[2] = MappedMemoryReadLong(sh->regs.R[15]);
1472
sh->regs.R[15] += 4;
1473
sh->regs.R[1] = MappedMemoryReadLong(sh->regs.R[15]);
1474
sh->regs.R[15] += 4;
1475
sh->regs.R[0] = MappedMemoryReadLong(sh->regs.R[15]);
1476
sh->regs.R[15] += 4;
1477
1478
sh->regs.PC = MappedMemoryReadLong(sh->regs.R[15]);
1479
sh->regs.R[15] += 4;
1480
sh->regs.SR.all = MappedMemoryReadLong(sh->regs.R[15]) & 0x000003F3;
1481
sh->regs.R[15] += 4;
1482
1483
sh->cycles += 24;
1484
SH2SetRegisters(sh, &sh->regs);
1485
}
1486
1487
//////////////////////////////////////////////////////////////////////////////
1488
1489
int FASTCALL BiosHandleFunc(SH2_struct * sh)
1490
{
1491
SH2GetRegisters(sh, &sh->regs);
1492
1493
// Let's see if it's a bios function
1494
switch((sh->regs.PC - 0x200) >> 2)
1495
{
1496
case 0x04: // 0x06000210
1497
BiosPowerOnMemoryClear(sh);
1498
break;
1499
case 0x1B: // 0x0600026C
1500
BiosExecuteCDPlayer(sh);
1501
break;
1502
case 0x1D: // 0x06000274
1503
BiosCheckMPEGCard(sh);
1504
break;
1505
case 0x20: // 0x06000280
1506
BiosChangeScuInterruptPriority(sh);
1507
break;
1508
case 0x27: // 0x0600029C
1509
BiosCDINIT2(sh);
1510
break;
1511
case 0x37: // 0x060002DC
1512
BiosCDINIT1(sh);
1513
break;
1514
case 0x40: // 0x06000300
1515
BiosSetScuInterrupt(sh);
1516
break;
1517
case 0x41: // 0x06000304
1518
BiosGetScuInterrupt(sh);
1519
break;
1520
case 0x44: // 0x06000310
1521
BiosSetSh2Interrupt(sh);
1522
break;
1523
case 0x45: // 0x06000314
1524
BiosGetSh2Interrupt(sh);
1525
break;
1526
case 0x48: // 0x06000320
1527
BiosChangeSystemClock(sh);
1528
break;
1529
case 0x4C: // 0x06000330
1530
BiosGetSemaphore(sh);
1531
break;
1532
case 0x4D: // 0x06000334
1533
BiosClearSemaphore(sh);
1534
break;
1535
case 0x50: // 0x06000340
1536
BiosSetScuInterruptMask(sh);
1537
break;
1538
case 0x51: // 0x06000344
1539
BiosChangeScuInterruptMask(sh);
1540
break;
1541
case 0x56: // 0x06000358
1542
BiosBUPInit(sh);
1543
break;
1544
case 0x60: // 0x06000380
1545
break;
1546
case 0x61: // 0x06000384
1547
BiosBUPSelectPartition(sh);
1548
break;
1549
case 0x62: // 0x06000388
1550
BiosBUPFormat(sh);
1551
break;
1552
case 0x63: // 0x0600038C
1553
BiosBUPStatus(sh);
1554
break;
1555
case 0x64: // 0x06000390
1556
BiosBUPWrite(sh);
1557
break;
1558
case 0x65: // 0x06000394
1559
BiosBUPRead(sh);
1560
break;
1561
case 0x66: // 0x06000398
1562
BiosBUPDelete(sh);
1563
break;
1564
case 0x67: // 0x0600039C
1565
BiosBUPDirectory(sh);
1566
break;
1567
case 0x68: // 0x060003A0
1568
BiosBUPVerify(sh);
1569
break;
1570
case 0x69: // 0x060003A4
1571
BiosBUPGetDate(sh);
1572
break;
1573
case 0x6A: // 0x060003A8
1574
BiosBUPSetDate(sh);
1575
break;
1576
case 0x6B: // 0x060003AC
1577
break;
1578
case 0x80: // Interrupt Handler
1579
case 0x81:
1580
case 0x82:
1581
case 0x83:
1582
case 0x84:
1583
case 0x85:
1584
case 0x86:
1585
case 0x87:
1586
case 0x88:
1587
case 0x89:
1588
case 0x8A:
1589
case 0x8B:
1590
case 0x8C:
1591
case 0x8D:
1592
case 0x90:
1593
case 0x91:
1594
case 0x92:
1595
case 0x93:
1596
case 0x94:
1597
case 0x95:
1598
case 0x96:
1599
case 0x97:
1600
case 0x98:
1601
case 0x99:
1602
case 0x9A:
1603
case 0x9B:
1604
case 0x9C:
1605
case 0x9D:
1606
case 0x9E:
1607
case 0x9F:
1608
BiosHandleScuInterrupt(sh, (sh->regs.PC - 0x300) >> 2);
1609
break;
1610
case 0xA0: // Interrupt Handler Return
1611
BiosHandleScuInterruptReturn(sh);
1612
break;
1613
default:
1614
return 0;
1615
}
1616
1617
return 1;
1618
}
1619
1620
//////////////////////////////////////////////////////////////////////////////
1621
1622
deviceinfo_struct *BupGetDeviceList(int *numdevices)
1623
{
1624
deviceinfo_struct *device;
1625
int devicecount=1;
1626
1627
if ((CartridgeArea->cartid & 0xF0) == 0x20)
1628
devicecount++;
1629
1630
if ((device = (deviceinfo_struct *)malloc(devicecount * sizeof(deviceinfo_struct))) == NULL)
1631
{
1632
*numdevices = 0;
1633
return NULL;
1634
}
1635
1636
*numdevices = devicecount;
1637
1638
device[0].id = 0;
1639
sprintf(device[0].name, "Internal Backup RAM");
1640
1641
if ((CartridgeArea->cartid & 0xF0) == 0x20)
1642
{
1643
device[1].id = 1;
1644
sprintf(device[1].name, "%d Mbit Backup RAM Cartridge", 1 << ((CartridgeArea->cartid & 0xF)+1));
1645
}
1646
1647
// For now it's only internal backup ram and cartridge, no floppy :(
1648
// device[2].id = 2;
1649
// sprintf(device[1].name, "Floppy Disk Drive");
1650
1651
return device;
1652
}
1653
1654
//////////////////////////////////////////////////////////////////////////////
1655
1656
int BupGetStats(u32 device, u32 *freespace, u32 *maxspace)
1657
{
1658
u32 ret;
1659
u32 size;
1660
u32 addr;
1661
u32 blocksize;
1662
1663
ret = GetDeviceStats(device, &size, &addr, &blocksize);
1664
1665
// Make sure there's a proper header, and return if there's any other errors
1666
if (ret == 1 || CheckHeader(device) != 0)
1667
return 0;
1668
1669
*maxspace = size / blocksize;
1670
*freespace = GetFreeSpace(device, size, addr, blocksize);
1671
1672
return 1;
1673
}
1674
1675
//////////////////////////////////////////////////////////////////////////////
1676
1677
saveinfo_struct *BupGetSaveList(u32 device, int *numsaves)
1678
{
1679
u32 ret;
1680
u32 size;
1681
u32 addr;
1682
u32 blocksize;
1683
saveinfo_struct *save;
1684
int savecount=0;
1685
u32 i, j;
1686
u32 workaddr;
1687
1688
ret = GetDeviceStats(device, &size, &addr, &blocksize);
1689
1690
// Make sure there's a proper header, and return if there's any other errors
1691
if (ret == 1 || CheckHeader(device) != 0)
1692
{
1693
*numsaves = 0;
1694
return NULL;
1695
}
1696
1697
for (i = ((2 * blocksize) << 1); i < (size << 1); i += (blocksize << 1))
1698
{
1699
// Find a block with the start of a save
1700
if (((s8)MappedMemoryReadByte(addr + i + 1)) < 0)
1701
savecount++;
1702
}
1703
1704
if ((save = (saveinfo_struct *)malloc(savecount * sizeof(saveinfo_struct))) == NULL)
1705
{
1706
*numsaves = 0;
1707
return NULL;
1708
}
1709
1710
*numsaves = savecount;
1711
1712
savecount = 0;
1713
1714
for (i = ((2 * blocksize) << 1); i < (size << 1); i += (blocksize << 1))
1715
{
1716
// Find a block with the start of a save
1717
if (((s8)MappedMemoryReadByte(addr + i + 1)) < 0)
1718
{
1719
workaddr = addr + i;
1720
1721
// Copy over filename
1722
for (j = 0; j < 11; j++)
1723
save[savecount].filename[j] = MappedMemoryReadByte(workaddr+0x9+(j * 2));
1724
save[savecount].filename[11] = '\0';
1725
1726
// Copy over comment
1727
for (j = 0; j < 10; j++)
1728
save[savecount].comment[j] = MappedMemoryReadByte(workaddr+0x21+(j * 2));
1729
save[savecount].comment[10] = '\0';
1730
1731
// Copy over language
1732
save[savecount].language = MappedMemoryReadByte(workaddr+0x1F);
1733
1734
// Copy over Date(fix me)
1735
save[savecount].year = 0;
1736
save[savecount].month = 0;
1737
save[savecount].day = 0;
1738
save[savecount].hour = 0;
1739
save[savecount].minute = 0;
1740
save[savecount].week = 0;
1741
1742
// Copy over data size
1743
save[savecount].datasize = (MappedMemoryReadByte(workaddr+0x3D) << 24) |
1744
(MappedMemoryReadByte(workaddr+0x3F) << 16) |
1745
(MappedMemoryReadByte(workaddr+0x41) << 8) |
1746
MappedMemoryReadByte(workaddr+0x43);
1747
1748
// Calculate size in blocks
1749
save[savecount].blocksize = CalcSaveSize(workaddr+0x45, blocksize) + 1;
1750
savecount++;
1751
}
1752
}
1753
1754
return save;
1755
}
1756
1757
//////////////////////////////////////////////////////////////////////////////
1758
1759
int BupDeleteSave(u32 device, const char *savename)
1760
{
1761
u32 ret;
1762
u32 size;
1763
u32 addr;
1764
u32 blocksize;
1765
u32 block;
1766
1767
ret = GetDeviceStats(device, &size, &addr, &blocksize);
1768
1769
// Make sure there's a proper header, and return if there's any other errors
1770
if (ret == 1 || CheckHeader(device) != 0)
1771
return -1;
1772
1773
// Let's find and delete the save game
1774
if ((block = FindSave2(device, savename, 2, size, addr, blocksize)) != 0)
1775
{
1776
// Delete old save
1777
DeleteSave(addr, block, blocksize);
1778
return 0;
1779
}
1780
1781
return -2;
1782
}
1783
1784
//////////////////////////////////////////////////////////////////////////////
1785
1786
void BupFormat(u32 device)
1787
{
1788
switch (device)
1789
{
1790
case 0:
1791
FormatBackupRam(BupRam, 0x10000);
1792
break;
1793
case 1:
1794
if ((CartridgeArea->cartid & 0xF0) == 0x20)
1795
{
1796
switch (CartridgeArea->cartid & 0xF)
1797
{
1798
case 1:
1799
FormatBackupRam(CartridgeArea->bupram, 0x100000);
1800
break;
1801
case 2:
1802
FormatBackupRam(CartridgeArea->bupram, 0x200000);
1803
break;
1804
case 3:
1805
FormatBackupRam(CartridgeArea->bupram, 0x400000);
1806
break;
1807
case 4:
1808
FormatBackupRam(CartridgeArea->bupram, 0x800000);
1809
break;
1810
default: break;
1811
}
1812
}
1813
break;
1814
case 2:
1815
LOG("Formatting FDD not supported\n");
1816
default: break;
1817
}
1818
}
1819
1820
//////////////////////////////////////////////////////////////////////////////
1821
1822
int BupCopySave(UNUSED u32 srcdevice, UNUSED u32 dstdevice, UNUSED const char *savename)
1823
{
1824
return 0;
1825
}
1826
1827
//////////////////////////////////////////////////////////////////////////////
1828
1829
int BupImportSave(UNUSED u32 device, const char *filename)
1830
{
1831
FILE *fp;
1832
u32 filesize;
1833
u8 *buffer;
1834
1835
if (!filename)
1836
return -1;
1837
1838
if ((fp = fopen(filename, "rb")) == NULL)
1839
return -1;
1840
1841
// Calculate file size
1842
fseek(fp, 0, SEEK_END);
1843
filesize = ftell(fp);
1844
fseek(fp, 0, SEEK_SET);
1845
1846
if ((buffer = (u8 *)malloc(filesize)) == NULL)
1847
{
1848
fclose(fp);
1849
return -2;
1850
}
1851
1852
fread((void *)buffer, 1, filesize, fp);
1853
fclose(fp);
1854
1855
// Write save here
1856
1857
free(buffer);
1858
return 0;
1859
}
1860
1861
//////////////////////////////////////////////////////////////////////////////
1862
1863
int BupExportSave(UNUSED u32 device, UNUSED const char *savename, UNUSED const char *filename)
1864
{
1865
return 0;
1866
}
1867
1868
//////////////////////////////////////////////////////////////////////////////
1869
1870
1871