ROMの入手1 - インターネットからの入手 違法にアップロードされたROMをダウンロードする方法 当然ながらダウンロードも違法行為(2010年1月1日より施行)
^ÇÇêÉëë=éáå a~í~=éáå
吸い出し機の仕組み - PRG-ROM, CHR-ROM ファミコンのカートリッジにはゲームプログラム本体(PRG-ROM)と グラフィックデータ(CHR-ROM)が存在する ines Header (16byte) PRG-ROM (32KB) CHR-ROM (8KB)
^ÇÇêÉëë=éáå `çåíêçä=éáå a~í~=éáå
void PPU::pattern_table_debug() { uint16_t base = 0x0000; uint8_t pal[4] = { 0x31, 0x21, 0x11, 0x01 }; int w = 0, h = 0; for(int k = 1; k <= (0x2000 / 16); k++) { for(int y = 0; y < 8; y++) { for(int x = 0; x < 8; x++) { uint8_t c = ((((vm.chr(base + y + 8) >> (7 - x)) & 1) << 1) ((vm.chr(base + y) >> (7 - x)) & 1)) & 3; screen_buff[(nes_screen_height * (y + h)) + (x + w)] = pal[c]; } } w += 8; if((k & 0x1f) == 0) h += 7; base += 16; } } }
jççáñáéç kçêã~ä
マッパー 初期はPRG32KB+CHR8KBの容量だったがゲームの規模が大きくなるにつ れ 容量が足らなくなるため ROM容量を拡張したものが出てくる 初期のPRG 32KB + CHR 8KBのROMをMapper 0(NROM)と言う - ROM Bank-switching PRG0 PRG1 Select=PRG0 Select=PRG0 Controller Bus PRG0 PRG2 CHR Bus Bus PPU
#include <stdio.h> int main(void) { printf( hello,world\n ); return 0; }
äç~ AÅMUM I ñ E F
~ÇÅ @ANM ^ MñNM =EfããÉÇá~íÉ=~ÇÇêÉëëáåÖF äç~ AÅMUM I ñ ^ jbjxmñ`mumhñz =E^ÄëçäìíÉ=fåÇÉñ=uF
ldx #$08 u U decrement: dex stx $0200 cpx #$03 bne decrement stx $0201 u N u MñOMM u P P u MñOMN brk
簡単なハード解析の例 - 回路のトレース どこがGNDに接続されていて この配線ならこのボタンの役割が 適当なのかな...などと考察しながら回路をトレースしていく
UÄáí=a^q^=_rp Rlj `mr j~éééê `çåíêçääéê R^j fll UÄáí=`lkqRli=_rp NSÄáí=^aaRbpp=_rp
0x10000 PRG-ROM 32KB 0x8000 0x6000 0x4020 SRAM Expansion ROM Mirrors (0x0000~0x07ff) 0x2000 0x0000 I/O Registers WRAM 4KB 0x0800 0x0200 0x0100 0x0000 RAM Stack Zero Page 256byte 256byte
// 1 void CPU::run() { uint16_t opcode = vm.read(++pc); switch(opcode) { case 0xa1: op_lda(addr_indirectx()); break; case 0xa5: op_lda(addr_zero()); break; case 0xa9: op_lda(addr_imm()); break; case 0xea: op_nop(); break; // } } // void CPU::op_lda(uint16_t addr) { reg_a = vm.read(addr); updateflag(reg_a); } uint16_t CPU::addr_imm() { return pc++; }
1 10の総和を求める メモリダンプ CPUトレース 機械語サンプル
タイミング調整 - エミュレートしたファミコン(のCPUだけ) タイミング調整をしていないので本来1.48MHz動作のはずが仮想2.13GHz動作に
t (s)
void CPU::run() { uint16_t opcode = vm.read(++pc); } switch(opcode) { // } executed_clock += cpu_cycles[opcode]; const uint8_t cpu_cycles[0x100] = { 7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6, 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7, 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 4, 6, 6, 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7, 6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6, 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7, 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 5, 4, 6, 6, 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7, 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, 2, 5, 2, 6, 4, 4, 4, 4, 2, 4, 2, 5, 5, 4, 5, 5, 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, 2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 4, 4, 4, 4, 4, 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7, 2, 6, 3, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7 };