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