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