JAVASCRIPT   185

cpu.js

Guest on 22nd August 2021 06:40:27 PM

  1. //
  2. //  Central Processing Unit
  3. //___________________________//
  4.  
  5. /**
  6.  * @namespace The central processing unit for the nes.
  7.  */
  8.  
  9. nes.cpu = {
  10.  
  11.         //
  12.         //  Properties
  13.         //______________//
  14.  
  15.         /**
  16.          * The nes' memory, representing each byte as a number.
  17.          * @type Array
  18.          */
  19.  
  20.         mem:null,
  21.  
  22.         /**
  23.          * The accumulator register.
  24.          * @type Number
  25.          */
  26.  
  27.         REG_ACC:0,
  28.  
  29.         /**
  30.          * The x register.
  31.          * @type Number
  32.          */
  33.  
  34.         REG_X:0,
  35.  
  36.         /**
  37.          * The y register.
  38.          * @type Number
  39.          */
  40.  
  41.         REG_Y:0,
  42.  
  43.         /**
  44.          * The stack pointer.
  45.          * @type Number
  46.          */
  47.  
  48.         REG_SP:0,
  49.  
  50.         /**
  51.          * The program counter.
  52.          * <br>
  53.          * A 16-bit register that holds the address of the next instruction to be executed.
  54.          * @type Number
  55.          */
  56.  
  57.         REG_PC:0,
  58.  
  59.         /**
  60.          * The sign status flag.
  61.          * <br>
  62.          * Kept in the cpu status byte as the 8th bit.
  63.          * @type Number
  64.          */
  65.  
  66.         F_SIGN:0,
  67.  
  68.         /**
  69.          * The overflow status flag.
  70.          * <br>
  71.          * Kept in the cpu status byte as the 7th bit.
  72.          * @type Number
  73.          */
  74.  
  75.         F_OVERFLOW:0,
  76.  
  77.         /**
  78.          * The break status flag.
  79.          * <br>
  80.          * Kept in the cpu status byte as the 5th bit.
  81.          * @type Number
  82.          */
  83.  
  84.         F_BRK:0,
  85.  
  86.         /**
  87.          * The decimal status flag.
  88.          * <br>
  89.          * Kept in the cpu status byte as the 4th bit.
  90.          * @type Number
  91.          */
  92.  
  93.         F_DECIMAL:0,
  94.  
  95.         /**
  96.          * The interrupt status flag.
  97.          * <br>
  98.          * Kept in the cpu status byte as the 3rd bit.
  99.          * @type Number
  100.          */
  101.  
  102.         F_INTERRUPT:0,
  103.  
  104.         /**
  105.          * The zero status flag.
  106.          * <br>
  107.          * Kept in the cpu status byte as the 2nd bit, inverted.
  108.          * @type Number
  109.          */
  110.  
  111.         F_ZERO:0,
  112.  
  113.         /**
  114.          * The carry status flag.
  115.          * <br>
  116.          * Kept in the cpu status byte as the 1st bit.
  117.          * @type Number
  118.          */
  119.  
  120.         F_CARRY:0,
  121.  
  122.         /**
  123.          * A flag indicating whether or not an interrupt has been requested.
  124.          * @type Boolean
  125.          */
  126.  
  127.         interruptRequested:false,
  128.  
  129.         /**
  130.          * The type of interrupt requested, 0:normal ,1:non-maskable, 2:reset.
  131.          * @type Number
  132.          */
  133.  
  134.         interruptType:0,
  135.  
  136.         /**
  137.          * The number of cpu cycles to halt.
  138.          * @type Number
  139.          */
  140.  
  141.         cyclesToHalt:0,
  142.  
  143.         /**
  144.          * A lookup table holding cyptic information on the cpu operations.
  145.          * @type Array
  146.          */
  147.  
  148.         opInfo:[117506570,100796962,255,255,255,50462754,84017154,255,50397732,33686818,33620994,255,255,67306274,100860674,255,33685769,84020002,255,255,255,67241506,100795906,255,33620493,67307810,255,255,255,67307554,117639170,255,100860700,100796929,255,255,50462726,50462721,84017191,255,67174950,33686785,33621031,255,67306246,67306241,100860711,255,33685767,84019969,255,255,255,67241473,100795943,255,33620524,67307777,255,255,255,67307521,117639207,255,100729385,100796951,255,255,255,50462743,84017184,255,50397731,33686807,33621024,255,50529051,67306263,100860704,255,33685771,84019991,255,255,255,67241495,100795936,255,33620495,67307799,255,255,255,67307543,117639200,255,100729386,100796928,255,255,255,50462720,84017192,255,67174949,33686784,33621032,255,84085787,67306240,100860712,255,33685772,84019968,255,255,255,67241472,100795944,255,33620526,67307776,255,255,255,67307520,117639208,255,255,100796975,255,255,50462769,50462767,50462768,255,33620502,255,33620533,255,67306289,67306287,67306288,255,33685763,100797231,255,255,67241521,67241519,67241776,255,33620535,84085039,33620534,255,255,84084783,255,255,33686815,100796957,33686814,255,50462751,50462749,50462750,255,33620531,33686813,33620530,255,67306271,67306269,67306270,255,33685764,84019997,255,255,67241503,67241501,67241758,255,33620496,67307805,33620532,255,67307551,67307549,67307806,255,33686803,100796945,255,255,50462739,50462737,84017172,255,33620506,33686801,33620501,255,67306259,67306257,100860692,255,33685768,84019985,255,255,255,67241489,100795924,255,33620494,67307793,255,255,255,67307537,117639188,255,33686802,100796971,255,255,50462738,50462763,84017176,255,33620505,33686827,33620513,255,67306258,67306283,100860696,255,33685765,84020011,255,255,255,67241515,100795928,255,33620525,67307819,255,255,255,67307563,117639192,255],
  149.  
  150.         //
  151.         //  Methods
  152.         //___________//
  153.  
  154.         /**
  155.          * Resets the memory and cpu state.
  156.          */
  157.  
  158.         reset:function nes_cpu_reset(){
  159.                 //Clear the memory.
  160.                 this.mem = new Array(0x10000);
  161.                 //Set addresses up to 0x2000 to 0xFF.
  162.                 for(var i=0;i<0x2000;i++){
  163.                         this.mem[i] = 0xFF;
  164.                 }
  165.                 //Set some odd addresses to some odd values.
  166.                 for(var i=0;i<4;i++){
  167.                         this.mem[i*0x800+0x008] = 0xF7;
  168.                         this.mem[i*0x800+0x009] = 0xEF;
  169.                         this.mem[i*0x800+0x00A] = 0xDF;
  170.                         this.mem[i*0x800+0x00F] = 0xBF;
  171.                 }
  172.                 //Set all other addresses to 0.
  173.                 for(var i=0x2001;i<0x10000;i++){
  174.                         this.mem[i] = 0;
  175.                 }
  176.                 //Reset the CPU registers.
  177.                 this.REG_ACC = 0;
  178.                 this.REG_X = 0;
  179.                 this.REG_Y = 0;
  180.                 //Reset the stack pointer.
  181.                 this.REG_SP = 0x01FF;
  182.                 //Reset the program counter.
  183.                 this.REG_PC = 0x7FFF;
  184.                 //Reset the CPU status flags.
  185.                 this.F_SIGN = 0;
  186.                 this.F_OVERFLOW = 0;
  187.                 this.F_BRK = 1;
  188.                 this.F_DECIMAL = 0;
  189.                 this.F_INTERRUPT = 1;
  190.                 this.F_ZERO = 1;
  191.                 this.F_CARRY = 0;
  192.                 //Reset the interrupt flags.
  193.                 this.interruptRequested = false;
  194.                 this.interruptType = 0;
  195.                 //Reset the cycles to halt number to 0.
  196.                 this.cyclesToHalt = 0;
  197.         },
  198.  
  199.         /**
  200.          * Sets the specified interrupt type as having been requested.
  201.          * @param {Number} type
  202.          */
  203.  
  204.         requestInterrupt:function nes_cpu_requestInterrupt(type){
  205.                 //Check if an interrupt is not already requested and the new interrupt is normal.
  206.                 if(!this.interruptRequested && type !== 0){
  207.                         //Set the request.
  208.                         this.interruptRequested = true;
  209.                         this.interruptType = type;
  210.                 }
  211.         },
  212.  
  213.         /**
  214.          * Sets the specified value in memory at the stack pointer.
  215.          * @param {Number} value
  216.          */
  217.  
  218.         push:function nes_cpu_push(value){
  219.                 //Write the value to the memory at the stack pointer.
  220.                 nes.mmc.write(this.REG_SP,value);
  221.                 //???
  222.                 this.REG_SP = 0x0100|((this.REG_SP-1)&0xFF);
  223.         },
  224.  
  225.         /**
  226.          * Returns the value in memory at the stack pointer.
  227.          * @returns {Number}
  228.          */
  229.  
  230.         pull:function nes_cpu_pull(){
  231.                 //???
  232.                 this.REG_SP = 0x0100|((this.REG_SP+1)&0xFF);
  233.                 //Return the address at the stack pointer.
  234.                 return nes.mmc.load(this.REG_SP);
  235.         },
  236.  
  237.         /**
  238.          * Sets the cpu state(made up of the 7 flags) in memory at the stack pointer.
  239.          */
  240.  
  241.         pushStatus:function nes_cpu_pushStatus(){
  242.                 //Push the cpu status onto the stack.
  243.                 this.push((this.F_SIGN<<7)|(this.F_OVERFLOW<<6)|32|(this.F_BRK<<4)|(this.F_DECIMAL<<3)|(this.F_INTERRUPT<<2)|((this.F_ZERO === 0?1:0)<<1)|this.F_CARRY);
  244.         },
  245.  
  246.         /**
  247.          * Adds the specified number of cycles to be halted.
  248.          * @param {Number} cycles
  249.          */
  250.  
  251.         haltCycles:function nes_cpu_haltCycles(cycles){
  252.                 //Add the specified number of cycles to halt.
  253.                 this.cyclesToHalt += cycles;
  254.         },
  255.  
  256.         /**
  257.          * Emulates a single cpu instruction, returning the number of cycles it required.
  258.          * @returns {Number}
  259.          */
  260.  
  261.         emulate:function nes_cpu_emulate(){
  262.                 //Check if an interrupt was requested.
  263.                 if(this.interruptRequested){
  264.                         //Reset the interrupt requested flag.
  265.                         this.interruptRequested = false;
  266.                         //Switch between the interrupt types.
  267.                         switch(this.interruptType){
  268.                                 //Normal Interrupt
  269.                                 case 0:{
  270.                                         if(this.F_INTERRUPT === 0){
  271.                                                 //???
  272.                                                 this.REG_PC++;
  273.                                                 this.push((this.REG_PC>>8)&0xFF);
  274.                                                 this.push(this.REG_PC&0xFF);
  275.                                                 //Push the cpu status onto the stack.
  276.                                                 this.pushStatus();
  277.                                                 this.F_INTERRUPT = 1;
  278.                                                 this.F_BRK = 0;
  279.                                                 //???
  280.                                                 this.REG_PC = (this.mem[0xFFFE]|(this.mem[0xFFFF]<<8))-1;
  281.                                         }
  282.                                         break;
  283.                                 }
  284.                                 //Non-Maskable Interrupt
  285.                                 case 1:{
  286.                                         //Check whether vBlank interrupts are enabled.
  287.                                         if((this.mem[0x2000]&128) !== 0){
  288.                                                 //???
  289.                                                 this.REG_PC++;
  290.                                                 this.push((this.REG_PC>>8)&0xFF);
  291.                                                 this.push(this.REG_PC&0xFF);
  292.                                                 //Push the cpu status onto the stack.
  293.                                                 this.pushStatus();
  294.                                                 //???
  295.                                                 this.REG_PC = (this.mem[0xFFFA]|(this.mem[0xFFFB]<<8))-1;
  296.                                         }
  297.                                         break;
  298.                                 }
  299.                                 //Reset Interrupt
  300.                                 case 2:{
  301.                                         //???
  302.                                         this.REG_PC = (this.mem[0xFFFC]|(this.mem[0xFFFD]<<8))-1;
  303.                                         break;
  304.                                 }
  305.                         }
  306.                 }
  307.                 //???
  308.                 var opinf = this.opInfo[this.mem[this.REG_PC+1]];
  309.                 var cycleCount = opinf>>24;
  310.                 var cycleAdd = 0;
  311.                 //Get the address mode.
  312.                 var addrMode = (opinf>>8)&0xFF;
  313.                 //Increment PC by number of op bytes.
  314.                 var opaddr = this.REG_PC;
  315.                 this.REG_PC += (opinf>>16)&0xFF;
  316.                 //Switch between the address modes.
  317.                 switch(addrMode){
  318.                         //Zero Page Mode
  319.                         //Use the address given after the opcode, but without high byte.
  320.                         case 0:{
  321.                                 var addr = this.mem[opaddr+2];
  322.                                 break;
  323.                         }
  324.                         //Relative Mode
  325.                         //???
  326.                         case 1:{
  327.                                 var addr = this.mem[opaddr+2];
  328.                                 if(addr < 0x80){
  329.                                         addr += this.REG_PC;
  330.                                 }
  331.                                 else{
  332.                                         addr += this.REG_PC-256;
  333.                                 }
  334.                                 break;
  335.                         }
  336.                         //Ignore
  337.                         //Address is implied in instruction.
  338.                         case 2:{
  339.                                 break;
  340.                         }
  341.                         //Absolute Mode
  342.                         //Use the two bytes following the operation code as the address.
  343.                         case 3:{
  344.                                 var addr = nes.mmc.load16bit(opaddr+2);
  345.                                 break;
  346.                         }
  347.                         //Accumulator Mode
  348.                         //The address is in the accumulator register.
  349.                         case 4:{
  350.                                 var addr = this.REG_ACC;
  351.                                 break;
  352.                         }
  353.                         //Imediate Mode
  354.                         //The address is given after the operation code.
  355.                         case 5:{
  356.                                 var addr = this.REG_PC;
  357.                                 break;
  358.                         }
  359.                         //Zero Page Indexed Mode X
  360.                         //Use the address after the operation code plus the x register.
  361.                         case 6:{
  362.                                 var addr = (this.mem[opaddr+2]+this.REG_X)&0xFF;
  363.                                 break;
  364.                         }
  365.                         //Zero Page Indexed Mode Y
  366.                         //Use the address after the operation code plus the y register.
  367.                         case 7:{
  368.                                 var addr = (this.mem[opaddr+2]+this.REG_Y)&0xFF;
  369.                                 break;
  370.                         }
  371.                         //Absolute Indexed Mode X
  372.                         //Same as zero page indexed x without the high byte.
  373.                         case 8:{
  374.                                 var addr = nes.mmc.load16bit(opaddr+2);
  375.                                 if((addr&0xFF00) !== ((addr+this.REG_X)&0xFF00)){
  376.                                         cycleAdd = 1;
  377.                                 }
  378.                                 addr += this.REG_X;
  379.                                 break;
  380.                         }
  381.                         //Absolute Indexed Mode Y
  382.                         //Same as zero page indexed y without the high byte.
  383.                         case 9:{
  384.                                 var addr = nes.mmc.load16bit(opaddr+2);
  385.                                 if((addr&0xFF00) !== ((addr+this.REG_Y)&0xFF00)){
  386.                                         cycleAdd = 1;
  387.                                 }
  388.                                 addr += this.REG_Y;
  389.                                 break;
  390.                         }
  391.                         //Pre-Indexed Indirect Mode
  392.                         //The address is in the 16-bit address starting at the given location plus the x register.
  393.                         case 10:{
  394.                                 var addr = this.mem[opaddr+2];
  395.                                 if((addr&0xFF00) !== ((addr+this.REG_X)&0xFF00)){
  396.                                         cycleAdd = 1;
  397.                                 }
  398.                                 addr = nes.mmc.load16bit((addr+this.REG_X)&0xFF);
  399.                                 break;
  400.                         }
  401.                         //Post-Indexed Indirect Mode
  402.                         case 11:{
  403.                                 //The address is in the 16-bit address starting at the given location plus the y register.
  404.                                 var addr = nes.mmc.load16bit(nes.mmc.load(opaddr+2));
  405.                                 if((addr&0xFF00) !== ((addr+this.REG_Y)&0xFF00)){
  406.                                         cycleAdd = 1;
  407.                                 }
  408.                                 addr += this.REG_Y;
  409.                                 break;
  410.                         }
  411.                         //Indirect Absolute Mode
  412.                         //Use the 16-bit address specified at the given location.
  413.                         case 12:{
  414.                                 var addr = nes.mmc.load16bit(opaddr+2);
  415.                                 addr = nes.mmc.load(addr)+(nes.mmc.load((addr&0xFF00)|(((addr&0xFF)+1)&0xFF))<<8);
  416.                                 break;
  417.                         }
  418.                 }
  419.                 //Wrap around for addresses above 0xFFFF.
  420.                 addr &= 0xFFFF;
  421.                 //Switch between the operations.
  422.                 switch(opinf&0xFF){
  423.  
  424.                         //ADC
  425.                         case 0:{
  426.                                 //Add with carry.
  427.                                 temp = this.REG_ACC+nes.mmc.load(addr)+this.F_CARRY;
  428.                                 this.F_OVERFLOW = ((!(((this.REG_ACC^nes.mmc.load(addr))&0x80) !== 0) && ((this.REG_ACC^temp)&0x80) !== 0)?1:0);
  429.                                 this.F_CARRY = temp > 255?1:0;
  430.                                 this.F_SIGN = (temp>>7)&1;
  431.                                 this.F_ZERO = temp&0xFF;
  432.                                 this.REG_ACC = temp&255;
  433.                                 cycleCount += cycleAdd;
  434.                                 break;
  435.                         }
  436.  
  437.                         //AND
  438.                         case 1:{
  439.                                 //AND memory with accumulator.
  440.                                 this.REG_ACC = this.REG_ACC & nes.mmc.load(addr);
  441.                                 this.F_SIGN = (this.REG_ACC>>7)&1;
  442.                                 this.F_ZERO = this.REG_ACC;
  443.                                 if(addrMode !== 11){
  444.                                         cycleCount += cycleAdd;
  445.                                 }
  446.                                 break;
  447.                         }
  448.  
  449.                         //ASL
  450.                         case 2:{
  451.                                 //Shift left one bit.
  452.                                 if(addrMode === 4){
  453.                                         this.F_CARRY = (this.REG_ACC>>7)&1;
  454.                                         this.REG_ACC = (this.REG_ACC<<1)&255;
  455.                                         this.F_SIGN = (this.REG_ACC>>7)&1;
  456.                                         this.F_ZERO = this.REG_ACC;
  457.                                 }
  458.                                 else{
  459.                                         var temp = nes.mmc.load(addr);
  460.                                         this.F_CARRY = (temp>>7)&1;
  461.                                         temp = (temp<<1)&255;
  462.                                         this.F_SIGN = (temp>>7)&1;
  463.                                         this.F_ZERO = temp;
  464.                                         nes.mmc.write(addr,temp);
  465.                                 }
  466.                                 break;
  467.                         }
  468.  
  469.                         //BCC
  470.                         case 3:{
  471.                                 //Branch on carry clear.
  472.                                 if(this.F_CARRY === 0){
  473.                                         cycleCount += ((opaddr&0xFF00) !== (addr&0xFF00)?2:1);
  474.                                         this.REG_PC = addr;
  475.                                 }
  476.                                 break;
  477.                         }
  478.  
  479.                         //BCS
  480.                         case 4:{
  481.                                 //Branch on carry set.
  482.                                 if(this.F_CARRY === 1){
  483.                                         cycleCount += ((opaddr&0xFF00) !== (addr&0xFF00)?2:1);
  484.                                         this.REG_PC = addr;
  485.                                 }
  486.                                 break;
  487.                         }
  488.  
  489.                         //BEQ
  490.                         case 5:{
  491.                                 //Branch on zero.
  492.                                 if(this.F_ZERO === 0){
  493.                                         cycleCount += ((opaddr&0xFF00) !== (addr&0xFF00)?2:1);
  494.                                         this.REG_PC = addr;
  495.                                 }
  496.                                 break;
  497.                         }
  498.  
  499.                         //BIT
  500.                         case 6:{
  501.                                 //Test bits.
  502.                                 var temp = nes.mmc.load(addr);
  503.                                 this.F_SIGN = (temp>>7)&1;
  504.                                 this.F_OVERFLOW = (temp>>6)&1;
  505.                                 this.F_ZERO = temp&this.REG_ACC;
  506.                                 break;
  507.                         }
  508.  
  509.                         //BMI
  510.                         case 7:{
  511.                                 //Branch on negative result.
  512.                                 if(this.F_SIGN === 1){
  513.                                         cycleCount++;
  514.                                         this.REG_PC = addr;
  515.                                 }
  516.                                 break;
  517.                         }
  518.  
  519.                         //BNE
  520.                         case 8:{
  521.                                 //Branch on not zero.
  522.                                 if(this.F_ZERO !== 0){
  523.                                         cycleCount += ((opaddr&0xFF00) !== (addr&0xFF00)?2:1);
  524.                                         this.REG_PC = addr;
  525.                                 }
  526.                                 break;
  527.                         }
  528.  
  529.                         //BPL
  530.                         case 9:{
  531.                                 //Branch on positive result.
  532.                                 if(this.F_SIGN === 0){
  533.                                         cycleCount += ((opaddr&0xFF00) !== (addr&0xFF00)?2:1);
  534.                                         this.REG_PC = addr;
  535.                                 }
  536.                                 break;
  537.                         }
  538.  
  539.                         //BRK
  540.                         case 10:{
  541.                                 //Simulate interrupt request.
  542.                                 this.REG_PC += 2;
  543.                                 this.push((this.REG_PC>>8)&255);
  544.                                 this.push(this.REG_PC&255);
  545.                                 this.F_BRK = 1;
  546.                                 this.pushStatus();
  547.                                 this.F_INTERRUPT = 1;
  548.                                 this.REG_PC = nes.mmc.load16bit(0xFFFE)-1;
  549.                                 break;
  550.                         }
  551.  
  552.                         //BVC
  553.                         case 11:{
  554.                                 //Branch on overflow clear.
  555.                                 if(this.F_OVERFLOW === 0){
  556.                                         cycleCount += ((opaddr&0xFF00) !== (addr&0xFF00)?2:1);
  557.                                         this.REG_PC = addr;
  558.                                 }
  559.                                 break;
  560.                         }
  561.  
  562.                         //BVS
  563.                         case 12:{
  564.                                 //Branch on overflow set.
  565.                                 if(this.F_OVERFLOW === 1){
  566.                                         cycleCount += ((opaddr&0xFF00) !== (addr&0xFF00)?2:1);
  567.                                         this.REG_PC = addr;
  568.                                 }
  569.                                 break;
  570.                         }
  571.  
  572.                         //CLC
  573.                         case 13:{
  574.                                 //Clear the carry flag.
  575.                                 this.F_CARRY = 0;
  576.                                 break;
  577.                         }
  578.  
  579.                         //CLD
  580.                         case 14:{
  581.                                 //Clear the decimal flag.
  582.                                 this.F_DECIMAL = 0;
  583.                                 break;
  584.                         }
  585.  
  586.                         //CLI
  587.                         case 15:{
  588.                                 //Clear the interrupt flag.
  589.                                 this.F_INTERRUPT = 0;
  590.                                 break;
  591.                         }
  592.  
  593.                         //CLV
  594.                         case 16:{
  595.                                 //Clear the overflow flag.
  596.                                 this.F_OVERFLOW = 0;
  597.                                 break;
  598.                         }
  599.  
  600.                         //CMP
  601.                         case 17:{
  602.                                 //Compare memory and accumulator.
  603.                                 temp = this.REG_ACC-nes.mmc.load(addr);
  604.                                 this.F_CARRY = (temp >= 0?1:0);
  605.                                 this.F_SIGN = (temp>>7)&1;
  606.                                 this.F_ZERO = temp&0xFF;
  607.                                 cycleCount += cycleAdd;
  608.                                 break;
  609.                         }
  610.  
  611.                         //CPX
  612.                         case 18:{
  613.                                 //Compare memory and index X.
  614.                                 temp = this.REG_X-nes.mmc.load(addr);
  615.                                 this.F_CARRY = (temp >= 0?1:0);
  616.                                 this.F_SIGN = (temp>>7)&1;
  617.                                 this.F_ZERO = temp&0xFF;
  618.                                 break;
  619.                         }
  620.  
  621.                         //CPY
  622.                         case 19:{
  623.                                 //Compare memory and index Y.
  624.                                 temp = this.REG_Y-nes.mmc.load(addr);
  625.                                 this.F_CARRY = (temp >= 0?1:0);
  626.                                 this.F_SIGN = (temp>>7)&1;
  627.                                 this.F_ZERO = temp&0xFF;
  628.                                 break;
  629.                         }
  630.  
  631.                         //DEC
  632.                         case 20:{
  633.                                 //Decrement memory by one.
  634.                                 temp = (nes.mmc.load(addr)-1)&0xFF;
  635.                                 this.F_SIGN = (temp>>7)&1;
  636.                                 this.F_ZERO = temp;
  637.                                 nes.mmc.write(addr,temp);
  638.                                 break;
  639.                         }
  640.  
  641.                         //DEX
  642.                         case 21:{
  643.                                 //Decrement index X by one.
  644.                                 this.REG_X = (this.REG_X-1)&0xFF;
  645.                                 this.F_SIGN = (this.REG_X>>7)&1;
  646.                                 this.F_ZERO = this.REG_X;
  647.                                 break;
  648.                         }
  649.  
  650.                         //DEC
  651.                         case 22:{
  652.                                 //Decrement index Y by one.
  653.                                 this.REG_Y = (this.REG_Y-1)&0xFF;
  654.                                 this.F_SIGN = (this.REG_Y>>7)&1;
  655.                                 this.F_ZERO = this.REG_Y;
  656.                                 break;
  657.                         }
  658.  
  659.                         //EOR
  660.                         case 23:{
  661.                                 //XOR Memory with accumulator, store in accumulator.
  662.                                 this.REG_ACC = (nes.mmc.load(addr)^this.REG_ACC)&0xFF;
  663.                                 this.F_SIGN = (this.REG_ACC>>7)&1;
  664.                                 this.F_ZERO = this.REG_ACC;
  665.                                 cycleCount += cycleAdd;
  666.                                 break;
  667.                         }
  668.  
  669.                         //INC
  670.                         case 24:{
  671.                                 //Increment memory by one.
  672.                                 temp = (nes.mmc.load(addr)+1)&0xFF;
  673.                                 this.F_SIGN = (temp>>7)&1;
  674.                                 this.F_ZERO = temp;
  675.                                 nes.mmc.write(addr,temp);
  676.                                 break;
  677.                         }
  678.  
  679.                         //INX
  680.                         case 25:{
  681.                                 //Increment index X by one.
  682.                                 this.REG_X = (this.REG_X+1)&0xFF;
  683.                                 this.F_SIGN = (this.REG_X>>7)&1;
  684.                                 this.F_ZERO = this.REG_X;
  685.                                 break;
  686.                         }
  687.  
  688.                         //INY
  689.                         case 26:{
  690.                                 //Increment index Y by one.
  691.                                 this.REG_Y = (this.REG_Y+1)&0xFF;
  692.                                 this.F_SIGN = (this.REG_Y>>7)&1;
  693.                                 this.F_ZERO = this.REG_Y;
  694.                                 break;
  695.                         }
  696.  
  697.                         //JMP
  698.                         case 27:{
  699.                                 //Jump to new location.
  700.                                 this.REG_PC = addr-1;
  701.                                 break;
  702.                         }
  703.  
  704.                         //JSR
  705.                         case 28:{
  706.                                 //Jump to new location, saving return address by pushing the return address onto the stack.
  707.                                 this.push((this.REG_PC>>8)&255);
  708.                                 this.push(this.REG_PC&255);
  709.                                 this.REG_PC = addr-1;
  710.                                 break;
  711.                         }
  712.  
  713.                         //LDA
  714.                         case 29:{
  715.                                 //Load accumulator with memory.
  716.                                 this.REG_ACC = nes.mmc.load(addr);
  717.                                 this.F_SIGN = (this.REG_ACC>>7)&1;
  718.                                 this.F_ZERO = this.REG_ACC;
  719.                                 cycleCount += cycleAdd;
  720.                                 break;
  721.                         }
  722.  
  723.                         //LDX
  724.                         case 30:{
  725.                                 //Load index X with memory.
  726.                                 this.REG_X = nes.mmc.load(addr);
  727.                                 this.F_SIGN = (this.REG_X>>7)&1;
  728.                                 this.F_ZERO = this.REG_X;
  729.                                 cycleCount += cycleAdd;
  730.                                 break;
  731.                         }
  732.  
  733.                         //LDY
  734.                         case 31:{
  735.                                 //Load index Y with memory.
  736.                                 this.REG_Y = nes.mmc.load(addr);
  737.                                 this.F_SIGN = (this.REG_Y>>7)&1;
  738.                                 this.F_ZERO = this.REG_Y;
  739.                                 cycleCount += cycleAdd;
  740.                                 break;
  741.                         }
  742.  
  743.                         //LSR
  744.                         case 32:{
  745.                                 //Shift right one bit.
  746.                                 if(addrMode === 4){
  747.                                         var temp = this.REG_ACC&0xFF;
  748.                                         this.F_CARRY = temp&1;
  749.                                         this.REG_ACC = temp>>1;
  750.                                 }
  751.                                 else{
  752.                                         var temp = nes.mmc.load(addr)&0xFF;
  753.                                         this.F_CARRY = temp&1;
  754.                                         nes.mmc.write(addr,temp>>1);
  755.                                 }
  756.                                 this.F_SIGN = 0;
  757.                                 this.F_ZERO = temp>>1;
  758.                                 break;
  759.                         }
  760.  
  761.                         //NOP
  762.                         case 33:{
  763.                                 //No operation, ignore.
  764.                                 break;
  765.                         }
  766.  
  767.                         //ORA
  768.                         case 34:{
  769.                                 //OR memory with accumulator, store in accumulator.
  770.                                 temp = (nes.mmc.load(addr)|this.REG_ACC)&255;
  771.                                 this.F_SIGN = (temp>>7)&1;
  772.                                 this.F_ZERO = temp;
  773.                                 this.REG_ACC = temp;
  774.                                 if(addrMode !== 11){
  775.                                         cycleCount += cycleAdd;
  776.                                 }
  777.                                 break;
  778.                         }
  779.  
  780.                         //PHA
  781.                         case 35:{
  782.                                 //Push accumulator onto the stack.
  783.                                 this.push(this.REG_ACC);
  784.                                 break;
  785.                         }
  786.  
  787.                         //PHP
  788.                         case 36:{
  789.                                 //Push processor status onto the stack.
  790.                                 this.F_BRK = 1;
  791.                                 this.pushStatus();
  792.                                 break;
  793.                         }
  794.  
  795.                         //PLA
  796.                         case 37:{
  797.                                 //Pull accumulator from the stack.
  798.                                 this.REG_ACC = this.pull();
  799.                                 this.F_SIGN = (this.REG_ACC>>7)&1;
  800.                                 this.F_ZERO = this.REG_ACC;
  801.                                 break;
  802.                         }
  803.  
  804.                         //PLP
  805.                         case 38:{
  806.                                 //Pull processor status from the stack.
  807.                                 temp = this.pull();
  808.                                 this.F_SIGN = (temp>>7)&1;
  809.                                 this.F_OVERFLOW = (temp>>6)&1;
  810.                                 this.F_BRK = (temp>>4)&1;
  811.                                 this.F_DECIMAL = (temp>>3)&1;
  812.                                 this.F_INTERRUPT = (temp>>2)&1;
  813.                                 this.F_ZERO = (((temp>>1)&1) === 1)?0:1;
  814.                                 this.F_CARRY = temp&1;
  815.                                 break;
  816.                         }
  817.  
  818.                         //ROL
  819.                         case 39:{
  820.                                 //Rotate one bit left.
  821.                                 var add = this.F_CARRY;
  822.                                 if(addrMode === 4){
  823.                                         var temp = ((this.REG_ACC<<1)&0xFF)+add;
  824.                                         this.F_CARRY = (this.REG_ACC>>7)&1;
  825.                                         this.REG_ACC = temp;
  826.                                 }
  827.                                 else{
  828.                                         var temp = nes.mmc.load(addr);
  829.                                         this.F_CARRY = (temp>>7)&1;
  830.                                         temp = ((temp<<1)&0xFF)+add;
  831.                                         nes.mmc.write(addr,temp);
  832.                                 }
  833.                                 this.F_SIGN = (temp>>7)&1;
  834.                                 this.F_ZERO = temp;
  835.                                 break;
  836.                         }
  837.  
  838.                         //ROR
  839.                         case 40:{
  840.                                 //Rotate one bit right.
  841.                                 if(addrMode === 4){
  842.                                         var temp = (this.REG_ACC>>1)+(this.F_CARRY<<7);
  843.                                         this.F_CARRY = this.REG_ACC&1;
  844.                                         this.REG_ACC = temp;
  845.                                 }
  846.                                 else{
  847.                                         var temp = nes.mmc.load(addr);
  848.                                         var add = this.F_CARRY<<7;
  849.                                         this.F_CARRY = temp&1;
  850.                                         temp = (temp>>1)+add;
  851.                                         nes.mmc.write(addr,temp);
  852.                                 }
  853.                                 this.F_SIGN = (temp>>7)&1;
  854.                                 this.F_ZERO = temp;
  855.                                 break;
  856.                         }
  857.  
  858.                         //RTI
  859.                         case 41:{
  860.                                 //Return from interrupt, pull the status and program counter from the stack.
  861.                                 temp = this.pull();
  862.                                 this.F_SIGN = (temp>>7)&1;
  863.                                 this.F_OVERFLOW = (temp>>6)&1;
  864.                                 this.F_BRK = (temp>>4)&1;
  865.                                 this.F_DECIMAL = (temp>>3)&1;
  866.                                 this.F_INTERRUPT = (temp>>2)&1
  867.                                 this.F_ZERO = ((temp>>1)&1) === 0?1:0;
  868.                                 this.F_CARRY = temp&1;
  869.                                 this.REG_PC = this.pull()+(this.pull()<<8);
  870.                                 if(this.REG_PC === 0xFFFF){
  871.                                         //Return from NSF play routine.
  872.                                         return;
  873.                                 }
  874.                                 this.REG_PC--;
  875.                                 break;
  876.                         }
  877.  
  878.                         //RTS
  879.                         case 42:{
  880.                                 //Return from subroutine, pull PC from stack.
  881.                                 this.REG_PC = this.pull()+(this.pull()<<8);
  882.                                 if(this.REG_PC === 0xFFFF){
  883.                                         //Return from NSF play routine.
  884.                                         return;
  885.                                 }
  886.                                 break;
  887.                         }
  888.  
  889.                         //SBC
  890.                         case 43:{
  891.                                 //Subtract memory with borrow.
  892.                                 temp = this.REG_ACC-nes.mmc.load(addr)-(1-this.F_CARRY);
  893.                                 this.F_SIGN = (temp>>7)&1;
  894.                                 this.F_ZERO = temp&0xFF;
  895.                                 this.F_OVERFLOW = ((((this.REG_ACC^temp)&0x80) !== 0 && ((this.REG_ACC^nes.mmc.load(addr))&0x80) !== 0)?1:0);
  896.                                 this.F_CARRY = (temp < 0?0:1);
  897.                                 this.REG_ACC = (temp&0xFF);
  898.                                 if(addrMode !== 11){
  899.                                         cycleCount+=cycleAdd;
  900.                                 }
  901.                                 break;
  902.                         }
  903.  
  904.                         //SEC
  905.                         case 44:{
  906.                                 //Set carry flag.
  907.                                 this.F_CARRY = 1;
  908.                                 break;
  909.                         }
  910.  
  911.                         //SED
  912.                         case 45:{
  913.                                 //Set decimal mode.
  914.                                 this.F_DECIMAL = 1;
  915.                                 break;
  916.                         }
  917.  
  918.                         //SEI
  919.                         case 46:{
  920.                                 //Set interrupt disable status.
  921.                                 this.F_INTERRUPT = 1;
  922.                                 break;
  923.                         }
  924.  
  925.                         //STA
  926.                         case 47:{
  927.                                 //Store accumulator in memory.
  928.                                 nes.mmc.write(addr,this.REG_ACC);
  929.                                 break;
  930.                         }
  931.  
  932.                         //STX
  933.                         case 48:{
  934.                                 //Store index X in memory.
  935.                                 nes.mmc.write(addr,this.REG_X);
  936.                                 break;
  937.                         }
  938.  
  939.                         //STY
  940.                         case 49:{
  941.                                 //Store index Y in memory.
  942.                                 nes.mmc.write(addr,this.REG_Y);
  943.                                 break;
  944.                         }
  945.  
  946.                         //TAX
  947.                         case 50:{
  948.                                 //Transfer accumulator to index X.
  949.                                 this.REG_X = this.REG_ACC;
  950.                                 this.F_SIGN = (this.REG_ACC>>7)&1;
  951.                                 this.F_ZERO = this.REG_ACC;
  952.                                 break;
  953.                         }
  954.  
  955.                         //TAY
  956.                         case 51:{
  957.                                 //Transfer accumulator to index Y.
  958.                                 this.REG_Y = this.REG_ACC;
  959.                                 this.F_SIGN = (this.REG_ACC>>7)&1;
  960.                                 this.F_ZERO = this.REG_ACC;
  961.                                 break;
  962.                         }
  963.  
  964.                         //TSX
  965.                         case 52:{
  966.                                 //Transfer stack pointer to index X.
  967.                                 this.REG_X = this.REG_SP-0x0100;
  968.                                 this.F_SIGN = (this.REG_SP>>7)&1;
  969.                                 this.F_ZERO = this.REG_X;
  970.                                 break;
  971.                         }
  972.  
  973.                         //TXA
  974.                         case 53:{
  975.                                 //Transfer index X to accumulator.
  976.                                 this.REG_ACC = this.REG_X;
  977.                                 this.F_SIGN = (this.REG_X>>7)&1;
  978.                                 this.F_ZERO = this.REG_X;
  979.                                 break;
  980.                         }
  981.  
  982.                         //TXS
  983.                         case 54:{
  984.                                 //Transfer index X to stack pointer.
  985.                                 this.REG_SP = 0x0100|((this.REG_X+0x0100)&0xFF);
  986.                                 break;
  987.                         }
  988.  
  989.                         //TYA
  990.                         case 55:{
  991.                                 //Transfer index Y to accumulator.
  992.                                 this.REG_ACC = this.REG_Y;
  993.                                 this.F_SIGN = (this.REG_Y>>7)&1;
  994.                                 this.F_ZERO = this.REG_Y;
  995.                                 break;
  996.                         }
  997.  
  998.                         //???
  999.                         default:{
  1000.                                 //Invalid operation code, stop emulation.
  1001.                                 nes.stop();
  1002.                                 alert('Game crashed, invalid opcode('+opinf&0xFF+') at address 0x'+opaddr.toString(16)+'.');
  1003.                                 break;
  1004.                         }
  1005.  
  1006.                 }
  1007.                 //Return the number of cycles.
  1008.                 return cycleCount;
  1009.         }
  1010.  
  1011. };

Raw Paste


Login or Register to edit or fork this paste. It's free.