main.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232
  1. /*
  2. * Main application source file - The TI-NESulator Project
  3. * main.c
  4. *
  5. * Created by Manoel TRAPIER.
  6. * Copyright (c) 2003-2007 986Corp. All rights reserved.
  7. *
  8. * $LastChangedDate: 2007-05-31 18:02:16 +0200 (jeu, 31 mai 2007) $
  9. * $Author: mtrapier $
  10. * $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/main.c $
  11. * $Revision: 58 $
  12. *
  13. */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <signal.h>
  18. #include <sys/mman.h>
  19. #include <sys/time.h>
  20. #include <time.h>
  21. #ifndef WIN32
  22. //#include <Allegro/allegro.h>
  23. #include <allegro.h>
  24. #else
  25. #define USE_CONSOLE
  26. #include <allegro.h>
  27. #endif
  28. #if ISPAL && !ISNTSC
  29. //#define VBLANK_TIME 70
  30. //#define HBLANK_TIME 261
  31. int VBLANK_TIME = 70;
  32. int HBLANK_TIME = 140;
  33. double APU_BASEFREQ = 1.7734474;
  34. #elif !ISPAL && ISNTSC
  35. int VBLANK_TIME = 20;
  36. int HBLANK_TIME = 119;
  37. double APU_BASEFREQ = 1.7897725;
  38. //#define VBLANK_TIME 20
  39. //#define HBLANK_TIME 260
  40. #else
  41. #error Cannot use ISPAL with ISNTSC together !
  42. #endif
  43. /* Should find something better for sharing the copu interface... */
  44. #include <corecpu/M6502.h>
  45. #include <ppu/ppu.h>
  46. #include <NESCarts.h>
  47. #include <paddle.h>
  48. #include <mappers/manager.h>
  49. #include <memory/manager.h>
  50. #include <plugins/manager.h>
  51. #ifdef USE_SOUND
  52. #include <Sound.h>
  53. #endif
  54. #include <palette.h>
  55. #define V_MAJOR 0
  56. #define V_MINOR 29
  57. #define VS_ID "$Id: main.c 58 2007-05-31 16:02:16Z mtrapier $"
  58. #define VS_REVISION "$Revision: 58 $"
  59. #define VS_LASTCHANGEDDATE "$LastChangedDate: 2007-05-31 18:02:16 +0200 (jeu, 31 mai 2007) $"
  60. #define VS_HEADURL "$HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/main.c $"
  61. #define VS_AUTHOR "$Author: mtrapier $"
  62. #define MAXLASTOP 42
  63. word latestop[MAXLASTOP];
  64. M6502 MainCPU;
  65. BITMAP *Buffer;
  66. byte *FDSRom;
  67. byte *FDSRam;
  68. /* Command line options */
  69. byte START_DEBUG = 0;
  70. byte START_WITH_FDS = 0;
  71. char *CART_FILENAME = NULL;
  72. char *PALETTE_FILENAME = NULL;
  73. #define fatal(s) { printf("%s",s); exit(-1); }
  74. Paddle P1, P2;
  75. unsigned short ScanLine;
  76. volatile int frame = 0;
  77. volatile extern int icount;
  78. char MapperWantIRQ = 0;
  79. char WantClosing = 0;
  80. struct timeval timeStart;
  81. struct timeval timeEnd;
  82. volatile unsigned long FPS, IPS;
  83. PALETTE pal;
  84. short IRQScanHit = -1;
  85. NesCart *Cart;
  86. /* palette */
  87. unsigned long ColorPalette[ 8 * 63 ];
  88. #define SET_RGB(r,g,b) ((((r<<8)|g)<<8)|b)|0xFF000000
  89. void CloseHook(void)
  90. {
  91. WantClosing = 1;
  92. }
  93. void ips_fps_counter(void)
  94. {
  95. FPS = frame;
  96. IPS = icount;
  97. frame = 0;
  98. icount = 0;
  99. }
  100. END_OF_FUNCTION(ips_fps_counter);
  101. void SaveSaveRam(char *name)
  102. {
  103. FILE *fp;
  104. int i;
  105. char fname[512];
  106. //byte car;
  107. strcpy(fname, name);
  108. strcat(fname, ".svt");
  109. if ((fp = fopen(fname, "wb")))
  110. {
  111. printf("Saving savestate '%s'\n", fname);
  112. for( i = 0x60; i < 0x80; i++)
  113. {
  114. fwrite(get_page_ptr(i), 1, 0x100, fp);
  115. }
  116. fclose(fp);
  117. }
  118. }
  119. void LoadSaveRam(char *name)
  120. {
  121. FILE *fp;
  122. int i;
  123. char fname[512];
  124. strcpy(fname, name);
  125. strcat(fname, ".svt");
  126. if ((fp = fopen(fname, "rb")))
  127. {
  128. printf("Loading savestate '%s'\n", fname);
  129. for( i = 0x60; i < 0x80; i++)
  130. {
  131. fread(get_page_ptr(i), 1, 0x0100, fp);
  132. }
  133. fclose(fp);
  134. }
  135. }
  136. void LoadPalette(char *filename, PALETTE pal)
  137. {
  138. FILE *fp;
  139. unsigned char r, v, b, i;
  140. printf("%s: try to load pallette file '%s'", __func__, filename);
  141. if ((fp = fopen(filename, "rb")) != NULL)
  142. {
  143. for (i = 0; i < 64; i++)
  144. {
  145. fread(&r, 1, 1, fp);
  146. fread(&v, 1, 1, fp);
  147. fread(&b, 1, 1, fp);
  148. /* r = (r * 64) / 255;
  149. v = (v * 64) / 255;
  150. b = (b * 64) / 255;*/
  151. #ifdef USE_24BITS
  152. ColorPalette[i + (0 * 63)] = SET_RGB(r,v,b);
  153. /* Red emphase */
  154. ColorPalette[i + (1 * 63)] = SET_RGB(r + 10, v - 05, b - 05);
  155. /* Green emphase */
  156. ColorPalette[i + (2 * 63)] = SET_RGB(r - 05, v + 10, b - 05);
  157. /* Red + green emphase */
  158. ColorPalette[i + (3 * 63)] = SET_RGB(r + 05, v + 05, b - 10);
  159. /* Blue emphase */
  160. ColorPalette[i + (4 * 63)] = SET_RGB(r - 05, v - 05, b + 10);
  161. /* Red + blue emphase */
  162. ColorPalette[i + (5 * 63)] = SET_RGB(r + 05, v - 10, b + 05);
  163. /* Blue + green emphase */
  164. ColorPalette[i + (6 * 63)] = SET_RGB(r - 10, v + 05, b + 05);
  165. /* Red + Green + Blue emphase */
  166. ColorPalette[i + (7 * 63)] = SET_RGB(r + 00, v + 00, b + 00);*/
  167. #else /* Else Use 8Bits */
  168. pal[i].r = r;
  169. pal[i].g = v;
  170. pal[i].b = b;
  171. pal[i + 64].r = r;
  172. pal[i + 64].g = v;
  173. pal[i + 64].b = b;
  174. pal[i + 128].r = r;
  175. pal[i + 128].g = v;
  176. pal[i + 128].b = b;
  177. pal[i + 192].r = r;
  178. pal[i + 192].g = v;
  179. pal[i + 192].b = b;
  180. #endif
  181. }
  182. fclose(fp);
  183. printf(" [ OK ]\n");
  184. }
  185. else
  186. {
  187. printf("Error loading palette '%s'!\n", filename);
  188. exit(-1);
  189. }
  190. }
  191. int DAsm(char *S, word A);
  192. int oppos = 0;
  193. void pushop(word op)
  194. {
  195. latestop[oppos] = op;
  196. // printf("%d\n", oppos);
  197. oppos = (oppos+1)%42;
  198. }
  199. void showlastop(FILE *fp)
  200. {
  201. #ifdef DEBUG
  202. int i,j;
  203. char S[256];
  204. i = oppos;
  205. do
  206. {
  207. j=(DAsm(S,latestop[i])-1);
  208. fprintf(fp, "0x%04X : %s\n", MainCPU.PC.W,S);
  209. i = (i+1)%42;
  210. }
  211. while(i != oppos);
  212. #endif
  213. }
  214. void *signalhandler(int sig)
  215. {
  216. static int state=0;
  217. M6502 *R = &MainCPU;
  218. byte F;
  219. int J, I;
  220. static char FA[8] = "NVRBDIZC";
  221. char S[128];
  222. char name[512];
  223. static FILE *fp = NULL;
  224. sprintf(name, "crashdump-%d.txt", time(NULL));
  225. if (state != 0)
  226. {
  227. fprintf(stderr, "\n\n\nCrashed within signal!\nEmergency exit\n");
  228. exit(42);
  229. }
  230. state = 1;
  231. if (fp == NULL)
  232. fp = fopen(name, "wt");
  233. state = 2;
  234. if (fp) fprintf(stderr,
  235. "\n\n\n\n\n"
  236. "#sick# TI-NESulator %d.%d #sick#\n"
  237. "see %s for more information",
  238. V_MAJOR,
  239. V_MINOR,
  240. name);
  241. if (!fp) fp = stderr;
  242. fprintf(fp,"\n\n\n\n\n"
  243. "#sick# TI-NESulator %d.%d #sick# signal: ",
  244. V_MAJOR,
  245. V_MINOR);
  246. switch(sig)
  247. {
  248. default:
  249. case SIGABRT: fprintf(fp,"Abnormal termination"); break;
  250. case SIGILL: fprintf(fp,"Illegal instruction"); break;
  251. case SIGINT: fprintf(fp,"CTRL+C signal"); break;
  252. case SIGSEGV: fprintf(fp,"Segmentation fault"); break;
  253. case SIGTERM: fprintf(fp,"Termination request"); break;
  254. }
  255. fprintf(fp,"\nAn error occured during the excution.\n Crash report information :\n");
  256. #ifdef DEBUG
  257. DAsm(S, R->PC.W);
  258. #endif
  259. fprintf(fp, "CPU: A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
  260. R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W);
  261. for (J = 0, F = R->P; J < 8; J++, F <<= 1)
  262. fprintf(fp, "%c", F & 0x80 ? FA[J] : '.');
  263. fprintf(fp, "]\nCPU: ");
  264. fprintf(fp, "AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\nLast execution :\n",
  265. Rd6502(R->PC.W), S,
  266. Rd6502(0x0100 + (byte) (R->S + 1)),
  267. Rd6502(0x0100 + (byte) (R->S + 2)),
  268. Rd6502(0x0100 + (byte) (R->S + 3)));
  269. showlastop(fp);
  270. // fprintf(fp, "PPU: CR1: 0x%02X (NT:%d AI:%d SP:%d BP:%d SS:%d NMI:%d)\n",ppu.ControlRegister1.b, ppu.ControlRegister1.s.NameTblAddr, ppu.ControlRegister1.s.AddrIncrmt, ppu.ControlRegister1.s.SptPattern, ppu.ControlRegister1.s.BgPattern, ppu.ControlRegister1.s.SpriteSize, ppu.ControlRegister1.s.VBlank_NMI);
  271. // fprintf(fp, "PPU: CR2: 0x%02X (FBC/CI:%d SV:%d BV:%d SC:%d BC:%d DT:%d)\n",ppu.ControlRegister2.b,ppu.ControlRegister2.s.Colour,ppu.ControlRegister2.s.SpriteVisibility,ppu.ControlRegister2.s.BgVisibility,ppu.ControlRegister2.s.SpriteClipping,ppu.ControlRegister2.s.BgClipping,ppu.ControlRegister2.s.DisplayType);
  272. // fprintf(fp, "PPU: SR: 0x%02X (VB:%d S0:%d SSC:%d VWF:%d)\n", ppu.StatusRegister.b,ppu.StatusRegister.s.VBlankOccur,ppu.StatusRegister.s.Sprite0Occur,ppu.StatusRegister.s.SprtCount,ppu.StatusRegister.s.VRAMProtect);
  273. // fprintf(fp, "PPU: M:%d ST:%d VRAMPtr:0x%04X T:0x%04X\n",ppu.MirrorDir,ppu.ScreenType,ppu.VRAMAddrReg2.W,ppu.TmpVRamPtr);
  274. mapper_dump(fp);
  275. for(I = 0; I < 0xFFFF; I += 0x10)
  276. fprintf(fp, "%04X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X | %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
  277. I,
  278. Rd6502(I+0x00), Rd6502(I+0x01), Rd6502(I+0x02), Rd6502(I+0x03),
  279. Rd6502(I+0x04), Rd6502(I+0x05), Rd6502(I+0x06), Rd6502(I+0x07),
  280. Rd6502(I+0x08), Rd6502(I+0x09), Rd6502(I+0x0A), Rd6502(I+0x0B),
  281. Rd6502(I+0x0C), Rd6502(I+0x0D), Rd6502(I+0x0E), Rd6502(I+0x0F),
  282. // --- //
  283. isprint(Rd6502(I+0x00))?Rd6502(I+0x00):'_',
  284. isprint(Rd6502(I+0x01))?Rd6502(I+0x01):'_',
  285. isprint(Rd6502(I+0x02))?Rd6502(I+0x02):'_',
  286. isprint(Rd6502(I+0x03))?Rd6502(I+0x03):'_',
  287. isprint(Rd6502(I+0x04))?Rd6502(I+0x04):'_',
  288. isprint(Rd6502(I+0x05))?Rd6502(I+0x05):'_',
  289. isprint(Rd6502(I+0x06))?Rd6502(I+0x06):'_',
  290. isprint(Rd6502(I+0x07))?Rd6502(I+0x07):'_',
  291. isprint(Rd6502(I+0x08))?Rd6502(I+0x08):'_',
  292. isprint(Rd6502(I+0x09))?Rd6502(I+0x09):'_',
  293. isprint(Rd6502(I+0x0A))?Rd6502(I+0x0A):'_',
  294. isprint(Rd6502(I+0x0B))?Rd6502(I+0x0B):'_',
  295. isprint(Rd6502(I+0x0C))?Rd6502(I+0x0C):'_',
  296. isprint(Rd6502(I+0x0D))?Rd6502(I+0x0D):'_',
  297. isprint(Rd6502(I+0x0E))?Rd6502(I+0x0E):'_',
  298. isprint(Rd6502(I+0x0F))?Rd6502(I+0x0F):'_');
  299. DumpMemoryState(fp);
  300. fprintf(stderr, "\nPlease join this informations when submiting crash report\n");
  301. if (fp != stderr) fclose(fp);
  302. //getchar();
  303. exit(-42);
  304. }
  305. byte Page40[256];
  306. void WrHook4000Multiplexer(byte addr, byte value)
  307. {
  308. static byte SQ1V = 0;
  309. static byte SQ2V = 0;
  310. static byte TRIV = 0;
  311. static byte NOIV = 0;
  312. static unsigned short SQ1P = 0;
  313. static unsigned short SQ2P = 0;
  314. static unsigned short TRIP = 0;
  315. static unsigned short NOIP = 0;
  316. static byte Sq1_reg0 = 0;
  317. static byte Sq1_reg1 = 0;
  318. static byte Sq1_reg2 = 0;
  319. static byte Sq1_reg3 = 0;
  320. static byte Sq2_reg0 = 0;
  321. static byte Sq2_reg1 = 0;
  322. static byte Sq2_reg2 = 0;
  323. static byte Sq2_reg3 = 0;
  324. double SQ;
  325. switch(addr)
  326. {
  327. #ifdef USE_SOUND
  328. case 0x00: /* DDLE NNNN */
  329. Sq1_reg0 = value;
  330. if (Sq1_reg0 & 0x10)
  331. {
  332. SQ1V = 0x0F/*(0x04+(value&0x0F))& 0x0F*/;
  333. }
  334. else
  335. {
  336. SQ1V = value&0x0F;
  337. }
  338. break;
  339. case 0x01: /* EPPP NSSS */
  340. Sq1_reg1 = value;
  341. break;
  342. case 0x02:
  343. /*printf("Sq1 reg0: 0x%02X - duty:0x%X loop:0x%X env:0x%X vol:0x%X\n",
  344. Sq1_reg0,
  345. (Sq1_reg0&0xC0)>>6,
  346. (Sq1_reg0&0x20)>>5,
  347. (Sq1_reg0&0x10)>>4,
  348. Sq1_reg0&0x0F);
  349. printf("Sq1 reg1: 0x%02X - sweep:0x%X period:0x%X neg:0x%X shift:0x%X\n",
  350. Sq1_reg1,
  351. (Sq1_reg1&0x80)>>8,
  352. (Sq1_reg1&0x70)>>4,
  353. (Sq1_reg1&0x08)>>3,
  354. Sq1_reg1&0x07);
  355. printf("Sq1 reg2: 0x%02X\n", value);
  356. printf("Sq1 reg3: 0x%02X\n", Sq1_reg3);*/
  357. SQ1P = value | ((Sq1_reg3&0x7) << 8);
  358. SQ = APU_BASEFREQ * 1000 * 1000 / (SQ1P+1 /*+
  359. (Sq1_reg1&0x80)?0:( (Sq1_reg1&0x08)?(SQ1P>>(Sq1_reg1&0x07)):(SQ1P<<(Sq1_reg1&0x07)) )*/);
  360. SetSound(0,SND_MELODIC);
  361. //printf("SQ1V = %d - SQ = %f - SQ1P = %d\n", SQ1V, SQ, SQ1P);
  362. // { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 0, SQ1P, SQ1V); fclose(fp); }
  363. Sound(0, (int) SQ/22, (0xFF/0x0F) * SQ1V);
  364. // printf("40%02X: 0x%02X (SQ1P:%d SQ:%f (%d))\n", addr, value, SQ1P, SQ, (int) SQ);
  365. Sq1_reg2 = value;
  366. break;
  367. case 0x03:
  368. Sq1_reg3 = value;
  369. SQ1P = Sq1_reg2 | ((value&0x7) << 8);
  370. SQ = APU_BASEFREQ * 1000 * 1000 / (SQ1P+1 /*+
  371. (Sq1_reg1&0x80)?0:( (Sq1_reg1&0x08)?(SQ1P>>(Sq1_reg1&0x07)):(SQ1P<<(Sq1_reg1&0x07)) )*/);
  372. // { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 0, SQ1P, SQ1V); fclose(fp); }
  373. Sound(0, (int) SQ/22, (0xFF/0x0F) * SQ1V);
  374. break;
  375. case 0x04:
  376. Sq2_reg0 = value;
  377. if (Sq2_reg0 & 0x10)
  378. {
  379. SQ2V = 0x0F;
  380. //SQ2V = (0x04+(value&0x0F))& 0x0F;
  381. }
  382. else
  383. {
  384. SQ2V = value&0x0F;
  385. }
  386. break;
  387. case 0x05:
  388. Sq2_reg1 = value;
  389. break;
  390. case 0x06:
  391. Sq2_reg2 = value;
  392. SQ2P = Sq2_reg2 | ((Sq2_reg3&0x7) << 8);
  393. SQ = APU_BASEFREQ * 1000 * 1000 / (SQ2P+1 /*+
  394. (Sq2_reg1&0x80)?0:( (Sq2_reg1&0x08)?(SQ2P>>(Sq2_reg1&0x07)):(SQ2P<<(Sq2_reg1&0x07)) )*/);
  395. /* printf("Sq2 reg0: 0x%02X - duty:0x%X loop:0x%X env:0x%X vol:0x%X\n",
  396. Sq2_reg0,
  397. (Sq2_reg0&0xC0)>>6,
  398. (Sq2_reg0&0x20)>>5,
  399. (Sq2_reg0&0x10)>>4,
  400. Sq2_reg0&0x0F);
  401. printf("Sq2 reg1: 0x%02X - sweep:0x%X period:0x%X neg:0x%X shift:0x%X\n",
  402. Sq2_reg1,
  403. (Sq2_reg1&0x80)>>8,
  404. (Sq2_reg1&0x70)>>4,
  405. (Sq2_reg1&0x08)>>3,
  406. Sq2_reg1&0x07);
  407. printf("Sq2 reg2: 0x%02X\n", value);
  408. printf("Sq2 reg3: 0x%02X\n", Sq2_reg3);
  409. printf("SQ2V = %d - SQ = %f - SQ2P = %d\n", SQ2V, SQ, SQ2P);*/
  410. // { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 1, SQ2P, SQ2V); fclose(fp); }
  411. Sound(1, (int) SQ/22, (0xFF/0x0F) * SQ2V);
  412. break;
  413. case 0x07:
  414. Sq2_reg3 = value;
  415. SQ2P = Sq2_reg2 | ((Sq2_reg3&0x7) << 8);
  416. //SQ2P = (SQ2P & 0x00FF) | ((value&0x7) << 8);
  417. SQ = APU_BASEFREQ * 1000 * 1000 / (SQ2P+1 /*+
  418. (Sq2_reg1&0x80)?0:( (Sq2_reg1&0x08)?(SQ2P>>(Sq2_reg1&0x07)):(SQ2P<<(Sq2_reg1&0x07)) )*/);
  419. // { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 1, SQ2P, SQ2V); fclose(fp); }
  420. Sound(1, (int) SQ/22, (0xFF/0x0F) * SQ2V);
  421. break;
  422. case 0x0A:
  423. TRIP = (TRIP & 0xFF00) | value;
  424. SQ = APU_BASEFREQ * 1000 * 1000 / TRIP;
  425. // { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 2, TRIP, 255); fclose(fp); }
  426. Sound(2, (int) SQ/22, 127);
  427. break;
  428. case 0x0B:
  429. TRIP = (TRIP & 0x00FF) | ((value&0x7) << 8);;
  430. SQ = APU_BASEFREQ * 1000 * 1000 / TRIP;
  431. // { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 2, TRIP, 255); fclose(fp); }
  432. Sound(2, (int) SQ/22, 127);
  433. break;
  434. /* case 0x0C:
  435. NOIV = value & 0x0F;
  436. break;
  437. case 0x0E:
  438. NOIP = value & 0x0F;
  439. SQ = APU_BASEFREQ * 1000 * 1000 / NOIP;
  440. // { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 2, TRIP, 255); fclose(fp); }
  441. SetSound(3, SND_NOISE);
  442. Sound(3, (int) SQ/22, (0xFF/0x0F) * NOIV);
  443. break;
  444. case 0x0F:
  445. break;*/
  446. case 0x15:
  447. /* DMC, Noise, Triangle, Sq 2, Sq 1 */
  448. //SetChannels(0, (value&0x01)?0x01:0);
  449. /* printf("40%02X: 0x%02X [%c%c%c%c%c]\n", addr, value,
  450. (value&0x10)?'d':'.',
  451. (value&0x08)?'n':'.',
  452. (value&0x04)?'t':'.',
  453. (value&0x02)?'2':'.',
  454. (value&0x01)?'1':'.');*/
  455. break;
  456. #endif
  457. case 0x14:
  458. ppu_fillSprRamDMA(value);
  459. break;
  460. case 0x16:
  461. WritePaddle(&P1, value);
  462. //WritePaddle(&P2, value);
  463. break;
  464. case 0x17:
  465. // printf("40%02X: 0x%02X\n", addr, value);
  466. break;
  467. // default:
  468. //Page40[addr] = value;
  469. // printf("40%02X: 0x%02X\n", addr, value);
  470. // printf("pAPU: 0x%X @ 0x40%X\n", value, addr);
  471. }
  472. }
  473. byte RdHook4000Multiplexer(byte addr)
  474. {
  475. byte ret;
  476. switch(addr)
  477. {
  478. case 0x16:
  479. ret = ReadPaddle(&P1);
  480. break;
  481. case 0x17:
  482. ret = 0x40;
  483. break;
  484. case 0x15:
  485. ret = 0x1F;
  486. default:
  487. ret = 0x42;
  488. }
  489. return ret;
  490. }
  491. void printUsage(int argc, char *argv[])
  492. {
  493. printf("Usage : %s game.nes [-p number][-f][-b filename.pal][ filename.nes\n"
  494. " -p: to add plugin 'number'\n"
  495. " -f: to start in FDS mode\n"
  496. " -d: to start directily into the debugguer\n"
  497. " -b: to use palette file 'filename.pal'\n",
  498. argv[0]);
  499. exit(0);
  500. }
  501. int main(int argc, char *argv[])
  502. {
  503. int i;
  504. unsigned char j, k;
  505. unsigned char *MemoryPage;
  506. /* Here we will fill the memory */
  507. /*
  508. --------------------------------------- $10000
  509. Upper Bank of Cartridge ROM
  510. --------------------------------------- $C000
  511. Lower Bank of Cartridge ROM
  512. --------------------------------------- $8000
  513. Cartridge RAM (may be battery-backed)
  514. --------------------------------------- $6000
  515. Expansion Modules
  516. --------------------------------------- $5000
  517. Input/Output
  518. --------------------------------------- $2000
  519. 2kB Internal RAM, mirrored 4 times
  520. --------------------------------------- $0000
  521. */
  522. /* Print the banner */
  523. printf("--------------------------------------------------------------------------------\n"
  524. "Welcome to TI-NESulator v%d.%d - by Godzil\n"
  525. "Copyright 2003-2007 TRAPIER Manoel (godzil@godzil.net)\n"
  526. "%s\n%s\n%s\n"
  527. "--------------------------------------------------------------------------------\n\n",
  528. V_MAJOR,
  529. V_MINOR,
  530. VS_REVISION,
  531. VS_LASTCHANGEDDATE,
  532. VS_AUTHOR);
  533. printf("Install signal handlers...\t[");
  534. // signal(SIGABRT,signalhandler);
  535. printf("A");
  536. // signal(SIGILL,signalhandler);
  537. printf("I");
  538. /*signal(SIGINT,signalhandler);*/
  539. printf(".");
  540. // signal(SIGSEGV,signalhandler);
  541. printf("S");
  542. // signal(SIGTERM,signalhandler);
  543. printf("T]\n");
  544. /* */
  545. printf("Initialize memory...\t\t");
  546. InitMemory();
  547. printf("[ OK ]\n");
  548. printf("Parsing parameters (%d)...\n", argc);
  549. /* Now we use a real argument parser ! */
  550. for(i = 1 ; (i < argc) && (argv[i][0]=='-'); i++)
  551. {
  552. switch(argv[i][1])
  553. {
  554. default: /* Option not recognized */
  555. case 'h': /* ask for help */
  556. printUsage(argc, argv);
  557. break;
  558. case 'p':
  559. if (atoi(argv[i+1]) != 0)
  560. {
  561. printf("-Load plugin #%d...\n", atoi(argv[i+1]));
  562. if ( plugin_load(atoi(argv[i+1])) == -1)
  563. {
  564. plugin_list();
  565. exit(0);
  566. }
  567. i++;
  568. }
  569. else
  570. {
  571. plugin_list();
  572. exit(0);
  573. }
  574. break;
  575. case 'f':
  576. printf("-Start with fds!\n");
  577. START_WITH_FDS = 1;
  578. break;
  579. case 'd':
  580. printf("-Start with debug!\n");
  581. START_DEBUG = 1;
  582. break;
  583. case 'b':
  584. printf("-Palette file is %s\n", argv[i+1]);
  585. PALETTE_FILENAME = argv[i+1];
  586. i++;
  587. break;
  588. }
  589. }
  590. CART_FILENAME = argv[argc-1];
  591. if (CART_FILENAME == NULL)
  592. printUsage(argc, argv);
  593. printf("Allocating 6502 memory\t\t");
  594. /* Allocating first 0x7FF memory */
  595. MemoryPage = (unsigned char *)malloc (0x800);
  596. set_page_ptr_2k(0,MemoryPage);
  597. for (i = 0; i < 0x08; i++)
  598. {
  599. set_page_readable(i, true);
  600. set_page_writeable(i, true);
  601. }
  602. /* Set ghost starting from 0x800 */
  603. set_page_ghost(0x08,true,0x00);
  604. set_page_ghost(0x09,true,0x01);
  605. set_page_ghost(0x0A,true,0x02);
  606. set_page_ghost(0x0B,true,0x03);
  607. set_page_ghost(0x0C,true,0x04);
  608. set_page_ghost(0x0D,true,0x05);
  609. set_page_ghost(0x0E,true,0x06);
  610. set_page_ghost(0x0F,true,0x07);
  611. /* Set ghost starting from 0x1000 */
  612. set_page_ghost(0x10,true,0x00);
  613. set_page_ghost(0x11,true,0x01);
  614. set_page_ghost(0x12,true,0x02);
  615. set_page_ghost(0x13,true,0x03);
  616. set_page_ghost(0x14,true,0x04);
  617. set_page_ghost(0x15,true,0x05);
  618. set_page_ghost(0x16,true,0x06);
  619. set_page_ghost(0x17,true,0x07);
  620. /* Set ghost starting from 0x1800 */
  621. set_page_ghost(0x18,true,0x00);
  622. set_page_ghost(0x19,true,0x01);
  623. set_page_ghost(0x1A,true,0x02);
  624. set_page_ghost(0x1B,true,0x03);
  625. set_page_ghost(0x1C,true,0x04);
  626. set_page_ghost(0x1D,true,0x05);
  627. set_page_ghost(0x1E,true,0x06);
  628. set_page_ghost(0x1F,true,0x07);
  629. /* Set 0x4000 registers */
  630. /* "hack" : only page $40 is used by multiple devices, we need to multiplexe
  631. it*/
  632. set_page_wr_hook(0x40, WrHook4000Multiplexer);
  633. set_page_rd_hook(0x40, RdHook4000Multiplexer);
  634. set_page_readable(0x40, true);
  635. set_page_writeable(0x40, true);
  636. /* Exp ROM : Nothing to do actually */
  637. /* SRAM (0x6000 : 0x2000 bytes ) */
  638. MemoryPage = (unsigned char *)malloc (0x2000);
  639. set_page_ptr_8k(0x60, MemoryPage);
  640. /* ROM ptr will be set by mapper */
  641. /* But we will set the readable bit */
  642. for (i = 0x80; i < 0x100; i++)
  643. {
  644. set_page_readable(i, true);
  645. set_page_writeable(i, false);
  646. }
  647. printf("[ OK ]\n");
  648. #define Value(s) (((s%0xFF) + (rand()%0xFF-128) )%0xFF)
  649. printf("Testing memory validity...\n");
  650. map_sram();
  651. for(i = 0x0000; i < 0x2000; i ++)
  652. {
  653. j = Value(i);
  654. MemoryPage[i] = j;
  655. }
  656. for(i = 0x6000; i < 0x8000; i ++)
  657. {
  658. if (MemoryPage[i-0x6000] != (k = Rd6502(i)))
  659. printf("Error RdRead @ 0x%X [should:%d,is:%d]\n", i, MemoryPage[i-0x6000], k);
  660. if (MemoryPage[i-0x6000] != (k = Op6502(i)))
  661. printf("Error OpRead @ 0x%X [should:%d,is:%d]\n", i, MemoryPage[i-0x6000], k);
  662. }
  663. printf("Testing memory... (<0x2000)\n");
  664. for( i = 0 ; i < 0x2000 ; i++ ) {
  665. j = Value(i);
  666. Wr6502(i, j);
  667. if ((k=Rd6502(i)) != j)
  668. printf("Error read/write @ 0x%X [w:%d,r:%d]\n", i, j, k);
  669. if ((k=Op6502(i)) != j)
  670. printf("Error opcode @ 0x%X [w:%d,r:%d]\n", i, j, k);
  671. }
  672. printf("Testing memory... (0x6000-0x8000)\n");
  673. for(i=0x6000;i<0x8000;i++) {
  674. j = Value(i);
  675. Wr6502(i, j);
  676. if ((k=Rd6502(i)) != j)
  677. printf("Error read/write @ 0x%X [w:%d,r:%d]\n", i, j, k);
  678. if ((k=Op6502(i)) != j)
  679. printf("Error opcode @ 0x%X [w:%d,r:%d]\n", i, j, k);
  680. }
  681. printf("Reseting main RAM...\t\t");
  682. //Force the stack to be empty of zero
  683. for( i = 0x100 ; i < 0x200 ; i++ ) {
  684. Wr6502(i, 0x00);
  685. }
  686. printf("[ OK ]\n");
  687. if (START_WITH_FDS)
  688. {
  689. int fd;
  690. printf("Loading FDS ROM...\t\t");
  691. fd = open("../data/disksys.rom", O_RDONLY);
  692. FDSRom = mmap(NULL, 8*1024, PROT_READ, MAP_PRIVATE, fd, 0);
  693. printf("%p [ OK ]\n", FDSRom);
  694. close(fd);
  695. set_page_ptr_8k(0xE0, FDSRom);
  696. printf("Allocating FDS RAM...\t\t");
  697. FDSRam = (byte*) malloc( (8+16) * 1024);
  698. if (FDSRam == NULL)
  699. fatal("Allocation error\n");
  700. for (i = 0x80; i < 0xE0; i++)
  701. {
  702. set_page_ptr(i, FDSRam + (i*0x100));
  703. set_page_readable(i, true);
  704. set_page_writeable(i, true);
  705. }
  706. Cart->MapperID = 100;
  707. }
  708. else
  709. {
  710. Cart = malloc( sizeof (NesCart));
  711. if (Cart == NULL)
  712. fatal("Memory allocation error...\n");
  713. printf("Please Wait while loading %s cartridge...\n", CART_FILENAME);
  714. if (LoadCart(CART_FILENAME, Cart) != 0)
  715. fatal("Loading error...\n");
  716. if (Cart->Flags & iNES_BATTERY)
  717. {
  718. LoadSaveRam(CART_FILENAME);
  719. }
  720. }
  721. unmap_sram();
  722. InitPaddle(&P1);
  723. printf("Initializing Allegro...\t\t");
  724. allegro_init();
  725. install_timer();
  726. install_keyboard();
  727. printf("[ OK ]\n");
  728. printf("Set graphic mode...\t\t");
  729. set_color_depth(8);
  730. set_gfx_mode(GFX_AUTODETECT_WINDOWED, 512 + 256, 480, 512 + 256, 480);
  731. Buffer = create_bitmap(512 + 256, 480);
  732. clear_to_color(Buffer, 0x0D);
  733. set_close_button_callback(CloseHook);
  734. set_window_title("TI-NESulator");
  735. printf("[ OK ]\n");
  736. printf("Init PPU...\n");
  737. if (ppu_init() != 0)
  738. fatal("PPU Initialisation error..\n");
  739. //DumpMemoryState();
  740. if (Cart->Flags & iNES_4SCREEN)
  741. {
  742. ppu_setScreenMode(PPU_SCMODE_FOURSC);
  743. }
  744. else
  745. {
  746. ppu_setScreenMode(PPU_SCMODE_NORMAL);
  747. ppu_setMirroring((Cart->Flags & iNES_MIRROR)?PPU_MIRROR_VERTICAL:PPU_MIRROR_HORIZTAL);
  748. }
  749. printf("Init mapper...\t\t\t");
  750. if (mapper_init(Cart) == -1)
  751. return -1;
  752. printf("[ OK ]\n");
  753. if (PALETTE_FILENAME == NULL)
  754. {
  755. set_palette(basicPalette);
  756. }
  757. else
  758. {
  759. LoadPalette(PALETTE_FILENAME, pal);
  760. set_palette(pal);
  761. }
  762. /* for(i = 0; i < 256; i++)
  763. {
  764. r = (r * 64) / 255;
  765. v = (v * 64) / 255;
  766. b = (b * 64) / 255;
  767. pal[i].r = r;
  768. pal[i].g = v;
  769. pal[i].b = b;
  770. pal[i + 64].r = r;
  771. pal[i + 64].g = v;
  772. pal[i + 64].b = b;
  773. pal[i + 128].r = r;
  774. pal[i + 128].g = v;
  775. pal[i + 128].b = b;
  776. pal[i + 192].r = r;
  777. pal[i + 192].g = v;
  778. pal[i + 192].b = b;
  779. printf(" { 0x%02X, 0x%02X, 0x%02X, 0x%02X },\n",
  780. (basicPalette[i].r * 64) / 255,
  781. (basicPalette[i].g * 64) / 255,
  782. (basicPalette[i].b * 64) / 255,
  783. basicPalette[i].filler);
  784. printf(" { 0x%02X, 0x%02X, 0x%02X, 0x%02X },\n",
  785. pal[i].r,
  786. pal[i].g,
  787. pal[i].b,
  788. pal[i].filler);
  789. }
  790. exit(0);*/
  791. #ifdef USE_SOUND
  792. InitSound(48000,!0);
  793. SetSound(0, SND_RECTANGLE);
  794. SetSound(1, SND_RECTANGLE);
  795. SetSound(2, SND_TRIANGLE);
  796. SetSound(3, SND_NOISE);
  797. #endif
  798. /* short val = 0xCE;
  799. while(1)
  800. {
  801. Wr6502(0x4000, 0x74);
  802. Wr6502(0x4001, 0x68);
  803. Wr6502(0x4002, val & 0xFF);
  804. Wr6502(0x4003, 0x08 | ((val & 0x700) >> 8));
  805. if (key[KEY_UP])
  806. val++;
  807. if (key[KEY_DOWN])
  808. val--;
  809. usleep(500);
  810. }
  811. exit(0);*/
  812. /* int K, L1, V = 127, L2, I;
  813. if(440>=48000/3) printf("Pwet\n");
  814. K=48000/440;
  815. L1=0;
  816. V<<=7;
  817. for(I=0;I<SND_BUFSIZE;I++)
  818. {
  819. L2=L1+K;
  820. printf("L1:%d L2:%d K:%d V:%d\n", L1, L2, K, V);
  821. //L1&0x8000?(L2&0x8000? V:0):(L2&0x8000? 0:-V)
  822. //printf("Wave[%d] = %d\n", I, L1&0x8000?(L2&0x8000? V:0):(L2&0x8000? 0:-V));
  823. L1=L2;
  824. }
  825. printf("Phaser: %d\n", L1);
  826. exit(0);*/
  827. printf("Press ESC to pause emulation and jump to debugguer\n");
  828. install_int(ips_fps_counter, 1000);
  829. ScanLine = 0;
  830. //Do a loop every HBlank
  831. MainCPU.IPeriod = HBLANK_TIME;
  832. //MainCPU.IPeriod = 260;
  833. Reset6502(&MainCPU);
  834. MainCPU.Trace = 0;
  835. if (START_DEBUG)
  836. MainCPU.Trace = 1;
  837. gettimeofday(&timeStart, NULL);
  838. Run6502(&MainCPU);
  839. if (Cart->Flags & iNES_BATTERY)
  840. {
  841. SaveSaveRam(CART_FILENAME);
  842. }
  843. return 0;
  844. }
  845. END_OF_MAIN()
  846. /** Rd6502()/Wr6502/Op6502() *********************************/
  847. /** These functions are called when access to RAM occurs. **/
  848. /** They allow to control memory access. Op6502 is the same **/
  849. /** as Rd6502, but used to read *opcodes* only, when many **/
  850. /** checks can be skipped to make it fast. It is only **/
  851. /** required if there is a #define FAST_RDOP. **/
  852. /************************************ TO BE WRITTEN BY USER **/
  853. void Wr6502(register word Addr, register byte Value)
  854. { /* Write to memory */
  855. WriteMemory((Addr&0xFF00)>>8,Addr&0x00FF, Value);
  856. }
  857. byte Rd6502(register word Addr)
  858. { /* Read memory for normal use */
  859. return ReadMemory((Addr&0xFF00)>>8,Addr&0x00FF);
  860. }
  861. extern byte *memory_pages[0xFF];
  862. byte Op6502(register word Addr)
  863. { /* Read OpCodes */
  864. byte *ptr;
  865. return (ptr = memory_pages[(Addr&0xFF00)>>8])>1?ptr[Addr&0x00FF]:0;
  866. //return ReadMemory((Addr&0xFF00)>>8,Addr&0x00FF);
  867. }
  868. /** Loop6502() ***********************************************/
  869. /** 6502 emulation calls this function periodically to **/
  870. /** check if the system hardware requires any interrupts. **/
  871. /** This function must return one of following values: **/
  872. /** INT_NONE, INT_IRQ, INT_NMI, or INT_QUIT to exit the **/
  873. /** emulation loop. **/
  874. /************************************ TO BE WRITTEN BY USER **/
  875. byte Loop6502(register M6502 * R)
  876. {
  877. byte ret;
  878. short skey;
  879. printf("pouic\n");
  880. long WaitTime;
  881. static long delta=0;
  882. ret = INT_NONE;
  883. if ( mapper_irqloop (ScanLine) )
  884. {
  885. ret = INT_IRQ;
  886. IRQScanHit = ScanLine;
  887. }
  888. if ( MapperWantIRQ == 1)
  889. {
  890. MapperWantIRQ = 0;
  891. ret = INT_IRQ;
  892. }
  893. if ( ppu_hblank(ScanLine) != 0 )
  894. {
  895. /* if (ret == INT_IRQ)
  896. MapperWantIRQ = 1;*/
  897. ret = INT_NMI;
  898. }
  899. if (ScanLine == 241)
  900. frame++;
  901. //if (ScanLine >= (241 + VBLANK_TIME))
  902. if (ScanLine >= 262)
  903. { /* End of VBlank Time */
  904. /* Sync at 60FPS */
  905. /* Get current time in microseconds */
  906. gettimeofday(&timeEnd, NULL);
  907. /* Calculate the waiting time, 16666 is the time of one frame in microseconds at a 60Hz rate) */
  908. WaitTime = (timeEnd.tv_sec) - (timeStart.tv_sec);
  909. WaitTime *= 1000000;
  910. WaitTime += (timeEnd.tv_usec - timeStart.tv_usec);
  911. WaitTime = 16666 - WaitTime + delta;
  912. /* If we press Page Up, we dont we to accelerate "time" */
  913. if (!key[KEY_PGUP])
  914. if ((WaitTime >= 0) && (WaitTime < 100000))
  915. usleep(WaitTime);
  916. //usleep(WaitTime<0?0:(WaitTime>100000?0:WaitTime));
  917. /* Now get the time after sleep */
  918. gettimeofday(&timeStart, NULL);
  919. /* Now calculate How many microseconds we really spend in sleep and
  920. calculate a delta for next iteration */
  921. delta = (timeStart.tv_sec) - (timeEnd.tv_sec);
  922. delta *= 1000000;
  923. delta += (timeStart.tv_usec - timeEnd.tv_usec);
  924. delta = WaitTime - delta;
  925. /* To avoid strange time warp when stoping emulation or using acceleration a lot */
  926. if ((delta > 10000) || (delta < -10000))
  927. delta = 0;
  928. ScanLine = 0;
  929. }
  930. else
  931. ScanLine++;
  932. if (keypressed())
  933. {
  934. skey = (readkey() & 0xFF);
  935. if (skey == 27)
  936. R->Trace = 1;
  937. if (skey == '9')
  938. {
  939. VBLANK_TIME += 1;
  940. printf("VBLT: %d\n", VBLANK_TIME);
  941. }
  942. if (skey == '6')
  943. {
  944. VBLANK_TIME -= 1;
  945. printf("VBLT: %d\n", VBLANK_TIME);
  946. }
  947. if (skey == '7')
  948. {
  949. HBLANK_TIME += 1;
  950. printf("HBLT: %d\n", HBLANK_TIME);
  951. MainCPU.IPeriod = HBLANK_TIME;
  952. }
  953. if (skey == '4')
  954. {
  955. HBLANK_TIME -= 1;
  956. printf("HBLT: %d\n", HBLANK_TIME);
  957. MainCPU.IPeriod = HBLANK_TIME;
  958. }
  959. // if ((skey == '&') || (skey == '1'))
  960. // ppu.ForceBgVisibility = ~ppu.ForceBgVisibility;
  961. // if ((skey == 'ª') || (skey == '2'))
  962. // ppu.ForceSpriteVisibility = ~ppu.ForceSpriteVisibility;
  963. // if ((skey == '"') || (skey == '3'))
  964. // ppu.DisplayNameTables = ~ppu.DisplayNameTables;
  965. // if ((skey == '\'') || (skey == '4'))
  966. // ppu.DisplayAttributeTable = ~ppu.DisplayAttributeTable;
  967. // if ((skey == '(') || (skey == '5'))
  968. // ppu.DisplayPalette = ~ppu.DisplayPalette;
  969. // if ((skey == '-') || (skey == 'fl') || (skey == '6'))
  970. // ppu.DisplayVRAM = ~ppu.DisplayVRAM;
  971. if ((skey == 'r') || (skey == 'R'))
  972. {
  973. //Reset6502(R);
  974. MainCPU.PC.B.l=Rd6502(0xFFFC);
  975. MainCPU.PC.B.h=Rd6502(0xFFFD);
  976. }
  977. plugin_keypress(skey);
  978. }
  979. if (WantClosing == 1)
  980. {
  981. ret = INT_QUIT;
  982. }
  983. return ret;
  984. }
  985. /** Patch6502() **********************************************/
  986. /** Emulation calls this function when it encounters an **/
  987. /** unknown opcode. This can be used to patch the code to **/
  988. /** emulate BIOS calls, such as disk and tape access. The **/
  989. /** function should return 1 if the exception was handled, **/
  990. /** or 0 if the opcode was truly illegal. **/
  991. /************************************ TO BE WRITTEN BY USER **/
  992. byte Patch6502(register byte Op, register M6502 * R)
  993. {
  994. //printf("Invalid Opcode : 0x%X @ 0x%04X !\n", Op, R->PC.W);
  995. return 1;
  996. }