Advertisement
Guest User

NES

a guest
Nov 5th, 2012
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 31.85 KB | None | 0 0
  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <cstdint>
  4. #include <cstring>
  5. #include <SDL.h>
  6.  
  7. SDL_Surface *screen = NULL;
  8.  
  9. class PPU
  10. {
  11.     public:
  12.     uint8_t ctrl0;
  13.     uint8_t ctrl1;
  14.  
  15.     uint8_t mapper;
  16.  
  17.     uint16_t addr;
  18.     bool lohi;
  19.  
  20.     uint8_t pat0[0x1000];
  21.     uint8_t pat1[0x1000];
  22.     uint8_t nt0[0x3C0];
  23.     uint8_t at0[0x40];
  24.     uint8_t nt1[0x3C0];
  25.     uint8_t at1[0x40];
  26.     uint8_t nt2[0x3C0];
  27.     uint8_t at2[0x40];
  28.     uint8_t nt3[0x3C0];
  29.     uint8_t at3[0x40];
  30.     uint8_t spr_pal[0x10];
  31.     uint8_t bg_pal[0x10];
  32.     uint8_t oam[0x100];
  33.     uint16_t scanline;
  34.     uint16_t cycles;
  35.     uint16_t cycles_next;
  36.  
  37.     uint16_t vram_addr;
  38.  
  39.     uint8_t nmi;
  40.  
  41.     int tilenum;
  42.  
  43.     PPU()
  44.     {
  45.         vram_addr = 0x2000;
  46.         cycles_next = 0;
  47.         tilenum = 0;
  48.         lohi = 0;
  49.         for(int i = 0;i<16;i++) bg_pal[i] = 0;
  50.  
  51.     }
  52.  
  53.     void wb(uint16_t addr, uint8_t value)
  54.     {
  55.         if(addr >= 0 && addr < 0x1000) pat0[addr] = value;
  56.         if(addr >= 0x1000 && addr < 0x2000) pat1[addr - 0x1000] = value;
  57.         if(mapper == 0)
  58.         {
  59.             if(addr >= 0x2000 && addr < 0x23C0) nt0[addr - 0x2000] = value;
  60.             if(addr >= 0x23C0 && addr < 0x2400) at0[addr - 0x23C0] = value;
  61.             if(addr >= 0x2400 && addr < 0x27C0) nt1[addr - 0x2400] = value;
  62.             if(addr >= 0x27C0 && addr < 0x2800) at1[addr - 0x27C0] = value;
  63.             if(addr >= 0x2800 && addr < 0x2BC0) nt0[addr - 0x2800] = value;
  64.             if(addr >= 0x2BC0 && addr < 0x2C00) at0[addr - 0x2BC0] = value;
  65.             if(addr >= 0x2C00 && addr < 0x2FC0) nt1[addr - 0x2C00] = value;
  66.             if(addr >= 0x2FC0 && addr < 0x3000) at1[addr - 0x2FC0] = value;
  67.         }
  68.         if(addr >= 0x3F00 && addr < 0x3F10) bg_pal[addr - 0x3F00] = value;
  69.         if(addr >= 0x3F10 && addr < 0x3F20) spr_pal[addr - 0x3F10] = value;
  70.         if(addr >= 0x3F20 && addr < 0x3F30) bg_pal[addr - 0x3F20] = value;
  71.         if(addr >= 0x3F30 && addr < 0x3F40) spr_pal[addr - 0x3F30] = value;
  72.         if(addr >= 0x3F40 && addr < 0x3F50) bg_pal[addr - 0x3F40] = value;
  73.         if(addr >= 0x3F50 && addr < 0x3F60) spr_pal[addr - 0x3F50] = value;
  74.         if(addr >= 0x3F40 && addr < 0x3F50) bg_pal[addr - 0x3F40] = value;
  75.         if(addr >= 0x3F50 && addr < 0x3F60) spr_pal[addr - 0x3F50] = value;
  76.         if(addr >= 0x3F60 && addr < 0x3F70) bg_pal[addr - 0x3F60] = value;
  77.         if(addr >= 0x3F70 && addr < 0x3F80) spr_pal[addr - 0x3F70] = value;
  78.     }
  79.  
  80.     uint8_t rb(uint16_t addr)
  81.     {
  82.         if(addr >= 0 && addr < 0x1000) return pat0[addr];
  83.         if(addr >= 0x1000 && addr < 0x2000) return pat1[addr - 0x1000];
  84.         if(mapper == 0)
  85.         {
  86.             if(addr >= 0x2000 && addr < 0x23C0) return nt0[addr - 0x2000];
  87.             if(addr >= 0x23C0 && addr < 0x2400) return at0[addr - 0x23C0];
  88.             if(addr >= 0x2400 && addr < 0x27C0) return nt1[addr - 0x2400];
  89.             if(addr >= 0x27C0 && addr < 0x2800) return at1[addr - 0x27C0];
  90.             if(addr >= 0x2800 && addr < 0x2BC0) return nt0[addr - 0x2800];
  91.             if(addr >= 0x2BC0 && addr < 0x2C00) return at0[addr - 0x2BC0];
  92.             if(addr >= 0x2C00 && addr < 0x2FC0) return nt1[addr - 0x2C00];
  93.             if(addr >= 0x2FC0 && addr < 0x3000) return at1[addr - 0x2FC0];
  94.         }
  95.         if(addr >= 0x3F00 && addr < 0x3F10) return bg_pal[addr - 0x3F00];
  96.         if(addr >= 0x3F10 && addr < 0x3F20) return spr_pal[addr - 0x3F10];
  97.         if(addr >= 0x3F20 && addr < 0x3F30) return bg_pal[addr - 0x3F20];
  98.         if(addr >= 0x3F30 && addr < 0x3F40) return spr_pal[addr - 0x3F30];
  99.         if(addr >= 0x3F40 && addr < 0x3F50) return bg_pal[addr - 0x3F40];
  100.         if(addr >= 0x3F50 && addr < 0x3F60) return spr_pal[addr - 0x3F50];
  101.         if(addr >= 0x3F60 && addr < 0x3F70) return bg_pal[addr - 0x3F60];
  102.         if(addr >= 0x3F70 && addr < 0x3F80) return spr_pal[addr - 0x3F70];
  103.         if(addr >= 0x3F80 && addr < 0x3F90) return bg_pal[addr - 0x3F80];
  104.         if(addr >= 0x3F90 && addr < 0x3FA0) return spr_pal[addr - 0x3F90];
  105.     }
  106.  
  107.     void putpixel(uint8_t color,int x, int y)
  108.     {
  109.         uint8_t *p = (uint8_t*)screen->pixels + ((y * 256 + x) * 3);
  110.  
  111.         //printf("PPU color: %02x\n",color);
  112.  
  113.         switch(color & 0x3F)
  114.         {
  115.             case 0x00:
  116.             p[0] = 124;
  117.             p[1] = 124;
  118.             p[2] = 124;
  119.             break;
  120.             case 0x0C:
  121.             p[0] = 88;
  122.             p[1] = 64;
  123.             p[2] = 0;
  124.             break;
  125.             case 0x0D:
  126.             p[0] = 0;
  127.             p[1] = 0;
  128.             p[2] = 0;
  129.             break;
  130.             case 0x0E:
  131.             p[0] = 0;
  132.             p[1] = 0;
  133.             p[2] = 0;
  134.             break;
  135.             case 0x0F:
  136.             p[0] = 0;
  137.             p[1] = 0;
  138.             p[2] = 0;
  139.             break;
  140.             case 0x20:
  141.             p[0] = 0xFF;
  142.             p[1] = 0xFF;
  143.             p[2] = 0xFF;
  144.             case 0x21:
  145.             p[0] = 252;
  146.             p[1] = 188;
  147.             p[2] = 60;
  148.             case 0x22:
  149.             p[0] = 252;
  150.             p[1] = 136;
  151.             p[2] = 104;
  152.             case 0x30:
  153.             p[0] = 0xFF;
  154.             p[1] = 0xFF;
  155.             p[2] = 0xFF;
  156.         }
  157.     }
  158.  
  159.     void dumpscan()
  160.     {
  161.         //printf("Scanline %i\n",scanline);
  162.         //printf("Cycles %i\n",cycles);
  163.     }
  164.  
  165.     void tick()
  166.     {
  167.         if(cycles_next > 0)
  168.         {
  169.             cycles_next--;
  170.             return;
  171.         }
  172.         if(scanline >= 0 && scanline < 239)
  173.         {
  174.             if(cycles<255)
  175.             {
  176.                 uint8_t tile_num = rb(0x2000 + (((cycles + 1) >> 3) * ((scanline + 1) >> 3)));
  177.                 uint8_t tile_pal = 0;
  178.                 uint8_t tile_pat_0 = (rb((tile_num << 1) + 0x1000) & (1<<(cycles>>5))) >> (1<<(cycles>>5));
  179.                 uint8_t tile_pat_1 = (rb((tile_num << 1) + 0x1001) & (1<<(cycles>>5))) >> (1<<(cycles>>5));
  180.                 uint8_t tile_pat = tile_pat_0 | (tile_pat_1 << 1);
  181.                 uint8_t tile_pix = rb(0x3F00 + tile_pat);
  182.                 putpixel(tile_pix,cycles,scanline);
  183.             }
  184.         }
  185.         if(scanline == 241 && cycles<=2)
  186.         {
  187.             nmi = 1;
  188.         }
  189.         else nmi = 0;
  190.         if(scanline == 261 && cycles == 339)
  191.         {
  192.             printf("Frame complete.\n");
  193.         }
  194.         cycles++;
  195.         if(cycles >= 340)
  196.         {
  197.             cycles = 0;
  198.             scanline++;
  199.         }
  200.         if(scanline >= 262)
  201.         {
  202.             scanline = 0;
  203.         }
  204.     }
  205. };
  206.  
  207. class CPU
  208. {
  209. public:
  210.     PPU ppu;
  211.     uint8_t mapper;
  212.     uint8_t PRGbanks;
  213.     uint8_t CHRbanks;
  214.     uint8_t ram[0x2000];
  215.     uint8_t ioregs[0x2020];
  216.     uint8_t exprom[0x1980];
  217.     uint8_t sram[0x2000];
  218.     uint8_t rom[0x8000];
  219.     uint8_t* totalrom;
  220.     uint8_t* chrrom;
  221.     uint16_t pc;
  222.     uint8_t a,x,y,s;
  223. /* Processor Status Register
  224.  * Bit 0 - Carry
  225.  * Bit 1 - Zero
  226.  * Bit 2 - Interrupt
  227.  * Bit 3 - Decimal Mode, not used in NES
  228.  * Bit 4 - Software Interrupts
  229.  * Bit 5 - 1
  230.  * Bit 6 - Overflow
  231.  * Bit 7 - Negative
  232.  */
  233.     uint8_t p;
  234.     uint16_t cycles;
  235.  
  236.     uint8_t rb(uint16_t addr)
  237.         {
  238.         if(addr >= 0x0000 && addr < 0x2000)
  239.         {
  240.             return ram[addr];
  241.         }
  242.         if(addr >= 0x2000 && addr < 0x4020)
  243.         {
  244.             return ioregs[addr - 0x2000];
  245.         }
  246.         if(addr >= 0x4020 && addr < 0x6000)
  247.         {
  248.             return exprom[addr - 0x4020];
  249.         }
  250.         if(addr >= 0x6000 && addr < 0x8000)
  251.         {
  252.             return sram[addr - 0x6000];
  253.         }
  254.         if(addr >= 0x8000)
  255.         {
  256.             return rom[addr - 0x8000];
  257.         }
  258.     }
  259.  
  260.     CPU()
  261.     {
  262.         a = 0x00;
  263.         x = 0x00;
  264.         y = 0x00;
  265.         s = 0xFD;
  266.         p = 0x34;
  267.         pc = 0x8000;
  268.         cycles = 0;
  269.     }
  270.     void CHRSwap4(uint8_t value, uint16_t addr)
  271.     {
  272.         memcpy((addr>=0x1000) ? ppu.pat1 : ppu.pat0,chrrom + (value * 0x1000),0x1000);
  273.     }
  274.     void CHRSwap8(uint8_t value, uint16_t addr)
  275.     {
  276.         memcpy(ppu.pat0,chrrom + (value * 0x1000),0x1000);
  277.         memcpy(ppu.pat1,chrrom + (value * 0x1000) + 0x1000,0x1000);
  278.     }
  279.     void PRGSwap8(uint8_t value, uint16_t addr)
  280.     {
  281.         memcpy(rom + (addr - 0x8000),totalrom + (value * 0x2000),0x2000);
  282.     }
  283.     void PRGSwap16(uint8_t value, uint16_t addr)
  284.     {
  285.         memcpy(rom + (addr - 0x8000),totalrom + (value * 0x4000),0x4000);
  286.     }
  287.     void PRGSwap32(uint8_t value, uint16_t addr)
  288.     {
  289.         memcpy(rom + (addr - 0x8000),totalrom + (value * 0x8000),0x8000);
  290.     }
  291.     void wb(uint16_t addr, uint8_t value)
  292.     {
  293.         if(addr >= 0x0000 && addr < 0x2000)
  294.         {
  295.             ram[addr] = value;
  296.         }
  297.         if(addr >= 0x2000 && addr < 0x4020)
  298.         {
  299.             if(addr==0x2000){printf("PPU: CRTL0 write %02x\n",value); ppu.ctrl0 = value;}
  300.             if(addr==0x2001){printf("PPU: CRTL1 write %02x\n",value); ppu.ctrl1 = value;}
  301.             if(addr==0x2006){printf("PPU: ADDR write %02x\n",value); if(ppu.lohi == 0){ppu.addr &= 0xFF00; ppu.addr |= value;} else{ppu.addr &= 0xFF; ppu.addr |= (value<<8);} ppu.lohi = ~ppu.lohi;}
  302.             if(addr==0x2007){printf("PPU: DATA write %02x to PPU address %04x\n",value, ppu.addr); ppu.wb(ppu.addr,value);}
  303.             ioregs[addr - 0x2000] = value;
  304.         }
  305.         if(addr >= 0x4020 && addr < 0x6000)
  306.         {
  307.             exprom[addr - 0x4020] = value;
  308.         }
  309.         if(addr >= 0x6000 && addr < 0x8000)
  310.         {
  311.             sram[addr - 0x6000] = value;
  312.         }
  313.         if(addr >= 0x8000)
  314.         {
  315.             if(mapper == 0) return; //printf("Why am I trying to write to ROM?\n");
  316.             else if(mapper == 2) PRGSwap16(value & 7,0x8000);
  317.             else if(mapper == 3) CHRSwap8(value & 3,0);
  318.             else if(mapper == 7) PRGSwap32(value & 15,0x8000); //TODO: Mirroring
  319.             else if(mapper == 9)
  320.             {
  321.                 if(addr >= 0xA000 && addr < 0xB000) PRGSwap8(value,0x8000);
  322.                 if(addr >= 0xB000 && addr < 0xD000) CHRSwap4(value,0x0000);
  323.                 if(addr >= 0xD000 && addr < 0xE000) CHRSwap4(value,0x1000);
  324.                 if(addr >= 0xE000 && addr < 0xF000) CHRSwap4(value,0x1000); //TODO: Mirroring
  325.             }
  326.             else if(mapper == 13) CHRSwap4(value & 3,0x1000);
  327.             else if(mapper == 34) PRGSwap32(value & 3,0x8000);
  328.             else if(mapper == 66)
  329.             {
  330.                 PRGSwap32(value & 0x30,0x8000);
  331.                 CHRSwap8(value & 3,0x0000);
  332.             }
  333.             else if(mapper == 75)
  334.             {
  335.                 if(addr == 0x8000) PRGSwap8(value & 15,0x8000);
  336.                 if(addr == 0xA000) PRGSwap8(value & 15,0xA000);
  337.                 if(addr == 0xC000) PRGSwap8(value & 15,0xC000);
  338.                 //TODO: CHR swapping
  339.             }
  340.             else if(mapper == 180) PRGSwap16(value & 7,0xC000);
  341.         }
  342.     }
  343.     void LoadROM(FILE* fp)
  344.     {
  345.         if(mapper == 0)
  346.         {
  347.             fseek(fp,0x10,SEEK_SET);
  348.             if(PRGbanks == 2)
  349.             {
  350.                 fread(rom,1,0x8000,fp);
  351.                 fread(chrrom,1,0x2000*CHRbanks,fp);
  352.             }
  353.             if(PRGbanks == 1) fread(rom+0x4000,1,0x4000,fp);
  354.         }
  355.         else if(mapper == 2)
  356.         {
  357.             uint8_t* rom_ptr = rom + 0x4000;
  358.             fseek(fp,(PRGbanks - 1) * 0x4000,SEEK_SET);
  359.             fread(rom_ptr,1,0x4000,fp);
  360.             fseek(fp,0x10,SEEK_SET);
  361.             fread(rom,1,0x4000,fp);
  362.         }
  363.         else if(mapper == 3)
  364.         {
  365.             fseek(fp,(PRGbanks * 0x4000) + 0x10,SEEK_SET);
  366.             fread(ppu.pat0,1,0x2000,fp);
  367.         }
  368.         else if(mapper == 7)
  369.         {
  370.             fseek(fp,0x10,SEEK_SET);
  371.             fread(rom,1,0x8000,fp);
  372.         }
  373.         else if(mapper == 13)
  374.         {
  375.             fseek(fp,(PRGbanks * 0x4000) + 0x10,SEEK_SET);
  376.             fread(ppu.pat0,1,0x1000,fp);
  377.             fread(ppu.pat1,1,0x1000,fp);
  378.         }
  379.         else if(mapper == 34)
  380.         {
  381.             fseek(fp,0x10,SEEK_SET);
  382.             fread(rom,1,0x8000,fp);
  383.         }
  384.         else if(mapper == 66)
  385.         {
  386.             fseek(fp,0x10,SEEK_SET);
  387.             fread(rom,1,0x8000,fp);
  388.         }
  389.         else if(mapper == 75)
  390.         {
  391.             uint8_t* rom_ptr = rom + 0x6000;
  392.             fseek(fp,(PRGbanks - 1) * 0x2000,SEEK_SET);
  393.             fread(rom_ptr,1,0x2000,fp);
  394.             fseek(fp,0x10,SEEK_SET);
  395.             fread(rom,1,0x6000,fp);
  396.         }
  397.         else if(mapper == 180)
  398.         {
  399.             fseek(fp,0x10,SEEK_SET);
  400.             fread(rom,1,0x8000,fp);
  401.         }
  402.     }
  403.     void dumpregs()
  404.     {
  405.         //printf("a = %02x\n",a);
  406.         //printf("x = %02x\n",x);
  407.         //printf("y = %02x\n",y);
  408.         //printf("s = %02x\n",s);
  409.         //printf("p = %02x\n",p);
  410.         //printf("pc = %04x\n",pc);
  411.     }
  412.     int tick()
  413.     {
  414.         for(int i = 0;i<3;i++) ppu.tick();
  415.         if(ppu.nmi == 1)
  416.         {
  417.             pc = (rb(0xFFFA) << 8) | rb(0xFFFB); //Read NMI vector
  418.         }
  419.         if(cycles != 0)
  420.         {
  421.             cycles--;
  422.             return 0;
  423.         }
  424.         else
  425.         {
  426.             uint8_t op = rb(pc);
  427.             switch(op)
  428.             {
  429.                 case 0x00:
  430.                     //printf("BRK\n");
  431.                     pc = (rb(0xFFFE) << 8) | rb(0xFFFF); //Read BRK vector
  432.                     cycles+=6;
  433.                     break;
  434.                 case 0x01:
  435.                     //printf("ORA ($%02x,X)\n",rb(pc+1));
  436.                     a |= rb(rb(pc+1)+x);
  437.                     if(a==0) p |= 2;
  438.                     else p &= 0xFD;
  439.                     if((a&0x80) == 0x80) p |= 0x80;
  440.                     else p &= 0x7F;
  441.                             cycles+=6;
  442.                             pc+=2;
  443.                             break;
  444.                 case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52: case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
  445.                     printf("KIL\n");
  446.                     return 1;
  447.                     break;
  448.                 case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64: case 0x74: case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
  449.                     //printf("NOP\n");
  450.                     cycles+=1;
  451.                     pc+=2;
  452.                     break;
  453.                 case 0x05:
  454.                             //printf("ORA $%02x\n",rb(pc+1));
  455.                         a |= rb(rb(pc+1));
  456.                     if(a==0) p |= 2;
  457.                     else p &= 0xFD;
  458.                     if((a&0x80) == 0x80) p |= 0x80;
  459.                     else p &= 0x7F;
  460.                             cycles+=2;
  461.                     pc+=2;
  462.                         break;
  463.                 case 0x06:
  464.                 {
  465.                     //printf("ASL $%02x\n",rb(pc+1));
  466.                     p |= (rb(pc+1) & 0x80) >> 7;
  467.                     wb(rb(pc+1),(rb(rb(pc+1)) << 1) & 0xFF);
  468.                     int tmp = (rb(pc+1) << 1) & 0xFF;
  469.                     if(tmp==0) p |= 2;
  470.                     else p &= 0xFD;
  471.                     if((tmp&0x80) == 0x80) p |= 0x80;
  472.                     else p &= 0x7F;
  473.                     cycles+=5;
  474.                     pc+=2;
  475.                     break;
  476.                 }
  477.                 case 0x07:
  478.                 {
  479.                     //printf("SLO $%02x\n",rb(pc+1));
  480.                     p |= (rb(pc+1) & 0x80) >> 7;
  481.                     wb(rb(pc+1),((rb(rb(pc+1)) << 1) & 0xFF) | a);
  482.                     int tmp = ((rb(pc+1) << 1) & 0xFF) | a;
  483.                     if(tmp==0) p |= 2;
  484.                     else p &= 0xFD;
  485.                     if((tmp&0x80) == 0x80) p |= 0x80;
  486.                     else p &= 0x7F;
  487.                     cycles+=5;
  488.                     pc+=2;
  489.                     break;
  490.                 }
  491.                 case 0x08:
  492.                     //printf("PHP\n");
  493.                     wb(s,p);
  494.                     s-=1;
  495.                     cycles+=2;
  496.                     pc+=1;
  497.                     break;
  498.                 case 0x09:
  499.                     //printf("ORA #$%02x\n",rb(pc+1));
  500.                     a |= rb(pc+1);
  501.                     if(a==0) p |= 2;
  502.                     else p &= 0xFD;
  503.                     if((a&0x80) == 0x80) p |= 0x80;
  504.                     else p &= 0x7F;
  505.                     cycles+=2;
  506.                     pc+=2;
  507.                     break;
  508.                 case 0x0A:
  509.                     //printf("ASL A\n");
  510.                     p |= (a & 0x80) >> 7;
  511.                     a = a << 1;
  512.                     if(a==0) p |= 2;
  513.                     else p &= 0xFD;
  514.                     if((a&0x80) == 0x80) p |= 0x80;
  515.                     else p &= 0x7F;
  516.                     cycles+=2;
  517.                     pc+=1;
  518.                     break;
  519.                 case 0x10:
  520.                     //printf("BPL #$%02x\n",rb(pc+1));
  521.                     cycles+=2;
  522.                     if((p & 0x80) != 0x80)
  523.                     {
  524.                         cycles+=1;
  525.                         if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  526.                         pc += (int8_t)rb(pc+1);
  527.                         pc += 2;
  528.                     }
  529.                     else pc+=2;
  530.                     break;
  531.                 case 0x18:
  532.                     //printf("CLC\n");
  533.                     p &= 0xFE;
  534.                     cycles+=2;
  535.                     pc+=1;
  536.                     break;
  537.                 case 0x20:
  538.                     //printf("JSR $%04x\n",(rb(pc+2)<<8) | rb(pc+1));
  539.                     wb((s-2) | 0x100,pc+2);
  540.                     wb((s-1) | 0x100,pc+2>>8);
  541.                     s-=2;
  542.                     cycles+=6;
  543.                     pc=(rb(pc+2)<<8) | rb(pc+1);
  544.                     break;
  545.                 case 0x24:
  546.                     //printf("BIT $%02x\n", rb(pc+1));
  547.                     if((a & rb(rb(pc+1))) == 0) p |= 2;
  548.                     else p &= 0xFD;
  549.                     p &= 0x3F;
  550.                     p |= rb(rb(pc+1)) & 0xC0;
  551.                     cycles+=2;
  552.                     pc+=2;
  553.                     break;
  554.                 case 0x28:
  555.                     //printf("PLP\n");
  556.                     p = rb(s+1);
  557.                     s+=1;
  558.                     cycles+=4;
  559.                     pc+=1;
  560.                     break;
  561.                     case 0x29:
  562.                         //printf("AND #$%02x\n",rb(pc+1));
  563.                     a &= rb(pc+1);
  564.                     if(a==0) p |= 2;
  565.                     else p &= 0xFD;
  566.                     if((a&0x80) == 0x80) p |= 0x80;
  567.                     else p &= 0x7F;
  568.                     cycles+=2;
  569.                     pc+=2;
  570.                     break;
  571.                 case 0x2C:
  572.                     //printf("BIT $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
  573.                     if((a & rb((rb(pc+2)<<8) | rb(pc+1))) == 0) p |= 2;
  574.                     else p &= 0xFD;
  575.                     p |= rb((rb(pc+2)<<8) | rb(pc+1)) & 0xC0;
  576.                     cycles+=4;
  577.                     pc+=3;
  578.                     break;
  579.                 case 0x30:
  580.                     //printf("BMI $%02x\n",rb(pc+1));
  581.                     cycles+=2;
  582.                     if((p & 0x80) == 0x80)
  583.                     {
  584.                         cycles+=1;
  585.                         if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  586.                         pc += (int8_t)rb(pc+1);
  587.                         pc += 2;
  588.                     }
  589.                     else pc+=2;
  590.                     break;
  591.                 case 0x38:
  592.                     //printf("SEC\n");
  593.                     p |= 0x01;
  594.                     cycles+=2;
  595.                     pc+=1;
  596.                     break;
  597.                 case 0x46:
  598.                     //printf("LSR $%02x\n", rb(pc+1));
  599.                     if((rb(rb(pc+1)) & 0x01) == 0) p |= 2;
  600.                     else p &= 0xFD;
  601.                     if((rb(rb(pc+1)) & 0x80) == 0x80) p |= 0x80;
  602.                     else p &= 0x7F;
  603.                     wb(rb(pc+1),rb(rb(pc+1))>>1);
  604.                     cycles+=5;
  605.                     pc+=2;
  606.                     break;
  607.                 case 0x48:
  608.                     //printf("PHA\n");
  609.                     wb(s,a);
  610.                     s-=1;
  611.                     cycles+=2;
  612.                     pc+=1;
  613.                     break;
  614.                 case 0x49:
  615.                     //printf("EOR #$%02x\n",rb(pc+1));
  616.                     a ^= rb(pc+1);
  617.                     if(a==0) p |= 2;
  618.                     else p &= 0xFD;
  619.                     if((a&0x80) == 0x80) p |= 0x80;
  620.                     else p &= 0x7F;
  621.                     cycles+=2;
  622.                     pc+=2;
  623.                     break;
  624.                 case 0x4A:
  625.                     //printf("LSR A\n");
  626.                     if((a & 0x01) == 0) p |= 2;
  627.                     else
  628.                     {
  629.                         p &= 0xFD;
  630.                         p |= 1;
  631.                     }
  632.                     if((a & 0x80) == 0x80) p |= 0x80;
  633.                     else p &= 0x7F;
  634.                     a = a>>1;
  635.                     cycles+=2;
  636.                     pc+=1;
  637.                     break;
  638.                 case 0x4C:
  639.                     //printf("JMP $%04x\n",(rb(pc+2)<<8) | rb(pc+1));
  640.                     cycles+=3;
  641.                     pc=(rb(pc+2)<<8) | rb(pc+1);
  642.                     break;
  643.                 case 0x50:
  644.                     //printf("BVC $%02x\n",rb(pc+1));
  645.                     cycles+=2;
  646.                     if((p & 0x40) == 0)
  647.                     {
  648.                         cycles+=1;
  649.                         if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  650.                         pc += (int8_t)rb(pc+1);
  651.                         pc += 2;
  652.                     }
  653.                     else pc+=2;
  654.                     break;
  655.                 case 0x60:
  656.                     //printf("RTS\n");
  657.                     pc = (((rb((s+1) | 0x100)<<8) | rb(s | 0x100)) + 1);
  658.                     s+=2;
  659.                     cycles+=6;
  660.                     break;
  661.                 case 0x65:
  662.                     //printf("ADC $%02x\n",rb(pc+1));
  663.                     a += (p&1) + rb(rb(pc+1));
  664.                     if(a==0) p |= 2;
  665.                     else p &= 0xFD;
  666.                     if((a&0x80) == 0x80) p |= 0x80;
  667.                     else p &= 0x7F;
  668.                     cycles+=4;
  669.                     if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  670.                     pc+=2;
  671.                     break;
  672.                 case 0x68:
  673.                     //printf("PLA\n");
  674.                     a = rb(s+1);
  675.                     s+=1;
  676.                     if(a==0) p |= 2;
  677.                     else p &= 0xFD;
  678.                     if((a&0x80) == 0x80) p |= 0x80;
  679.                     else p &= 0x7F;
  680.                     cycles+=4;
  681.                     pc+=1;
  682.                     break;
  683.                 case 0x69:
  684.                 {
  685.                     //printf("ADC #$%02x\n",rb(pc+1));
  686.                     uint8_t tmp = a;
  687.                     a += (p&1) + rb(pc+1);
  688.                     if(a==0) p |= 2;
  689.                     else p &= 0xFD;
  690.                     if((a&0x80) == 0x80) p |= 0x80;
  691.                     else p &= 0x7F;
  692.                     if(a>=0x80) p |= 0x40;
  693.                     else p &= 0xBF;
  694.                     if(a<tmp) p |= 1;
  695.                     else p &= 0xFE;
  696.                     cycles+=1;
  697.                     pc+=2;
  698.                     break;
  699.                 }
  700.                 case 0x6C:
  701.                 {
  702.                     uint16_t tmp = (rb(pc+2)<<8) | rb(pc+1);
  703.                     //printf("JMP ($%04x)\n",(rb(pc+2)<<8) | rb(pc+1));
  704.                     cycles+=5;
  705.                     pc = (rb(tmp)<<8) | rb(tmp+1);
  706.                     break;
  707.                 }
  708.                 case 0x70:
  709.                     //printf("BVS $%02x\n",rb(pc+1));
  710.                     cycles+=2;
  711.                     if((p & 0x40) == 0x40)
  712.                     {
  713.                         cycles+=1;
  714.                         if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  715.                         pc += (int8_t)rb(pc+1);
  716.                         pc += 2;
  717.                     }
  718.                     else pc+=2;
  719.                     break;
  720.                 case 0x78:
  721.                     //printf("SEI\n");
  722.                     p |= 0x08;
  723.                     cycles+=2;
  724.                     pc+=1;
  725.                     break;
  726.                 case 0x79:
  727.                     //printf("ADC $%04x,Y\n",(rb(pc+2)<<8) | rb(pc+1));
  728.                     a += (p&1) + rb(((rb(pc+2)<<8) | rb(pc+1)) + y);
  729.                     if(a==0) p |= 2;
  730.                     else p &= 0xFD;
  731.                     if((a&0x80) == 0x80) p |= 0x80;
  732.                     else p &= 0x7F;
  733.                     cycles+=4;
  734.                     if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  735.                     pc+=3;
  736.                     break;
  737.                 case 0x85:
  738.                     //printf("STA $%02x\n",rb(pc+1));
  739.                     wb((uint16_t)rb(pc+1),a);
  740.                     cycles+=3;
  741.                     pc+=2;
  742.                     break;
  743.                 case 0x86:
  744.                     //printf("STX $%02x\n",rb(pc+1));
  745.                     wb((uint16_t)rb(pc+1),x);
  746.                     cycles+=3;
  747.                     pc+=2;
  748.                     break;
  749.                 case 0x88:
  750.                     //printf("DEY\n");
  751.                     y--;
  752.                     if(y==0) p |= 2;
  753.                     else p &= 0xFD;
  754.                     if((y&0x80) == 0x80) p |= 0x80;
  755.                     else p &= 0x7F;
  756.                     cycles+=2;
  757.                     pc+=1;
  758.                     break;
  759.                 case 0x8A:
  760.                     //printf("TXA\n");
  761.                     a = x;
  762.                     if(a==0) p |= 2;
  763.                     else p &= 0xFD;
  764.                     if((a&0x80) == 0x80) p |= 0x80;
  765.                     else p &= 0x7F;
  766.                     cycles+=2;
  767.                     pc+=1;
  768.                     break;
  769.                 case 0x8C:
  770.                     //printf("STY $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
  771.                     wb((rb(pc+2)<<8) | rb(pc+1),y);
  772.                     cycles+=4;
  773.                     pc+=3;
  774.                     break;
  775.                 case 0x8D:
  776.                     //printf("STA $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
  777.                     wb((rb(pc+2)<<8) | rb(pc+1),a);
  778.                     cycles+=4;
  779.                     pc+=3;
  780.                     break;
  781.                 case 0x8E:
  782.                     //printf("STX $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
  783.                     wb((rb(pc+2)<<8) | rb(pc+1),x);
  784.                     cycles+=4;
  785.                     pc+=3;
  786.                     break;
  787.                 case 0x90:
  788.                     //printf("BCC $%02x\n",rb(pc+1));
  789.                     cycles+=2;
  790.                     if((p & 1) != 1)
  791.                     {
  792.                         cycles+=1;
  793.                         if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  794.                         pc += (int8_t)rb(pc+1);
  795.                         pc += 2;
  796.                     }
  797.                     else pc+=2;
  798.                     break;
  799.                 case 0x91:
  800.                     //printf("STA $%02x\n", rb(pc+1));
  801.                         wb((uint16_t)rb(pc+1) + y,a);
  802.                         cycles+=6;
  803.                         pc+=2;
  804.                         break;
  805.                 case 0x95:
  806.                     //printf("STA $%02x,X\n",rb(pc+1));
  807.                     wb((uint16_t)rb(pc+1)+x,a);
  808.                     cycles+=3;
  809.                     pc+=2;
  810.                     break;
  811.                 case 0x98:
  812.                     //printf("TYA\n");
  813.                     a = y;
  814.                     if(a==0) p |= 2;
  815.                     else p &= 0xFD;
  816.                     if((a&0x80) == 0x80) p |= 0x80;
  817.                     else p &= 0x7F;
  818.                     cycles+=2;
  819.                     pc+=1;
  820.                     break;
  821.                 case 0x99:
  822.                     //printf("STA $%04x,Y\n", (rb(pc+2)<<8) | rb(pc+1));
  823.                     wb(((rb(pc+2)<<8) | rb(pc+1)) + y,a);
  824.                     cycles+=5;
  825.                     pc+=3;
  826.                     break;
  827.                 case 0x9A:
  828.                     //printf("TXS\n");
  829.                     s = x;
  830.                     cycles+=2;
  831.                     pc+=1;
  832.                     break;
  833.                 case 0x9D:
  834.                     //printf("STA $%04x,X\n", (rb(pc+2)<<8) | rb(pc+1));
  835.                     wb(((rb(pc+2)<<8) | rb(pc+1)) + x,a);
  836.                     cycles+=5;
  837.                     pc+=3;
  838.                     break;
  839.                     case 0xA0:
  840.                         //printf("LDY #$%02x\n", rb(pc+1));
  841.                     y = rb(pc+1);
  842.                     if(y==0) p |= 2;
  843.                     else p &= 0xFD;
  844.                     if((y&0x80) == 0x80) p |= 0x80;
  845.                     else p &= 0x7F;
  846.                     cycles+=2;
  847.                     pc+=2;
  848.                         break;
  849.                 case 0xA2:
  850.                     //printf("LDX #$%02x\n", rb(pc+1));
  851.                     x = rb(pc+1);
  852.                     if(x==0) p |= 2;
  853.                     else p &= 0xFD;
  854.                     if((x&0x80) == 0x80) p |= 0x80;
  855.                     else p &= 0x7F;
  856.                     cycles+=2;
  857.                     pc+=2;
  858.                     break;
  859.                 case 0xA4:
  860.                     //printf("LDY $%02x\n",rb(pc+1));
  861.                     y = rb(rb(pc+1));
  862.                     if(y==0) p |= 2;
  863.                     else p &= 0xFD;
  864.                     if((y&0x80) == 0x80) p |= 0x80;
  865.                     else p &= 0x7F;
  866.                     if(y <= 0x80) p |= 0x80;
  867.                     if(y == 0x00) p &= 0x7F;
  868.                     cycles+=4;
  869.                     pc+=2;
  870.                     break;
  871.                 case 0xA5:
  872.                     //printf("LDA $%02x\n", rb(pc+1));
  873.                     a = rb(pc+1);
  874.                     if(a==0) p |= 2;
  875.                     else p &= 0xFD;
  876.                     if((a&0x80) == 0x80) p |= 0x80;
  877.                     else p &= 0x7F;
  878.                     if(a <= 0x80) p |= 0x80;
  879.                     if(a == 0x00) p &= 0x7F;
  880.                     cycles+=2;
  881.                     pc+=2;
  882.                     break;
  883.                 case 0xA6:
  884.                     //printf("LDX $%02x\n", rb(pc+1));
  885.                     x = rb(pc+1);
  886.                     if(x==0) p |= 2;
  887.                     else p &= 0xFD;
  888.                     if((x&0x80) == 0x80) p |= 0x80;
  889.                     else p &= 0x7F;
  890.                     if(x <= 0x80) p |= 0x80;
  891.                     if(x == 0x00) p &= 0x7F;
  892.                     cycles+=2;
  893.                     pc+=2;
  894.                     break;
  895.                 case 0xA8:
  896.                     //printf("TAY\n");
  897.                     y = a;
  898.                     if(y==0) p |= 2;
  899.                     else p &= 0xFD;
  900.                     if((y&0x80) == 0x80) p |= 0x80;
  901.                     else p &= 0x7F;
  902.                     cycles+=2;
  903.                     pc+=1;
  904.                     break;
  905.                 case 0xA9:
  906.                     //printf("LDA #$%02x\n", rb(pc+1));
  907.                     a = rb(pc+1);
  908.                     if(a==0) p |= 2;
  909.                     else p &= 0xFD;
  910.                     if((a&0x80) == 0x80) p |= 0x80;
  911.                     else p &= 0x7F;
  912.                     cycles+=2;
  913.                     pc+=2;
  914.                     break;
  915.                 case 0xAA:
  916.                     //printf("TAX\n");
  917.                     x = a;
  918.                     if(x==0) p |= 2;
  919.                     else p &= 0xFD;
  920.                     if((x&0x80) == 0x80) p |= 0x80;
  921.                     else p &= 0x7F;
  922.                     cycles+=2;
  923.                     pc+=1;
  924.                     break;
  925.                 case 0xAC:
  926.                     //printf("LDY $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
  927.                     y = rb((rb(pc+2)<<8) | rb(pc+1));
  928.                     if(y==0) p |= 2;
  929.                     else p &= 0xFD;
  930.                     if((y&0x80) == 0x80) p |= 0x80;
  931.                     else p &= 0x7F;
  932.                     if(y <= 0x80) p |= 0x80;
  933.                     if(y == 0x00) p &= 0x7F;
  934.                     cycles+=4;
  935.                     pc+=3;
  936.                     break;
  937.                 case 0xAD:
  938.                     //printf("LDA $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
  939.                     a = rb((rb(pc+2)<<8) | rb(pc+1));
  940.                     if(a==0) p |= 2;
  941.                     else p &= 0xFD;
  942.                     if((a&0x80) == 0x80) p |= 0x80;
  943.                     else p &= 0x7F;
  944.                     if(a <= 0x80) p |= 0x80;
  945.                     if(a == 0x00) p &= 0x7F;
  946.                     cycles+=4;
  947.                     pc+=3;
  948.                     break;
  949.                 case 0xAE:
  950.                     //printf("LDX $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
  951.                     x = rb((rb(pc+2)<<8) | rb(pc+1));
  952.                     if(x==0) p |= 2;
  953.                     else p &= 0xFD;
  954.                     if((x&0x80) == 0x80) p |= 0x80;
  955.                     else p &= 0x7F;
  956.                     if(x <= 0x80) p |= 0x80;
  957.                     if(x == 0x00) p &= 0x7F;
  958.                     cycles+=4;
  959.                     pc+=3;
  960.                     break;
  961.                     case 0xB0:
  962.                         //printf("BCS $%02x\n",rb(pc+1));
  963.                     cycles+=2;
  964.                     if((p & 1) != 0)
  965.                     {
  966.                         cycles+=1;
  967.                         if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  968.                         pc += (int8_t)rb(pc+1);
  969.                         pc += 2;
  970.                     }
  971.                     else pc+=2;
  972.                         break;
  973.                     case 0xB1:
  974.                     //printf("LDA ($%02x),Y\n", rb(pc+1));
  975.                     a = rb(rb(pc+1) + y);
  976.                     if(a==0) p |= 2;
  977.                     else p &= 0xFD;
  978.                     if((a&0x80) == 0x80) p |= 0x80;
  979.                     else p &= 0x7F;
  980.                     if(a <= 0x80) p |= 0x80;
  981.                     if(a == 0x00) p &= 0x7F;
  982.                     cycles+=4;
  983.                     if((pc & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  984.                     pc+=2;
  985.                     break;
  986.                 case 0xB4:
  987.                     //printf("LDY $%02x,X\n",rb(pc+1));
  988.                     y = rb(rb(pc+1)+x);
  989.                     if(y==0) p |= 2;
  990.                     else p &= 0xFD;
  991.                     if((y&0x80) == 0x80) p |= 0x80;
  992.                     else p &= 0x7F;
  993.                     if(y <= 0x80) p |= 0x80;
  994.                     if(y == 0x00) p &= 0x7F;
  995.                     cycles+=3;
  996.                     pc+=2;
  997.                     break;
  998.                 case 0xB5:
  999.                     //printf("LDA $%02x,X\n", rb(pc+1));
  1000.                     a = rb(rb(pc+1)+x);
  1001.                     if(a==0) p |= 2;
  1002.                     else p &= 0xFD;
  1003.                     if((a&0x80) == 0x80) p |= 0x80;
  1004.                     else p &= 0x7F;
  1005.                     if(a <= 0x80) p |= 0x80;
  1006.                     if(a == 0x00) p &= 0x7F;
  1007.                     cycles+=4;
  1008.                     pc+=2;
  1009.                     break;
  1010.                 case 0xB8:
  1011.                     //printf("CLV\n");
  1012.                     p &= 0xBF;
  1013.                     cycles+=2;
  1014.                     pc+=1;
  1015.                     break;
  1016.                  case 0xB9:
  1017.                     //printf("LDA $%04x,Y\n",(rb(pc+2)<<8) | rb(pc+1));
  1018.                     a = rb(((rb(pc+2)<<8) | rb(pc+1)) + y);
  1019.                     cycles+=4;
  1020.                     if((pc & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  1021.                     pc+=3;
  1022.                     break;
  1023.                 case 0xBA:
  1024.                     //printf("TSX\n");
  1025.                     x = s;
  1026.                     cycles+=2;
  1027.                     pc+=1;
  1028.                     break;
  1029.                 case 0xBC:
  1030.                     //printf("LDY $%04x,X\n", (rb(pc+2)<<8) | rb(pc+1));
  1031.                     y = rb(((rb(pc+2)<<8) | rb(pc+1))+x);
  1032.                     if(y==0) p |= 2;
  1033.                     else p &= 0xFD;
  1034.                     if((y&0x80) == 0x80) p |= 0x80;
  1035.                     else p &= 0x7F;
  1036.                     if(y <= 0x80) p |= 0x80;
  1037.                     if(y == 0x00) p &= 0x7F;
  1038.                     cycles+=4;
  1039.                     pc+=3;
  1040.                     break;
  1041.                     case 0xBD:
  1042.                         //printf("LDA $%04x,X\n",(rb(pc+2)<<8) | rb(pc+1));
  1043.                     a = rb(((rb(pc+2)<<8) | rb(pc+1)) + x);
  1044.                     cycles+=4;
  1045.                     if((pc & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  1046.                     pc+=3;
  1047.                     break;
  1048.                 case 0xBE:
  1049.                     //printf("LDX $%04x,Y\n", (rb(pc+2)<<8) | rb(pc+1));
  1050.                     x = rb(((rb(pc+2)<<8) | rb(pc+1))+y);
  1051.                     if(x==0) p |= 2;
  1052.                     else p &= 0xFD;
  1053.                     if((x&0x80) == 0x80) p |= 0x80;
  1054.                     else p &= 0x7F;
  1055.                     if(x <= 0x80) p |= 0x80;
  1056.                     if(x == 0x00) p &= 0x7F;
  1057.                     cycles+=4;
  1058.                     if((pc & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  1059.                     pc+=3;
  1060.                     break;
  1061.                 case 0xC0:
  1062.                         //printf("CPY #$%02x\n",rb(pc+1));
  1063.                     if((y - rb(pc+1)) == 0) p |= 2;
  1064.                     else p &= 0xFD;
  1065.                     if(((y - rb(pc+1)) & 0xFF) >= 0x80) p |= 0x80;
  1066.                     else p &= 0x7F;
  1067.                     if((y >= rb(pc+1))) p |= 1;
  1068.                     else p &= 0xFE;
  1069.                     cycles+=2;
  1070.                     pc+=2;
  1071.                         break;
  1072.                 case 0xC8:
  1073.                     //printf("INY\n");
  1074.                     y++;
  1075.                     if(y==0) p |= 2;
  1076.                     else p &= 0xFD;
  1077.                     if((y&0x80) == 0x80) p |= 0x80;
  1078.                     else p &= 0x7F;
  1079.                     cycles+=2;
  1080.                     pc+=1;
  1081.                     break;
  1082.                     case 0xC9:
  1083.                         //printf("CMP #$%02x\n",rb(pc+1));
  1084.                     if((a - rb(pc+1)) == 0) p |= 2;
  1085.                     else p &= 0xFD;
  1086.                     if(((a - rb(pc+1)) & 0xFF) >= 0x80) p |= 0x80;
  1087.                     else p &= 0x7F;
  1088.                     if((a >= rb(pc+1))) p |= 1;
  1089.                     else p &= 0xFE;
  1090.                     cycles+=2;
  1091.                     pc+=2;
  1092.                         break;
  1093.                 case 0xCA:
  1094.                     //printf("DEX\n");
  1095.                     x--;
  1096.                     if(x==0) p |= 2;
  1097.                     else p &= 0xFD;
  1098.                     if((x&0x80) == 0x80) p |= 0x80;
  1099.                     else p &= 0x7F;
  1100.                     cycles+=2;
  1101.                     pc+=1;
  1102.                     break;
  1103.                 case 0xCC:
  1104.                     //printf("CPY $%04x\n",(rb(pc+2)<<8) | rb(pc+1));
  1105.                     if((y - ((rb(pc+2)<<8) | rb(pc+1))) == 0) p |= 2;
  1106.                     else p &= 0xFD;
  1107.                     if(y >= 0x80) p |= 0x80;
  1108.                     else p &= 0x7F;
  1109.                     if((y >= ((rb(pc+2)<<8) | rb(pc+1)))) p |= 1;
  1110.                     else p &= 0xFE;
  1111.                     cycles+=2;
  1112.                     pc+=3;
  1113.                     break;
  1114.                 case 0xD0:
  1115.                     //printf("BNE $%02x\n",rb(pc+1));
  1116.                     cycles+=2;
  1117.                     if((p & 2) == 0)
  1118.                     {
  1119.                         cycles+=1;
  1120.                         if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  1121.                         pc += (int8_t)rb(pc+1);
  1122.                         pc += 2;
  1123.                     }
  1124.                     else pc+=2;
  1125.                     break;
  1126.                 case 0xD8:
  1127.                     //printf("CLD\n");
  1128.                     p &= 0xF7;
  1129.                     cycles+=2;
  1130.                     pc+=1;
  1131.                     break;
  1132.                 case 0xDE:
  1133.                     //printf("DEC $%04x,X\n",(rb(pc+2)<<8) | rb(pc+1));
  1134.                     wb((rb(pc+2)<<8) | rb(pc+1),rb((rb(pc+2)<<8) | rb(pc+1))+1);
  1135.                     if((rb((rb(pc+2)<<8) | rb(pc+1)))==0) p |= 2;
  1136.                     else p &= 0xFD;
  1137.                     if(((rb((rb(pc+2)<<8) | rb(pc+1)))&0x80) == 0x80) p |= 0x80;
  1138.                     else p &= 0x7F;
  1139.                     cycles+=6;
  1140.                     pc+=3;
  1141.                     break;
  1142.                 case 0xE0:
  1143.                         //printf("CPX #$%02x\n",rb(pc+1));
  1144.                     if((x - rb(pc+1)) == 0) p |= 2;
  1145.                     else p &= 0xFD;
  1146.                     if(((x - rb(pc+1)) & 0xFF) >= 0x80) p |= 0x80;
  1147.                     else p &= 0x7F;
  1148.                     if((x >= rb(pc+1))) p |= 1;
  1149.                     else p &= 0xFE;
  1150.                     cycles+=2;
  1151.                     pc+=2;
  1152.                         break;
  1153.                 case 0xE8:
  1154.                     //printf("INX\n");
  1155.                     x++;
  1156.                     if(x==0) p |= 2;
  1157.                     else p &= 0xFD;
  1158.                     if((x&0x80) == 0x80) p |= 0x80;
  1159.                     else p &= 0x7F;
  1160.                     cycles+=2;
  1161.                     pc+=1;
  1162.                     break;
  1163.                 case 0xE9:
  1164.                 {
  1165.                     uint8_t tmp = a;
  1166.                     //printf("SBC #$%02x\n",rb(pc+1));
  1167.                     a = a + ~rb(pc+1) + (p&1);
  1168.                     if(tmp>=a) p |= 1;
  1169.                     else p &= 0xFE;
  1170.                     if(a==0) p |= 2;
  1171.                     else p &= 0xFD;
  1172.                     if((tmp ^ rb(pc+1)) & (tmp ^ a) & 0x80) p |= 0x40;
  1173.                     else p &= 0xBF;
  1174.                     if((a&0x80) == 0x80) p |= 0x80;
  1175.                     else p &= 0x7F;
  1176.                     cycles+=4;
  1177.                     pc+=2;
  1178.                     break;
  1179.                 }
  1180.                 case 0xEA:
  1181.                     //printf("NOP\n");
  1182.                     cycles+=2;
  1183.                     pc+=1;
  1184.                     break;
  1185.                 case 0xED:
  1186.                     //printf("SBC $%04x\n",(rb(pc+2)<<8) | rb(pc+1));
  1187.                     a -= (p&1) + rb(((rb(pc+2)<<8) | rb(pc+1)));
  1188.                     if(a==0) p |= 2;
  1189.                     else p &= 0xFD;
  1190.                     if((a&0x80) == 0x80) p |= 0x80;
  1191.                     else p &= 0x7F;
  1192.                     cycles+=4;
  1193.                     pc+=3;
  1194.                     break;
  1195.                 case 0xEE:
  1196.                     //printf("INC $%04x\n",(rb(pc+2)<<8) | rb(pc+1));
  1197.                     wb((rb(pc+2)<<8) | rb(pc+1),rb((rb(pc+2)<<8) | rb(pc+1))+1);
  1198.                     if((rb((rb(pc+2)<<8) | rb(pc+1)))==0) p |= 2;
  1199.                     else p &= 0xFD;
  1200.                     if(((rb((rb(pc+2)<<8) | rb(pc+1)))&0x80) == 0x80) p |= 0x80;
  1201.                     else p &= 0x7F;
  1202.                     cycles+=6;
  1203.                     pc+=3;
  1204.                     break;
  1205.                 case 0xF0:
  1206.                     //printf("BEQ $%02x\n",rb(pc+1));
  1207.                     cycles+=2;
  1208.                     if((p & 2) == 2)
  1209.                     {
  1210.                         cycles+=1;
  1211.                         if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
  1212.                         pc += (int8_t)rb(pc+1);
  1213.                         pc += 2;
  1214.                     }
  1215.                     else pc+=2;
  1216.                     break;
  1217.                 case 0xF5:
  1218.                     //printf("SBC $%02x,X\n",(rb(pc+2)<<8) | rb(pc+1));
  1219.                     a -= (p&1) + rb(rb(pc+1)+x);
  1220.                     if(a==0) p |= 2;
  1221.                     else p &= 0xFD;
  1222.                     if((a&0x80) == 0x80) p |= 0x80;
  1223.                     else p &= 0x7F;
  1224.                     cycles+=4;
  1225.                     pc+=2;
  1226.                     break;
  1227.                 case 0xF6:
  1228.                     //printf("INC $%02x,X\n",rb(pc+1));
  1229.                     wb(rb(pc+1),rb(rb(pc+1))+1);
  1230.                     if((rb(rb(pc+1)))==0) p |= 2;
  1231.                     else p &= 0xFD;
  1232.                     if(((rb(rb(pc+1)))&0x80) == 0x80) p |= 0x80;
  1233.                     else p &= 0x7F;
  1234.                     cycles+=6;
  1235.                     pc+=2;
  1236.                     break;
  1237.                 case 0xF8:
  1238.                     //printf("SED\n");
  1239.                     p |= 8;
  1240.                     cycles+=2;
  1241.                     pc+=1;
  1242.                     break;
  1243.                 case 0xF9:
  1244.                     //printf("SBC $%04x,Y\n",(rb(pc+2)<<8) | rb(pc+1));
  1245.                     a -= (p&1) + rb(((rb(pc+2)<<8) | rb(pc+1))+y);
  1246.                     if(a==0) p |= 2;
  1247.                     else p &= 0xFD;
  1248.                     if((a&0x80) == 0x80) p |= 0x80;
  1249.                     else p &= 0x7F;
  1250.                     cycles+=4;
  1251.                     pc+=3;
  1252.                     break;
  1253.                 default:
  1254.                     printf("Unsupported opcode %02x. Aborting!\n",op);
  1255.                     return 1;
  1256.                     break;
  1257.             }
  1258.             //dumpregs();
  1259.             return 0;
  1260.         }
  1261.     }
  1262. };
  1263.  
  1264. void banner()
  1265. {
  1266.     //printf("MSE NES driver version v1:\n\n");
  1267.     //printf("Written by Alegend45\n\n\n");
  1268. }
  1269.  
  1270. int main(int ac, char** av)
  1271. {
  1272.     banner();
  1273.     FILE* fp = fopen(av[1],"rb");
  1274.     CPU a;
  1275.  
  1276.     if(fp != NULL)
  1277.     {
  1278.         fseek(fp,4,SEEK_SET);
  1279.         a.PRGbanks = fgetc(fp);
  1280.         a.CHRbanks = fgetc(fp);
  1281.         fseek(fp,6,SEEK_SET);
  1282.         a.mapper = fgetc(fp) >> 4;
  1283.         a.mapper |= fgetc(fp) & 0xF0;
  1284.         a.ppu.mapper = a.mapper;
  1285.         fseek(fp,0,SEEK_END);
  1286.         long pos = ftell(fp);
  1287.         a.totalrom = (uint8_t*)malloc(pos - 0x10);
  1288.         a.chrrom = (uint8_t*)malloc(pos - 0x10);
  1289.         a.LoadROM(fp);
  1290.  
  1291.         fclose(fp);
  1292.  
  1293.         SDL_Init(SDL_INIT_VIDEO);
  1294.  
  1295.         screen = SDL_SetVideoMode(256,240,24,SDL_SWSURFACE);
  1296.  
  1297.         a.dumpregs();
  1298.  
  1299.         SDL_Event e;
  1300.  
  1301.         for(;;)
  1302.         {
  1303.             if(a.tick() == 1)
  1304.             {
  1305.                 SDL_Quit();
  1306.                 return 1;
  1307.             }
  1308.             else
  1309.             {
  1310.                 if(SDL_PollEvent(&e)) if(e.type == SDL_QUIT) return 2;
  1311.                 SDL_Flip(screen);
  1312.             }
  1313.         }
  1314.     }
  1315.     return 0;
  1316. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement