Open qiaobaaa opened 4 months ago
main.c
int main(void) { //注意文件路径格式,不然会出现找不到文件 char game_name[] = "D:\mario.nes"; int tmp; tmp = nes_loadrom(game_name); if (tmp != 0) { printf("NES rom load failed, error code: %d\n", tmp); exit(tmp); }
return 0;
}
nes.h
int nes_loadrom(char* rom);
nes.c
cartridge_t cartridge;
int nes_loadrom(char rom) { FILE file;
file = fopen(rom, "rb+");
if (file == NULL)
{
return FILE_NOT_EXIST;
}
if (fread(cartridge.header,sizeof(uint8_t),16,file)!=16)
{
return FILE_HEADER_READ_FAILED;
}
else if (cartridge.header[0] != 0x4e || cartridge.header[1] != 0x45 || cartridge.header[2] != 0x53 || cartridge.header[3] != 0x1a)
{
return NOT_IS_NES_FORMAT;
}
else
{
/* 读取 ROM 信息 */
cartridge.prg_rom_size = 16 * 1024 * cartridge.header[4];
cartridge.chr_rom_size = 8 * 1024 * cartridge.header[5];
cartridge.prg_ram_size = 8 * 1024 * cartridge.header[8];
if (cartridge.chr_rom_size == 0)
{
cartridge.chr_rom_size = 8 * 1024;
}
if (cartridge.prg_ram_size == 0)
{
cartridge.prg_ram_size = 8 * 1024;
}
}
return 0;
}
cartridge.h
typedef struct Cartridge { /**
//CPU复位 void cpu_resrt() { cpu.reg_sp -= 3; cpu.reg_p |= FLAG_INTERRUPT; memory_write_byte(0x4015, 0); cpu.reg_pc = memory_read_word(0xfffc); }
//检查并设置zero flag与negative flag void cpu_checknz(uint8_t n) { if ((n >> 7) & 1) { cpu.reg_p |= FLAG_NEGATIVE; } else { cpu.reg_p &= ~FLAG_NEGATIVE; } if (n == 0) { cpu.reg_p = FLAG_ZERO; } else { cpu.reg_p &= ~FLAG_ZERO; } }
//修改flag void cpu_modify_flag(uint8_t flag, int value) { if (value) { cpu.reg_p |= flag; } else { cpu.reg_p &= ~flag; } }
//栈操作 void cpu_stack_push_byte(uint8_t data) { memory_write_byte(0x100 + cpu.reg_sp, data); cpu.reg_sp -= 1; } void cpu_stack_push_word(uint16_t data) { memory_write_word(0x0ff + cpu.reg_sp, data); cpu.reg_sp -= 2; } uint8_t cpu_stack_pop_byte() { cpu.reg_sp += 1; return memory_read_byte(0x100 + cpu.reg_sp); } uint16_t cpu_stack_pop_word() { cpu.reg_sp += 2; return memory_read_word(0x0ff + cpu.reg_sp); }
/ 存储 CPU 经过寻址后得到的地址和该地址对应的值 / uint16_t op_address; uint8_t op_value; uint8_t additional_cycles; // 对于某些寻址方式, 如果跨页访问, 需要多使用一个 CPU Cycle
/* implied (1 字节)
void cpu_addressing_implied() { additional_cycles = 0; }
/* accumulator (1 字节)
/* immediate (2 字节)
/* zeropage (2 字节)
/* zeropage, X-indexed (2 字节)
/* zeropage, Y-indexed (2 字节)
/* absolute (3 字节)
/* absolute, X-indexed (3 字节)
/* absolute, Y-indexed (3 字节)
/* relative (2 字节)
/* indirect (3 字节)
间接寻址. 对应地址内存单元中的数做为地址. */ void cpu_addressing_indirect() { uint16_t arg_addr = memory_read_word(cpu.reg_pc);
/ 据说这是 6502 的 Bug / if ((arg_addr & 0xff) == 0xff) { // 有 Bug 的情况下 op_address = (memory_read_byte(arg_addr & 0xff00) << 8) + memory_read_byte(arg_addr); } else { // 正常情况下 op_address = memory_read_word(arg_addr); } cpu.reg_pc += 2; additional_cycles = 0; }
/* indirect, X-indexed (2 字节)
/* indirect, Y-indexed (2 字节)
//56种常规指令集 //ALU: 算术逻辑单元
void cpu_ora() { cpu.reg_a |= op_value; cpu_checknz(cpu.reg_a); }
int num[13] = { 0 }; int b[4] = { 6,3,7,1 }; int t[4] = { 1,2,4,8 }; for (int x = 0; x < 4; x++) { if (x == 0 || x == 2) { for (int i = 0; i < 4; i++) { if ((b[x] & t[i]) != 0) { printf("第 %d 位为1 \n", i + 1); num[j] = 1; j++; } else { printf("第 %d 位为0 \n", i + 1); num[j] = 0; j++; } } } else if (x==1) { for (int i = 0; i < 3; i++) { if ((b[x] & t[i]) != 0) { printf("第 %d 位为1 \n", i + 1); num[j] = 1; j++; } else { printf("第 %d 位为0 \n", i + 1); num[j] = 0; j++; } } } else { for (int i = 0; i < 2; i++) { if ((b[x] & t[i]) != 0) { printf("第 %d 位为1 \n", i + 1); num[j] = 1; j++; } else { printf("第 %d 位为0 \n", i + 1); num[j] = 0; j++; } } } }