M6502.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /** M6502: portable 6502 emulator ****************************/
  2. /** **/
  3. /** M6502.c **/
  4. /** **/
  5. /** This file contains implementation for 6502 CPU. Don't **/
  6. /** forget to provide Rd6502(), Wr6502(), Loop6502(), and **/
  7. /** possibly Op6502() functions to accomodate the emulated **/
  8. /** machine's architecture. **/
  9. /** **/
  10. /** Copyright (C) Marat Fayzullin 1996-2002 **/
  11. /** Alex Krasivsky 1996 **/
  12. /** You are not allowed to distribute this software **/
  13. /** commercially. Please, notify me, if you make any **/
  14. /** changes to this file. **/
  15. /*************************************************************/
  16. /*
  17. * $LastChangedDate$
  18. * $Author$
  19. * $HeadURL$
  20. * $Revision$
  21. */
  22. #include "M6502.h"
  23. #include "Tables.h"
  24. #include <stdio.h>
  25. /** INLINE ***************************************************/
  26. /** Different compilers inline C functions differently. **/
  27. /*************************************************************/
  28. #ifdef __GNUC__
  29. #define INLINE inline
  30. #else
  31. #define INLINE static
  32. #endif
  33. int icount = 0;
  34. /** System-Dependent Stuff ***********************************/
  35. /** This is system-dependent code put here to speed things **/
  36. /** up. It has to stay inlined to be fast. **/
  37. /*************************************************************/
  38. #ifdef INES
  39. #define FAST_RDOP
  40. extern byte *Page[];
  41. INLINE byte Op6502(register word A) { return(Page[A>>13][A&0x1FFF]); }
  42. #endif
  43. /** FAST_RDOP ************************************************/
  44. /** With this #define not present, Rd6502() should perform **/
  45. /** the functions of Rd6502(). **/
  46. /*************************************************************/
  47. #ifndef FAST_RDOP
  48. #define Op6502(A) Rd6502(A)
  49. #endif
  50. /** Addressing Methods ***************************************/
  51. /** These macros calculate and return effective addresses. **/
  52. /*************************************************************/
  53. #define MC_Ab(Rg) M_LDWORD(Rg)
  54. #define MC_Zp(Rg) Rg.W=Op6502(R->PC.W++)
  55. #define MC_Zx(Rg) Rg.W=(byte)(Op6502(R->PC.W++)+R->X)
  56. #define MC_Zy(Rg) Rg.W=(byte)(Op6502(R->PC.W++)+R->Y)
  57. #define MC_Ax(Rg) M_LDWORD(Rg);Rg.W+=R->X
  58. #define MC_Ay(Rg) M_LDWORD(Rg);Rg.W+=R->Y
  59. #define MC_Ix(Rg) K.W=(byte)(Op6502(R->PC.W++)+R->X); \
  60. Rg.B.l=Op6502(K.W++);Rg.B.h=Op6502(K.W)
  61. #define MC_Iy(Rg) K.W=Op6502(R->PC.W++); \
  62. Rg.B.l=Op6502(K.W++);Rg.B.h=Op6502(K.W); \
  63. Rg.W+=R->Y
  64. /** Reading From Memory **************************************/
  65. /** These macros calculate address and read from it. **/
  66. /*************************************************************/
  67. #define MR_Ab(Rg) MC_Ab(J);Rg=Rd6502(J.W)
  68. #define MR_Im(Rg) Rg=Op6502(R->PC.W++)
  69. #define MR_Zp(Rg) MC_Zp(J);Rg=Rd6502(J.W)
  70. #define MR_Zx(Rg) MC_Zx(J);Rg=Rd6502(J.W)
  71. #define MR_Zy(Rg) MC_Zy(J);Rg=Rd6502(J.W)
  72. #define MR_Ax(Rg) MC_Ax(J);Rg=Rd6502(J.W)
  73. #define MR_Ay(Rg) MC_Ay(J);Rg=Rd6502(J.W)
  74. #define MR_Ix(Rg) MC_Ix(J);Rg=Rd6502(J.W)
  75. #define MR_Iy(Rg) MC_Iy(J);Rg=Rd6502(J.W)
  76. /** Writing To Memory ****************************************/
  77. /** These macros calculate address and write to it. **/
  78. /*************************************************************/
  79. #define MW_Ab(Rg) MC_Ab(J);Wr6502(J.W,Rg)
  80. #define MW_Zp(Rg) MC_Zp(J);Wr6502(J.W,Rg)
  81. #define MW_Zx(Rg) MC_Zx(J);Wr6502(J.W,Rg)
  82. #define MW_Zy(Rg) MC_Zy(J);Wr6502(J.W,Rg)
  83. #define MW_Ax(Rg) MC_Ax(J);Wr6502(J.W,Rg)
  84. #define MW_Ay(Rg) MC_Ay(J);Wr6502(J.W,Rg)
  85. #define MW_Ix(Rg) MC_Ix(J);Wr6502(J.W,Rg)
  86. #define MW_Iy(Rg) MC_Iy(J);Wr6502(J.W,Rg)
  87. /** Modifying Memory *****************************************/
  88. /** These macros calculate address and modify it. **/
  89. /*************************************************************/
  90. #define MM_Ab(Cmd) MC_Ab(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
  91. #define MM_Zp(Cmd) MC_Zp(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
  92. #define MM_Zx(Cmd) MC_Zx(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
  93. #define MM_Ax(Cmd) MC_Ax(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
  94. /** Other Macros *********************************************/
  95. /** Calculating flags, stack, jumps, arithmetics, etc. **/
  96. /*************************************************************/
  97. #define M_FL(Rg) R->P=(R->P&~(Z_FLAG|N_FLAG))|ZNTable[Rg]
  98. #define M_LDWORD(Rg) Rg.B.l=Op6502(R->PC.W++);Rg.B.h=Op6502(R->PC.W++)
  99. #define M_PUSH(Rg) Wr6502(0x0100|R->S,Rg);R->S--
  100. #define M_POP(Rg) R->S++;Rg=Op6502(0x0100|R->S)
  101. #define M_JR R->PC.W+=(offset)Op6502(R->PC.W)+1;R->ICount--
  102. #ifdef NO_DECIMAL
  103. #define M_ADC(Rg) \
  104. K.W=R->A+Rg+(R->P&C_FLAG); \
  105. R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
  106. R->P|=(~(R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
  107. (K.B.h? C_FLAG:0)|ZNTable[K.B.l]; \
  108. R->A=K.B.l
  109. /* Warning! C_FLAG is inverted before SBC and after it */
  110. #define M_SBC(Rg) \
  111. K.W=R->A-Rg-(~R->P&C_FLAG); \
  112. R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
  113. R->P|=((R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
  114. (K.B.h? 0:C_FLAG)|ZNTable[K.B.l]; \
  115. R->A=K.B.l
  116. #else /* NO_DECIMAL */
  117. #define M_ADC(Rg) \
  118. if(R->P&D_FLAG) \
  119. { \
  120. K.B.l=(R->A&0x0F)+(Rg&0x0F)+(R->P&C_FLAG); \
  121. if(K.B.l>9) K.B.l+=6; \
  122. K.B.h=(R->A>>4)+(Rg>>4)+(K.B.l>15? 1:0); \
  123. R->A=(K.B.l&0x0F)|(K.B.h<<4); \
  124. R->P=(R->P&~C_FLAG)|(K.B.h>15? C_FLAG:0); \
  125. } \
  126. else \
  127. { \
  128. K.W=R->A+Rg+(R->P&C_FLAG); \
  129. R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
  130. R->P|=(~(R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
  131. (K.B.h? C_FLAG:0)|ZNTable[K.B.l]; \
  132. R->A=K.B.l; \
  133. }
  134. /* Warning! C_FLAG is inverted before SBC and after it */
  135. #define M_SBC(Rg) \
  136. if(R->P&D_FLAG) \
  137. { \
  138. K.B.l=(R->A&0x0F)-(Rg&0x0F)-(~R->P&C_FLAG); \
  139. if(K.B.l&0x10) K.B.l-=6; \
  140. K.B.h=(R->A>>4)-(Rg>>4)-((K.B.l&0x10)>>4); \
  141. if(K.B.h&0x10) K.B.h-=6; \
  142. R->A=(K.B.l&0x0F)|(K.B.h<<4); \
  143. R->P=(R->P&~C_FLAG)|(K.B.h>15? 0:C_FLAG); \
  144. } \
  145. else \
  146. { \
  147. K.W=R->A-Rg-(~R->P&C_FLAG); \
  148. R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
  149. R->P|=((R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
  150. (K.B.h? 0:C_FLAG)|ZNTable[K.B.l]; \
  151. R->A=K.B.l; \
  152. }
  153. #endif /* NO_DECIMAL */
  154. #define M_CMP(Rg1,Rg2) \
  155. K.W=Rg1-Rg2; \
  156. R->P&=~(N_FLAG|Z_FLAG|C_FLAG); \
  157. R->P|=ZNTable[K.B.l]|(K.B.h? 0:C_FLAG)
  158. #define M_BIT(Rg) \
  159. R->P&=~(N_FLAG|V_FLAG|Z_FLAG); \
  160. R->P|=(Rg&(N_FLAG|V_FLAG))|(Rg&R->A? 0:Z_FLAG)
  161. #define M_AND(Rg) R->A&=Rg;M_FL(R->A)
  162. #define M_ORA(Rg) R->A|=Rg;M_FL(R->A)
  163. #define M_EOR(Rg) R->A^=Rg;M_FL(R->A)
  164. #define M_INC(Rg) Rg++;M_FL(Rg)
  165. #define M_DEC(Rg) Rg--;M_FL(Rg)
  166. #define M_ASL(Rg) R->P&=~C_FLAG;R->P|=Rg>>7;Rg<<=1;M_FL(Rg)
  167. #define M_LSR(Rg) R->P&=~C_FLAG;R->P|=Rg&C_FLAG;Rg>>=1;M_FL(Rg)
  168. #define M_ROL(Rg) K.B.l=(Rg<<1)|(R->P&C_FLAG); \
  169. R->P&=~C_FLAG;R->P|=Rg>>7;Rg=K.B.l; \
  170. M_FL(Rg)
  171. #define M_ROR(Rg) K.B.l=(Rg>>1)|(R->P<<7); \
  172. R->P&=~C_FLAG;R->P|=Rg&C_FLAG;Rg=K.B.l; \
  173. M_FL(Rg)
  174. /** Reset6502() **********************************************/
  175. /** This function can be used to reset the registers before **/
  176. /** starting execution with Run6502(). It sets registers to **/
  177. /** their initial values. **/
  178. /*************************************************************/
  179. void Reset6502(M6502 *R)
  180. {
  181. R->A=R->X=R->Y=0x00;
  182. R->P=Z_FLAG;
  183. R->S=0xFF;
  184. R->PC.B.l=Rd6502(0xFFFC);
  185. R->PC.B.h=Rd6502(0xFFFD);
  186. R->ICount=R->IPeriod;
  187. R->IRequest=INT_NONE;
  188. R->AfterCLI=0;
  189. }
  190. /** Exec6502() ***********************************************/
  191. /** This function will execute a single 6502 opcode. It **/
  192. /** will then return next PC, and current register values **/
  193. /** in R. **/
  194. /*************************************************************/
  195. word Exec6502(M6502 *R)
  196. {
  197. register pair J,K;
  198. register byte I;
  199. I=Op6502(R->PC.W++);
  200. R->ICount-=Cycles[I];
  201. switch(I)
  202. {
  203. #include "Codes.h"
  204. }
  205. /* We are done */
  206. return(R->PC.W);
  207. }
  208. /** Int6502() ************************************************/
  209. /** This function will generate interrupt of a given type. **/
  210. /** INT_NMI will cause a non-maskable interrupt. INT_IRQ **/
  211. /** will cause a normal interrupt, unless I_FLAG set in R. **/
  212. /*************************************************************/
  213. void Int6502(M6502 *R,byte Type)
  214. {
  215. register pair J;
  216. if((Type==INT_NMI)||((Type==INT_IRQ)&&!(R->P&I_FLAG)))
  217. {
  218. R->ICount-=7;
  219. M_PUSH(R->PC.B.h);
  220. M_PUSH(R->PC.B.l);
  221. M_PUSH(R->P & ~(B_FLAG|R_FLAG));
  222. R->P&=~D_FLAG;
  223. if(R->IAutoReset&&(Type==R->IRequest)) R->IRequest=INT_NONE;
  224. if(Type==INT_NMI) J.W=0xFFFA; else { R->P|=I_FLAG;J.W=0xFFFE; }
  225. R->PC.B.l=Rd6502(J.W++);
  226. R->PC.B.h=Rd6502(J.W);
  227. }
  228. }
  229. #ifdef TRACE_EXECUTION
  230. enum Addressing_Modes
  231. {
  232. Ac = 0, Il, Im, Ab, Zp, Zx, Zy, Ax, Ay, Rl, Ix, Iy, In, No
  233. };
  234. static char *mnCAP[] =
  235. {
  236. "ADC", "AND", "ASL", "BCC", "BCS", "BEQ", "BIT", "BMI",
  237. "BNE", "BPL", "BRK", "BVC", "BVS", "CLC", "CLD", "CLI",
  238. "CLV", "CMP", "CPX", "CPY", "DEC", "DEX", "DEY", "INX",
  239. "INY", "EOR", "INC", "JMP", "JSR", "LDA", "NOP", "LDX",
  240. "LDY", "LSR", "ORA", "PHA", "PHP", "PLA", "PLP", "ROL",
  241. "ROR", "RTI", "RTS", "SBC", "STA", "STX", "STY", "SEC",
  242. "SED", "SEI", "TAX", "TAY", "TXA", "TYA", "TSX", "TXS"
  243. };
  244. #define DAsm DAsmCAP
  245. static byte ad[512] =
  246. {
  247. 10, Il, 34, Ix, No, No, No, No, No, No, 34, Zp, 2, Zp, No, No,
  248. 36, Il, 34, Im, 2, Ac, No, No, No, No, 34, Ab, 2, Ab, No, No,
  249. 9, Rl, 34, Iy, No, No, No, No, No, No, 34, Zx, 2, Zx, No, No,
  250. 13, Il, 34, Ay, No, No, No, No, No, No, 34, Ax, 2, Ax, No, No,
  251. 28, Ab, 1, Ix, No, No, No, No, 6, Zp, 1, Zp, 39, Zp, No, No,
  252. 38, Il, 1, Im, 39, Ac, No, No, 6, Ab, 1, Ab, 39, Ab, No, No,
  253. 7, Rl, 1, Iy, No, No, No, No, No, No, 1, Zx, 39, Zx, No, No,
  254. 47, Il, 1, Ay, No, No, No, No, No, No, 1, Ax, 39, Ax, No, No,
  255. 41, Il, 25, Ix, No, No, No, No, No, No, 25, Zp, 33, Zp, No, No,
  256. 35, Il, 25, Im, 33, Ac, No, No, 27, Ab, 25, Ab, 33, Ab, No, No,
  257. 11, Rl, 25, Iy, No, No, No, No, No, No, 25, Zx, 33, Zx, No, No,
  258. 15, Il, 25, Ay, No, No, No, No, No, No, 25, Ax, 33, Ax, No, No,
  259. 42, Il, 0, Ix, No, No, No, No, No, No, 0, Zp, 40, Zp, No, No,
  260. 37, Il, 0, Im, 40, Ac, No, No, 27, In, 0, Ab, 40, Ab, No, No,
  261. 12, Rl, 0, Iy, No, No, No, No, No, No, 0, Zx, 40, Zx, No, No,
  262. 49, Il, 0, Ay, No, No, No, No, No, No, 0, Ax, 40, Ax, No, No,
  263. No, No, 44, Ix, No, No, No, No, 46, Zp, 44, Zp, 45, Zp, No, No,
  264. 22, Il, No, No, 52, Il, No, No, 46, Ab, 44, Ab, 45, Ab, No, No,
  265. 3, Rl, 44, Iy, No, No, No, No, 46, Zx, 44, Zx, 45, Zy, No, No,
  266. 53, Il, 44, Ay, 55, Il, No, No, No, No, 44, Ax, No, No, No, No,
  267. 32, Im, 29, Ix, 31, Im, No, No, 32, Zp, 29, Zp, 31, Zp, No, No,
  268. 51, Il, 29, Im, 50, Il, No, No, 32, Ab, 29, Ab, 31, Ab, No, No,
  269. 4, Rl, 29, Iy, No, No, No, No, 32, Zx, 29, Zx, 31, Zy, No, No,
  270. 16, Il, 29, Ay, 54, Il, No, No, 32, Ax, 29, Ax, 31, Ay, No, No,
  271. 19, Im, 17, Ix, No, No, No, No, 19, Zp, 17, Zp, 20, Zp, No, No,
  272. 24, Il, 17, Im, 21, Il, No, No, 19, Ab, 17, Ab, 20, Ab, No, No,
  273. 8, Rl, 17, Iy, No, No, No, No, No, No, 17, Zx, 20, Zx, No, No,
  274. 14, Il, 17, Ay, No, No, No, No, No, No, 17, Ax, 20, Ax, No, No,
  275. 18, Im, 43, Ix, No, No, No, No, 18, Zp, 43, Zp, 26, Zp, No, No,
  276. 23, Il, 43, Im, 30, Il, No, No, 18, Ab, 43, Ab, 26, Ab, No, No,
  277. 5, Rl, 43, Iy, No, No, No, No, No, No, 43, Zx, 26, Zx, No, No,
  278. 48, Il, 43, Ay, No, No, No, No, No, No, 43, Ax, 26, Ax, No, No
  279. };
  280. #define RDWORD(A) (Rd6502(A+1)*256+Rd6502(A))
  281. /** DAsm() ****************************************************/
  282. /** This function will disassemble a single command and **/
  283. /** return the number of bytes disassembled. **/
  284. /**************************************************************/
  285. int DAsmCAP(char *S, word A)
  286. {
  287. byte J;
  288. word B, OP, TO;
  289. B = A;
  290. OP = Rd6502(B++) * 2;
  291. switch (ad[OP + 1])
  292. {
  293. case Ac:
  294. sprintf(S, "%s A", mnCAP[ad[OP]]);
  295. break;
  296. case Il:
  297. sprintf(S, "%s", mnCAP[ad[OP]]);
  298. break;
  299. case Rl:
  300. J = Rd6502(B++);
  301. TO = A + 2 + ((J < 0x80) ? J : (J - 256));
  302. sprintf(S, "%s $%04x", mnCAP[ad[OP]], TO);
  303. break;
  304. case Im:
  305. sprintf(S, "%s #$%02x", mnCAP[ad[OP]], Rd6502(B++));
  306. break;
  307. case Zp:
  308. sprintf(S, "%s $%02x", mnCAP[ad[OP]], Rd6502(B++));
  309. break;
  310. case Zx:
  311. sprintf(S, "%s $%02x,X", mnCAP[ad[OP]], Rd6502(B++));
  312. break;
  313. case Zy:
  314. sprintf(S, "%s $%02x,Y", mnCAP[ad[OP]], Rd6502(B++));
  315. break;
  316. case Ix:
  317. sprintf(S, "%s ($%02x,X)", mnCAP[ad[OP]], Rd6502(B++));
  318. break;
  319. case Iy:
  320. sprintf(S, "%s ($%02x),Y", mnCAP[ad[OP]], Rd6502(B++));
  321. break;
  322. case Ab:
  323. sprintf(S, "%s $%04x", mnCAP[ad[OP]], RDWORD(B));
  324. B += 2;
  325. break;
  326. case Ax:
  327. sprintf(S, "%s $%04x,X", mnCAP[ad[OP]], RDWORD(B));
  328. B += 2;
  329. break;
  330. case Ay:
  331. sprintf(S, "%s $%04x,Y", mnCAP[ad[OP]], RDWORD(B));
  332. B += 2;
  333. break;
  334. case In:
  335. sprintf(S, "%s ($%04x)", mnCAP[ad[OP]], RDWORD(B));
  336. B += 2;
  337. break;
  338. default:
  339. sprintf(S, ".db $%02x; <Invalid OPcode>", OP / 2);
  340. }
  341. return (B - A);
  342. }
  343. extern unsigned short ScanLine;
  344. #endif
  345. /** Run6502() ************************************************/
  346. /** This function will run 6502 code until Loop6502() call **/
  347. /** returns INT_QUIT. It will return the PC at which **/
  348. /** emulation stopped, and current register values in R. **/
  349. /*************************************************************/
  350. word Run6502(M6502 *R)
  351. {
  352. register pair J,K;
  353. register byte I;
  354. byte nb_of_cycle;
  355. for(;;)
  356. {
  357. #ifdef DEBUG
  358. /* Turn tracing on when reached trap address */
  359. if(R->PC.W==R->Trap) R->Trace=1;
  360. /* Call single-step debugger, exit if requested */
  361. if(R->Trace)
  362. if(!Debug6502(R)) return(R->PC.W);
  363. #endif
  364. #ifdef TRACE_EXECUTION
  365. while(1)
  366. {
  367. static char FA[8] = "NV.BDIZC";
  368. char S[128];
  369. byte F;
  370. int J, I;
  371. DAsm(S, R->PC.W);
  372. printf
  373. (
  374. "AT PC: [%02x - %s]\n",
  375. Rd6502(R->PC.W), S
  376. );
  377. break;
  378. }
  379. #endif
  380. I=Op6502(R->PC.W++);
  381. nb_of_cycle = Cycles[I];
  382. //#ifdef DEBUG
  383. // pushop(I);
  384. //#endif
  385. icount++;
  386. switch(I)
  387. {
  388. #include "Codes.h"
  389. }
  390. #ifdef TRACE_EXECUTION
  391. while(1)
  392. {
  393. static char FA[8] = "NV.BDIZC";
  394. char S[128];
  395. byte F;
  396. int J, I;
  397. printf
  398. (
  399. "A:%02x X:%02x Y:%02x S:%04x, PC:%04x Flags:[",
  400. R->A, R->X, R->Y, R->S + 0x0100, R->PC.W
  401. );
  402. for (J = 0, F = R->P; J < 8; J++, F <<= 1)
  403. printf("%c", F & 0x80 ? FA[J] : '.');
  404. printf("], Stack[%02x, %02x, %02x], %03d, %03d\n",
  405. Rd6502(0x0100 + (byte) (R->S + 1)),
  406. Rd6502(0x0100 + (byte) (R->S + 2)),
  407. Rd6502(0x0100 + (byte) (R->S + 3)),
  408. R->ICount,
  409. ScanLine
  410. );
  411. break;
  412. }
  413. #endif
  414. R->ICount-= nb_of_cycle;
  415. /* If cycle counter expired... */
  416. if(R->ICount<=0)
  417. {
  418. /* If we have come after CLI, get INT_? from IRequest */
  419. /* Otherwise, get it from the loop handler */
  420. if(R->AfterCLI)
  421. {
  422. I=R->IRequest; /* Get pending interrupt */
  423. R->ICount+=R->IBackup-1; /* Restore the ICount */
  424. R->AfterCLI=0; /* Done with AfterCLI state */
  425. }
  426. else
  427. {
  428. I=Loop6502(R); /* Call the periodic handler */
  429. R->ICount+=R->IPeriod; /* Reset the cycle counter */
  430. if(!I) I=R->IRequest; /* Realize pending interrupt */
  431. }
  432. if(I==INT_QUIT) return(R->PC.W); /* Exit if INT_QUIT */
  433. if(I) Int6502(R,I); /* Interrupt if needed */
  434. }
  435. }
  436. /* Execution stopped */
  437. return(R->PC.W);
  438. }