1 /* Mednafen - Multi-system Emulator
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18 #include "pcfx.h"
19
20 #include <string.h>
21 #include <trio/trio.h>
22 #include <stdarg.h>
23 #include <iconv.h>
24
25 #include "debug.h"
26 #include "v810/v810_cpuD.h"
27 #include "interrupt.h"
28 #include "timer.h"
29 #include "king.h"
30 #include "input.h"
31 #include "../cdrom/scsicd.h"
32
33 static void (*CPUHook)(uint32, bool bpoint) = NULL;
34 static bool CPUHookContinuous = false;
35 static void (*LogFunc)(const char *, const char *);
36 static iconv_t sjis_ict = (iconv_t)-1;
37 bool PCFX_LoggingOn = FALSE;
38
39 typedef struct __PCFX_BPOINT {
40 uint32 A[2];
41 int type;
42 bool logical;
43 } PCFX_BPOINT;
44
45 static std::vector<PCFX_BPOINT> BreakPointsPC, BreakPointsRead, BreakPointsWrite, BreakPointsIORead, BreakPointsIOWrite;
46 static std::vector<PCFX_BPOINT> BreakPointsAux0Read, BreakPointsAux0Write;
47 static bool FoundBPoint = 0;
48
49 struct BTEntry
50 {
51 uint32 from;
52 uint32 to;
53 uint32 branch_count;
54 uint32 ecode;
55 };
56
57 #define NUMBT 24
58 static bool BTEnabled = false;
59 static BTEntry BTEntries[NUMBT];
60 static int BTIndex = 0;
61
AddBranchTrace(uint32 from,uint32 to,uint32 ecode)62 static void AddBranchTrace(uint32 from, uint32 to, uint32 ecode)
63 {
64 BTEntry *prevbt = &BTEntries[(BTIndex + NUMBT - 1) % NUMBT];
65
66 //if(BTEntries[(BTIndex - 1) & 0xF] == PC) return;
67
68 if(prevbt->from == from && prevbt->to == to && prevbt->ecode == ecode && prevbt->branch_count < 0xFFFFFFFF)
69 prevbt->branch_count++;
70 else
71 {
72 BTEntries[BTIndex].from = from;
73 BTEntries[BTIndex].to = to;
74 BTEntries[BTIndex].ecode = ecode;
75 BTEntries[BTIndex].branch_count = 1;
76
77 BTIndex = (BTIndex + 1) % NUMBT;
78 }
79 }
80
PCFXDBG_EnableBranchTrace(bool enable)81 void PCFXDBG_EnableBranchTrace(bool enable)
82 {
83 BTEnabled = enable;
84 if(!enable)
85 {
86 BTIndex = 0;
87 memset(BTEntries, 0, sizeof(BTEntries));
88 }
89 }
90
PCFXDBG_GetBranchTrace(void)91 std::vector<BranchTraceResult> PCFXDBG_GetBranchTrace(void)
92 {
93 BranchTraceResult tmp;
94 std::vector<BranchTraceResult> ret;
95
96 for(int x = 0; x < NUMBT; x++)
97 {
98 const BTEntry *bt = &BTEntries[(x + BTIndex) % NUMBT];
99
100 tmp.count = bt->branch_count;
101 trio_snprintf(tmp.from, sizeof(tmp.from), "%08x", bt->from);
102 trio_snprintf(tmp.to, sizeof(tmp.to), "%08x", bt->to);
103
104 tmp.code[0] = 0;
105
106 switch(bt->ecode)
107 {
108 case 0: break;
109 default: trio_snprintf(tmp.code, sizeof(tmp.code), "e");
110 break;
111
112 case 0xFFF0: // Reset
113 trio_snprintf(tmp.code, sizeof(tmp.code), "R");
114 break;
115
116 case 0xFFD0: // NMI
117 trio_snprintf(tmp.code, sizeof(tmp.code), "NMI");
118 break;
119
120 case 0xFFC0: // Address trap
121 trio_snprintf(tmp.code, sizeof(tmp.code), "ADTR");
122 break;
123
124 case 0xFFA0 ... 0xFFBF: // TRAP
125 trio_snprintf(tmp.code, sizeof(tmp.code), "TRAP");
126 break;
127
128 case 0xFF90: // Illegal/invalid instruction code
129 trio_snprintf(tmp.code, sizeof(tmp.code), "ILL");
130 break;
131
132 case 0xFF80: // Zero division
133 trio_snprintf(tmp.code, sizeof(tmp.code), "ZD");
134 break;
135
136 case 0xFF70:
137 trio_snprintf(tmp.code, sizeof(tmp.code), "FIV"); // FIV
138 break;
139
140 case 0xFF68:
141 trio_snprintf(tmp.code, sizeof(tmp.code), "FZD"); // FZD
142 break;
143
144 case 0xFF64:
145 trio_snprintf(tmp.code, sizeof(tmp.code), "FOV"); // FOV
146 break;
147
148 case 0xFF62:
149 trio_snprintf(tmp.code, sizeof(tmp.code), "FUD"); // FUD
150 break;
151
152 case 0xFF61:
153 trio_snprintf(tmp.code, sizeof(tmp.code), "FPR"); // FPR
154 break;
155
156 case 0xFF60:
157 trio_snprintf(tmp.code, sizeof(tmp.code), "FRO"); // FRO
158 break;
159
160 case 0xFE00 ... 0xFEFF:
161 trio_snprintf(tmp.code, sizeof(tmp.code), "INT%d", (bt->ecode >> 4) & 0xF);
162 break;
163 }
164
165 ret.push_back(tmp);
166 }
167 return(ret);
168 }
169
PCFXDBG_CheckBP(int type,uint32 address,uint32 value,unsigned int len)170 void PCFXDBG_CheckBP(int type, uint32 address, uint32 value, unsigned int len)
171 {
172 std::vector<PCFX_BPOINT>::iterator bpit, bpit_end;
173
174 if(type == BPOINT_READ)
175 {
176 bpit = BreakPointsRead.begin();
177 bpit_end = BreakPointsRead.end();
178
179 if(MDFN_UNLIKELY(address >= 0xA4000000 && address <= 0xABFFFFFF))
180 {
181 VDC_SimulateResult result;
182 unsigned which_vdc = (bool)(address & 0x8000000);
183
184 fx_vdc_chips[which_vdc]->SimulateRead16(1, &result);
185
186 if(result.ReadCount)
187 PCFXDBG_CheckBP(BPOINT_AUX_READ, 0x80000 | (which_vdc << 16) | result.ReadStart, 0, result.ReadCount);
188
189 if(result.WriteCount)
190 PCFXDBG_CheckBP(BPOINT_AUX_WRITE, 0x80000 | (which_vdc << 16) | result.WriteStart, 0/*FIXME(HOW? :b)*/, result.WriteCount);
191 }
192 }
193 else if(type == BPOINT_WRITE)
194 {
195 bpit = BreakPointsWrite.begin();
196 bpit_end = BreakPointsWrite.end();
197
198 if(MDFN_UNLIKELY(address >= 0xB4000000 && address <= 0xBBFFFFFF))
199 {
200 VDC_SimulateResult result;
201 unsigned which_vdc = (bool)(address & 0x8000000);
202
203 fx_vdc_chips[which_vdc]->SimulateWrite16(1, value, &result);
204
205 if(result.ReadCount)
206 PCFXDBG_CheckBP(BPOINT_AUX_READ, 0x80000 | (which_vdc << 16) | result.ReadStart, 0, result.ReadCount);
207
208 if(result.WriteCount)
209 PCFXDBG_CheckBP(BPOINT_AUX_WRITE, 0x80000 | (which_vdc << 16) | result.WriteStart, 0/*FIXME(HOW? :b)*/, result.WriteCount);
210 }
211 }
212 else if(type == BPOINT_IO_READ)
213 {
214 bpit = BreakPointsIORead.begin();
215 bpit_end = BreakPointsIORead.end();
216
217 if(address >= 0x400 && address <= 0x5FF)
218 {
219 VDC_SimulateResult result;
220 unsigned which_vdc = (bool)(address & 0x100);
221
222 fx_vdc_chips[which_vdc]->SimulateRead16((bool)(address & 4), &result);
223
224 if(result.ReadCount)
225 PCFXDBG_CheckBP(BPOINT_AUX_READ, 0x80000 | (which_vdc << 16) | result.ReadStart, 0, result.ReadCount);
226
227 if(result.WriteCount)
228 PCFXDBG_CheckBP(BPOINT_AUX_WRITE, 0x80000 | (which_vdc << 16) | result.WriteStart, 0/*FIXME(HOW? :b)*/, result.WriteCount);
229 }
230 }
231 else if(type == BPOINT_IO_WRITE)
232 {
233 bpit = BreakPointsIOWrite.begin();
234 bpit_end = BreakPointsIOWrite.end();
235
236 if(address >= 0x400 && address <= 0x5FF)
237 {
238 VDC_SimulateResult result;
239 unsigned which_vdc = (bool)(address & 0x100);
240
241 fx_vdc_chips[which_vdc]->SimulateWrite16((bool)(address & 4), value, &result);
242
243 if(result.ReadCount)
244 PCFXDBG_CheckBP(BPOINT_AUX_READ, 0x80000 | (which_vdc << 16) | result.ReadStart, 0, result.ReadCount);
245
246 if(result.WriteCount)
247 PCFXDBG_CheckBP(BPOINT_AUX_WRITE, 0x80000 | (which_vdc << 16) | result.WriteStart, 0/*FIXME(HOW? :b)*/, result.WriteCount);
248 }
249 }
250 else if(type == BPOINT_AUX_READ)
251 {
252 bpit = BreakPointsAux0Read.begin();
253 bpit_end = BreakPointsAux0Read.end();
254 }
255 else if(type == BPOINT_AUX_WRITE)
256 {
257 bpit = BreakPointsAux0Write.begin();
258 bpit_end = BreakPointsAux0Write.end();
259 }
260 else
261 return;
262
263 for(; bpit != bpit_end; bpit++)
264 {
265 uint32 tmp_address = address;
266 uint32 tmp_len = len;
267
268 while(tmp_len--)
269 {
270 if(tmp_address >= bpit->A[0] && tmp_address <= bpit->A[1])
271 {
272 FoundBPoint = TRUE;
273 break;
274 }
275 tmp_address++;
276 }
277 }
278 }
279
280 enum
281 {
282 SVT_NONE = 0,
283 SVT_PTR,
284 SVT_STRINGPTR,
285 SVT_INT,
286 SVT_UCHAR,
287 SVT_LONG,
288 SVT_ULONG,
289 };
290
291 typedef struct
292 {
293 unsigned int number;
294 const char *name;
295 int arguments;
296 int argument_types[16];
297 } syscall_t;
298
299 static const syscall_t SysDefs[] =
300 {
301 { 0, "fsys_init", 3, { SVT_PTR, SVT_PTR, SVT_PTR} },
302 { 1, "fsys_mount", 2, { SVT_PTR, SVT_PTR } },
303 { 2, "fsys_ctrl", 4, { SVT_STRINGPTR, SVT_INT, SVT_PTR, SVT_INT } },
304 { 3, "fsys_getfsys", 1, { SVT_PTR } },
305 { 4, "fsys_format", 2, { SVT_PTR, SVT_PTR } },
306 { 5, "fsys_diskfree", 1, { SVT_STRINGPTR } },
307 { 6, "fsys_getblocks", 1, { SVT_PTR } },
308 { 7, "fsys_open", 2, { SVT_STRINGPTR, SVT_INT } },
309 { 8, "fsys_read", 3, { SVT_INT, SVT_PTR, SVT_INT } },
310 { 9, "fsys_write", 3, { SVT_INT, SVT_PTR, SVT_INT } },
311 { 10, "fsys_seek", 3, { SVT_INT, SVT_LONG, SVT_INT } },
312 { 11, "fsys_htime", 2, { SVT_INT, SVT_LONG} },
313 { 12, "fsys_close", 1, { SVT_INT } },
314 { 13, "fsys_delete", 1, { SVT_STRINGPTR } },
315 { 14, "fsys_rename", 2, { SVT_STRINGPTR } },
316 { 15, "fsys_mkdir", 1, { SVT_STRINGPTR } },
317 { 16, "fsys_rmdir", 1, { SVT_STRINGPTR } },
318 { 17, "fsys_chdir", 1, { SVT_STRINGPTR } },
319 { 18, "fsys_curdir", 1, { SVT_PTR } },
320 { 19, "fsys_ffiles", 2, { SVT_PTR, SVT_PTR } },
321 { 20, "fsys_nfiles", 1, { SVT_PTR } },
322 { 21, "fsys_efiles", 1, { SVT_PTR } },
323 { 22, "fsys_datetime", 1, { SVT_ULONG } },
324 { 23, "fsys_m_init", 2, { SVT_PTR, SVT_PTR } },
325 { 24, "fsys_malloc", 1, { SVT_INT } },
326 { 25, "fsys_free", 1, { SVT_INT } },
327 { 26, "fsys_setblock", 2, { SVT_PTR, SVT_INT } },
328 };
329
DoSyscallLog(void)330 static void DoSyscallLog(void)
331 {
332 uint32 ws = 0;
333 unsigned int which = 0;
334 unsigned int nargs = 0;
335 const char *func_name = "<unknown>";
336 char argsbuffer[2048];
337
338 for(unsigned int i = 0; i < sizeof(SysDefs) / sizeof(syscall_t); i++)
339 {
340 if(SysDefs[i].number == PCFX_V810.GetPR(10))
341 {
342 nargs = SysDefs[i].arguments;
343 func_name = SysDefs[i].name;
344 which = i;
345 break;
346 }
347 }
348
349 {
350 char *pos = argsbuffer;
351
352 argsbuffer[0] = 0;
353
354 pos += trio_sprintf(pos, "(");
355 for(unsigned int i = 0; i < nargs; i++)
356 {
357 if(SysDefs[which].argument_types[i] == SVT_STRINGPTR)
358 {
359 uint8 quickiebuf[64 + 1];
360 int qbuf_index = 0;
361 bool error_thing = FALSE;
362
363 do
364 {
365 uint32 A = PCFX_V810.GetPR(6 + i) + qbuf_index;
366
367 quickiebuf[qbuf_index] = 0;
368
369 if(A >= 0x80000000 && A < 0xF0000000)
370 {
371 error_thing = TRUE;
372 break;
373 }
374
375 quickiebuf[qbuf_index] = mem_peekbyte(ws, A);
376 } while(quickiebuf[qbuf_index] && ++qbuf_index < 64);
377
378 if(qbuf_index == 64)
379 error_thing = TRUE;
380
381 quickiebuf[64] = 0;
382
383 if(error_thing)
384 pos += trio_sprintf(pos, "0x%08x, ", PCFX_V810.GetPR(6 + i));
385 else
386 {
387 uint8 quickiebuf_utf8[64 * 6 + 1];
388 char *in_ptr, *out_ptr;
389 size_t ibl, obl;
390
391 ibl = qbuf_index;
392 obl = sizeof(quickiebuf_utf8) - 1;
393
394 in_ptr = (char *)quickiebuf;
395 out_ptr = (char *)quickiebuf_utf8;
396
397 if(iconv(sjis_ict, (ICONV_CONST char **)&in_ptr, &ibl, &out_ptr, &obl) == (size_t) -1)
398 {
399 pos += trio_sprintf(pos, "0x%08x, ", PCFX_V810.GetPR(6 + i));
400 }
401 else
402 {
403 *out_ptr = 0;
404 pos += trio_sprintf(pos, "@0x%08x=\"%s\", ", PCFX_V810.GetPR(6 + i), quickiebuf_utf8);
405 }
406 }
407 }
408 else
409 pos += trio_sprintf(pos, "0x%08x, ", PCFX_V810.GetPR(6 + i));
410 }
411
412 // Get rid of the trailing comma and space
413 if(nargs)
414 pos-=2;
415
416 trio_sprintf(pos, ");");
417 }
418
419 PCFXDBG_DoLog("SYSCALL", "0x%02x, %s: %s", PCFX_V810.GetPR(10), func_name, argsbuffer);
420 }
421
CPUHandler(const v810_timestamp_t timestamp,uint32 PC)422 static void CPUHandler(const v810_timestamp_t timestamp, uint32 PC)
423 {
424 std::vector<PCFX_BPOINT>::iterator bpit;
425
426 for(bpit = BreakPointsPC.begin(); bpit != BreakPointsPC.end(); bpit++)
427 {
428 if(PC >= bpit->A[0] && PC <= bpit->A[1])
429 {
430 FoundBPoint = TRUE;
431 break;
432 }
433 }
434
435 fx_vdc_chips[0]->ResetSimulate();
436 fx_vdc_chips[1]->ResetSimulate();
437
438 PCFX_V810.CheckBreakpoints(PCFXDBG_CheckBP, mem_peekhword, NULL); // FIXME: mem_peekword
439
440 if(PCFX_LoggingOn)
441 {
442 // FIXME: There is a little race condition if a user turns on logging right between jump instruction and the first
443 // instruction at 0xFFF0000C, in which case the call-from address will be wrong.
444 static uint32 lastPC = ~0;
445
446 if(PC == 0xFFF0000C)
447 {
448 static const char *font_sizes[6] =
449 {
450 "KANJI16x16", "KANJI12x12", "ANK8x16", "ANK6x12", "ANK8x8", "ANK8x12"
451 };
452
453 // FIXME, overflow possible and speed
454 PCFXDBG_DoLog("ROMFONT", "0x%08x->0xFFF0000C, PR7=0x%08x=%s, PR6=0x%04x = %s", lastPC, PCFX_V810.GetPR(7), (PCFX_V810.GetPR(7) > 5) ? "?" : font_sizes[PCFX_V810.GetPR(7)], PCFX_V810.GetPR(6) & 0xFFFF, PCFXDBG_ShiftJIS_to_UTF8(PCFX_V810.GetPR(6) & 0xFFFF));
455 setvbuf(stdout, NULL, _IONBF, 0);
456 printf("%s", PCFXDBG_ShiftJIS_to_UTF8(PCFX_V810.GetPR(6) & 0xFFFF));
457 }
458 else if(PC == 0xFFF00008)
459 DoSyscallLog();
460
461 lastPC = PC;
462 }
463
464 CPUHookContinuous |= FoundBPoint;
465
466 if(CPUHookContinuous && CPUHook)
467 {
468 ForceEventUpdates(timestamp);
469 CPUHook(PC, FoundBPoint);
470 }
471
472 FoundBPoint = false;
473 }
474
RedoCPUHook(void)475 static void RedoCPUHook(void)
476 {
477 bool HappyTest;
478
479 HappyTest = CPUHook || PCFX_LoggingOn || BreakPointsPC.size() || BreakPointsRead.size() || BreakPointsWrite.size() ||
480 BreakPointsIOWrite.size() || BreakPointsIORead.size() || BreakPointsAux0Read.size() || BreakPointsAux0Write.size();
481
482 PCFX_V810.SetCPUHook(HappyTest ? CPUHandler : NULL, BTEnabled ? AddBranchTrace : NULL);
483 }
484
PCFXDBG_FlushBreakPoints(int type)485 void PCFXDBG_FlushBreakPoints(int type)
486 {
487 std::vector<PCFX_BPOINT>::iterator bpit;
488
489 if(type == BPOINT_READ)
490 BreakPointsRead.clear();
491 else if(type == BPOINT_WRITE)
492 BreakPointsWrite.clear();
493 else if(type == BPOINT_IO_READ)
494 BreakPointsIORead.clear();
495 else if(type == BPOINT_IO_WRITE)
496 BreakPointsIOWrite.clear();
497 else if(type == BPOINT_AUX_READ)
498 BreakPointsAux0Read.clear();
499 else if(type == BPOINT_AUX_WRITE)
500 BreakPointsAux0Write.clear();
501 else if(type == BPOINT_PC)
502 BreakPointsPC.clear();
503
504 RedoCPUHook();
505 KING_NotifyOfBPE(BreakPointsAux0Read.size(), BreakPointsAux0Write.size());
506 }
507
PCFXDBG_AddBreakPoint(int type,unsigned int A1,unsigned int A2,bool logical)508 void PCFXDBG_AddBreakPoint(int type, unsigned int A1, unsigned int A2, bool logical)
509 {
510 PCFX_BPOINT tmp;
511
512 tmp.A[0] = A1;
513 tmp.A[1] = A2;
514 tmp.type = type;
515
516 if(type == BPOINT_READ)
517 BreakPointsRead.push_back(tmp);
518 else if(type == BPOINT_WRITE)
519 BreakPointsWrite.push_back(tmp);
520 else if(type == BPOINT_IO_READ)
521 BreakPointsIORead.push_back(tmp);
522 else if(type == BPOINT_IO_WRITE)
523 BreakPointsIOWrite.push_back(tmp);
524 else if(type == BPOINT_AUX_READ)
525 BreakPointsAux0Read.push_back(tmp);
526 else if(type == BPOINT_AUX_WRITE)
527 BreakPointsAux0Write.push_back(tmp);
528 else if(type == BPOINT_PC)
529 BreakPointsPC.push_back(tmp);
530
531 RedoCPUHook();
532 KING_NotifyOfBPE(BreakPointsAux0Read.size(), BreakPointsAux0Write.size());
533 }
534
dis_readhw(uint32 A)535 static uint16 dis_readhw(uint32 A)
536 {
537 return(mem_peekhword(0, A));
538 }
539
PCFXDBG_Disassemble(uint32 & a,uint32 SpecialA,char * TextBuf)540 void PCFXDBG_Disassemble(uint32 &a, uint32 SpecialA, char *TextBuf)
541 {
542 return(v810_dis(a, 1, TextBuf, dis_readhw));
543 }
544
PCFXDBG_MemPeek(uint32 A,unsigned int bsize,bool hl,bool logical)545 uint32 PCFXDBG_MemPeek(uint32 A, unsigned int bsize, bool hl, bool logical)
546 {
547 uint32 ret = 0;
548 uint32 ws = 0;
549
550 for(unsigned int i = 0; i < bsize; i++)
551 {
552 A &= 0xFFFFFFFF;
553 ret |= mem_peekbyte(ws, A) << (i * 8);
554 A++;
555 }
556
557 return(ret);
558 }
559
PCFXDBG_GetRegister(const std::string & name,std::string * special)560 uint32 PCFXDBG_GetRegister(const std::string &name, std::string *special)
561 {
562 if(name == "PC")
563 {
564 return(PCFX_V810.GetPC());
565 }
566 const char *thestring = name.c_str();
567
568 if(!strncmp(thestring, "PR", 2))
569 {
570 return(PCFX_V810.GetPR(atoi(thestring + 2)));
571 }
572 else if(!strcmp(thestring, "HSP"))
573 return(PCFX_V810.GetPR(2));
574 else if(!strcmp(thestring, "SP"))
575 return(PCFX_V810.GetPR(3));
576 else if(!strcmp(thestring, "GP"))
577 return(PCFX_V810.GetPR(4));
578 else if(!strcmp(thestring, "TP"))
579 return(PCFX_V810.GetPR(5));
580 else if(!strcmp(thestring, "LP"))
581 return(PCFX_V810.GetPR(31));
582 else if(!strcmp(thestring, "TStamp"))
583 return(PCFX_V810.v810_timestamp);
584 else if(!strncmp(thestring, "SR", 2))
585 {
586 int which_one = atoi(thestring + 2);
587 uint32 val = PCFX_V810.GetSR(which_one);
588
589 if(special && which_one == PSW)
590 {
591 char buf[256];
592 trio_snprintf(buf, 256, "Z: %d, S: %d, OV: %d, CY: %d, ID: %d, AE: %d, EP: %d, NP: %d, IA: %2d",
593 (int)(bool)(val & PSW_Z), (int)(bool)(val & PSW_S), (int)(bool)(val & PSW_OV), (int)(bool)(val & PSW_CY),
594 (int)(bool)(val & PSW_ID), (int)(bool)(val & PSW_AE), (int)(bool)(val & PSW_EP), (int)(bool)(val & PSW_NP),
595 (val & PSW_IA) >> 16);
596 *special = std::string(buf);
597 }
598 return(val);
599 }
600 uint32 val = 0;
601
602 if(PCFXIRQ_GetRegister(name, val, special) || FXTIMER_GetRegister(name, val, special) || FXINPUT_GetRegister(name, val, special))
603 return(val);
604
605 return(val);
606 }
607
PCFXDBG_SetRegister(const std::string & name,uint32 value)608 void PCFXDBG_SetRegister(const std::string &name, uint32 value)
609 {
610 if(name == "PC")
611 {
612 PCFX_V810.SetPC(value & ~1);
613 return;
614 }
615
616 const char *thestring = name.c_str();
617
618 if(!strncmp(thestring, "PR", 2))
619 {
620 PCFX_V810.SetPR(atoi(thestring + 2), value);
621 }
622 else if(!strcmp(thestring, "HSP"))
623 PCFX_V810.SetPR(2, value);
624 else if(!strcmp(thestring, "SP"))
625 PCFX_V810.SetPR(3, value);
626 else if(!strcmp(thestring, "GP"))
627 PCFX_V810.SetPR(4, value);
628 else if(!strcmp(thestring, "TP"))
629 PCFX_V810.SetPR(5, value);
630 else if(!strcmp(thestring, "LP"))
631 PCFX_V810.SetPR(31, value);
632 else if(!strncmp(thestring, "SR", 2))
633 {
634 PCFX_V810.SetSR(atoi(thestring + 2), value);
635 }
636 else if(PCFXIRQ_SetRegister(name, value))
637 {
638
639 }
640
641 }
642
PCFXDBG_SetCPUCallback(void (* callb)(uint32 PC,bool bpoint),bool continuous)643 void PCFXDBG_SetCPUCallback(void (*callb)(uint32 PC, bool bpoint), bool continuous)
644 {
645 CPUHook = callb;
646 CPUHookContinuous = continuous;
647 RedoCPUHook();
648 }
649
PCFXDBG_DoLog(const char * type,const char * format,...)650 void PCFXDBG_DoLog(const char *type, const char *format, ...)
651 {
652 if(LogFunc)
653 {
654 char *temp;
655
656 va_list ap;
657 va_start(ap, format);
658
659 temp = trio_vaprintf(format, ap);
660 LogFunc(type, temp);
661 free(temp);
662
663 va_end(ap);
664 }
665 }
666
PCFXDBG_SetLogFunc(void (* func)(const char *,const char *))667 void PCFXDBG_SetLogFunc(void (*func)(const char *, const char *))
668 {
669 LogFunc = func;
670
671 PCFX_LoggingOn = func ? TRUE : FALSE;
672 SCSICD_SetLog(func ? PCFXDBG_DoLog : NULL);
673 KING_SetLogFunc(func ? PCFXDBG_DoLog : NULL);
674
675 if(PCFX_LoggingOn)
676 {
677 if(sjis_ict == (iconv_t)-1)
678 sjis_ict = iconv_open("UTF-8", "shift_jis");
679 }
680 else
681 {
682 if(sjis_ict != (iconv_t)-1)
683 {
684 iconv_close(sjis_ict);
685 sjis_ict = (iconv_t)-1;
686 }
687 }
688 RedoCPUHook();
689 }
690
PCFXDBG_ShiftJIS_to_UTF8(const uint16 sjc)691 char *PCFXDBG_ShiftJIS_to_UTF8(const uint16 sjc)
692 {
693 static char ret[16];
694 char inbuf[3];
695 char *in_ptr, *out_ptr;
696 size_t ibl, obl;
697
698 if(sjc < 256)
699 {
700 inbuf[0] = sjc;
701 inbuf[1] = 0;
702 ibl = 1;
703 }
704 else
705 {
706 inbuf[0] = sjc >> 8;
707 inbuf[1] = sjc >> 0;
708 inbuf[2] = 0;
709 ibl = 2;
710 }
711
712 in_ptr = inbuf;
713 out_ptr = ret;
714 obl = 16;
715
716 iconv(sjis_ict, (ICONV_CONST char **)&in_ptr, &ibl, &out_ptr, &obl);
717
718 *out_ptr = 0;
719
720 return(ret);
721 }
722