1 /* Copyright 2005 Guillaume Duhamel
2 Copyright 2005-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 /*! \file memory.c
22 \brief Memory access functions.
23 */
24
25 #ifdef PSP // see FIXME in T1MemoryInit()
26 # include <stdint.h>
27 #endif
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <sys/stat.h>
31 #include <ctype.h>
32
33 #include "memory.h"
34 #include "coffelf.h"
35 #include "cs0.h"
36 #include "cs1.h"
37 #include "cs2.h"
38 #include "debug.h"
39 #include "error.h"
40 #include "sh2core.h"
41 #include "scsp.h"
42 #include "scu.h"
43 #include "smpc.h"
44 #include "vdp1.h"
45 #include "vdp2.h"
46 #include "yabause.h"
47 #include "yui.h"
48 #include "movie.h"
49 #include "sh7034.h"
50 #include "ygr.h"
51
52 #ifdef HAVE_LIBGL
53 #define USE_OPENGL
54 #endif
55
56 #ifdef USE_OPENGL
57 #include "ygl.h"
58 #endif
59
60 #include "vidsoft.h"
61 #include "vidogl.h"
62
63 #ifdef SH2_TRACE
64 #include "sh2trace.h"
65 #endif
66
67 //////////////////////////////////////////////////////////////////////////////
68
69 u8 *SH1Rom;
70 u8 *SH1Dram;
71 u8 *SH1MpegRom;
72
73 u8 *HighWram;
74 u8 *LowWram;
75 u8 *BiosRom;
76 u8 *BupRam;
77
78 /* This flag is set to 1 on every write to backup RAM. Ports can freely
79 * check or clear this flag to determine when backup RAM has been written,
80 * e.g. for implementing autosave of backup RAM. */
81 u8 BupRamWritten;
82
83 //////////////////////////////////////////////////////////////////////////////
84
T1MemoryInit(u32 size)85 u8 * T1MemoryInit(u32 size)
86 {
87 #ifdef PSP // FIXME: could be ported to all arches, but requires stdint.h
88 // for uintptr_t
89 u8 * base;
90 u8 * mem;
91
92 if ((base = calloc((size * sizeof(u8)) + sizeof(u8 *) + 64, 1)) == NULL)
93 return NULL;
94
95 mem = base + sizeof(u8 *);
96 mem = mem + (64 - ((uintptr_t) mem & 63));
97 *(u8 **)(mem - sizeof(u8 *)) = base; // Save base pointer below memory block
98
99 return mem;
100 #else
101 return calloc(size, sizeof(u8));
102 #endif
103 }
104
105 //////////////////////////////////////////////////////////////////////////////
106
T1MemoryDeInit(u8 * mem)107 void T1MemoryDeInit(u8 * mem)
108 {
109 #ifdef PSP
110 if (mem)
111 free(*(u8 **)(mem - sizeof(u8 *)));
112 #else
113 free(mem);
114 #endif
115 }
116
117 //////////////////////////////////////////////////////////////////////////////
118
T3MemoryInit(u32 size)119 T3Memory * T3MemoryInit(u32 size)
120 {
121 T3Memory * mem;
122
123 if ((mem = (T3Memory *) calloc(1, sizeof(T3Memory))) == NULL)
124 return NULL;
125
126 if ((mem->base_mem = (u8 *) calloc(size, sizeof(u8))) == NULL)
127 {
128 free(mem);
129 return NULL;
130 }
131
132 mem->mem = mem->base_mem + size;
133
134 return mem;
135 }
136
137 //////////////////////////////////////////////////////////////////////////////
138
T3MemoryDeInit(T3Memory * mem)139 void T3MemoryDeInit(T3Memory * mem)
140 {
141 free(mem->base_mem);
142 free(mem);
143 }
144
145 //////////////////////////////////////////////////////////////////////////////
146
DummyInit(UNUSED u32 s)147 Dummy * DummyInit(UNUSED u32 s)
148 {
149 return NULL;
150 }
151
152 //////////////////////////////////////////////////////////////////////////////
153
DummyDeInit(UNUSED Dummy * d)154 void DummyDeInit(UNUSED Dummy * d)
155 {
156 }
157
158 //////////////////////////////////////////////////////////////////////////////
159
UnhandledMemoryReadByte(USED_IF_DEBUG u32 addr)160 u8 FASTCALL UnhandledMemoryReadByte(USED_IF_DEBUG u32 addr)
161 {
162 LOG("Unhandled byte read %08X\n", (unsigned int)addr);
163 return 0;
164 }
165
166 //////////////////////////////////////////////////////////////////////////////
167
UnhandledMemoryReadWord(USED_IF_DEBUG u32 addr)168 u16 FASTCALL UnhandledMemoryReadWord(USED_IF_DEBUG u32 addr)
169 {
170 LOG("Unhandled word read %08X\n", (unsigned int)addr);
171 return 0;
172 }
173
174 //////////////////////////////////////////////////////////////////////////////
175
UnhandledMemoryReadLong(USED_IF_DEBUG u32 addr)176 u32 FASTCALL UnhandledMemoryReadLong(USED_IF_DEBUG u32 addr)
177 {
178 LOG("Unhandled long read %08X\n", (unsigned int)addr);
179 return 0;
180 }
181
182 //////////////////////////////////////////////////////////////////////////////
183
UnhandledMemoryWriteByte(USED_IF_DEBUG u32 addr,UNUSED u8 val)184 void FASTCALL UnhandledMemoryWriteByte(USED_IF_DEBUG u32 addr, UNUSED u8 val)
185 {
186 LOG("Unhandled byte write %08X\n", (unsigned int)addr);
187 }
188
189 //////////////////////////////////////////////////////////////////////////////
190
UnhandledMemoryWriteWord(USED_IF_DEBUG u32 addr,UNUSED u16 val)191 void FASTCALL UnhandledMemoryWriteWord(USED_IF_DEBUG u32 addr, UNUSED u16 val)
192 {
193 LOG("Unhandled word write %08X\n", (unsigned int)addr);
194 }
195
196 //////////////////////////////////////////////////////////////////////////////
197
UnhandledMemoryWriteLong(USED_IF_DEBUG u32 addr,UNUSED u32 val)198 void FASTCALL UnhandledMemoryWriteLong(USED_IF_DEBUG u32 addr, UNUSED u32 val)
199 {
200 LOG("Unhandled long write %08X\n", (unsigned int)addr);
201 }
202
203 //////////////////////////////////////////////////////////////////////////////
204
HighWramMemoryReadByte(u32 addr)205 u8 FASTCALL HighWramMemoryReadByte(u32 addr)
206 {
207 return T2ReadByte(HighWram, addr & 0xFFFFF);
208 }
209
210 //////////////////////////////////////////////////////////////////////////////
211
HighWramMemoryReadWord(u32 addr)212 u16 FASTCALL HighWramMemoryReadWord(u32 addr)
213 {
214 return T2ReadWord(HighWram, addr & 0xFFFFF);
215 }
216
217 //////////////////////////////////////////////////////////////////////////////
218
HighWramMemoryReadLong(u32 addr)219 u32 FASTCALL HighWramMemoryReadLong(u32 addr)
220 {
221 return T2ReadLong(HighWram, addr & 0xFFFFF);
222 }
223
224 //////////////////////////////////////////////////////////////////////////////
225
HighWramMemoryWriteByte(u32 addr,u8 val)226 void FASTCALL HighWramMemoryWriteByte(u32 addr, u8 val)
227 {
228 T2WriteByte(HighWram, addr & 0xFFFFF, val);
229 }
230
231 //////////////////////////////////////////////////////////////////////////////
232
HighWramMemoryWriteWord(u32 addr,u16 val)233 void FASTCALL HighWramMemoryWriteWord(u32 addr, u16 val)
234 {
235 T2WriteWord(HighWram, addr & 0xFFFFF, val);
236 }
237
238 //////////////////////////////////////////////////////////////////////////////
239
HighWramMemoryWriteLong(u32 addr,u32 val)240 void FASTCALL HighWramMemoryWriteLong(u32 addr, u32 val)
241 {
242 T2WriteLong(HighWram, addr & 0xFFFFF, val);
243 }
244
245 //////////////////////////////////////////////////////////////////////////////
246
LowWramMemoryReadByte(u32 addr)247 u8 FASTCALL LowWramMemoryReadByte(u32 addr)
248 {
249 return T2ReadByte(LowWram, addr & 0xFFFFF);
250 }
251
252 //////////////////////////////////////////////////////////////////////////////
253
LowWramMemoryReadWord(u32 addr)254 u16 FASTCALL LowWramMemoryReadWord(u32 addr)
255 {
256 return T2ReadWord(LowWram, addr & 0xFFFFF);
257 }
258
259 //////////////////////////////////////////////////////////////////////////////
260
LowWramMemoryReadLong(u32 addr)261 u32 FASTCALL LowWramMemoryReadLong(u32 addr)
262 {
263 return T2ReadLong(LowWram, addr & 0xFFFFF);
264 }
265
266 //////////////////////////////////////////////////////////////////////////////
267
LowWramMemoryWriteByte(u32 addr,u8 val)268 void FASTCALL LowWramMemoryWriteByte(u32 addr, u8 val)
269 {
270 T2WriteByte(LowWram, addr & 0xFFFFF, val);
271 }
272
273 //////////////////////////////////////////////////////////////////////////////
274
LowWramMemoryWriteWord(u32 addr,u16 val)275 void FASTCALL LowWramMemoryWriteWord(u32 addr, u16 val)
276 {
277 T2WriteWord(LowWram, addr & 0xFFFFF, val);
278 }
279
280 //////////////////////////////////////////////////////////////////////////////
281
LowWramMemoryWriteLong(u32 addr,u32 val)282 void FASTCALL LowWramMemoryWriteLong(u32 addr, u32 val)
283 {
284 T2WriteLong(LowWram, addr & 0xFFFFF, val);
285 }
286
287 //////////////////////////////////////////////////////////////////////////////
288
BiosRomMemoryReadByte(u32 addr)289 u8 FASTCALL BiosRomMemoryReadByte(u32 addr)
290 {
291 return T2ReadByte(BiosRom, addr & 0x7FFFF);
292 }
293
294 //////////////////////////////////////////////////////////////////////////////
295
BiosRomMemoryReadWord(u32 addr)296 u16 FASTCALL BiosRomMemoryReadWord(u32 addr)
297 {
298 return T2ReadWord(BiosRom, addr & 0x7FFFF);
299 }
300
301 //////////////////////////////////////////////////////////////////////////////
302
BiosRomMemoryReadLong(u32 addr)303 u32 FASTCALL BiosRomMemoryReadLong(u32 addr)
304 {
305 return T2ReadLong(BiosRom, addr & 0x7FFFF);
306 }
307
308 //////////////////////////////////////////////////////////////////////////////
309
BiosRomMemoryWriteByte(UNUSED u32 addr,UNUSED u8 val)310 void FASTCALL BiosRomMemoryWriteByte(UNUSED u32 addr, UNUSED u8 val)
311 {
312 // read-only
313 }
314
315 //////////////////////////////////////////////////////////////////////////////
316
BiosRomMemoryWriteWord(UNUSED u32 addr,UNUSED u16 val)317 void FASTCALL BiosRomMemoryWriteWord(UNUSED u32 addr, UNUSED u16 val)
318 {
319 // read-only
320 }
321
322 //////////////////////////////////////////////////////////////////////////////
323
BiosRomMemoryWriteLong(UNUSED u32 addr,UNUSED u32 val)324 void FASTCALL BiosRomMemoryWriteLong(UNUSED u32 addr, UNUSED u32 val)
325 {
326 // read-only
327 }
328
329 //////////////////////////////////////////////////////////////////////////////
330
BupRamMemoryReadByte(u32 addr)331 u8 FASTCALL BupRamMemoryReadByte(u32 addr)
332 {
333 return T1ReadByte(BupRam, addr & 0xFFFF);
334 }
335
336 //////////////////////////////////////////////////////////////////////////////
337
BupRamMemoryReadWord(USED_IF_DEBUG u32 addr)338 u16 FASTCALL BupRamMemoryReadWord(USED_IF_DEBUG u32 addr)
339 {
340 LOG("bup\t: BackupRam read word - %08X\n", addr);
341 return 0;
342 }
343
344 //////////////////////////////////////////////////////////////////////////////
345
BupRamMemoryReadLong(USED_IF_DEBUG u32 addr)346 u32 FASTCALL BupRamMemoryReadLong(USED_IF_DEBUG u32 addr)
347 {
348 LOG("bup\t: BackupRam read long - %08X\n", addr);
349 return 0;
350 }
351
352 //////////////////////////////////////////////////////////////////////////////
353
BupRamMemoryWriteByte(u32 addr,u8 val)354 void FASTCALL BupRamMemoryWriteByte(u32 addr, u8 val)
355 {
356 T1WriteByte(BupRam, (addr & 0xFFFF) | 0x1, val);
357 BupRamWritten = 1;
358 }
359
360 //////////////////////////////////////////////////////////////////////////////
361
BupRamMemoryWriteWord(USED_IF_DEBUG u32 addr,UNUSED u16 val)362 void FASTCALL BupRamMemoryWriteWord(USED_IF_DEBUG u32 addr, UNUSED u16 val)
363 {
364 LOG("bup\t: BackupRam write word - %08X\n", addr);
365 }
366
367 //////////////////////////////////////////////////////////////////////////////
368
BupRamMemoryWriteLong(USED_IF_DEBUG u32 addr,UNUSED u32 val)369 void FASTCALL BupRamMemoryWriteLong(USED_IF_DEBUG u32 addr, UNUSED u32 val)
370 {
371 LOG("bup\t: BackupRam write long - %08X\n", addr);
372 }
373
374 //////////////////////////////////////////////////////////////////////////////
375 //sh2 specific functions
376
Sh2UnhandledMemoryReadByte(UNUSED SH2_struct * sh,USED_IF_DEBUG u32 addr)377 static u8 FASTCALL Sh2UnhandledMemoryReadByte(UNUSED SH2_struct *sh, USED_IF_DEBUG u32 addr)
378 {
379 LOG("Unhandled byte read %08X\n", (unsigned int)addr);
380 return 0;
381 }
382
383 //////////////////////////////////////////////////////////////////////////////
384
Sh2UnhandledMemoryReadWord(UNUSED SH2_struct * sh,USED_IF_DEBUG u32 addr)385 static u16 FASTCALL Sh2UnhandledMemoryReadWord(UNUSED SH2_struct *sh, USED_IF_DEBUG u32 addr)
386 {
387 LOG("Unhandled word read %08X\n", (unsigned int)addr);
388 return 0;
389 }
390
391 //////////////////////////////////////////////////////////////////////////////
392
Sh2UnhandledMemoryReadLong(UNUSED SH2_struct * sh,USED_IF_DEBUG u32 addr)393 static u32 FASTCALL Sh2UnhandledMemoryReadLong(UNUSED SH2_struct *sh, USED_IF_DEBUG u32 addr)
394 {
395 LOG("Unhandled long read %08X\n", (unsigned int)addr);
396 return 0;
397 }
398
399 //////////////////////////////////////////////////////////////////////////////
400
Sh2UnhandledMemoryWriteByte(UNUSED SH2_struct * sh,USED_IF_DEBUG u32 addr,UNUSED u8 val)401 static void FASTCALL Sh2UnhandledMemoryWriteByte(UNUSED SH2_struct *sh, USED_IF_DEBUG u32 addr, UNUSED u8 val)
402 {
403 LOG("Unhandled byte write %08X\n", (unsigned int)addr);
404 }
405
406 //////////////////////////////////////////////////////////////////////////////
407
Sh2UnhandledMemoryWriteWord(UNUSED SH2_struct * sh,USED_IF_DEBUG u32 addr,UNUSED u16 val)408 static void FASTCALL Sh2UnhandledMemoryWriteWord(UNUSED SH2_struct *sh, USED_IF_DEBUG u32 addr, UNUSED u16 val)
409 {
410 LOG("Unhandled word write %08X\n", (unsigned int)addr);
411 }
412
413 //////////////////////////////////////////////////////////////////////////////
414
Sh2UnhandledMemoryWriteLong(UNUSED SH2_struct * sh,USED_IF_DEBUG u32 addr,UNUSED u32 val)415 static void FASTCALL Sh2UnhandledMemoryWriteLong(UNUSED SH2_struct *sh, USED_IF_DEBUG u32 addr, UNUSED u32 val)
416 {
417 LOG("Unhandled long write %08X\n", (unsigned int)addr);
418 }
419
420 //////////////////////////////////////////////////////////////////////////////
421
Sh2HighWramMemoryReadByte(SH2_struct * sh,u32 addr)422 static u8 FASTCALL Sh2HighWramMemoryReadByte(SH2_struct *sh, u32 addr)
423 {
424 return HighWramMemoryReadByte(addr);
425 }
426
427 //////////////////////////////////////////////////////////////////////////////
428
Sh2HighWramMemoryReadWord(SH2_struct * sh,u32 addr)429 static u16 FASTCALL Sh2HighWramMemoryReadWord(SH2_struct *sh, u32 addr)
430 {
431 return HighWramMemoryReadWord(addr);
432 }
433
434 //////////////////////////////////////////////////////////////////////////////
435
Sh2HighWramMemoryReadLong(SH2_struct * sh,u32 addr)436 static u32 FASTCALL Sh2HighWramMemoryReadLong(SH2_struct *sh, u32 addr)
437 {
438 return HighWramMemoryReadLong(addr);
439 }
440
441 //////////////////////////////////////////////////////////////////////////////
442
Sh2HighWramMemoryWriteByte(SH2_struct * sh,u32 addr,u8 val)443 static void FASTCALL Sh2HighWramMemoryWriteByte(SH2_struct *sh, u32 addr, u8 val)
444 {
445 HighWramMemoryWriteByte(addr, val);
446 }
447
448 //////////////////////////////////////////////////////////////////////////////
449
Sh2HighWramMemoryWriteWord(SH2_struct * sh,u32 addr,u16 val)450 static void FASTCALL Sh2HighWramMemoryWriteWord(SH2_struct *sh, u32 addr, u16 val)
451 {
452 HighWramMemoryWriteWord(addr, val);
453 }
454
455 //////////////////////////////////////////////////////////////////////////////
456
Sh2HighWramMemoryWriteLong(SH2_struct * sh,u32 addr,u32 val)457 static void FASTCALL Sh2HighWramMemoryWriteLong(SH2_struct *sh, u32 addr, u32 val)
458 {
459 HighWramMemoryWriteLong(addr, val);
460 }
461
462 //////////////////////////////////////////////////////////////////////////////
463
Sh2LowWramMemoryReadByte(SH2_struct * sh,u32 addr)464 static u8 FASTCALL Sh2LowWramMemoryReadByte(SH2_struct *sh, u32 addr)
465 {
466 return LowWramMemoryReadByte(addr);
467 }
468
469 //////////////////////////////////////////////////////////////////////////////
470
Sh2LowWramMemoryReadWord(SH2_struct * sh,u32 addr)471 static u16 FASTCALL Sh2LowWramMemoryReadWord(SH2_struct *sh, u32 addr)
472 {
473 return LowWramMemoryReadWord(addr);
474 }
475
476 //////////////////////////////////////////////////////////////////////////////
477
Sh2LowWramMemoryReadLong(SH2_struct * sh,u32 addr)478 static u32 FASTCALL Sh2LowWramMemoryReadLong(SH2_struct *sh, u32 addr)
479 {
480 return LowWramMemoryReadLong(addr);
481 }
482
483 //////////////////////////////////////////////////////////////////////////////
484
Sh2LowWramMemoryWriteByte(SH2_struct * sh,u32 addr,u8 val)485 static void FASTCALL Sh2LowWramMemoryWriteByte(SH2_struct *sh, u32 addr, u8 val)
486 {
487 LowWramMemoryWriteByte(addr, val);
488 }
489
490 //////////////////////////////////////////////////////////////////////////////
491
Sh2LowWramMemoryWriteWord(SH2_struct * sh,u32 addr,u16 val)492 static void FASTCALL Sh2LowWramMemoryWriteWord(SH2_struct *sh, u32 addr, u16 val)
493 {
494 LowWramMemoryWriteWord(addr, val);
495 }
496
497 //////////////////////////////////////////////////////////////////////////////
498
Sh2LowWramMemoryWriteLong(SH2_struct * sh,u32 addr,u32 val)499 static void FASTCALL Sh2LowWramMemoryWriteLong(SH2_struct *sh, u32 addr, u32 val)
500 {
501 LowWramMemoryWriteLong(addr, val);
502 }
503
504 //////////////////////////////////////////////////////////////////////////////
505
Sh2BiosRomMemoryReadByte(SH2_struct * sh,u32 addr)506 static u8 FASTCALL Sh2BiosRomMemoryReadByte(SH2_struct *sh, u32 addr)
507 {
508 return BiosRomMemoryReadByte(addr);
509 }
510
511 //////////////////////////////////////////////////////////////////////////////
512
Sh2BiosRomMemoryReadWord(SH2_struct * sh,u32 addr)513 static u16 FASTCALL Sh2BiosRomMemoryReadWord(SH2_struct *sh, u32 addr)
514 {
515 return BiosRomMemoryReadWord(addr);
516 }
517
518 //////////////////////////////////////////////////////////////////////////////
519
Sh2BiosRomMemoryReadLong(SH2_struct * sh,u32 addr)520 static u32 FASTCALL Sh2BiosRomMemoryReadLong(SH2_struct *sh, u32 addr)
521 {
522 return BiosRomMemoryReadLong(addr);
523 }
524
525 //////////////////////////////////////////////////////////////////////////////
526
Sh2BiosRomMemoryWriteByte(UNUSED SH2_struct * sh,UNUSED u32 addr,UNUSED u8 val)527 static void FASTCALL Sh2BiosRomMemoryWriteByte(UNUSED SH2_struct *sh, UNUSED u32 addr, UNUSED u8 val)
528 {
529 // read-only
530 }
531
532 //////////////////////////////////////////////////////////////////////////////
533
Sh2BiosRomMemoryWriteWord(UNUSED SH2_struct * sh,UNUSED u32 addr,UNUSED u16 val)534 static void FASTCALL Sh2BiosRomMemoryWriteWord(UNUSED SH2_struct *sh, UNUSED u32 addr, UNUSED u16 val)
535 {
536 // read-only
537 }
538
539 //////////////////////////////////////////////////////////////////////////////
540
Sh2BiosRomMemoryWriteLong(UNUSED SH2_struct * sh,UNUSED u32 addr,UNUSED u32 val)541 static void FASTCALL Sh2BiosRomMemoryWriteLong(UNUSED SH2_struct *sh, UNUSED u32 addr, UNUSED u32 val)
542 {
543 // read-only
544 }
545
546 //////////////////////////////////////////////////////////////////////////////
547
Sh2BupRamMemoryReadByte(SH2_struct * sh,u32 addr)548 static u8 FASTCALL Sh2BupRamMemoryReadByte(SH2_struct *sh, u32 addr)
549 {
550 return BupRamMemoryReadByte(addr);
551 }
552
553 //////////////////////////////////////////////////////////////////////////////
554
Sh2BupRamMemoryReadWord(UNUSED SH2_struct * sh,USED_IF_DEBUG u32 addr)555 static u16 FASTCALL Sh2BupRamMemoryReadWord(UNUSED SH2_struct *sh, USED_IF_DEBUG u32 addr)
556 {
557 return BupRamMemoryReadWord(addr);;
558 }
559
560 //////////////////////////////////////////////////////////////////////////////
561
Sh2BupRamMemoryReadLong(UNUSED SH2_struct * sh,USED_IF_DEBUG u32 addr)562 static u32 FASTCALL Sh2BupRamMemoryReadLong(UNUSED SH2_struct *sh, USED_IF_DEBUG u32 addr)
563 {
564 return BupRamMemoryReadLong(addr);
565 }
566
567 //////////////////////////////////////////////////////////////////////////////
568
Sh2BupRamMemoryWriteByte(SH2_struct * sh,u32 addr,u8 val)569 static void FASTCALL Sh2BupRamMemoryWriteByte(SH2_struct *sh, u32 addr, u8 val)
570 {
571 BupRamMemoryWriteByte(addr, val);
572 }
573
574 //////////////////////////////////////////////////////////////////////////////
575
Sh2BupRamMemoryWriteWord(UNUSED SH2_struct * sh,USED_IF_DEBUG u32 addr,UNUSED u16 val)576 static void FASTCALL Sh2BupRamMemoryWriteWord(UNUSED SH2_struct *sh, USED_IF_DEBUG u32 addr, UNUSED u16 val)
577 {
578 BupRamMemoryWriteWord(addr, val);
579 }
580
581 //////////////////////////////////////////////////////////////////////////////
582
Sh2BupRamMemoryWriteLong(UNUSED SH2_struct * sh,USED_IF_DEBUG u32 addr,UNUSED u32 val)583 static void FASTCALL Sh2BupRamMemoryWriteLong(UNUSED SH2_struct *sh, USED_IF_DEBUG u32 addr, UNUSED u32 val)
584 {
585 BupRamMemoryWriteLong(addr, val);
586 }
587
588 //////////////////////////////////////////////////////////////////////////////
589
FillMemoryArea(SH2_struct * sh,unsigned short start,unsigned short end,readbytefunc r8func,readwordfunc r16func,readlongfunc r32func,writebytefunc w8func,writewordfunc w16func,writelongfunc w32func)590 static void FillMemoryArea(SH2_struct *sh, unsigned short start, unsigned short end,
591 readbytefunc r8func, readwordfunc r16func,
592 readlongfunc r32func, writebytefunc w8func,
593 writewordfunc w16func, writelongfunc w32func)
594 {
595 int i;
596
597 for (i=start; i < (end+1); i++)
598 {
599 sh->ReadByteList[i] = r8func;
600 sh->ReadWordList[i] = r16func;
601 sh->ReadLongList[i] = r32func;
602 sh->WriteByteList[i] = w8func;
603 sh->WriteWordList[i] = w16func;
604 sh->WriteLongList[i] = w32func;
605 }
606 }
607
608 //////////////////////////////////////////////////////////////////////////////
609
MappedMemoryInit(SH2_struct * msh2,SH2_struct * ssh2,SH2_struct * sh1)610 void MappedMemoryInit(SH2_struct *msh2, SH2_struct *ssh2, SH2_struct *sh1)
611 {
612 SH2_struct *sh2[2] = { msh2, ssh2 };
613 int i;
614
615 // MSH2/SSH2
616 for (i = 0; i < 2; i++)
617 {
618 // Initialize everything to unhandled to begin with
619 FillMemoryArea(sh2[i], 0x000, 0xFFF, &Sh2UnhandledMemoryReadByte,
620 &Sh2UnhandledMemoryReadWord,
621 &Sh2UnhandledMemoryReadLong,
622 &Sh2UnhandledMemoryWriteByte,
623 &Sh2UnhandledMemoryWriteWord,
624 &Sh2UnhandledMemoryWriteLong);
625 // Fill the rest
626 FillMemoryArea(sh2[i], 0x000, 0x00F, &Sh2BiosRomMemoryReadByte,
627 &Sh2BiosRomMemoryReadWord,
628 &Sh2BiosRomMemoryReadLong,
629 &Sh2BiosRomMemoryWriteByte,
630 &Sh2BiosRomMemoryWriteWord,
631 &Sh2BiosRomMemoryWriteLong);
632 FillMemoryArea(sh2[i], 0x010, 0x017, &SmpcReadByte,
633 &SmpcReadWord,
634 &SmpcReadLong,
635 &SmpcWriteByte,
636 &SmpcWriteWord,
637 &SmpcWriteLong);
638 FillMemoryArea(sh2[i], 0x018, 0x01F, &Sh2BupRamMemoryReadByte,
639 &Sh2BupRamMemoryReadWord,
640 &Sh2BupRamMemoryReadLong,
641 &Sh2BupRamMemoryWriteByte,
642 &Sh2BupRamMemoryWriteWord,
643 &Sh2BupRamMemoryWriteLong);
644 FillMemoryArea(sh2[i], 0x020, 0x02F, &Sh2LowWramMemoryReadByte,
645 &Sh2LowWramMemoryReadWord,
646 &Sh2LowWramMemoryReadLong,
647 &Sh2LowWramMemoryWriteByte,
648 &Sh2LowWramMemoryWriteWord,
649 &Sh2LowWramMemoryWriteLong);
650 FillMemoryArea(sh2[i], 0x100, 0x17F, &Sh2UnhandledMemoryReadByte,
651 &Sh2UnhandledMemoryReadWord,
652 &Sh2UnhandledMemoryReadLong,
653 &Sh2UnhandledMemoryWriteByte,
654 &SSH2InputCaptureWriteWord,
655 &Sh2UnhandledMemoryWriteLong);
656 FillMemoryArea(sh2[i], 0x180, 0x1FF, &Sh2UnhandledMemoryReadByte,
657 &Sh2UnhandledMemoryReadWord,
658 &Sh2UnhandledMemoryReadLong,
659 &Sh2UnhandledMemoryWriteByte,
660 &MSH2InputCaptureWriteWord,
661 &Sh2UnhandledMemoryWriteLong);
662 FillMemoryArea(sh2[i], 0x200, 0x3FF, CartridgeArea->Cs0ReadByte,
663 CartridgeArea->Cs0ReadWord,
664 CartridgeArea->Cs0ReadLong,
665 CartridgeArea->Cs0WriteByte,
666 CartridgeArea->Cs0WriteWord,
667 CartridgeArea->Cs0WriteLong);
668 FillMemoryArea(sh2[i], 0x400, 0x4FF, &Cs1ReadByte,
669 &Cs1ReadWord,
670 &Cs1ReadLong,
671 &Cs1WriteByte,
672 &Cs1WriteWord,
673 &Cs1WriteLong);
674 if (yabsys.use_cd_block_lle)
675 {
676 FillMemoryArea(sh2[i], 0x580, 0x58F,
677 &Cs2ReadByte,
678 &sh2_ygr_a_bus_read_word,
679 &sh2_ygr_a_bus_read_long,
680 &Cs2WriteByte,
681 &sh2_ygr_a_bus_write_word,
682 &sh2_ygr_a_bus_write_long);
683 }
684 else
685 {
686 FillMemoryArea(sh2[i], 0x580, 0x58F,
687 &Cs2ReadByte,
688 &Cs2ReadWord,
689 &Cs2ReadLong,
690 &Cs2WriteByte,
691 &Cs2WriteWord,
692 &Cs2WriteLong);
693 }
694 FillMemoryArea(sh2[i], 0x5A0, 0x5AF, &Sh2SoundRamReadByte,
695 &Sh2SoundRamReadWord,
696 &Sh2SoundRamReadLong,
697 &Sh2SoundRamWriteByte,
698 &Sh2SoundRamWriteWord,
699 &Sh2SoundRamWriteLong);
700 FillMemoryArea(sh2[i], 0x5B0, 0x5BF, &Sh2ScspReadByte,
701 &Sh2ScspReadWord,
702 &Sh2ScspReadLong,
703 &Sh2ScspWriteByte,
704 &Sh2ScspWriteWord,
705 &Sh2ScspWriteLong);
706 FillMemoryArea(sh2[i], 0x5C0, 0x5C7, &Sh2Vdp1RamReadByte,
707 &Sh2Vdp1RamReadWord,
708 &Sh2Vdp1RamReadLong,
709 &Sh2Vdp1RamWriteByte,
710 &Sh2Vdp1RamWriteWord,
711 &Sh2Vdp1RamWriteLong);
712 FillMemoryArea(sh2[i], 0x5C8, 0x5CF, &Sh2Vdp1FrameBufferReadByte,
713 &Sh2Vdp1FrameBufferReadWord,
714 &Sh2Vdp1FrameBufferReadLong,
715 &Sh2Vdp1FrameBufferWriteByte,
716 &Sh2Vdp1FrameBufferWriteWord,
717 &Sh2Vdp1FrameBufferWriteLong);
718 FillMemoryArea(sh2[i], 0x5D0, 0x5D7, &Sh2Vdp1ReadByte,
719 &Sh2Vdp1ReadWord,
720 &Sh2Vdp1ReadLong,
721 &Sh2Vdp1WriteByte,
722 &Sh2Vdp1WriteWord,
723 &Sh2Vdp1WriteLong);
724 FillMemoryArea(sh2[i], 0x5E0, 0x5EF, &Sh2Vdp2RamReadByte,
725 &Sh2Vdp2RamReadWord,
726 &Sh2Vdp2RamReadLong,
727 &Sh2Vdp2RamWriteByte,
728 &Sh2Vdp2RamWriteWord,
729 &Sh2Vdp2RamWriteLong);
730 FillMemoryArea(sh2[i], 0x5F0, 0x5F7, &Sh2Vdp2ColorRamReadByte,
731 &Sh2Vdp2ColorRamReadWord,
732 &Sh2Vdp2ColorRamReadLong,
733 &Sh2Vdp2ColorRamWriteByte,
734 &Sh2Vdp2ColorRamWriteWord,
735 &Sh2Vdp2ColorRamWriteLong);
736 FillMemoryArea(sh2[i], 0x5F8, 0x5FB, &Sh2Vdp2ReadByte,
737 &Sh2Vdp2ReadWord,
738 &Sh2Vdp2ReadLong,
739 &Sh2Vdp2WriteByte,
740 &Sh2Vdp2WriteWord,
741 &Sh2Vdp2WriteLong);
742 FillMemoryArea(sh2[i], 0x5FE, 0x5FE, &Sh2ScuReadByte,
743 &Sh2ScuReadWord,
744 &Sh2ScuReadLong,
745 &Sh2ScuWriteByte,
746 &Sh2ScuWriteWord,
747 &Sh2ScuWriteLong);
748 FillMemoryArea(sh2[i], 0x600, 0x7FF, &Sh2HighWramMemoryReadByte,
749 &Sh2HighWramMemoryReadWord,
750 &Sh2HighWramMemoryReadLong,
751 &Sh2HighWramMemoryWriteByte,
752 &Sh2HighWramMemoryWriteWord,
753 &Sh2HighWramMemoryWriteLong);
754 }
755
756 if (yabsys.use_cd_block_lle)
757 {
758 // SH1
759 FillMemoryArea(sh1, 0x000, 0xFFF, &Sh2UnhandledMemoryReadByte,
760 &Sh2UnhandledMemoryReadWord,
761 &Sh2UnhandledMemoryReadLong,
762 &Sh2UnhandledMemoryWriteByte,
763 &Sh2UnhandledMemoryWriteWord,
764 &Sh2UnhandledMemoryWriteLong);
765 }
766 }
767
768 //////////////////////////////////////////////////////////////////////////////
769
MappedMemoryReadByteCacheEnabled(SH2_struct * sh,u32 addr)770 u8 FASTCALL MappedMemoryReadByteCacheEnabled(SH2_struct *sh, u32 addr) {
771 return cache_memory_read_b(sh, &sh->onchip.cache, addr);
772 }
773
MappedMemoryReadByteNocache(SH2_struct * sh,u32 addr)774 u8 FASTCALL MappedMemoryReadByteNocache(SH2_struct *sh, u32 addr)
775 {
776 switch (addr >> 29)
777 {
778 case 0x0:
779 case 0x1:
780 case 0x5:
781 {
782 // Cache/Non-Cached
783 return sh->ReadByteList[(addr >> 16) & 0xFFF](sh, addr);
784 }
785 /*
786 case 0x2:
787 {
788 // Purge Area
789 break;
790 }
791 */
792 case 0x4:
793 case 0x6:
794 // Data Array
795 return DataArrayReadByte(sh, addr);
796 case 0x7:
797 {
798 if (addr >= 0xFFFFFE00)
799 {
800 // Onchip modules
801 addr &= 0x1FF;
802 return OnchipReadByte(sh, addr);
803 }
804 else if (addr >= 0xFFFF8000 && addr < 0xFFFFC000)
805 {
806 // ???
807 }
808 else
809 {
810 // Garbage data
811 }
812 break;
813 }
814 default:
815 {
816 return Sh2UnhandledMemoryReadByte(sh, addr);
817 }
818 }
819
820 return 0;
821 }
822
823 //////////////////////////////////////////////////////////////////////////////
824
MappedMemoryReadWordCacheEnabled(SH2_struct * sh,u32 addr)825 u16 FASTCALL MappedMemoryReadWordCacheEnabled(SH2_struct *sh, u32 addr) {
826 return cache_memory_read_w(sh, &sh->onchip.cache, addr);
827 }
828
MappedMemoryReadWordNocache(SH2_struct * sh,u32 addr)829 u16 FASTCALL MappedMemoryReadWordNocache(SH2_struct *sh, u32 addr)
830 {
831 switch (addr >> 29)
832 {
833 case 0x0:
834 case 0x1:
835 case 0x5:
836 {
837 // Cache/Non-Cached
838 return sh->ReadWordList[(addr >> 16) & 0xFFF](sh, addr);
839 }
840 /*
841 case 0x2:
842 {
843 // Purge Area
844 break;
845 }
846 */
847 case 0x4:
848 case 0x6:
849 // Data Array
850 return DataArrayReadWord(sh, addr);
851 case 0x7:
852 {
853 if (addr >= 0xFFFFFE00)
854 {
855 // Onchip modules
856 addr &= 0x1FF;
857 return OnchipReadWord(sh, addr);
858 }
859 else if (addr >= 0xFFFF8000 && addr < 0xFFFFC000)
860 {
861 // ???
862 }
863 else
864 {
865 // Garbage data
866 }
867 break;
868 }
869 default:
870 {
871 return Sh2UnhandledMemoryReadWord(sh, addr);
872 }
873 }
874
875 return 0;
876 }
877
878 //////////////////////////////////////////////////////////////////////////////
879
MappedMemoryReadLongCacheEnabled(SH2_struct * sh,u32 addr)880 u32 FASTCALL MappedMemoryReadLongCacheEnabled(SH2_struct *sh, u32 addr) {
881 return cache_memory_read_l(sh, &sh->onchip.cache, addr);
882 }
883
MappedMemoryReadLongNocache(SH2_struct * sh,u32 addr)884 u32 FASTCALL MappedMemoryReadLongNocache(SH2_struct *sh, u32 addr)
885 {
886 switch (addr >> 29)
887 {
888 case 0x0:
889 case 0x1:
890 case 0x5:
891 {
892 // Cache/Non-Cached
893 return sh->ReadLongList[(addr >> 16) & 0xFFF](sh, addr);
894 }
895 /*
896 case 0x2:
897 {
898 // Purge Area
899 break;
900 }
901 */
902 case 0x3:
903 {
904 // Address Array
905 return AddressArrayReadLong(sh, addr);
906 }
907 case 0x4:
908 case 0x6:
909 // Data Array
910 return DataArrayReadLong(sh, addr);
911 case 0x7:
912 {
913 if (addr >= 0xFFFFFE00)
914 {
915 // Onchip modules
916 addr &= 0x1FF;
917 return OnchipReadLong(sh, addr);
918 }
919 else if (addr >= 0xFFFF8000 && addr < 0xFFFFC000)
920 {
921 // ???
922 }
923 else
924 {
925 // Garbage data
926 }
927 break;
928 }
929 default:
930 {
931 return Sh2UnhandledMemoryReadLong(sh, addr);
932 }
933 }
934 return 0;
935 }
936
937 //////////////////////////////////////////////////////////////////////////////
938
MappedMemoryWriteByteCacheEnabled(SH2_struct * sh,u32 addr,u8 val)939 void FASTCALL MappedMemoryWriteByteCacheEnabled(SH2_struct *sh, u32 addr, u8 val) {
940 #ifdef SH2_TRACE
941 sh2_trace_writeb(addr, val);
942 #endif
943 cache_memory_write_b(sh, &sh->onchip.cache, addr, val);
944 }
MappedMemoryWriteByteNocache(SH2_struct * sh,u32 addr,u8 val)945 void FASTCALL MappedMemoryWriteByteNocache(SH2_struct *sh, u32 addr, u8 val)
946 {
947 #ifdef SH2_TRACE
948 sh2_trace_writeb(addr, val);
949 #endif
950 switch (addr >> 29)
951 {
952 case 0x0:
953 case 0x1:
954 case 0x5:
955 {
956 // Cache/Non-Cached
957 sh->WriteByteList[(addr >> 16) & 0xFFF](sh, addr, val);
958 return;
959 }
960 /*
961 case 0x2:
962 {
963 // Purge Area
964 return;
965 }
966 */
967 case 0x4:
968 case 0x6:
969 // Data Array
970 DataArrayWriteByte(sh, addr, val);
971 return;
972 case 0x7:
973 {
974 if (addr >= 0xFFFFFE00)
975 {
976 // Onchip modules
977 addr &= 0x1FF;
978 OnchipWriteByte(sh, addr, val);
979 return;
980 }
981 else if (addr >= 0xFFFF8000 && addr < 0xFFFFC000)
982 {
983 // ???
984 }
985 else
986 {
987 // Garbage data
988 }
989 return;
990 }
991 default:
992 {
993 Sh2UnhandledMemoryWriteByte(sh, addr, val);
994 return;
995 }
996 }
997 }
998
999 //////////////////////////////////////////////////////////////////////////////
1000
MappedMemoryWriteWordCacheEnabled(SH2_struct * sh,u32 addr,u16 val)1001 void FASTCALL MappedMemoryWriteWordCacheEnabled(SH2_struct *sh, u32 addr, u16 val) {
1002 #ifdef SH2_TRACE
1003 sh2_trace_writew(addr, val);
1004 #endif
1005 cache_memory_write_w(sh, &sh->onchip.cache, addr, val);
1006 }
1007
MappedMemoryWriteWordNocache(SH2_struct * sh,u32 addr,u16 val)1008 void FASTCALL MappedMemoryWriteWordNocache(SH2_struct *sh, u32 addr, u16 val)
1009 {
1010 #ifdef SH2_TRACE
1011 sh2_trace_writew(addr, val);
1012 #endif
1013 switch (addr >> 29)
1014 {
1015 case 0x0:
1016 case 0x1:
1017 case 0x5:
1018 {
1019 // Cache/Non-Cached
1020 sh->WriteWordList[(addr >> 16) & 0xFFF](sh, addr, val);
1021 return;
1022 }
1023 /*
1024 case 0x2:
1025 {
1026 // Purge Area
1027 return;
1028 }
1029 */
1030 case 0x4:
1031 case 0x6:
1032 // Data Array
1033 DataArrayWriteWord(sh, addr, val);
1034 return;
1035 case 0x7:
1036 {
1037 if (addr >= 0xFFFFFE00)
1038 {
1039 // Onchip modules
1040 addr &= 0x1FF;
1041 OnchipWriteWord(sh, addr, val);
1042 return;
1043 }
1044 else if (addr >= 0xFFFF8000 && addr < 0xFFFFC000)
1045 {
1046 // ???
1047 }
1048 else
1049 {
1050 // Garbage data
1051 }
1052 return;
1053 }
1054 default:
1055 {
1056 Sh2UnhandledMemoryWriteWord(sh, addr, val);
1057 return;
1058 }
1059 }
1060 }
1061
1062 //////////////////////////////////////////////////////////////////////////////
1063
MappedMemoryWriteLongCacheEnabled(SH2_struct * sh,u32 addr,u32 val)1064 void FASTCALL MappedMemoryWriteLongCacheEnabled(SH2_struct *sh, u32 addr, u32 val) {
1065 #ifdef SH2_TRACE
1066 sh2_trace_writel(addr, val);
1067 #endif
1068 cache_memory_write_l(sh, &sh->onchip.cache, addr, val);
1069 }
1070
MappedMemoryWriteLongNocache(SH2_struct * sh,u32 addr,u32 val)1071 void FASTCALL MappedMemoryWriteLongNocache(SH2_struct *sh, u32 addr, u32 val)
1072 {
1073 #ifdef SH2_TRACE
1074 sh2_trace_writel(addr, val);
1075 #endif
1076 switch (addr >> 29)
1077 {
1078 case 0x0:
1079 case 0x1:
1080 case 0x5:
1081 {
1082 // Cache/Non-Cached
1083 sh->WriteLongList[(addr >> 16) & 0xFFF](sh, addr, val);
1084 return;
1085 }
1086 case 0x2:
1087 {
1088 // Purge Area
1089 return;
1090 }
1091 case 0x3:
1092 {
1093 // Address Array
1094 AddressArrayWriteLong(sh, addr, val);
1095 return;
1096 }
1097 case 0x4:
1098 case 0x6:
1099 // Data Array
1100 DataArrayWriteLong(sh, addr, val);
1101 return;
1102 case 0x7:
1103 {
1104 if (addr >= 0xFFFFFE00)
1105 {
1106 // Onchip modules
1107 addr &= 0x1FF;
1108 OnchipWriteLong(sh, addr, val);
1109 return;
1110 }
1111 else if (addr >= 0xFFFF8000 && addr < 0xFFFFC000)
1112 {
1113 // ???
1114 }
1115 else
1116 {
1117 // Garbage data
1118 }
1119 return;
1120 }
1121 default:
1122 {
1123 Sh2UnhandledMemoryWriteLong(sh, addr, val);
1124 return;
1125 }
1126 }
1127 }
1128
1129 //////////////////////////////////////////////////////////////////////////////
1130
MappedMemoryLoad(SH2_struct * sh,const char * filename,u32 addr)1131 int MappedMemoryLoad(SH2_struct *sh, const char *filename, u32 addr)
1132 {
1133 FILE *fp;
1134 long filesize;
1135 u8 *buffer;
1136 u32 i;
1137 size_t num_read = 0;
1138
1139 if (!filename)
1140 return -1;
1141
1142 if ((fp = fopen(filename, "rb")) == NULL)
1143 return -1;
1144
1145 // Calculate file size
1146 fseek(fp, 0, SEEK_END);
1147 filesize = ftell(fp);
1148
1149 if (filesize <= 0)
1150 {
1151 YabSetError(YAB_ERR_FILEREAD, filename);
1152 fclose(fp);
1153 return -1;//error
1154 }
1155
1156 fseek(fp, 0, SEEK_SET);
1157
1158 if ((buffer = (u8 *)malloc(filesize)) == NULL)
1159 {
1160 fclose(fp);
1161 return -2;
1162 }
1163
1164 num_read = fread((void *)buffer, 1, filesize, fp);
1165 fclose(fp);
1166
1167 for (i = 0; i < filesize; i++)
1168 MappedMemoryWriteByteNocache(sh, addr+i, buffer[i]);
1169
1170 free(buffer);
1171
1172 return 0;
1173 }
1174
1175 //////////////////////////////////////////////////////////////////////////////
1176
MappedMemorySave(SH2_struct * sh,const char * filename,u32 addr,u32 size)1177 int MappedMemorySave(SH2_struct *sh, const char *filename, u32 addr, u32 size)
1178 {
1179 FILE *fp;
1180 u8 *buffer;
1181 u32 i;
1182
1183 if (!filename)
1184 return -1;
1185
1186 if ((fp = fopen(filename, "wb")) == NULL)
1187 return -1;
1188
1189 if ((buffer = (u8 *)malloc(size)) == NULL)
1190 {
1191 fclose(fp);
1192 return -2;
1193 }
1194
1195 for (i = 0; i < size; i++)
1196 buffer[i] = MappedMemoryReadByteNocache(sh, addr+i);
1197
1198 fwrite((void *)buffer, 1, size, fp);
1199 fclose(fp);
1200 free(buffer);
1201
1202 return 0;
1203 }
1204
1205 //////////////////////////////////////////////////////////////////////////////
1206
MappedMemoryLoadExec(const char * filename,u32 pc)1207 void MappedMemoryLoadExec(const char *filename, u32 pc)
1208 {
1209 char *p;
1210 size_t i;
1211
1212 if ((p = strrchr(filename, '.')))
1213 {
1214 p = strdup(p);
1215 for (i = 0; i < strlen(p); i++)
1216 p[i] = toupper(p[i]);
1217 if (strcmp(p, ".COF") == 0 || strcmp(p, ".COFF") == 0)
1218 {
1219 MappedMemoryLoadCoff(filename);
1220 free(p);
1221 return;
1222 }
1223 else if(strcmp(p, ".ELF") == 0)
1224 {
1225 MappedMemoryLoadElf(filename);
1226 free(p);
1227 return;
1228 }
1229
1230 free(p);
1231 }
1232
1233 YabauseResetNoLoad();
1234
1235 // Setup the vector table area, etc.
1236 YabauseSpeedySetup();
1237
1238 MappedMemoryLoad(MSH2, filename, pc);
1239 SH2GetRegisters(MSH2, &MSH2->regs);
1240 MSH2->regs.PC = pc;
1241 SH2SetRegisters(MSH2, &MSH2->regs);
1242 }
1243
1244 //////////////////////////////////////////////////////////////////////////////
1245
LoadSH1Rom(const char * filename)1246 int LoadSH1Rom(const char *filename)
1247 {
1248 return T123Load(SH1Rom, 0x10000, 2, filename);
1249 }
1250
1251 //////////////////////////////////////////////////////////////////////////////
1252
LoadMpegRom(const char * filename)1253 int LoadMpegRom(const char *filename)
1254 {
1255 return T123Load(SH1MpegRom, 0x80000, 2, filename);
1256 }
1257
1258 //////////////////////////////////////////////////////////////////////////////
1259
LoadBios(const char * filename)1260 int LoadBios(const char *filename)
1261 {
1262 return T123Load(BiosRom, 0x80000, 2, filename);
1263 }
1264
1265 //////////////////////////////////////////////////////////////////////////////
1266
LoadBackupRam(const char * filename)1267 int LoadBackupRam(const char *filename)
1268 {
1269 return T123Load(BupRam, 0x10000, 1, filename);
1270 }
1271
1272 //////////////////////////////////////////////////////////////////////////////
1273
FormatBackupRam(void * mem,u32 size)1274 void FormatBackupRam(void *mem, u32 size)
1275 {
1276 int i, i2;
1277 u32 i3;
1278 u8 header[32] = {
1279 0xFF, 'B', 0xFF, 'a', 0xFF, 'c', 0xFF, 'k',
1280 0xFF, 'U', 0xFF, 'p', 0xFF, 'R', 0xFF, 'a',
1281 0xFF, 'm', 0xFF, ' ', 0xFF, 'F', 0xFF, 'o',
1282 0xFF, 'r', 0xFF, 'm', 0xFF, 'a', 0xFF, 't'
1283 };
1284
1285 // Fill in header
1286 for(i2 = 0; i2 < 4; i2++)
1287 for(i = 0; i < 32; i++)
1288 T1WriteByte(mem, (i2 * 32) + i, header[i]);
1289
1290 // Clear the rest
1291 for(i3 = 0x80; i3 < size; i3+=2)
1292 {
1293 T1WriteByte(mem, i3, 0xFF);
1294 T1WriteByte(mem, i3+1, 0x00);
1295 }
1296 }
1297
1298 //////////////////////////////////////////////////////////////////////////////
1299
YabSaveStateBuffer(void ** buffer,size_t * size)1300 int YabSaveStateBuffer(void ** buffer, size_t * size)
1301 {
1302 FILE * fp;
1303 int status;
1304 size_t num_read = 0;
1305
1306 if (buffer != NULL) *buffer = NULL;
1307 *size = 0;
1308
1309 fp = tmpfile();
1310
1311 status = YabSaveStateStream(fp);
1312 if (status != 0)
1313 {
1314 fclose(fp);
1315 return status;
1316 }
1317
1318 fseek(fp, 0, SEEK_END);
1319 *size = ftell(fp);
1320 fseek(fp, 0, SEEK_SET);
1321
1322 if (buffer != NULL)
1323 {
1324 *buffer = malloc(*size);
1325 num_read = fread(*buffer, 1, *size, fp);
1326 }
1327
1328 fclose(fp);
1329 return 0;
1330 }
1331
1332 //////////////////////////////////////////////////////////////////////////////
1333
YabSaveState(const char * filename)1334 int YabSaveState(const char *filename)
1335 {
1336 FILE *fp;
1337 int status;
1338
1339 //use a second set of savestates for movies
1340 filename = MakeMovieStateName(filename);
1341 if (!filename)
1342 return -1;
1343
1344 if ((fp = fopen(filename, "wb")) == NULL)
1345 return -1;
1346
1347 status = YabSaveStateStream(fp);
1348 fclose(fp);
1349
1350 return status;
1351 }
1352
1353 //////////////////////////////////////////////////////////////////////////////
1354
1355 // FIXME: Here's a (possibly incomplete) list of data that should be added
1356 // to the next version of the save state file:
1357 // yabsys.DecilineStop (new format)
1358 // yabsys.SH2CycleFrac (new field)
1359 // yabsys.DecilineUSed (new field)
1360 // yabsys.UsecFrac (new field)
1361 // [scsp2.c] It would be nice to redo the format entirely because so
1362 // many fields have changed format/size from the old scsp.c
1363 // [scsp2.c] scsp_clock, scsp_clock_frac, ScspState.sample_timer (timing)
1364 // [scsp2.c] cdda_buf, cdda_next_in, cdda_next_out (CDDA buffer)
1365 // [sh2core.c] frc.div changed to frc.shift
1366 // [sh2core.c] wdt probably needs to be written as well
1367
YabSaveStateStream(FILE * fp)1368 int YabSaveStateStream(FILE *fp)
1369 {
1370 u32 i;
1371 int offset;
1372 IOCheck_struct check;
1373 u8 *buf;
1374 int totalsize;
1375 int outputwidth;
1376 int outputheight;
1377 int movieposition;
1378 int temp;
1379 u32 temp32;
1380
1381 check.done = 0;
1382 check.size = 0;
1383
1384 // Write signature
1385 fprintf(fp, "YSS");
1386
1387 // Write endianness byte
1388 #ifdef WORDS_BIGENDIAN
1389 fputc(0x00, fp);
1390 #else
1391 fputc(0x01, fp);
1392 #endif
1393
1394 // Write version(fix me)
1395 i = 2;
1396 ywrite(&check, (void *)&i, sizeof(i), 1, fp);
1397
1398 // Skip the next 4 bytes for now
1399 i = 0;
1400 ywrite(&check, (void *)&i, sizeof(i), 1, fp);
1401
1402 //write frame number
1403 ywrite(&check, (void *)&framecounter, 4, 1, fp);
1404
1405 //this will be updated with the movie position later
1406 ywrite(&check, (void *)&framecounter, 4, 1, fp);
1407
1408 // Go through each area and write each state
1409 i += CartSaveState(fp);
1410 i += Cs2SaveState(fp);
1411 i += SH2SaveState(MSH2, fp);
1412 i += SH2SaveState(SSH2, fp);
1413 i += SoundSaveState(fp);
1414 i += ScuSaveState(fp);
1415 i += SmpcSaveState(fp);
1416 i += Vdp1SaveState(fp);
1417 i += Vdp2SaveState(fp);
1418
1419 offset = StateWriteHeader(fp, "OTHR", 1);
1420
1421 // Other data
1422 ywrite(&check, (void *)BupRam, 0x10000, 1, fp); // do we really want to save this?
1423 ywrite(&check, (void *)HighWram, 0x100000, 1, fp);
1424 ywrite(&check, (void *)LowWram, 0x100000, 1, fp);
1425
1426 ywrite(&check, (void *)&yabsys.DecilineCount, sizeof(int), 1, fp);
1427 ywrite(&check, (void *)&yabsys.LineCount, sizeof(int), 1, fp);
1428 ywrite(&check, (void *)&yabsys.VBlankLineCount, sizeof(int), 1, fp);
1429 ywrite(&check, (void *)&yabsys.MaxLineCount, sizeof(int), 1, fp);
1430 temp = yabsys.DecilineStop >> YABSYS_TIMING_BITS;
1431 ywrite(&check, (void *)&temp, sizeof(int), 1, fp);
1432 temp = (yabsys.CurSH2FreqType == CLKTYPE_26MHZ) ? 268 : 286;
1433 ywrite(&check, (void *)&temp, sizeof(int), 1, fp);
1434 temp32 = (yabsys.UsecFrac * temp / 10) >> YABSYS_TIMING_BITS;
1435 ywrite(&check, (void *)&temp32, sizeof(u32), 1, fp);
1436 ywrite(&check, (void *)&yabsys.CurSH2FreqType, sizeof(int), 1, fp);
1437 ywrite(&check, (void *)&yabsys.IsPal, sizeof(int), 1, fp);
1438
1439 VIDCore->GetGlSize(&outputwidth, &outputheight);
1440
1441 totalsize=outputwidth * outputheight * sizeof(u32);
1442
1443 if ((buf = (u8 *)malloc(totalsize)) == NULL)
1444 {
1445 return -2;
1446 }
1447
1448 YuiSwapBuffers();
1449 #ifdef USE_OPENGL
1450 glPixelZoom(1,1);
1451 glReadBuffer(GL_BACK);
1452 glReadPixels(0, 0, outputwidth, outputheight, GL_RGBA, GL_UNSIGNED_BYTE, buf);
1453 #else
1454 memcpy(buf, dispbuffer, totalsize);
1455 #endif
1456 YuiSwapBuffers();
1457
1458 ywrite(&check, (void *)&outputwidth, sizeof(outputwidth), 1, fp);
1459 ywrite(&check, (void *)&outputheight, sizeof(outputheight), 1, fp);
1460
1461 ywrite(&check, (void *)buf, totalsize, 1, fp);
1462
1463 movieposition=ftell(fp);
1464 //write the movie to the end of the savestate
1465 SaveMovieInState(fp, check);
1466
1467 i += StateFinishHeader(fp, offset);
1468
1469 // Go back and update size
1470 fseek(fp, 8, SEEK_SET);
1471 ywrite(&check, (void *)&i, sizeof(i), 1, fp);
1472 fseek(fp, 16, SEEK_SET);
1473 ywrite(&check, (void *)&movieposition, sizeof(movieposition), 1, fp);
1474
1475 free(buf);
1476
1477 OSDPushMessage(OSDMSG_STATUS, 150, "STATE SAVED");
1478
1479 return 0;
1480 }
1481
1482 //////////////////////////////////////////////////////////////////////////////
1483
YabLoadStateBuffer(const void * buffer,size_t size)1484 int YabLoadStateBuffer(const void * buffer, size_t size)
1485 {
1486 FILE * fp;
1487 int status;
1488
1489 fp = tmpfile();
1490 fwrite(buffer, 1, size, fp);
1491
1492 fseek(fp, 0, SEEK_SET);
1493
1494 status = YabLoadStateStream(fp);
1495 fclose(fp);
1496
1497 return status;
1498 }
1499
1500 //////////////////////////////////////////////////////////////////////////////
1501
YabLoadState(const char * filename)1502 int YabLoadState(const char *filename)
1503 {
1504 FILE *fp;
1505 int status;
1506
1507 filename = MakeMovieStateName(filename);
1508 if (!filename)
1509 return -1;
1510
1511 if ((fp = fopen(filename, "rb")) == NULL)
1512 return -1;
1513
1514 status = YabLoadStateStream(fp);
1515 fclose(fp);
1516
1517 return status;
1518 }
1519
1520 //////////////////////////////////////////////////////////////////////////////
1521
YabLoadStateStream(FILE * fp)1522 int YabLoadStateStream(FILE *fp)
1523 {
1524 char id[3];
1525 u8 endian;
1526 int headerversion, version, size, chunksize, headersize;
1527 IOCheck_struct check;
1528 u8* buf;
1529 int totalsize;
1530 int outputwidth;
1531 int outputheight;
1532 int curroutputwidth;
1533 int curroutputheight;
1534 int movieposition;
1535 int temp;
1536 u32 temp32;
1537 int test_endian;
1538
1539 headersize = 0xC;
1540 check.done = 0;
1541 check.size = 0;
1542
1543 // Read signature
1544 yread(&check, (void *)id, 1, 3, fp);
1545
1546 if (strncmp(id, "YSS", 3) != 0)
1547 {
1548 return -2;
1549 }
1550
1551 // Read header
1552 yread(&check, (void *)&endian, 1, 1, fp);
1553 yread(&check, (void *)&headerversion, 4, 1, fp);
1554 yread(&check, (void *)&size, 4, 1, fp);
1555 switch(headerversion)
1556 {
1557 case 1:
1558 /* This is the "original" version of the format */
1559 break;
1560 case 2:
1561 /* version 2 adds video recording */
1562 yread(&check, (void *)&framecounter, 4, 1, fp);
1563 movieposition=ftell(fp);
1564 yread(&check, (void *)&movieposition, 4, 1, fp);
1565 headersize = 0x14;
1566 break;
1567 default:
1568 /* we're trying to open a save state using a future version
1569 * of the YSS format, that won't work, sorry :) */
1570 return -3;
1571 break;
1572 }
1573
1574 #ifdef WORDS_BIGENDIAN
1575 test_endian = endian == 1;
1576 #else
1577 test_endian = endian == 0;
1578 #endif
1579 if (test_endian)
1580 {
1581 // should setup reading so it's byte-swapped
1582 YabSetError(YAB_ERR_OTHER, (void *)"Load State byteswapping not supported");
1583 return -3;
1584 }
1585
1586 // Make sure size variable matches actual size minus header
1587 fseek(fp, 0, SEEK_END);
1588
1589 if (size != (ftell(fp) - headersize))
1590 {
1591 return -2;
1592 }
1593 fseek(fp, headersize, SEEK_SET);
1594
1595 // Verify version here
1596
1597 ScspMuteAudio(SCSP_MUTE_SYSTEM);
1598
1599 if (StateCheckRetrieveHeader(fp, "CART", &version, &chunksize) != 0)
1600 {
1601 // Revert back to old state here
1602 ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
1603 return -3;
1604 }
1605 CartLoadState(fp, version, chunksize);
1606
1607 if (StateCheckRetrieveHeader(fp, "CS2 ", &version, &chunksize) != 0)
1608 {
1609 // Revert back to old state here
1610 ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
1611 return -3;
1612 }
1613 Cs2LoadState(fp, version, chunksize);
1614
1615 if (StateCheckRetrieveHeader(fp, "MSH2", &version, &chunksize) != 0)
1616 {
1617 // Revert back to old state here
1618 ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
1619 return -3;
1620 }
1621 SH2LoadState(MSH2, fp, version, chunksize);
1622
1623 if (StateCheckRetrieveHeader(fp, "SSH2", &version, &chunksize) != 0)
1624 {
1625 // Revert back to old state here
1626 ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
1627 return -3;
1628 }
1629 SH2LoadState(SSH2, fp, version, chunksize);
1630
1631 if (StateCheckRetrieveHeader(fp, "SCSP", &version, &chunksize) != 0)
1632 {
1633 // Revert back to old state here
1634 ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
1635 return -3;
1636 }
1637 SoundLoadState(fp, version, chunksize);
1638
1639 if (StateCheckRetrieveHeader(fp, "SCU ", &version, &chunksize) != 0)
1640 {
1641 // Revert back to old state here
1642 ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
1643 return -3;
1644 }
1645 ScuLoadState(fp, version, chunksize);
1646
1647 if (StateCheckRetrieveHeader(fp, "SMPC", &version, &chunksize) != 0)
1648 {
1649 // Revert back to old state here
1650 ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
1651 return -3;
1652 }
1653 SmpcLoadState(fp, version, chunksize);
1654
1655 if (StateCheckRetrieveHeader(fp, "VDP1", &version, &chunksize) != 0)
1656 {
1657 // Revert back to old state here
1658 ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
1659 return -3;
1660 }
1661 Vdp1LoadState(fp, version, chunksize);
1662
1663 if (StateCheckRetrieveHeader(fp, "VDP2", &version, &chunksize) != 0)
1664 {
1665 // Revert back to old state here
1666 ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
1667 return -3;
1668 }
1669 Vdp2LoadState(fp, version, chunksize);
1670
1671 if (StateCheckRetrieveHeader(fp, "OTHR", &version, &chunksize) != 0)
1672 {
1673 // Revert back to old state here
1674 ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
1675 return -3;
1676 }
1677 // Other data
1678 yread(&check, (void *)BupRam, 0x10000, 1, fp);
1679 yread(&check, (void *)HighWram, 0x100000, 1, fp);
1680 yread(&check, (void *)LowWram, 0x100000, 1, fp);
1681
1682 yread(&check, (void *)&yabsys.DecilineCount, sizeof(int), 1, fp);
1683 yread(&check, (void *)&yabsys.LineCount, sizeof(int), 1, fp);
1684 yread(&check, (void *)&yabsys.VBlankLineCount, sizeof(int), 1, fp);
1685 yread(&check, (void *)&yabsys.MaxLineCount, sizeof(int), 1, fp);
1686 yread(&check, (void *)&temp, sizeof(int), 1, fp);
1687 yread(&check, (void *)&temp, sizeof(int), 1, fp);
1688 yread(&check, (void *)&temp32, sizeof(u32), 1, fp);
1689 yread(&check, (void *)&yabsys.CurSH2FreqType, sizeof(int), 1, fp);
1690 yread(&check, (void *)&yabsys.IsPal, sizeof(int), 1, fp);
1691 YabauseChangeTiming(yabsys.CurSH2FreqType);
1692 yabsys.UsecFrac = (temp32 << YABSYS_TIMING_BITS) * temp / 10;
1693
1694 if (headerversion > 1) {
1695
1696 yread(&check, (void *)&outputwidth, sizeof(outputwidth), 1, fp);
1697 yread(&check, (void *)&outputheight, sizeof(outputheight), 1, fp);
1698
1699 totalsize=outputwidth * outputheight * sizeof(u32);
1700
1701 if ((buf = (u8 *)malloc(totalsize)) == NULL)
1702 {
1703 return -2;
1704 }
1705
1706 yread(&check, (void *)buf, totalsize, 1, fp);
1707
1708 YuiSwapBuffers();
1709
1710 #ifdef USE_OPENGL
1711 if(VIDCore->id == VIDCORE_SOFT)
1712 glRasterPos2i(0, outputheight);
1713 if(VIDCore->id == VIDCORE_OGL)
1714 glRasterPos2i(0, outputheight/2);
1715 #endif
1716
1717 VIDCore->GetGlSize(&curroutputwidth, &curroutputheight);
1718 #ifdef USE_OPENGL
1719 glPixelZoom((float)curroutputwidth / (float)outputwidth, ((float)curroutputheight / (float)outputheight));
1720 glDrawPixels(outputwidth, outputheight, GL_RGBA, GL_UNSIGNED_BYTE, buf);
1721 #endif
1722 YuiSwapBuffers();
1723 free(buf);
1724
1725 fseek(fp, movieposition, SEEK_SET);
1726 MovieReadState(fp);
1727 }
1728
1729 ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
1730
1731 OSDPushMessage(OSDMSG_STATUS, 150, "STATE LOADED");
1732
1733 return 0;
1734 }
1735
1736 //////////////////////////////////////////////////////////////////////////////
1737
YabSaveStateSlot(const char * dirpath,u8 slot)1738 int YabSaveStateSlot(const char *dirpath, u8 slot)
1739 {
1740 char filename[512];
1741
1742 if (cdip == NULL)
1743 return -1;
1744
1745 #ifdef WIN32
1746 sprintf(filename, "%s\\%s_%03d.yss", dirpath, cdip->itemnum, slot);
1747 #else
1748 sprintf(filename, "%s/%s_%03d.yss", dirpath, cdip->itemnum, slot);
1749 #endif
1750 return YabSaveState(filename);
1751 }
1752
1753 //////////////////////////////////////////////////////////////////////////////
1754
YabLoadStateSlot(const char * dirpath,u8 slot)1755 int YabLoadStateSlot(const char *dirpath, u8 slot)
1756 {
1757 char filename[512];
1758
1759 if (cdip == NULL)
1760 return -1;
1761
1762 #ifdef WIN32
1763 sprintf(filename, "%s\\%s_%03d.yss", dirpath, cdip->itemnum, slot);
1764 #else
1765 sprintf(filename, "%s/%s_%03d.yss", dirpath, cdip->itemnum, slot);
1766 #endif
1767 return YabLoadState(filename);
1768 }
1769
1770 //////////////////////////////////////////////////////////////////////////////
1771
MappedMemoryAddMatch(u32 addr,u32 val,int searchtype,result_struct * result,u32 * numresults)1772 static int MappedMemoryAddMatch(u32 addr, u32 val, int searchtype, result_struct *result, u32 *numresults)
1773 {
1774 result[numresults[0]].addr = addr;
1775 result[numresults[0]].val = val;
1776 numresults[0]++;
1777 return 0;
1778 }
1779
1780 //////////////////////////////////////////////////////////////////////////////
1781
SearchIncrementAndCheckBounds(result_struct * prevresults,u32 * maxresults,u32 numresults,u32 * i,u32 inc,u32 * newaddr,u32 endaddr)1782 static INLINE int SearchIncrementAndCheckBounds(result_struct *prevresults,
1783 u32 *maxresults,
1784 u32 numresults, u32 *i,
1785 u32 inc, u32 *newaddr,
1786 u32 endaddr)
1787 {
1788 if (prevresults)
1789 {
1790 if (i[0] >= maxresults[0])
1791 {
1792 maxresults[0] = numresults;
1793 return 1;
1794 }
1795 newaddr[0] = prevresults[i[0]].addr;
1796 i[0]++;
1797 }
1798 else
1799 {
1800 newaddr[0] = inc;
1801
1802 if (newaddr[0] > endaddr || numresults >= maxresults[0])
1803 {
1804 maxresults[0] = numresults;
1805 return 1;
1806 }
1807 }
1808
1809 return 0;
1810 }
1811
1812 //////////////////////////////////////////////////////////////////////////////
1813
SearchString(u32 startaddr,u32 endaddr,int searchtype,const char * searchstr,result_struct * results,u32 * maxresults)1814 static int SearchString(u32 startaddr, u32 endaddr, int searchtype,
1815 const char *searchstr, result_struct *results,
1816 u32 *maxresults)
1817 {
1818 u8 *buf=NULL;
1819 u32 *buf32=NULL;
1820 u32 buflen=0;
1821 u32 counter;
1822 u32 addr;
1823 u32 numresults=0;
1824
1825 buflen=(u32)strlen(searchstr);
1826
1827 if ((buf32=(u32 *)malloc(buflen*sizeof(u32))) == NULL)
1828 return 0;
1829
1830 buf = (u8 *)buf32;
1831
1832 // Copy string to buffer
1833 switch (searchtype & 0x70)
1834 {
1835 case SEARCHSTRING:
1836 strcpy((char *)buf, searchstr);
1837 break;
1838 case SEARCHREL8BIT:
1839 case SEARCHREL16BIT:
1840 {
1841 char *text;
1842 char *searchtext=strdup(searchstr);
1843
1844 // Calculate buffer length and read values into table
1845 buflen = 0;
1846 for (text=strtok((char *)searchtext, " ,"); text != NULL; text=strtok(NULL, " ,"))
1847 {
1848 buf32[buflen] = strtoul(text, NULL, 0);
1849 buflen++;
1850 }
1851 free(searchtext);
1852
1853 break;
1854 }
1855 }
1856
1857 addr = startaddr;
1858 counter = 0;
1859
1860 for (;;)
1861 {
1862 // Fetch byte/word/etc.
1863 switch (searchtype & 0x70)
1864 {
1865 case SEARCHSTRING:
1866 {
1867 u8 val = MappedMemoryReadByteNocache(MSH2, addr);
1868 addr++;
1869
1870 if (val == buf[counter])
1871 {
1872 counter++;
1873 if (counter == buflen)
1874 MappedMemoryAddMatch(addr-buflen, val, searchtype, results, &numresults);
1875 }
1876 else
1877 counter = 0;
1878 break;
1879 }
1880 case SEARCHREL8BIT:
1881 {
1882 int diff;
1883 u32 j;
1884 u8 val2;
1885 u8 val = MappedMemoryReadByteNocache(MSH2, addr);
1886
1887 for (j = 1; j < buflen; j++)
1888 {
1889 // grab the next value
1890 val2 = MappedMemoryReadByteNocache(MSH2, addr+j);
1891
1892 // figure out the diff
1893 diff = (int)val2 - (int)val;
1894
1895 // see if there's a match
1896 if (((int)buf32[j] - (int)buf32[j-1]) != diff)
1897 break;
1898
1899 if (j == (buflen - 1))
1900 MappedMemoryAddMatch(addr, val, searchtype, results, &numresults);
1901
1902 val = val2;
1903 }
1904
1905 addr++;
1906
1907 break;
1908 }
1909 case SEARCHREL16BIT:
1910 {
1911 int diff;
1912 u32 j;
1913 u16 val2;
1914 u16 val = MappedMemoryReadWordNocache(MSH2, addr);
1915
1916 for (j = 1; j < buflen; j++)
1917 {
1918 // grab the next value
1919 val2 = MappedMemoryReadWordNocache(MSH2, addr+(j*2));
1920
1921 // figure out the diff
1922 diff = (int)val2 - (int)val;
1923
1924 // see if there's a match
1925 if (((int)buf32[j] - (int)buf32[j-1]) != diff)
1926 break;
1927
1928 if (j == (buflen - 1))
1929 MappedMemoryAddMatch(addr, val, searchtype, results, &numresults);
1930
1931 val = val2;
1932 }
1933
1934 addr+=2;
1935 break;
1936 }
1937 }
1938
1939 if (addr > endaddr || numresults >= maxresults[0])
1940 break;
1941 }
1942
1943 free(buf);
1944 maxresults[0] = numresults;
1945 return 1;
1946 }
1947
1948 //////////////////////////////////////////////////////////////////////////////
1949
MappedMemorySearch(u32 startaddr,u32 endaddr,int searchtype,const char * searchstr,result_struct * prevresults,u32 * maxresults)1950 result_struct *MappedMemorySearch(u32 startaddr, u32 endaddr, int searchtype,
1951 const char *searchstr,
1952 result_struct *prevresults, u32 *maxresults)
1953 {
1954 u32 i=0;
1955 result_struct *results;
1956 u32 numresults=0;
1957 unsigned long searchval = 0;
1958 int issigned=0;
1959 u32 addr;
1960
1961 if ((results = (result_struct *)malloc(sizeof(result_struct) * maxresults[0])) == NULL)
1962 return NULL;
1963
1964 switch (searchtype & 0x70)
1965 {
1966 case SEARCHSTRING:
1967 case SEARCHREL8BIT:
1968 case SEARCHREL16BIT:
1969 {
1970 // String/8-bit relative/16-bit relative search(not supported, yet)
1971 if (SearchString(startaddr, endaddr, searchtype, searchstr,
1972 results, maxresults) == 0)
1973 {
1974 maxresults[0] = 0;
1975 free(results);
1976 return NULL;
1977 }
1978
1979 return results;
1980 }
1981 case SEARCHHEX:
1982 sscanf(searchstr, "%08lx", &searchval);
1983 break;
1984 case SEARCHUNSIGNED:
1985 searchval = (unsigned long)strtoul(searchstr, NULL, 10);
1986 issigned = 0;
1987 break;
1988 case SEARCHSIGNED:
1989 searchval = (unsigned long)strtol(searchstr, NULL, 10);
1990 issigned = 1;
1991 break;
1992 }
1993
1994 if (prevresults)
1995 {
1996 addr = prevresults[i].addr;
1997 i++;
1998 }
1999 else
2000 addr = startaddr;
2001
2002 // Regular value search
2003 for (;;)
2004 {
2005 u32 val=0;
2006 u32 newaddr;
2007
2008 // Fetch byte/word/etc.
2009 switch (searchtype & 0x3)
2010 {
2011 case SEARCHBYTE:
2012 val = MappedMemoryReadByteNocache(MSH2, addr);
2013 // sign extend if neccessary
2014 if (issigned)
2015 val = (s8)val;
2016
2017 if (SearchIncrementAndCheckBounds(prevresults, maxresults, numresults, &i, addr+1, &newaddr, endaddr))
2018 return results;
2019 break;
2020 case SEARCHWORD:
2021 val = MappedMemoryReadWordNocache(MSH2, addr);
2022 // sign extend if neccessary
2023 if (issigned)
2024 val = (s16)val;
2025
2026 if (SearchIncrementAndCheckBounds(prevresults, maxresults, numresults, &i, addr+2, &newaddr, endaddr))
2027 return results;
2028 break;
2029 case SEARCHLONG:
2030 val = MappedMemoryReadLongNocache(MSH2, addr);
2031
2032 if (SearchIncrementAndCheckBounds(prevresults, maxresults, numresults, &i, addr+4, &newaddr, endaddr))
2033 return results;
2034 break;
2035 default:
2036 maxresults[0] = 0;
2037 if (results)
2038 free(results);
2039 return NULL;
2040 }
2041
2042 // Do a comparison
2043 switch (searchtype & 0xC)
2044 {
2045 case SEARCHEXACT:
2046 if (val == searchval)
2047 MappedMemoryAddMatch(addr, val, searchtype, results, &numresults);
2048 break;
2049 case SEARCHLESSTHAN:
2050 if ((!issigned && val < searchval) || (issigned && (signed)val < (signed)searchval))
2051 MappedMemoryAddMatch(addr, val, searchtype, results, &numresults);
2052 break;
2053 case SEARCHGREATERTHAN:
2054 if ((!issigned && val > searchval) || (issigned && (signed)val > (signed)searchval))
2055 MappedMemoryAddMatch(addr, val, searchtype, results, &numresults);
2056 break;
2057 default:
2058 maxresults[0] = 0;
2059 if (results)
2060 free(results);
2061 return NULL;
2062 }
2063
2064 addr = newaddr;
2065 }
2066
2067 maxresults[0] = numresults;
2068 return results;
2069 }
2070