Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdlib>
- #include <cstdio>
- #include <cstdint>
- #include <cstring>
- #include <SDL.h>
- SDL_Surface *screen = NULL;
- class PPU
- {
- public:
- uint8_t ctrl0;
- uint8_t ctrl1;
- uint8_t mapper;
- uint16_t addr;
- bool lohi;
- uint8_t pat0[0x1000];
- uint8_t pat1[0x1000];
- uint8_t nt0[0x3C0];
- uint8_t at0[0x40];
- uint8_t nt1[0x3C0];
- uint8_t at1[0x40];
- uint8_t nt2[0x3C0];
- uint8_t at2[0x40];
- uint8_t nt3[0x3C0];
- uint8_t at3[0x40];
- uint8_t spr_pal[0x10];
- uint8_t bg_pal[0x10];
- uint8_t oam[0x100];
- uint16_t scanline;
- uint16_t cycles;
- uint16_t cycles_next;
- uint16_t vram_addr;
- uint8_t nmi;
- int tilenum;
- PPU()
- {
- vram_addr = 0x2000;
- cycles_next = 0;
- tilenum = 0;
- lohi = 0;
- for(int i = 0;i<16;i++) bg_pal[i] = 0;
- }
- void wb(uint16_t addr, uint8_t value)
- {
- if(addr >= 0 && addr < 0x1000) pat0[addr] = value;
- if(addr >= 0x1000 && addr < 0x2000) pat1[addr - 0x1000] = value;
- if(mapper == 0)
- {
- if(addr >= 0x2000 && addr < 0x23C0) nt0[addr - 0x2000] = value;
- if(addr >= 0x23C0 && addr < 0x2400) at0[addr - 0x23C0] = value;
- if(addr >= 0x2400 && addr < 0x27C0) nt1[addr - 0x2400] = value;
- if(addr >= 0x27C0 && addr < 0x2800) at1[addr - 0x27C0] = value;
- if(addr >= 0x2800 && addr < 0x2BC0) nt0[addr - 0x2800] = value;
- if(addr >= 0x2BC0 && addr < 0x2C00) at0[addr - 0x2BC0] = value;
- if(addr >= 0x2C00 && addr < 0x2FC0) nt1[addr - 0x2C00] = value;
- if(addr >= 0x2FC0 && addr < 0x3000) at1[addr - 0x2FC0] = value;
- }
- if(addr >= 0x3F00 && addr < 0x3F10) bg_pal[addr - 0x3F00] = value;
- if(addr >= 0x3F10 && addr < 0x3F20) spr_pal[addr - 0x3F10] = value;
- if(addr >= 0x3F20 && addr < 0x3F30) bg_pal[addr - 0x3F20] = value;
- if(addr >= 0x3F30 && addr < 0x3F40) spr_pal[addr - 0x3F30] = value;
- if(addr >= 0x3F40 && addr < 0x3F50) bg_pal[addr - 0x3F40] = value;
- if(addr >= 0x3F50 && addr < 0x3F60) spr_pal[addr - 0x3F50] = value;
- if(addr >= 0x3F40 && addr < 0x3F50) bg_pal[addr - 0x3F40] = value;
- if(addr >= 0x3F50 && addr < 0x3F60) spr_pal[addr - 0x3F50] = value;
- if(addr >= 0x3F60 && addr < 0x3F70) bg_pal[addr - 0x3F60] = value;
- if(addr >= 0x3F70 && addr < 0x3F80) spr_pal[addr - 0x3F70] = value;
- }
- uint8_t rb(uint16_t addr)
- {
- if(addr >= 0 && addr < 0x1000) return pat0[addr];
- if(addr >= 0x1000 && addr < 0x2000) return pat1[addr - 0x1000];
- if(mapper == 0)
- {
- if(addr >= 0x2000 && addr < 0x23C0) return nt0[addr - 0x2000];
- if(addr >= 0x23C0 && addr < 0x2400) return at0[addr - 0x23C0];
- if(addr >= 0x2400 && addr < 0x27C0) return nt1[addr - 0x2400];
- if(addr >= 0x27C0 && addr < 0x2800) return at1[addr - 0x27C0];
- if(addr >= 0x2800 && addr < 0x2BC0) return nt0[addr - 0x2800];
- if(addr >= 0x2BC0 && addr < 0x2C00) return at0[addr - 0x2BC0];
- if(addr >= 0x2C00 && addr < 0x2FC0) return nt1[addr - 0x2C00];
- if(addr >= 0x2FC0 && addr < 0x3000) return at1[addr - 0x2FC0];
- }
- if(addr >= 0x3F00 && addr < 0x3F10) return bg_pal[addr - 0x3F00];
- if(addr >= 0x3F10 && addr < 0x3F20) return spr_pal[addr - 0x3F10];
- if(addr >= 0x3F20 && addr < 0x3F30) return bg_pal[addr - 0x3F20];
- if(addr >= 0x3F30 && addr < 0x3F40) return spr_pal[addr - 0x3F30];
- if(addr >= 0x3F40 && addr < 0x3F50) return bg_pal[addr - 0x3F40];
- if(addr >= 0x3F50 && addr < 0x3F60) return spr_pal[addr - 0x3F50];
- if(addr >= 0x3F60 && addr < 0x3F70) return bg_pal[addr - 0x3F60];
- if(addr >= 0x3F70 && addr < 0x3F80) return spr_pal[addr - 0x3F70];
- if(addr >= 0x3F80 && addr < 0x3F90) return bg_pal[addr - 0x3F80];
- if(addr >= 0x3F90 && addr < 0x3FA0) return spr_pal[addr - 0x3F90];
- }
- void putpixel(uint8_t color,int x, int y)
- {
- uint8_t *p = (uint8_t*)screen->pixels + ((y * 256 + x) * 3);
- //printf("PPU color: %02x\n",color);
- switch(color & 0x3F)
- {
- case 0x00:
- p[0] = 124;
- p[1] = 124;
- p[2] = 124;
- break;
- case 0x0C:
- p[0] = 88;
- p[1] = 64;
- p[2] = 0;
- break;
- case 0x0D:
- p[0] = 0;
- p[1] = 0;
- p[2] = 0;
- break;
- case 0x0E:
- p[0] = 0;
- p[1] = 0;
- p[2] = 0;
- break;
- case 0x0F:
- p[0] = 0;
- p[1] = 0;
- p[2] = 0;
- break;
- case 0x20:
- p[0] = 0xFF;
- p[1] = 0xFF;
- p[2] = 0xFF;
- case 0x21:
- p[0] = 252;
- p[1] = 188;
- p[2] = 60;
- case 0x22:
- p[0] = 252;
- p[1] = 136;
- p[2] = 104;
- case 0x30:
- p[0] = 0xFF;
- p[1] = 0xFF;
- p[2] = 0xFF;
- }
- }
- void dumpscan()
- {
- //printf("Scanline %i\n",scanline);
- //printf("Cycles %i\n",cycles);
- }
- void tick()
- {
- if(cycles_next > 0)
- {
- cycles_next--;
- return;
- }
- if(scanline >= 0 && scanline < 239)
- {
- if(cycles<255)
- {
- uint8_t tile_num = rb(0x2000 + (((cycles + 1) >> 3) * ((scanline + 1) >> 3)));
- uint8_t tile_pal = 0;
- uint8_t tile_pat_0 = (rb((tile_num << 1) + 0x1000) & (1<<(cycles>>5))) >> (1<<(cycles>>5));
- uint8_t tile_pat_1 = (rb((tile_num << 1) + 0x1001) & (1<<(cycles>>5))) >> (1<<(cycles>>5));
- uint8_t tile_pat = tile_pat_0 | (tile_pat_1 << 1);
- uint8_t tile_pix = rb(0x3F00 + tile_pat);
- putpixel(tile_pix,cycles,scanline);
- }
- }
- if(scanline == 241 && cycles<=2)
- {
- nmi = 1;
- }
- else nmi = 0;
- if(scanline == 261 && cycles == 339)
- {
- printf("Frame complete.\n");
- }
- cycles++;
- if(cycles >= 340)
- {
- cycles = 0;
- scanline++;
- }
- if(scanline >= 262)
- {
- scanline = 0;
- }
- }
- };
- class CPU
- {
- public:
- PPU ppu;
- uint8_t mapper;
- uint8_t PRGbanks;
- uint8_t CHRbanks;
- uint8_t ram[0x2000];
- uint8_t ioregs[0x2020];
- uint8_t exprom[0x1980];
- uint8_t sram[0x2000];
- uint8_t rom[0x8000];
- uint8_t* totalrom;
- uint8_t* chrrom;
- uint16_t pc;
- uint8_t a,x,y,s;
- /* Processor Status Register
- * Bit 0 - Carry
- * Bit 1 - Zero
- * Bit 2 - Interrupt
- * Bit 3 - Decimal Mode, not used in NES
- * Bit 4 - Software Interrupts
- * Bit 5 - 1
- * Bit 6 - Overflow
- * Bit 7 - Negative
- */
- uint8_t p;
- uint16_t cycles;
- uint8_t rb(uint16_t addr)
- {
- if(addr >= 0x0000 && addr < 0x2000)
- {
- return ram[addr];
- }
- if(addr >= 0x2000 && addr < 0x4020)
- {
- return ioregs[addr - 0x2000];
- }
- if(addr >= 0x4020 && addr < 0x6000)
- {
- return exprom[addr - 0x4020];
- }
- if(addr >= 0x6000 && addr < 0x8000)
- {
- return sram[addr - 0x6000];
- }
- if(addr >= 0x8000)
- {
- return rom[addr - 0x8000];
- }
- }
- CPU()
- {
- a = 0x00;
- x = 0x00;
- y = 0x00;
- s = 0xFD;
- p = 0x34;
- pc = 0x8000;
- cycles = 0;
- }
- void CHRSwap4(uint8_t value, uint16_t addr)
- {
- memcpy((addr>=0x1000) ? ppu.pat1 : ppu.pat0,chrrom + (value * 0x1000),0x1000);
- }
- void CHRSwap8(uint8_t value, uint16_t addr)
- {
- memcpy(ppu.pat0,chrrom + (value * 0x1000),0x1000);
- memcpy(ppu.pat1,chrrom + (value * 0x1000) + 0x1000,0x1000);
- }
- void PRGSwap8(uint8_t value, uint16_t addr)
- {
- memcpy(rom + (addr - 0x8000),totalrom + (value * 0x2000),0x2000);
- }
- void PRGSwap16(uint8_t value, uint16_t addr)
- {
- memcpy(rom + (addr - 0x8000),totalrom + (value * 0x4000),0x4000);
- }
- void PRGSwap32(uint8_t value, uint16_t addr)
- {
- memcpy(rom + (addr - 0x8000),totalrom + (value * 0x8000),0x8000);
- }
- void wb(uint16_t addr, uint8_t value)
- {
- if(addr >= 0x0000 && addr < 0x2000)
- {
- ram[addr] = value;
- }
- if(addr >= 0x2000 && addr < 0x4020)
- {
- if(addr==0x2000){printf("PPU: CRTL0 write %02x\n",value); ppu.ctrl0 = value;}
- if(addr==0x2001){printf("PPU: CRTL1 write %02x\n",value); ppu.ctrl1 = value;}
- 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;}
- if(addr==0x2007){printf("PPU: DATA write %02x to PPU address %04x\n",value, ppu.addr); ppu.wb(ppu.addr,value);}
- ioregs[addr - 0x2000] = value;
- }
- if(addr >= 0x4020 && addr < 0x6000)
- {
- exprom[addr - 0x4020] = value;
- }
- if(addr >= 0x6000 && addr < 0x8000)
- {
- sram[addr - 0x6000] = value;
- }
- if(addr >= 0x8000)
- {
- if(mapper == 0) return; //printf("Why am I trying to write to ROM?\n");
- else if(mapper == 2) PRGSwap16(value & 7,0x8000);
- else if(mapper == 3) CHRSwap8(value & 3,0);
- else if(mapper == 7) PRGSwap32(value & 15,0x8000); //TODO: Mirroring
- else if(mapper == 9)
- {
- if(addr >= 0xA000 && addr < 0xB000) PRGSwap8(value,0x8000);
- if(addr >= 0xB000 && addr < 0xD000) CHRSwap4(value,0x0000);
- if(addr >= 0xD000 && addr < 0xE000) CHRSwap4(value,0x1000);
- if(addr >= 0xE000 && addr < 0xF000) CHRSwap4(value,0x1000); //TODO: Mirroring
- }
- else if(mapper == 13) CHRSwap4(value & 3,0x1000);
- else if(mapper == 34) PRGSwap32(value & 3,0x8000);
- else if(mapper == 66)
- {
- PRGSwap32(value & 0x30,0x8000);
- CHRSwap8(value & 3,0x0000);
- }
- else if(mapper == 75)
- {
- if(addr == 0x8000) PRGSwap8(value & 15,0x8000);
- if(addr == 0xA000) PRGSwap8(value & 15,0xA000);
- if(addr == 0xC000) PRGSwap8(value & 15,0xC000);
- //TODO: CHR swapping
- }
- else if(mapper == 180) PRGSwap16(value & 7,0xC000);
- }
- }
- void LoadROM(FILE* fp)
- {
- if(mapper == 0)
- {
- fseek(fp,0x10,SEEK_SET);
- if(PRGbanks == 2)
- {
- fread(rom,1,0x8000,fp);
- fread(chrrom,1,0x2000*CHRbanks,fp);
- }
- if(PRGbanks == 1) fread(rom+0x4000,1,0x4000,fp);
- }
- else if(mapper == 2)
- {
- uint8_t* rom_ptr = rom + 0x4000;
- fseek(fp,(PRGbanks - 1) * 0x4000,SEEK_SET);
- fread(rom_ptr,1,0x4000,fp);
- fseek(fp,0x10,SEEK_SET);
- fread(rom,1,0x4000,fp);
- }
- else if(mapper == 3)
- {
- fseek(fp,(PRGbanks * 0x4000) + 0x10,SEEK_SET);
- fread(ppu.pat0,1,0x2000,fp);
- }
- else if(mapper == 7)
- {
- fseek(fp,0x10,SEEK_SET);
- fread(rom,1,0x8000,fp);
- }
- else if(mapper == 13)
- {
- fseek(fp,(PRGbanks * 0x4000) + 0x10,SEEK_SET);
- fread(ppu.pat0,1,0x1000,fp);
- fread(ppu.pat1,1,0x1000,fp);
- }
- else if(mapper == 34)
- {
- fseek(fp,0x10,SEEK_SET);
- fread(rom,1,0x8000,fp);
- }
- else if(mapper == 66)
- {
- fseek(fp,0x10,SEEK_SET);
- fread(rom,1,0x8000,fp);
- }
- else if(mapper == 75)
- {
- uint8_t* rom_ptr = rom + 0x6000;
- fseek(fp,(PRGbanks - 1) * 0x2000,SEEK_SET);
- fread(rom_ptr,1,0x2000,fp);
- fseek(fp,0x10,SEEK_SET);
- fread(rom,1,0x6000,fp);
- }
- else if(mapper == 180)
- {
- fseek(fp,0x10,SEEK_SET);
- fread(rom,1,0x8000,fp);
- }
- }
- void dumpregs()
- {
- //printf("a = %02x\n",a);
- //printf("x = %02x\n",x);
- //printf("y = %02x\n",y);
- //printf("s = %02x\n",s);
- //printf("p = %02x\n",p);
- //printf("pc = %04x\n",pc);
- }
- int tick()
- {
- for(int i = 0;i<3;i++) ppu.tick();
- if(ppu.nmi == 1)
- {
- pc = (rb(0xFFFA) << 8) | rb(0xFFFB); //Read NMI vector
- }
- if(cycles != 0)
- {
- cycles--;
- return 0;
- }
- else
- {
- uint8_t op = rb(pc);
- switch(op)
- {
- case 0x00:
- //printf("BRK\n");
- pc = (rb(0xFFFE) << 8) | rb(0xFFFF); //Read BRK vector
- cycles+=6;
- break;
- case 0x01:
- //printf("ORA ($%02x,X)\n",rb(pc+1));
- a |= rb(rb(pc+1)+x);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=6;
- pc+=2;
- break;
- case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52: case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
- printf("KIL\n");
- return 1;
- break;
- 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:
- //printf("NOP\n");
- cycles+=1;
- pc+=2;
- break;
- case 0x05:
- //printf("ORA $%02x\n",rb(pc+1));
- a |= rb(rb(pc+1));
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=2;
- break;
- case 0x06:
- {
- //printf("ASL $%02x\n",rb(pc+1));
- p |= (rb(pc+1) & 0x80) >> 7;
- wb(rb(pc+1),(rb(rb(pc+1)) << 1) & 0xFF);
- int tmp = (rb(pc+1) << 1) & 0xFF;
- if(tmp==0) p |= 2;
- else p &= 0xFD;
- if((tmp&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=5;
- pc+=2;
- break;
- }
- case 0x07:
- {
- //printf("SLO $%02x\n",rb(pc+1));
- p |= (rb(pc+1) & 0x80) >> 7;
- wb(rb(pc+1),((rb(rb(pc+1)) << 1) & 0xFF) | a);
- int tmp = ((rb(pc+1) << 1) & 0xFF) | a;
- if(tmp==0) p |= 2;
- else p &= 0xFD;
- if((tmp&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=5;
- pc+=2;
- break;
- }
- case 0x08:
- //printf("PHP\n");
- wb(s,p);
- s-=1;
- cycles+=2;
- pc+=1;
- break;
- case 0x09:
- //printf("ORA #$%02x\n",rb(pc+1));
- a |= rb(pc+1);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=2;
- break;
- case 0x0A:
- //printf("ASL A\n");
- p |= (a & 0x80) >> 7;
- a = a << 1;
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=1;
- break;
- case 0x10:
- //printf("BPL #$%02x\n",rb(pc+1));
- cycles+=2;
- if((p & 0x80) != 0x80)
- {
- cycles+=1;
- if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc += (int8_t)rb(pc+1);
- pc += 2;
- }
- else pc+=2;
- break;
- case 0x18:
- //printf("CLC\n");
- p &= 0xFE;
- cycles+=2;
- pc+=1;
- break;
- case 0x20:
- //printf("JSR $%04x\n",(rb(pc+2)<<8) | rb(pc+1));
- wb((s-2) | 0x100,pc+2);
- wb((s-1) | 0x100,pc+2>>8);
- s-=2;
- cycles+=6;
- pc=(rb(pc+2)<<8) | rb(pc+1);
- break;
- case 0x24:
- //printf("BIT $%02x\n", rb(pc+1));
- if((a & rb(rb(pc+1))) == 0) p |= 2;
- else p &= 0xFD;
- p &= 0x3F;
- p |= rb(rb(pc+1)) & 0xC0;
- cycles+=2;
- pc+=2;
- break;
- case 0x28:
- //printf("PLP\n");
- p = rb(s+1);
- s+=1;
- cycles+=4;
- pc+=1;
- break;
- case 0x29:
- //printf("AND #$%02x\n",rb(pc+1));
- a &= rb(pc+1);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=2;
- break;
- case 0x2C:
- //printf("BIT $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
- if((a & rb((rb(pc+2)<<8) | rb(pc+1))) == 0) p |= 2;
- else p &= 0xFD;
- p |= rb((rb(pc+2)<<8) | rb(pc+1)) & 0xC0;
- cycles+=4;
- pc+=3;
- break;
- case 0x30:
- //printf("BMI $%02x\n",rb(pc+1));
- cycles+=2;
- if((p & 0x80) == 0x80)
- {
- cycles+=1;
- if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc += (int8_t)rb(pc+1);
- pc += 2;
- }
- else pc+=2;
- break;
- case 0x38:
- //printf("SEC\n");
- p |= 0x01;
- cycles+=2;
- pc+=1;
- break;
- case 0x46:
- //printf("LSR $%02x\n", rb(pc+1));
- if((rb(rb(pc+1)) & 0x01) == 0) p |= 2;
- else p &= 0xFD;
- if((rb(rb(pc+1)) & 0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- wb(rb(pc+1),rb(rb(pc+1))>>1);
- cycles+=5;
- pc+=2;
- break;
- case 0x48:
- //printf("PHA\n");
- wb(s,a);
- s-=1;
- cycles+=2;
- pc+=1;
- break;
- case 0x49:
- //printf("EOR #$%02x\n",rb(pc+1));
- a ^= rb(pc+1);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=2;
- break;
- case 0x4A:
- //printf("LSR A\n");
- if((a & 0x01) == 0) p |= 2;
- else
- {
- p &= 0xFD;
- p |= 1;
- }
- if((a & 0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- a = a>>1;
- cycles+=2;
- pc+=1;
- break;
- case 0x4C:
- //printf("JMP $%04x\n",(rb(pc+2)<<8) | rb(pc+1));
- cycles+=3;
- pc=(rb(pc+2)<<8) | rb(pc+1);
- break;
- case 0x50:
- //printf("BVC $%02x\n",rb(pc+1));
- cycles+=2;
- if((p & 0x40) == 0)
- {
- cycles+=1;
- if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc += (int8_t)rb(pc+1);
- pc += 2;
- }
- else pc+=2;
- break;
- case 0x60:
- //printf("RTS\n");
- pc = (((rb((s+1) | 0x100)<<8) | rb(s | 0x100)) + 1);
- s+=2;
- cycles+=6;
- break;
- case 0x65:
- //printf("ADC $%02x\n",rb(pc+1));
- a += (p&1) + rb(rb(pc+1));
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=4;
- if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc+=2;
- break;
- case 0x68:
- //printf("PLA\n");
- a = rb(s+1);
- s+=1;
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=4;
- pc+=1;
- break;
- case 0x69:
- {
- //printf("ADC #$%02x\n",rb(pc+1));
- uint8_t tmp = a;
- a += (p&1) + rb(pc+1);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(a>=0x80) p |= 0x40;
- else p &= 0xBF;
- if(a<tmp) p |= 1;
- else p &= 0xFE;
- cycles+=1;
- pc+=2;
- break;
- }
- case 0x6C:
- {
- uint16_t tmp = (rb(pc+2)<<8) | rb(pc+1);
- //printf("JMP ($%04x)\n",(rb(pc+2)<<8) | rb(pc+1));
- cycles+=5;
- pc = (rb(tmp)<<8) | rb(tmp+1);
- break;
- }
- case 0x70:
- //printf("BVS $%02x\n",rb(pc+1));
- cycles+=2;
- if((p & 0x40) == 0x40)
- {
- cycles+=1;
- if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc += (int8_t)rb(pc+1);
- pc += 2;
- }
- else pc+=2;
- break;
- case 0x78:
- //printf("SEI\n");
- p |= 0x08;
- cycles+=2;
- pc+=1;
- break;
- case 0x79:
- //printf("ADC $%04x,Y\n",(rb(pc+2)<<8) | rb(pc+1));
- a += (p&1) + rb(((rb(pc+2)<<8) | rb(pc+1)) + y);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=4;
- if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc+=3;
- break;
- case 0x85:
- //printf("STA $%02x\n",rb(pc+1));
- wb((uint16_t)rb(pc+1),a);
- cycles+=3;
- pc+=2;
- break;
- case 0x86:
- //printf("STX $%02x\n",rb(pc+1));
- wb((uint16_t)rb(pc+1),x);
- cycles+=3;
- pc+=2;
- break;
- case 0x88:
- //printf("DEY\n");
- y--;
- if(y==0) p |= 2;
- else p &= 0xFD;
- if((y&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=1;
- break;
- case 0x8A:
- //printf("TXA\n");
- a = x;
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=1;
- break;
- case 0x8C:
- //printf("STY $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
- wb((rb(pc+2)<<8) | rb(pc+1),y);
- cycles+=4;
- pc+=3;
- break;
- case 0x8D:
- //printf("STA $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
- wb((rb(pc+2)<<8) | rb(pc+1),a);
- cycles+=4;
- pc+=3;
- break;
- case 0x8E:
- //printf("STX $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
- wb((rb(pc+2)<<8) | rb(pc+1),x);
- cycles+=4;
- pc+=3;
- break;
- case 0x90:
- //printf("BCC $%02x\n",rb(pc+1));
- cycles+=2;
- if((p & 1) != 1)
- {
- cycles+=1;
- if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc += (int8_t)rb(pc+1);
- pc += 2;
- }
- else pc+=2;
- break;
- case 0x91:
- //printf("STA $%02x\n", rb(pc+1));
- wb((uint16_t)rb(pc+1) + y,a);
- cycles+=6;
- pc+=2;
- break;
- case 0x95:
- //printf("STA $%02x,X\n",rb(pc+1));
- wb((uint16_t)rb(pc+1)+x,a);
- cycles+=3;
- pc+=2;
- break;
- case 0x98:
- //printf("TYA\n");
- a = y;
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=1;
- break;
- case 0x99:
- //printf("STA $%04x,Y\n", (rb(pc+2)<<8) | rb(pc+1));
- wb(((rb(pc+2)<<8) | rb(pc+1)) + y,a);
- cycles+=5;
- pc+=3;
- break;
- case 0x9A:
- //printf("TXS\n");
- s = x;
- cycles+=2;
- pc+=1;
- break;
- case 0x9D:
- //printf("STA $%04x,X\n", (rb(pc+2)<<8) | rb(pc+1));
- wb(((rb(pc+2)<<8) | rb(pc+1)) + x,a);
- cycles+=5;
- pc+=3;
- break;
- case 0xA0:
- //printf("LDY #$%02x\n", rb(pc+1));
- y = rb(pc+1);
- if(y==0) p |= 2;
- else p &= 0xFD;
- if((y&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=2;
- break;
- case 0xA2:
- //printf("LDX #$%02x\n", rb(pc+1));
- x = rb(pc+1);
- if(x==0) p |= 2;
- else p &= 0xFD;
- if((x&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=2;
- break;
- case 0xA4:
- //printf("LDY $%02x\n",rb(pc+1));
- y = rb(rb(pc+1));
- if(y==0) p |= 2;
- else p &= 0xFD;
- if((y&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(y <= 0x80) p |= 0x80;
- if(y == 0x00) p &= 0x7F;
- cycles+=4;
- pc+=2;
- break;
- case 0xA5:
- //printf("LDA $%02x\n", rb(pc+1));
- a = rb(pc+1);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(a <= 0x80) p |= 0x80;
- if(a == 0x00) p &= 0x7F;
- cycles+=2;
- pc+=2;
- break;
- case 0xA6:
- //printf("LDX $%02x\n", rb(pc+1));
- x = rb(pc+1);
- if(x==0) p |= 2;
- else p &= 0xFD;
- if((x&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(x <= 0x80) p |= 0x80;
- if(x == 0x00) p &= 0x7F;
- cycles+=2;
- pc+=2;
- break;
- case 0xA8:
- //printf("TAY\n");
- y = a;
- if(y==0) p |= 2;
- else p &= 0xFD;
- if((y&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=1;
- break;
- case 0xA9:
- //printf("LDA #$%02x\n", rb(pc+1));
- a = rb(pc+1);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=2;
- break;
- case 0xAA:
- //printf("TAX\n");
- x = a;
- if(x==0) p |= 2;
- else p &= 0xFD;
- if((x&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=1;
- break;
- case 0xAC:
- //printf("LDY $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
- y = rb((rb(pc+2)<<8) | rb(pc+1));
- if(y==0) p |= 2;
- else p &= 0xFD;
- if((y&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(y <= 0x80) p |= 0x80;
- if(y == 0x00) p &= 0x7F;
- cycles+=4;
- pc+=3;
- break;
- case 0xAD:
- //printf("LDA $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
- a = rb((rb(pc+2)<<8) | rb(pc+1));
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(a <= 0x80) p |= 0x80;
- if(a == 0x00) p &= 0x7F;
- cycles+=4;
- pc+=3;
- break;
- case 0xAE:
- //printf("LDX $%04x\n", (rb(pc+2)<<8) | rb(pc+1));
- x = rb((rb(pc+2)<<8) | rb(pc+1));
- if(x==0) p |= 2;
- else p &= 0xFD;
- if((x&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(x <= 0x80) p |= 0x80;
- if(x == 0x00) p &= 0x7F;
- cycles+=4;
- pc+=3;
- break;
- case 0xB0:
- //printf("BCS $%02x\n",rb(pc+1));
- cycles+=2;
- if((p & 1) != 0)
- {
- cycles+=1;
- if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc += (int8_t)rb(pc+1);
- pc += 2;
- }
- else pc+=2;
- break;
- case 0xB1:
- //printf("LDA ($%02x),Y\n", rb(pc+1));
- a = rb(rb(pc+1) + y);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(a <= 0x80) p |= 0x80;
- if(a == 0x00) p &= 0x7F;
- cycles+=4;
- if((pc & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc+=2;
- break;
- case 0xB4:
- //printf("LDY $%02x,X\n",rb(pc+1));
- y = rb(rb(pc+1)+x);
- if(y==0) p |= 2;
- else p &= 0xFD;
- if((y&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(y <= 0x80) p |= 0x80;
- if(y == 0x00) p &= 0x7F;
- cycles+=3;
- pc+=2;
- break;
- case 0xB5:
- //printf("LDA $%02x,X\n", rb(pc+1));
- a = rb(rb(pc+1)+x);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(a <= 0x80) p |= 0x80;
- if(a == 0x00) p &= 0x7F;
- cycles+=4;
- pc+=2;
- break;
- case 0xB8:
- //printf("CLV\n");
- p &= 0xBF;
- cycles+=2;
- pc+=1;
- break;
- case 0xB9:
- //printf("LDA $%04x,Y\n",(rb(pc+2)<<8) | rb(pc+1));
- a = rb(((rb(pc+2)<<8) | rb(pc+1)) + y);
- cycles+=4;
- if((pc & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc+=3;
- break;
- case 0xBA:
- //printf("TSX\n");
- x = s;
- cycles+=2;
- pc+=1;
- break;
- case 0xBC:
- //printf("LDY $%04x,X\n", (rb(pc+2)<<8) | rb(pc+1));
- y = rb(((rb(pc+2)<<8) | rb(pc+1))+x);
- if(y==0) p |= 2;
- else p &= 0xFD;
- if((y&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(y <= 0x80) p |= 0x80;
- if(y == 0x00) p &= 0x7F;
- cycles+=4;
- pc+=3;
- break;
- case 0xBD:
- //printf("LDA $%04x,X\n",(rb(pc+2)<<8) | rb(pc+1));
- a = rb(((rb(pc+2)<<8) | rb(pc+1)) + x);
- cycles+=4;
- if((pc & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc+=3;
- break;
- case 0xBE:
- //printf("LDX $%04x,Y\n", (rb(pc+2)<<8) | rb(pc+1));
- x = rb(((rb(pc+2)<<8) | rb(pc+1))+y);
- if(x==0) p |= 2;
- else p &= 0xFD;
- if((x&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- if(x <= 0x80) p |= 0x80;
- if(x == 0x00) p &= 0x7F;
- cycles+=4;
- if((pc & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc+=3;
- break;
- case 0xC0:
- //printf("CPY #$%02x\n",rb(pc+1));
- if((y - rb(pc+1)) == 0) p |= 2;
- else p &= 0xFD;
- if(((y - rb(pc+1)) & 0xFF) >= 0x80) p |= 0x80;
- else p &= 0x7F;
- if((y >= rb(pc+1))) p |= 1;
- else p &= 0xFE;
- cycles+=2;
- pc+=2;
- break;
- case 0xC8:
- //printf("INY\n");
- y++;
- if(y==0) p |= 2;
- else p &= 0xFD;
- if((y&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=1;
- break;
- case 0xC9:
- //printf("CMP #$%02x\n",rb(pc+1));
- if((a - rb(pc+1)) == 0) p |= 2;
- else p &= 0xFD;
- if(((a - rb(pc+1)) & 0xFF) >= 0x80) p |= 0x80;
- else p &= 0x7F;
- if((a >= rb(pc+1))) p |= 1;
- else p &= 0xFE;
- cycles+=2;
- pc+=2;
- break;
- case 0xCA:
- //printf("DEX\n");
- x--;
- if(x==0) p |= 2;
- else p &= 0xFD;
- if((x&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=1;
- break;
- case 0xCC:
- //printf("CPY $%04x\n",(rb(pc+2)<<8) | rb(pc+1));
- if((y - ((rb(pc+2)<<8) | rb(pc+1))) == 0) p |= 2;
- else p &= 0xFD;
- if(y >= 0x80) p |= 0x80;
- else p &= 0x7F;
- if((y >= ((rb(pc+2)<<8) | rb(pc+1)))) p |= 1;
- else p &= 0xFE;
- cycles+=2;
- pc+=3;
- break;
- case 0xD0:
- //printf("BNE $%02x\n",rb(pc+1));
- cycles+=2;
- if((p & 2) == 0)
- {
- cycles+=1;
- if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc += (int8_t)rb(pc+1);
- pc += 2;
- }
- else pc+=2;
- break;
- case 0xD8:
- //printf("CLD\n");
- p &= 0xF7;
- cycles+=2;
- pc+=1;
- break;
- case 0xDE:
- //printf("DEC $%04x,X\n",(rb(pc+2)<<8) | rb(pc+1));
- wb((rb(pc+2)<<8) | rb(pc+1),rb((rb(pc+2)<<8) | rb(pc+1))+1);
- if((rb((rb(pc+2)<<8) | rb(pc+1)))==0) p |= 2;
- else p &= 0xFD;
- if(((rb((rb(pc+2)<<8) | rb(pc+1)))&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=6;
- pc+=3;
- break;
- case 0xE0:
- //printf("CPX #$%02x\n",rb(pc+1));
- if((x - rb(pc+1)) == 0) p |= 2;
- else p &= 0xFD;
- if(((x - rb(pc+1)) & 0xFF) >= 0x80) p |= 0x80;
- else p &= 0x7F;
- if((x >= rb(pc+1))) p |= 1;
- else p &= 0xFE;
- cycles+=2;
- pc+=2;
- break;
- case 0xE8:
- //printf("INX\n");
- x++;
- if(x==0) p |= 2;
- else p &= 0xFD;
- if((x&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=2;
- pc+=1;
- break;
- case 0xE9:
- {
- uint8_t tmp = a;
- //printf("SBC #$%02x\n",rb(pc+1));
- a = a + ~rb(pc+1) + (p&1);
- if(tmp>=a) p |= 1;
- else p &= 0xFE;
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((tmp ^ rb(pc+1)) & (tmp ^ a) & 0x80) p |= 0x40;
- else p &= 0xBF;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=4;
- pc+=2;
- break;
- }
- case 0xEA:
- //printf("NOP\n");
- cycles+=2;
- pc+=1;
- break;
- case 0xED:
- //printf("SBC $%04x\n",(rb(pc+2)<<8) | rb(pc+1));
- a -= (p&1) + rb(((rb(pc+2)<<8) | rb(pc+1)));
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=4;
- pc+=3;
- break;
- case 0xEE:
- //printf("INC $%04x\n",(rb(pc+2)<<8) | rb(pc+1));
- wb((rb(pc+2)<<8) | rb(pc+1),rb((rb(pc+2)<<8) | rb(pc+1))+1);
- if((rb((rb(pc+2)<<8) | rb(pc+1)))==0) p |= 2;
- else p &= 0xFD;
- if(((rb((rb(pc+2)<<8) | rb(pc+1)))&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=6;
- pc+=3;
- break;
- case 0xF0:
- //printf("BEQ $%02x\n",rb(pc+1));
- cycles+=2;
- if((p & 2) == 2)
- {
- cycles+=1;
- if((((pc) + (int8_t)rb(pc+1)) & 0xFF00) != ((pc+2) & 0xFF00)) cycles+=1;
- pc += (int8_t)rb(pc+1);
- pc += 2;
- }
- else pc+=2;
- break;
- case 0xF5:
- //printf("SBC $%02x,X\n",(rb(pc+2)<<8) | rb(pc+1));
- a -= (p&1) + rb(rb(pc+1)+x);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=4;
- pc+=2;
- break;
- case 0xF6:
- //printf("INC $%02x,X\n",rb(pc+1));
- wb(rb(pc+1),rb(rb(pc+1))+1);
- if((rb(rb(pc+1)))==0) p |= 2;
- else p &= 0xFD;
- if(((rb(rb(pc+1)))&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=6;
- pc+=2;
- break;
- case 0xF8:
- //printf("SED\n");
- p |= 8;
- cycles+=2;
- pc+=1;
- break;
- case 0xF9:
- //printf("SBC $%04x,Y\n",(rb(pc+2)<<8) | rb(pc+1));
- a -= (p&1) + rb(((rb(pc+2)<<8) | rb(pc+1))+y);
- if(a==0) p |= 2;
- else p &= 0xFD;
- if((a&0x80) == 0x80) p |= 0x80;
- else p &= 0x7F;
- cycles+=4;
- pc+=3;
- break;
- default:
- printf("Unsupported opcode %02x. Aborting!\n",op);
- return 1;
- break;
- }
- //dumpregs();
- return 0;
- }
- }
- };
- void banner()
- {
- //printf("MSE NES driver version v1:\n\n");
- //printf("Written by Alegend45\n\n\n");
- }
- int main(int ac, char** av)
- {
- banner();
- FILE* fp = fopen(av[1],"rb");
- CPU a;
- if(fp != NULL)
- {
- fseek(fp,4,SEEK_SET);
- a.PRGbanks = fgetc(fp);
- a.CHRbanks = fgetc(fp);
- fseek(fp,6,SEEK_SET);
- a.mapper = fgetc(fp) >> 4;
- a.mapper |= fgetc(fp) & 0xF0;
- a.ppu.mapper = a.mapper;
- fseek(fp,0,SEEK_END);
- long pos = ftell(fp);
- a.totalrom = (uint8_t*)malloc(pos - 0x10);
- a.chrrom = (uint8_t*)malloc(pos - 0x10);
- a.LoadROM(fp);
- fclose(fp);
- SDL_Init(SDL_INIT_VIDEO);
- screen = SDL_SetVideoMode(256,240,24,SDL_SWSURFACE);
- a.dumpregs();
- SDL_Event e;
- for(;;)
- {
- if(a.tick() == 1)
- {
- SDL_Quit();
- return 1;
- }
- else
- {
- if(SDL_PollEvent(&e)) if(e.type == SDL_QUIT) return 2;
- SDL_Flip(screen);
- }
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement