Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ファミコンエミュレータの創り方

bokuweb
September 07, 2018
41k

 ファミコンエミュレータの創り方

bokuweb

September 07, 2018
Tweet

Transcript

  1. CVJMEFSTDPOUPLZP
    ϑΝϛίϯΤϛϡϨʔλ
    ͷ૑Γํ
    !CPLVXFC

    View Slide

  2. !CPLVXFC
    IUUQCMPHCPLVXFCNF
    w ૊ΈࠐΈϋʔυιϑτ΢ΣΞΤϯδχΞ
    w 8FCϑϩϯτΤϯυΤϯδχΞ
    w ࢁ͔Β߱Γ͖ͯ·ͨ͠
    CPLVXFC
    ࣗݾ঺հ

    View Slide

  3. ͍͞͠ΐʹ
    !3VTU8FC"TTFNCMZ XJUIFNTDSJQUFO
    Ͱ
    ϑΝϛίϯΤϛϡϨʔλΛ࣮૷ͯ͠Έͨ࿩͠Λ͢ΔηογϣϯͰ͢
    !3VTU8FC"TTFNCMZͷجૅ΍ৄࡉʹ͸͋·Γ৮Ε·ͤΜ
    !ϑΝϛίϯͷϋʔυ΢ΣΞ΍੍໿ɺͦͷΤϛϡϨʔγϣϯํ๏
    Λॏ఺తʹ͓࿩͢Δͭ΋ΓͰ͢

    View Slide

  4. 2ϑΝϛίϯͷ࣮ػͰ
    ༡Μͩ͜ͱ͋Δਓ"

    View Slide

  5. %&.0
    IUUQTHJUIVCDPNCPLVXFCSVTUZOFT

    View Slide

  6. $16 31" 3*$0)੡
    CJU.)[
    116 ϐΫνϟʔϓϩηοαϢχοτ31$
    30. ࠷େϓϩάϥϜ30.,J#ΩϟϥΫλ30.,J#
    83". ϫʔΩϯά3".,J#
    73". ϏσΦ3".,J#
    ࠷େൃ৭਺ ৭
    ը໘ղ૾౓ ºϐΫηϧ
    α΢ϯυ ۣܗ೾ɺࡾ֯೾ɺϊΠζɺ%1$.
    ίϯτϩʔϥ ˢɺˣɺˡɺˠɺ"ɺ#ɺ45"35ɺ4&-&$5
    ϑΝϛίϯͷεϖοΫ

    View Slide

  7. $16
    31"
    116
    31$
    73".
    ,J#
    83".
    ,J#
    #6'
    Χηοτ
    .)[
    .)[
    /.*
    CJU116CVT
    CJU$16CVT
    "16
    ϑΝϛίϯ
    σΟεϓϨΠ
    α΢ϯυ
    ίϯτϩʔϥ
    ϑΝϛίϯͷϒϩοΫਤ

    View Slide

  8. ΤϛϡϨʔλΛ࡞Δʹ͸
    ͜ΕΒͷσόΠεΛҰͭҰͭ
    ࣮૷͍ͯ͘͠ඞཁ͕͋Δ

    View Slide

  9. ·ͣ͸ϑΝϛίϯͷΧηοτ

    View Slide

  10. 2த਎͕Ͳ͏ͳͬͯΔ͔
    ஌ͬͯ·͔͢ʁ

    View Slide

  11. ϓϩάϥϜ30.
    "த਎͸͜͏ͳ͍ͬͯΔ

    View Slide

  12. "த਎͸͜͏ͳ͍ͬͯΔ
    ΩϟϥΫλʔ30.

    View Slide

  13. ຊମͱͷ઀ଓίωΫλ
    "த਎͸͜͏ͳ͍ͬͯΔ

    View Slide

  14. -------
    GND -- |01 31| -- +5V
    CPU A11 -> |02 32| <- M2
    CPU A10 -> |03 33| <- CPU A12
    CPU A9 -> |04 34| <- CPU A13
    CPU A8 -> |05 35| <- CPU A14
    CPU A7 -> |06 36| <> CPU D7
    CPU A6 -> |07 37| <> CPU D6
    CPU A5 -> |08 38| <> CPU D5
    CPU A4 -> |09 39| <> CPU D4
    CPU A3 -> |10 40| <> CPU D3
    CPU A2 -> |11 41| <> CPU D2
    CPU A1 -> |12 42| <> CPU D1
    CPU A0 -> |13 43| <> CPU D0
    CPU R/W -> |14 44| <- /ROMSEL (/A15 + /M2)
    /IRQ <- |15 45| <- Audio from 2A03
    GND -- |16 46| -> Audio to RF
    PPU /RD -> |17 47| <- PPU /WR
    CIRAM A10 <- |18 48| -> CIRAM /CE
    PPU A6 -> |19 49| <- PPU /A13
    PPU A5 -> |20 50| <- PPU A7
    PPU A4 -> |21 51| <- PPU A8
    PPU A3 -> |22 52| <- PPU A9
    PPU A2 -> |23 53| <- PPU A10
    PPU A1 -> |24 54| <- PPU A11
    PPU A0 -> |25 55| <- PPU A12
    PPU D0 <> |26 56| <- PPU A13
    PPU D1 <> |27 57| <> PPU D7
    PPU D2 <> |28 58| <> PPU D6
    PPU D3 <> |29 59| <> PPU D5
    +5V -- |30 60| <> PPU D4
    -------
    ΧηοτͷίωΫλϐϯ഑ྻΛݟΔͱ
    $16116ͷCJUόε৴߸͕ͦΕͧΕ઀ଓ͞Ε͍ͯΔ
    Χηοτͷϐϯ഑ྻ
    $16ͷόε৴߸
    116ͷόε৴߸

    View Slide

  15. ΩϟϥΫλʔ
    30.
    116 $16
    ϑΝϛίϯຊମ
    ϓϩάϥϜ
    30.
    Χηοτ
    $16όεΛհͯ͠
    Ϧʔυ͞ΕΔ
    116όεΛհͯ͠
    Ϧʔυ͞ΕΔ
    Χηοτͱຊମͱͷόε઀ଓ

    View Slide

  16. ϓϩάϥϜ30.ͱ͸

    View Slide

  17. ήʔϜϓϩάϥϜ͕֨ೲ͞Εͨ30.
    $16͸ϓϩάϥϜ30.͔Β໋ྩϑΣονͯ͠ϓϩάϥϜ
    Λ࣮ߦ͢Δ
    void main()
    {
    char i;
    *(char*)0x2000 = 0x00;
    *(char*)0x2001 = 0x00;
    ͜Μͳͷ͕
    "'''"ʜ
    ͜Μͳײ͡Ͱ٧·ͬͯΔ
    ϓϩάϥϜ30.ͱ͸

    View Slide

  18. ΩϟϥΫλʔ30.ͱ͸

    View Slide

  19. ºͷήʔϜը૾͕֨ೲ͞Εͨ30.ʢ࠷େ,J#ʣ
    എܠͱΩϟϥΫλʔͦΕͧΕͷσʔλ͕٧·ͬͯΔ
    116͕ΩϟϥΫλʔ30.͔Βը૾σʔλΛಡΜͰ
    ը໘্ʹ഑ஔ͢Δ
    ΩϟϥΫλʔ30.ͱ͸

    View Slide

  20. ՄࢹԽͯ͠ΈΔͱ

    View Slide

  21. ҎԼ͸ઌఔͷσϞʮGBMMJOHʯͷΩϟϥΫλʔ30.ͷத਎
    ΩϟϥΫλʔ30.ͱ͸

    View Slide

  22. ̔#ZUFº#ZUFͰºαΠζͷը૾͕දݱ͞ΕΔ
    ҎԼ͸30.಺ͷεϓϥΠτΠϯσοΫε͕ϋʔτϚʔΫͩͬͨ৔߹ͷྫ
    "EESFTTT %BUB
    Y Y
    Y Y'
    Y Y''
    Y Y''
    Y Y''
    Y Y&
    Y Y$
    Y Y
    "EESFTTT %BUB
    Y Y
    Y Y'
    Y" Y#'
    Y# Y#'
    Y$ Y''
    Y% Y&
    Y& Y$
    Y' Y

























    ΩϟϥΫλʔ30.ͷσʔλ

    View Slide

  23. ΤϛϡϨʔλͰ͸͜ΕΒͷ৘ใΛ
    Ͳ͏औΓѻ͑͹͍͍͔

    View Slide

  24. J/&4ϑΥʔϚοτ

    View Slide

  25. $POTUBOU&" /&4GPMMPXFECZ.4%04FOEPGpMF

    4J[FPG13(30.JO,#VOJUT
    4J[FPG$)330.JO,#VOJUT 7BMVFNFBOTUIFCPBSEVTFT$)33".

    'MBHT
    'MBHT
    4J[FPG13(3".JO,#VOJUT 7BMVFJOGFST,#GPSDPNQBUJCJMJUZTFF13(3".DJSDVJU

    'MBHT
    'MBHT VOPGpDJBM

    ;FSPpMMFE
    #ZUF ,J#ZUF#MPDLTJ[F
    J/&4
    IFBEFS
    J/&4
    IFBEFS ϓϩάϥϜ30.
    ϓϩάϥϜ30. ΩϟϥΫλʔ30.
    ,J#ZUF#MPDLTJ[F
    J/&4IFBEFS
    ֦ுྖҬ
    J/&4ϑΥʔϚοτͷத਎
    #ZIFBEFSͷ#ZUFʹ
    ֤30.ͷϒϩοΫαΠζ͕
    ֨ೲ͞Ε͍ͯΔ

    View Slide

  26. ·ͣ͸OFTΛಡΜͰղੳͯ͠
    ֤30.Λ੾Γग़ͯ͠΍Δඞཁ͕͋Δ

    View Slide

  27. XBTN͔ΒOFTϑΝΠϧΛಡΉͷ͸େม
    ࠓճ͸+BWB4DSJQUଆͰOFTϑΝΠϧΛ
    GFUDIͯ͠3VTU XBTN
    ଆʹҾ͖౉͢͜ͱʹͨ͠

    View Slide

  28. const run = Module.cwrap("run", null, ["number", "number"]);
    const res = await fetch("./PATH_TO_NES_FILE.nes");
    const arrayBuf = await res.arrayBuffer();
    const nes = new Uint8Array(arrayBuf);
    const size = nes.byteLength;
    const ptr = Module._malloc(size);
    const buf = new Uint8Array(Module.HEAPU8.buffer, ptr, size);
    buf.set(nes);
    run(size, buf.byteOffset);
    +BWB4DSJQUଆͷॳظԽॲཧ
    3VTUଆͷؔ਺Λ+4
    ͔Βݺ΂ΔΑ͏ʹ ͜Ε͸Ҿ਺

    View Slide

  29. const run = Module.cwrap("run", null, ["number", "number"]);
    const res = await fetch("./PATH_TO_NES_FILE.nes");
    const arrayBuf = await res.arrayBuffer();
    const nes = new Uint8Array(arrayBuf);
    const size = nes.byteLength;
    const ptr = Module._malloc(size);
    const buf = new Uint8Array(Module.HEAPU8.buffer, ptr, size);
    buf.set(nes);
    run(size, buf.byteOffset);
    +BWB4DSJQUଆͷॳظԽॲཧ
    OFTϑΝΠϧΛϑΣον
    ͯ͠"SSBZ#VGGFSʹม׵

    View Slide

  30. const run = Module.cwrap("run", null, ["number", "number"]);
    const res = await fetch("./PATH_TO_NES_FILE.nes");
    const arrayBuf = await res.arrayBuffer();
    const nes = new Uint8Array(arrayBuf);
    const size = nes.byteLength;
    const ptr = Module._malloc(size);
    const buf = new Uint8Array(Module.HEAPU8.buffer, ptr, size);
    buf.set(nes);
    run(size, buf.byteOffset);
    +BWB4DSJQUଆͷॳظԽॲཧ
    OFTϑΝΠϧ෼ͷྖҬΛ
    NBMMPDͰ֬อ
    ʢFNTDSJQUFOΛ࢖༻ͨ͠৔߹
    .PEVMFʹੜ͑ͯΔʣ
    +4ଆ͔Β͸XBTNଆͷϝϞϦ͸"SSBZ#VGGFS
    ʹݟ͑ΔͷͰCZUF0GGTFUΛJ/&4σʔλͷઌ಄
    ʢ͢ͳΘͪϙΠϯλʣͱͯ͠αΠζͱҰॹʹڭ͑
    ͯ΍Δ

    View Slide

  31. #[no_mangle]
    pub fn run(len: usize, ptr: *mut u8) {
    let buf: &mut [u8] = unsafe { std::slice::from_raw_parts_mut(ptr, len + 1) };
    let cassette = parse(buf);
    let prom = Rom::new(cassette.program_rom);
    let crom = Rom::new(cassette.character_rom);
    // ... লུ ….
    }
    pub fn parse(buf: &mut [u8]) -> Cassette {
    let program_rom_pages = buf[4] as usize;
    let character_rom_pages = buf[5] as usize;
    let character_rom_start = NES_HEADER_SIZE + program_rom_pages * PROGRAM_ROM_SIZE;
    let character_rom_end = character_rom_start + character_rom_pages * CHARACTER_ROM_SIZE;
    Cassette {
    program_rom: buf[NES_HEADER_SIZE..character_rom_start].to_vec(),
    character_ram: buf[character_rom_start..character_rom_end].to_vec(),
    }
    }
    3VTU XBTN
    ଆͷॳظԽॲཧ
    +4ଆ͔ΒJ/&4σʔλͷ
    αΠζͱϙΠϯλΛ΋Β͏
    QBSTF֤ͯ͠30.Λ෼཭
    ޙड़͢Δ$16͕ϓϩάϥϜ30.
    ͷ಺༰Λ࣮ߦ͢Ε͹ήʔϜ͕։࢝͢Δʣ

    View Slide

  32. #[no_mangle]
    pub fn run(len: usize, ptr: *mut u8) {
    let buf: &mut [u8] = unsafe { std::slice::from_raw_parts_mut(ptr, len + 1) };
    let cassette = parse(buf);
    let prom = Rom::new(cassette.program_rom);
    let crom = Rom::new(cassette.character_rom);
    // ... লུ ….
    }
    pub fn parse(buf: &mut [u8]) -> Cassette {
    let program_rom_pages = buf[4] as usize;
    let character_rom_pages = buf[5] as usize;
    let character_rom_start = NES_HEADER_SIZE + program_rom_pages * PROGRAM_ROM_SIZE;
    let character_rom_end = character_rom_start + character_rom_pages * CHARACTER_ROM_SIZE;
    Cassette {
    program_rom: buf[NES_HEADER_SIZE..character_rom_start].to_vec(),
    character_ram: buf[character_rom_start..character_rom_end].to_vec(),
    }
    }
    3VTU XBTN
    ଆͷॳظԽॲཧ
    J/&4ϔομͷ৘ใ͔Β
    ֤30.Λ੾Γग़͢

    View Slide

  33. build:
    mkdir -p wasm
    rm -rf target/wasm32-unknown-emscripten/release/deps/*.wasm
    rm -rf target/wasm32-unknown-emscripten/release/rustynes.js
    cargo rustc --release \
    --target=wasm32-unknown-emscripten -- \
    -C opt-level=3 \
    -C link-args="-O3 -s -s EXPORTED_FUNCTIONS=['_run'] -s EXTRA_EXPORTED_RUNTIME_METHODS=['cwrap']" \
    --verbose
    cp target/wasm32-unknown-emscripten/release/rustynes.js wasm/rustynes.js
    cp target/wasm32-unknown-emscripten/release/deps/*.wasm wasm/rustynes.wasm
    wasm-gc wasm/rustynes.wasm wasm/rustynes.wasm
    ϏϧυίϚϯυ
    +4ଆʹFYQPSU͢Δؔ਺Λ
    ࢦఆͯ͠΍Δඞཁ͕͋Δ

    View Slide

  34. ϝϞϦʢ3".30.ʣ

    View Slide

  35. pub struct Ram {
    pub field: Vec,
    }
    impl Ram {
    pub fn new(buf: Vec) -> Ram {
    Ram { field: buf }
    }
    pub fn read(&self, addr: u16) -> u8 {
    self.field[addr as usize]
    }
    pub fn write(&mut self, addr: u16, data: u8) {
    self.field[addr as usize] = data;
    }
    }
    3".ͷ࣮૷

    View Slide

  36. $16͕ϝϞϦʹͲͷΑ͏ʹ
    ΞΫηε͢Δ͔஌ͬͯ·͔͢ʁ
    ׂ
    Ѫ

    View Slide

  37. ͲͷΑ͏ʹϝϞϦʹ
    ΞΫηε͢Δͷ͔ݟͯΈΔ
    ׂ
    Ѫ

    View Slide

  38. ΞυϨε
    νοϓηϨΫτ
    Ϧʔυ
    σʔλ
    Y%&"%
    Y#&
    43".ͷY%&"%൪஍ʹϦʔυΞΫηεΛߦ͍Y#&͕ಡΈग़͞ΕΔྫ
    43".ͷϦʔυλΠϛϯάྫ
    όεʹ͸ଞʹ΋༷ʑͳσόΠε͕઀ଓ͞ΕΔ
    Մೳੑ͕͋ΔͷͰͲͷσόΠε͕༗ޮ͔ࣔ͢৴߸
    νοϓηϨΫτɺΞυϨεɺϦʔυ৴߸ͳͲ
    Ϧʔυʹඞཁͳ৴߸͕ଗ͏ͱ3".͔Βσʔλ
    ׂ
    Ѫ

    View Slide

  39. ΞυϨε
    νοϓηϨΫτ
    Ϧʔυ
    σʔλ
    Y%&"%
    Y#&
    43".ͷY%&"%൪஍ʹϦʔυΞΫηεΛߦ͍Y#&͕ಡΈग़͞ΕΔྫ
    43".ͷϦʔυλΠϛϯάྫ
    ͜ͷλΠϛϯάͰY#&Λϥον͢Δ
    σʔλ͸Ϧʔυ৴߸ͷ্ཱ͕ͪΓ΍ͦͷޙͷ
    $16ΫϩοΫͷ্ཱ͕ͪΓͰऔΓࠐ·ΕΔ΋ͷ͕ଟ͍
    σόΠεʹϓϦϯτ͞Ε͍ͯΔ਺ࣈ͸͍͍ͩͨ͜͜ͷ਺ࣈ
    ʢDZDMF
    खݩͷ30.͸ͳͷͰ
    DZDMFOTҎ্ʹͯ͠Ͷͱ͍͏ҙຯ
    ׂ
    Ѫ

    View Slide

  40. ͢ͳΘͪɺ͜ΕΒͷ৴߸ΛλΠϛϯάΛकΓͭͭ
    ༩͑ͯ΍Ε͹Χηοτͷ30.͔Βσʔλ͕ಡΊΔ
    ׂ
    Ѫ

    View Slide

  41. $16

    View Slide

  42. w "QQMF**΍1$Τϯδϯʹ΋࠾༻͞Εͨϕʔε
    w ಈ࡞ΫϩοΫ͸.)[
    w .04͔ΒෆཁͳػೳΛ࡟ͬͯ"16ͱ%"$Λ࣮૷ͨ͠
    3JDPI੡ͷΧελϜ඼
    ϑΝϛίϯͷ$16

    View Slide

  43. $16ͷϨδελҰཡ
    ໊শ αΠζ ৄࡉ
    " CJU ΞΩϡϜϨʔλ
    9 CJU ΠϯσοΫεϨδελ
    : CJU ΠϯσοΫεϨδελ
    4 CJU ελοΫϙΠϯλ
    1 CJU εςʔλεϨδελ
    1$ CJU ϓϩάϥϜΧ΢ϯλ
    ελοΫϙΠϯλ͸ϏοτͷΞυϨεۭؒΛࢦ͢ඞཁ͕͋Δ͕
    ্ҐCJU͸Yʹݻఆ͞Ε͍ͯΔ
    ʢ83".ͷ͏ͪYʙY''ׂ͕Γ౰ͯΒΕΔʣ
    ͢ͳΘͪɺελοΫϙΠϯλϨδελ͕Y"ͷ৔߹ɺ
    ελοΫϙΠϯλ͸Y"ʹͳΔ
    ԋࢉ͸"ϨδελͰߦΘΕɺ9 :Ϩδελ͸ΠϯσοΫεʹ࢖༻͞ΕΔ


    View Slide

  44. εςʔλεϨδελ
    CJU ໊শ ৄࡉ ಺༰
    CJU / ωΨςΟϒ ԋࢉ݁ՌͷCJU͕ͷ࣌ʹηοτ
    CJU 7 Φʔόʔϑϩʔ 1ԋࢉ݁Ռ͕ΦʔόʔϑϩʔΛىͨ࣌͜͠ʹηο
    τ
    CJU 3 ༧໿ࡁΈ ৗʹηοτ͞Ε͍ͯΔ
    CJU # ϒϨʔΫϞʔυ #3,ൃੜ࣌ʹηοτɺ*32ൃੜ࣌ʹΫϦΞ
    CJU % σγϚϧϞʔυ σϑΥϧτɺ#$%Ϟʔυ ະ࣮૷

    CJU * *32ېࢭ *32ڐՄɺ*32ېࢭ
    CJU ; θϩ ԋࢉ݁Ռ͕ͷ࣌ʹηοτ
    CJU $ ΩϟϦʔ ΩϟϦʔൃੜ࣌ʹηοτ
    εςʔλεϨδελͷৄࡉ
    CJU͸ৗʹͰɺCJU͸/&4Ͱ͸ະ࣮૷

    *32͸ׂΓࠐΈɺ#3,͸ιϑτ΢ΤΞׂΓࠐΈ

    View Slide

  45. struct Status {
    negative: bool,
    overflow: bool,
    reserved: bool,
    break_mode: bool,
    decimal_mode: bool,
    interrupt: bool,
    zero: bool,
    carry: bool,
    }
    #[allow(non_snake_case)]
    pub struct Registers {
    A: u8,
    X: u8,
    Y: u8,
    SP: u8,
    PC: u16,
    P: Status,
    }
    $16ͷϨδελͷ࣮૷

    View Slide

  46. ΞυϨε αΠζ ༻్
    YʙY'' Y 83".
    YʙY''' 83".ͷϛϥʔ
    YʙY Y 116Ϩδελ
    YʙY''' 116Ϩδελͷϛϥʔ
    YʙY' Y "16*0ɺίϯτϩʔϥɺ%."
    YʙY''' Y'& ֦ு30.
    YʙY''' Y ֦ு3".
    YʙY#''' Y ϓϩάϥϜ30.
    Y$ʙY'''' Y ϓϩάϥϜ30.
    $16ͷϝϞϦϚοϓ
    Χηοτͷ
    ϓϩάϥϜ30.

    View Slide

  47. impl<'a> CpuBus for Bus<'a> {
    fn read_word(&mut self, addr: u16) -> u16 {
    // …লུ…
    }
    fn read(&mut self, addr: u16) -> u8 {
    match addr {
    0x0000...0x07FF => self.work_ram.read(addr),
    0x0800...0x1FFF => self.work_ram.read(addr - 0x0800),
    0x2000...0x3FFF => self.ppu.read(addr - 0x2000),
    0x4016 => self.keypad.read(),
    0x4017 => unimplemented!(), // 2player controller
    0x4000...0x401F => self.apu.read(addr - 0x4000),
    0x6000...0x7FFF => unimplemented!(), // battery back up ram
    0x8000...0xBFFF => self.program_rom.read(addr - 0x8000),
    0xC000...0xFFFF if self.program_rom.size() <= 0x4000 => self.program_rom.read(addr - 0xC000)
    0xC000...0xFFFF => self.program_rom.read(addr - 0x8000),
    _ => panic!("[READ] There is an illegal address. (0x{:x}) access detected.", addr),
    }
    }
    fn write(&mut self, addr: u16, data: u8) {
    // …লུ…
    }
    }
    $16͸$QV#VTϞδϡʔϧΛհ֤ͯ͠σόΠεʹΞΫηε͢ΔΑ͏ʹ
    $16όεͷ࣮૷
    ϝϞϦϚοϓΛ൓ө

    View Slide

  48. $16͸Ͳͷ൪஍͔Β
    ͲͷλΠϛϯάͰىಈ͢Δ͔

    View Slide

  49. ׂΓࠐΈ

    View Slide

  50. ׂΓࠐΈ͕ൃੜ͢Δͱ$16͸ݱࡏͷ
    ίϯςΩετΛελοΫʹୀආ͠
    ࢦఆΞυϨεʢׂΓࠐΈϕΫλςʔϒϧʣ
    ʹ֨ೲ͞Εͨ൪஍ΑΓ࣮ߦ։࢝ʢ࠶։ʣ͢Δ
    ͷׂΓࠐΈ

    View Slide

  51. ͨͱ͑͹ɺϦηοτʢϑΝϛίϯͷ࢛֯ͷϘλϯͰ͢Ͷʣ΋ׂΓࠐΈͷҰछͰ
    Ϧηοτ͕ൃੜͨ͠৔߹Y'''$ɺY'''%͔ΒCJUͷΞυϨεΛϦʔυ͠
    1$ʢϓϩάϥϜΧ΢ϯλʣʹηοτ͠ɺηοτ͞ΕͨΞυϨε͔Β࣮ߦ͠·͢
    ׂΓࠐΈ ԼҐόΠτ ্ҐόΠτ ֓ཁ
    /.* Y'''" Y'''#
    ϊϯϚεΧϥϒϧׂΓࠐΈͱݴͬͯ$16͸ଆͰϚεΫͰ͖ͳ
    ׂ͍ΓࠐΈͰ͢ɻ116ͷׂΓࠐΈग़ྗ৴߸͕઀ଓ͞Ε͍ͯ·
    ͢
    3&4&5 Y'''$ Y'''% ϦηοτϘλϯԡԼ࣌΍ిݯ౤ೖ࣌ʹ͔͔ΔׂΓࠐΈͰ͢
    *32ɺ#3, Y'''& Y''''
    #3,͸ιϑτ΢ΣΞׂΓࠐΈͰ#3,໋ྩΛ࣮ߦͨ͠ͱ͖ʹൃ
    ੜ͠·͢ɻ*32͸"16΍Χηοτʹ઀ଓ͞Ε͍ͯ·͢
    ͷ৔߹ҎԼͷΑ͏ͳׂΓࠐΈཁҼ͕༻ҙ͞Ε͍ͯ·͢
    ͷׂΓࠐΈ

    View Slide

  52. ϦηοτׂΓࠐΈͷ৔߹

    View Slide

  53. pub fn reset(registers: &mut T,
    bus: &mut U) {
    let pc = bus.read_word(0xFFFC);
    registers.set_PC(pc);
    }
    جຊతʹ͸ϓϩάϥϜ30.͸Yʹ഑ஔ͞Ε͍ͯΔͷͰ
    Y'''$͔ΒYɺY'''%͔ΒY͕Ϧʔυ͞ΕΔέʔε͕ଟ͍
    ͦ͏͢Δͱ࣍αΠΫϧ͸ϓϩάϥϜ30.ͷઌ಄Ͱ͋ΔY͔Β࣮ߦ͞ΕΔ
    ϦηοτׂΓࠐΈͷ࣮૷
    Y'''$Λ্ҐόΠτ
    Y'''%ΛԼҐόΠτ
    ͱͨ͠CJUΛϦʔυ
    Ϧʔυ͞ΕͨCJUͷΞυϨεΛ
    1$ʢϓϩάϥϜΧ΢ϯλʣʹηοτ
    ࣍αΠΫϧ͸ηοτͨ͠ΞυϨε͔Β࣮ߦ͞ΕΔ

    View Slide

  54. /.*ͷ৔߹

    View Slide

  55. pub fn process_nmi(registers: &mut T, bus: &mut U) {
    registers.set_break(false);
    push((registers.get_PC() >> 8) as u8, registers, bus);
    push(registers.get_PC() as u8, registers, bus);
    push_status(registers, bus);
    registers.set_interrupt(true);
    let next = bus.read_word(0xFFFA);
    registers.set_PC(next);
    }
    /.*ͷ࣮૷
    1$ͷ্ҐCJUɺ1$ͷԼҐCJU
    ͷॱʹελοΫʹ164)

    View Slide

  56. pub fn process_nmi(registers: &mut T, bus: &mut U) {
    registers.set_break(false);
    push((registers.get_PC() >> 8) as u8, registers, bus);
    push(registers.get_PC() as u8, registers, bus);
    push_status(registers, bus);
    registers.set_interrupt(true);
    let next = bus.read_word(0xFFFA);
    registers.set_PC(next);
    }
    /.*ͷ࣮૷
    εςʔλεϨδελΛ
    ελοΫʹ164)

    View Slide

  57. pub fn process_nmi(registers: &mut T, bus: &mut U) {
    registers.set_break(false);
    push((registers.get_PC() >> 8) as u8, registers, bus);
    push(registers.get_PC() as u8, registers, bus);
    push_status(registers, bus);
    registers.set_interrupt(true);
    let next = bus.read_word(0xFFFA);
    registers.set_PC(next);
    }
    /.*ͷ࣮૷
    Y'''" Y'''#͔ΒΞυϨεΛ
    Ϧʔυ͠1$ʹηοτ

    View Slide

  58. ྫ͑͹/.*લͷ1$͕YɺεςʔλεϨδελ͕Y""
    ελοΫϙΠϯλ͕Y''ͩͱ͢Δͱ/.*ޙͷελοΫ͸ҎԼͷΠϝʔδ
    Y''
    Y'&'
    Y'&&
    Y'&%
    Y'&
    ελοΫϙΠϯλ
    ʜ
    Y
    Y
    Y""
    1$ͷ্ҐΞυϨε
    1$ͷԼҐΞυϨε
    εςʔλεϨδελ
    ࣍ճͷ164)͸͜͜ʹੵ·ΕΔ
    /.*ͷ࣮ߦޙͷελοΫΠϝʔδ

    View Slide

  59. ͷ໋ྩ

    View Slide

  60. Ͱ͸"%$ Ճࢉ
    46# ݮࢉ
    ͳͲͷԋࢉͱ
    ԋࢉͷద༻ઌ΍ద༻ݩʢϨδελ΍ϝϞϦʣΛܾఆ͢Δ
    ΞυϨογϯάϞʔυ͕CJUͰදݱ͞Ε͍ͯΔ
    ͷ໋ྩ

    View Slide

  61. ͨͱ͑͹

    View Slide

  62. Y"͸-%"ͱ͍͏Ϩδελ"ʹ஋Λϩʔυ͢Δϩʔυ໋ྩͱ
    *NNFEJBUFͱ͍͏ଈ஋ΛऔΓѻ͏ΞυϨογϯάϞʔυ
    Y"͸-%"ͱ͍͏Ϩδελ"ʹ஋Λϩʔυ͢Δϩʔυ໋ྩͱ
    [FSPQBHFͱ͍͏্ҐCJU͕YͰ͋Δ൪஍Λૢ࡞͢ΔΞυϨογϯάϞʔυ
    ಉ͡-%"໋ྩͰ΋ΦϖϥϯυΛଈ஋ͱͯ͠ѻͬͨΓ্ҐYͷΞυϨεΛѻͬͨΓ
    ΞυϨγϯάϞʔυຖͷόϦΤʔγϣϯ͕͋Δ
    ԋࢉͷछྨºΞυϨογϯάϞʔυͰ໋ྩ͸໢ཏͰ͖ͦ͏
    -%"໋ྩ

    View Slide

  63. ུশ ໊લ ֓ཁ
    JNQM *NQMJFE ϨδελΛૢ࡞͢Δ
    " "DDVNVMBUPS "ϨδελΛૢ࡞͢Δ
    *NNFEJBUF Φϖίʔυ͕֨ೲ͞Ε͍ͯͨ࣍ͷ൪஍ʹ֨ೲ͞Ε͍ͯΔ஋Λσʔλͱͯ͠ѻ͏
    [QH ;FSPQBHF
    YΛ্ҐΞυϨεɺ1$ʢΦϖίʔυͷ࣍ͷ൪஍ʣʹ֨ೲ͞Εͨ஋ΛԼҐΞυϨεͱͨ͠൪஍Λԋ
    ࢉର৅ͱ͢Δ
    [QH 9
    [QH :
    ;FSPQBHF
    JOEFYFE
    YΛ্ҐΞυϨεɺ1$ʢΦϖίʔυͷ࣍ͷ൪஍ʣʹ֨ೲ͞Εͨ஋ʹ9Ϩδελ·ͨ͸:Ϩδελ
    ΛՃࢉͨ͠஋ΛԼҐΞυϨεͱͨ͠൪஍Λԋࢉର৅ͱ͢Δ
    BCT "CTPMVUF
    1$ʢΦϖίʔυͷ࣍ͷ൪஍ʣʹ֨ೲ͞Εͨ஋ΛԼҐΞυϨεɺ1$ʢΦϖίʔυͷ࣍ͷ࣍ͷ൪஍ʣʹ
    ֨ೲ͞Εͨ஋Λ্ҐΞυϨεͱͨ͠൪஍Λԋࢉର৅ͱ͢Δ
    BCT 9
    BCT :
    "CTPMVUF
    JOEFYFE
    "CTPMVUF"EESFTTJOHͰಘΒΕΔ஋ʹ9Ϩδελ·ͨ͸:ϨδελΛՃࢉͨ͠൪஍Λԋࢉର৅ͱ͢Δ
    SFM 3FMBUJWF 1$ʢΦϖίʔυͷ࣍ͷ൪஍ʣʹ֨ೲ͞Εͨ஋ͱͦͷ࣍ͷ൪஍ΛՃࢉͨ͠൪஍Λԋࢉର৅ͱ͢Δ
    9 *OE
    *OEFYFE
    *OEJSFDU
    YΛ্ҐΞυϨεɺ1$ʢΦϖίʔυͷ࣍ͷ൪஍ʣʹ֨ೲ͞Εͨ஋ΛԼҐΞυϨεͱͨ͠൪஍ʹϨ
    δελ9ͷ஋ΛՃࢉɺͦͷ൪஍ͷ஋ΛԼҐΞυϨεɺͦͷ࣍ͷ൪஍ͷ஋Λ্ҐΞυϨεͱͨ͠൪஍Λ
    ԋࢉର৅ͱ͢Δ
    *OE :
    *OEJSFDU
    JOEFYFE
    YΛ্ҐΞυϨεɺ1$ʢΦϖίʔυͷ࣍ͷ൪஍ʣʹ֨ೲ͞Εͨ஋ΛԼҐΞυϨεͱͨ͠൪஍ͷ஋
    ΛԼҐΞυϨεɺͦͷ࣍ͷ൪஍ͷ஋Λ্ҐΞυϨεͱͨ͠൪஍ʹϨδελ:ΛՃࢉͨ͠൪஍Λԋࢉର
    ৅ͱ͢Δ
    *OE
    "CTPMVUF
    JOEFYFE
    "CTPMVUF"EESFTTJOHͰಘΒΕΔ൪஍ʹ֨ೲ͞Ε͍ͯΔ஋ΛԼҐΞυϨεɺͦͷ࣍ͷ൪஍ʹ֨ೲ͞
    Ε͍ͯΔ஋Λ্ҐΞυϨεͱͨ͠൪஍Λԋࢉର৅ͱ͢Δ
    ΞυϨογϯάϞʔυ

    View Slide

  64. ໋ྩද

    View Slide

  65. ଟ͍

    View Slide

  66. ໋͍͔ͭ͘ྩΛϐοΫΞοϓ
    ͯ͠આ໌͠·͢

    View Slide

  67. -%"JNN
    ଈ஋Λ"Ϩδελʹϩʔυ͢Δ

    View Slide

  68. Yʹͱ͍͏໋ྩ͕֨ೲ͞Ε͍ͯΔ৔߹
    ϝϞϦͱ࣮ߦखॱҎԼͷΑ͏ʹͳΔʢ1$΋Yͱ͢Δʣ
    -%"
    ʢY"ʣ
    Y
    Y"
    Y
    ʜ
    Y
    -%""
    $16͸1$ ͢ͳΘͪY
    ͔Β໋ྩΛϑΣον͠1$Λ
    ϑΣον݁ՌY"͔Β-%"JNNͰ͋Δͱ൑ผ͞ΕΔ
    $16͸Y͔ΒΦϖϥϯυY"ΛϑΣον͠1$Λ
    Ϩδελ"ʹY"Λ֨ೲ͠ɺ࣍ͷ໋ྩ΁
    -%"JNN
    ࣍ͷ໋ྩ
    ͜ͷ஋Λ"Ϩδελ
    ʹϩʔυ͢Δ
    1$

    View Slide

  69. pub fn lda_imm(operand: Word, registers: &mut T) {
    registers
    .set_A(operand as Data)
    .update_negative_by(operand as Data)
    .update_zero_by(operand as Data);
    }
    #[test]
    fn test_lda_immediate() {
    let mut reg = Registers::new();
    lda_imm(0xA5, &mut reg);
    assert_eq!(reg.get_A(), 0xA5);
    }
    ଈ஋Λ"Ϩδελʹϩʔυ͢Δ
    -%"JNN
    "ϨδελʹΦϖϥϯυ
    ʹηοτ
    ηοτ͞Εͨ஋ʹରԠ͢Δ
    εςʔλεϑϥάΛηοτ

    View Slide

  70. -%"[QH
    ্ҐΛYԼҐΛΦϖϥϯυͱͨ͠ΞυϨεʹ
    ֨ೲ͞Ε͍ͯΔ஋Λ"Ϩδελʹϩʔυ͢Δ

    View Slide

  71. Yʹͱ͍͏໋ྩ͕֨ೲɺYʹ
    Y"͕֨ೲ͞Ε͍ͯΔ৔߹ϝϞϦͱ࣮ߦखॱҎԼͷΑ͏ʹͳΔ
    ʢ1$΋Yͱ͢Δʣ
    -%"
    ʢY"ʣ
    Y
    Y
    Y
    ʜ
    Y
    -%"
    $16͸1$ ͢ͳΘͪY
    ͔Β໋ྩΛϑΣον͠1$Λ
    ϑΣον݁ՌY"͔Β-%"[QHͰ͋Δͱ൑ผ͞ΕΔ
    $16͸Y͔ΒΦϖϥϯυYΛϑΣον͠1$Λ
    $16͸Y͔ΒY"ΛϦʔυ
    Ϩδελ"ʹY"Λ֨ೲ͠ɺ࣍ͷ໋ྩ΁
    Y"
    Y
    ʜ
    Y
    ʜ
    Y
    ᶃY൪஍ͷ಺༰ΛϦʔυ
    ᶄY"Λ"Ϩδελʹηοτ
    -%"[QH
    ࣍ͷ໋ྩ
    1$

    View Slide

  72. pub fn lda(operand: Word, registers: &mut T, bus: &mut U) {
    let computed = bus.read(operand);
    registers
    .set_A(computed)
    .update_negative_by(computed)
    .update_zero_by(computed);
    }
    #[test]
    fn test_lda() {
    let mut reg = Registers::new();
    let mut bus = MockBus::new();
    bus.mem[0xAA] = 0xA5;
    lda(0xAA, &mut reg, &mut bus);
    assert_eq!(reg.get_A(), 0xA5);
    }
    -%"[QH
    ্ҐΛYԼҐΛΦϖϥϯυͱͨ͠ΞυϨεʹ
    ֨ೲ͞Ε͍ͯΔ஋Λ"Ϩδελʹϩʔυ͢Δϩʔυ͢Δ
    Φϖϥϯυͷ஋ΞυϨεͱͯ͠Ϧʔυ
    Ϧʔυ͞Εͨ஋Λ"Ϩδελʹηοτ

    View Slide

  73. ͜͜·Ͱͷ$16ͷಈ࡞Λ·ͱΊΔͱ

    View Slide

  74. Ϧηοτ
    ແ͠
    ແ͠
    ༗Γ
    ༗Γ
    ׂΓࠐΈ
    ༗ແ
    Φϖϥϯυ
    ༗ແ
    Ϩδελͷ
    ঢ়ଶΛୀආ
    1$͔Β໋ྩ
    ΛϑΣον 1$

    1$͔ΒΦϖϥϯυΛ
    ϑΣον 1$

    ໋ྩΛ࣮ߦ
    ׂΓࠐΈϕΫλ
    ͷ஋Λ1$
    ʹηοτ
    $16ͷಈ࡞Πϝʔδ
    Y'''$'''%ʹ
    ֨ೲ͞Εͨ൪஍͔Β։࢝

    View Slide

  75. pub fn run(
    registers: &mut T,
    bus: &mut U,
    nmi: &mut bool,
    ) -> Data {
    if *nmi {
    process_nmi(registers, bus);
    *nmi = false;
    }
    let code = fetch(registers, bus);
    let ref map = opecode::MAP;
    let code = &*map.get(&code).unwrap();
    let operand = fetch_operand(&code, registers, bus);
    match code.name {
    Instruction::LDA if code.mode == Addressing::Immediate => lda_imm(operand, registers),
    Instruction::LDA => lda(operand, registers, bus),
    // …লུ…
    }
    code.cycle
    }
    $16ͷ࣮૷
    ׂΓࠐΈͷνΣοΫ

    View Slide

  76. pub fn run(
    registers: &mut T,
    bus: &mut U,
    nmi: &mut bool,
    ) -> Data {
    if *nmi {
    process_nmi(registers, bus);
    *nmi = false;
    }
    let code = fetch(registers, bus);
    let ref map = opecode::MAP;
    let code = &*map.get(&code).unwrap();
    let operand = fetch_operand(&code, registers, bus);
    match code.name {
    Instruction::LDA if code.mode == Addressing::Immediate => lda_imm(operand, registers),
    Instruction::LDA => lda(operand, registers, bus),
    // …লུ…
    }
    code.cycle
    }
    $16ͷ࣮૷
    1$͔Β໋ྩΛϑΣον
    σίʔυ
    ࣙॻ͔Β໋ྩͷछผɾΞυϨογϯά
    ϞʔυɺαΠΫϧ਺ͳͲΛҾ͍ͯ͘Δ

    View Slide

  77. $16ͷ࣮૷
    let mut m = HashMap::new();
    m.insert(0xA9, Opecode { name: Instruction::LDA, mode: Addressing::Immediate, cycle: cycles[0xA9] });
    m.insert(0xA5, Opecode { name: Instruction::LDA, mode: Addressing::ZeroPage, cycle: cycles[0xA5] });
    m.insert(0xB5, Opecode { name: Instruction::LDA, mode: Addressing::ZeroPageX, cycle: cycles[0xB5] });
    m.insert(0xAD, Opecode { name: Instruction::LDA, mode: Addressing::Absolute, cycle: cycles[0xAD] });
    m.insert(0xBD, Opecode { name: Instruction::LDA, mode: Addressing::AbsoluteX, cycle: cycles[0xBD] });
    m.insert(0xB9, Opecode { name: Instruction::LDA, mode: Addressing::AbsoluteY, cycle: cycles[0xB9] });
    m.insert(0xA2, Opecode { name: Instruction::LDX, mode: Addressing::Immediate, cycle: cycles[0xA2] });
    m.insert(0xA6, Opecode { name: Instruction::LDX, mode: Addressing::ZeroPage, cycle: cycles[0xA6] });
    // …লུ…
    ΞυϨογϯάϞʔυ΍αΠΫϧ਺
    Λ൑ผ

    View Slide

  78. pub fn run(
    registers: &mut T,
    bus: &mut U,
    nmi: &mut bool,
    ) -> Data {
    if *nmi {
    process_nmi(registers, bus);
    *nmi = false;
    }
    let code = fetch(registers, bus);
    let ref map = opecode::MAP;
    let code = &*map.get(&code).unwrap();
    let operand = fetch_operand(&code, registers, bus);
    match code.name {
    Instruction::LDA if code.mode == Addressing::Immediate => lda_imm(operand, registers),
    Instruction::LDA => lda(operand, registers, bus),
    // …লུ…
    }
    code.cycle
    }
    $16ͷ࣮૷
    1$͔ΒΦϖϥϯυΛϑΣον
    αΠΫϧ਺Λฦ͢
    -%"JNNҎ֎ͷ-%"໋ྩ
    -%"JNN໋ྩ

    View Slide

  79. ͋ͱ͸໋֤ͭͭ͜͜ྩΛ࣮૷$

    View Slide

  80. ͪͳΈʹޮ཰ͷ͍͍ςετํ๏͸

    View Slide

  81. ςετ30.Λ࢖༻͢Δ

    View Slide

  82. OFTUFTUOFT

    View Slide

  83. 116

    View Slide

  84. w ϐΫνϟʔϓϩηογϯάϢχοτͷུ
    w 73".ͳͲͷ಺༰Λ΋ͱʹεϓϥΠτͱόοΫάϥ΢ϯυ
    ͷϨΠϠʔΛ߹੒ͯ͠ग़ྗ͢Δ
    w $16ͷഒͷΫϩοΫͰಈ࡞
    w ͍Θ͹ݪ࢝తͳ(16ͱ͍ͬͯ΋͍͍͔΋
    116ͱ͸

    View Slide

  85. 116ͷϝϞϦϚοϓ

    View Slide

  86. ΞυϨε αΠζ ֓ཁ
    YʙY''' Y ύλʔϯςʔϒϧ
    YʙY''' Y ύλʔϯςʔϒϧ
    YʙY#' Y$ ωʔϜςʔϒϧ
    Y$ʙY'' Y ଐੑςʔϒϧ
    YʙY#' Y$ ωʔϜςʔϒϧ
    Y$ʙY'' Y ଐੑςʔϒϧ
    YʙY##' Y$ ωʔϜςʔϒϧ
    Y#$ʙY#'' Y ଐੑςʔϒϧ
    Y$ʙY'#' Y$ ωʔϜςʔϒϧ
    Y'$ʙY''' Y ଐੑςʔϒϧ
    YʙY&'' YY&''ͷϛϥʔ
    Y'ʙY'' Y όοΫάϥ΢ϯυύϨοτςʔϒϧ
    Y'ʙY'' Y εϓϥΠτύϨοτςʔϒϧ
    Y'ʙY''' Y'Y''ͷϛϥʔ
    116ͷϝϞϦϚοϓ
    Χηοτͷ
    ΩϟϥΫλʔ30.

    View Slide

  87. Α͘Θ͔Βͳ͍ςʔϒϧ
    ͕͍ͬͺ͍

    View Slide

  88. ϝϞϦϚοϓͷ֤߲໨ʹ͍ͭͯ
    આ໌͍ͯ͘͠

    View Slide

  89. ωʔϜςʔϒϧ

    View Slide

  90. 73".ྖҬ಺഑ஔ͞ΕΔɺը໘ʹରͯ͠ͲͷΑ͏ʹ
    എܠλΠϧΛෑ͖٧ΊΔ͔ΛܾΊΔςʔϒϧ
    ը໘ղ૾౓͸YϐΫηϧͳͷͰYϐΫηϧͷλΠϧ͕
    Yʢ͢ͳΘͪຕʣͰෑ͖٧ΊΒΕΔ͜ͱʹͳΔ
    ͳͷͰ
    ֤ωʔϜςʔϒϧͷαΠζ͸
    Y$#ZUF
    ωʔϜςʔϒϧͱ͸

    View Slide

  91. ͨͱ͑͹ҎԼͷը໘ͷ৔߹Y$ͷՕॴʹ)͕දࣔ͞͞ΕͯΔ
    ͢ͳΘͪɺɹɹʹ)Λද͢εϓϥΠτ൪߸Λॻ͖ࠐΊ͹͜ͷҐஔʹɹ͕දࣔ͞ΕΔ
    ωʔϜςʔϒϧ
    ͷઌ಄
    λΠϧ
    λΠϧ
    ωʔϜςʔϒϧ
    ͷ$൪஍ʹ૬౰
    Y$൪஍ )
    ωʔϜςʔϒϧ
    ͷऴ୺
    ωʔϜςʔϒϧͱ͸

    View Slide

  92. )FMMP 8PSMEͷαϯϓϧ30.ͷΩϟϥΫλʔ30.ͷ಺༰͸ҎԼͷΑ͏ʹͳ͍ͬͯΔ
    )ͷΠϯσοΫε͸ͳͷͰ
    ɺɹɹʹ)Λද͢ΛϥΠτ͢Ε͹Α͍
    Y$൪஍
    ωʔϜςʔϒϧͱ͸

    View Slide

  93. ଐੑςʔϒϧ

    View Slide

  94. എܠʹͲͷύϨοτΛద༻͢Δ͔Λܾఆ͢Δςʔϒϧ
    ஫ҙ఺ͱͯ͠͸ύϨοτ͸YϐΫηϧͷϒϩοΫ୯Ґ
    ͢ͳΘͪʢYλΠϧʣʹύϨοτʢ̐৭ʣద༻͞ΕΔ
    ϒϩοΫʹ͖ͭCJUͷ৘ใΛ͓࣋ͬͯΓɺը໘YͳͷͰ
    YϒϩοΫϒϩοΫɺϒϩοΫʹ͖ͭCJU
    ͳͷͰόΠτͷྖҬΛ࢖༻͢Δ
    ଐੑςʔϒϧͱ͸

    View Slide

  95. ྫ͑͹ଐੑςʔϒϧͷઌ಄൪஍Ͱ͋ΔY$൪஍͕Y&Ͱ͋Ε͹
    @@@CͳͷͰҎԼͷΑ͏ʹϒϩοΫʹద༻͞ΕΔύϨοτ͕ܾఆ͢Δ
    ԾʹҎԼͷύϨοτ͕ઃఆ͞Ε͍ͯͨͱ͢Δͱ
    λΠϧ ϒϩοΫ

    λΠϧ ϒϩοΫ



    ͜ͷϒϩοΫ Y
    ͸
    ͳͷͰ͕
    ࢖༻Ͱ͖Δ
    ύϨοτ

    ͜ͷϒϩοΫ͸
    ͜ͷϒϩοΫ͸
    ͜ͷϒϩοΫ͸
    ଐੑςʔϒϧͱ͸

    View Slide

  96. ύϨοτςʔϒϧ

    View Slide

  97. എܠ༻ʹ৭ͷύϨοτ͕ͭʢY'ʙY''ʣ
    εϓϥΠτ༻ʹ̐৭ͷύϨοτ͕ͭʢY'ʙY''ʣ
    ༻ҙ͞Ε͍ͯΔ
    ͨͩ͠ɺ֤എܠ༻ύϨοτͷઌ಄ͷ৭͸എܠ৭
    ֤εϓϥΠτ༻ύϨοτͷઌ಄ͷ৭͸ಁ໌ͱͯ͠ѻΘΕΔ
    ಉ࣌ʹ࢖༻Ͱ͖Δ৭͸എܠ༻͸࠷େ৭
    εϓϥΠτ༻͸࠷େ৭ಉ࣌ʹ࢖༻Ͱ͖Δ
    ύϨοτςʔϒϧͱ͸

    View Slide

  98. ͨͱ͑͹εύʔϚϦΦϒϥβʔεͷΦʔϓχϯάը໘͸ҎԼͷΑ͏ͳ
    ύϨοτ͕ઃఆ͞Ε͍ͯΔ
    ύϨοτY' ύϨοτY' ύϨοτY' ύϨοτY'$
    ύϨοτY' ύϨοτY' ύϨοτY' ύϨοτY'$
    എܠ༻ύϨοτʢഎܠ৭৭৭YύϨοτͰ৭ʣ
    εϓϥΠτ༻ύϨοτʢ৭͸ಁ໌৭ͳͷͰ৭YύϨοτͰ৭ʣ
    ֤ςʔϒϧͷઌ಄
    ͸ಁ໌৭ͱͯ͠
    ѻΘΕΔ
    ಁ໌৭ ಁ໌৭ ಁ໌৭
    ֤ςʔϒϧͷઌ಄
    ͸എܠ৭
    എܠ৭ എܠ৭ എܠ৭
    ϚϦΦ͸ӈଆͷ৭Ͱදݱ͞Ε͍ͯΔ
    ύϨοτςʔϒϧͱ͸

    View Slide

  99. ஋ͱ৭ͱͷରԠ͸ʁ

    View Slide

  100. [email protected]ΑΓ
    ϑΝϛίϯͷ৭͸116͕/54$৴߸Λ௚઀ੜ੒͢Δؔ܎্3(#Ͱ͸ͳ͘
    ً౓ʢϧϛφϯεʣͱ৭౓ʢΫϩϚʣͰදݱ͞ΕΔ
    ͨͱ͑͹εʔύʔϚϦΦϒϥβʔεͷۭͷ৭͸Y͸ҎԼͷΑ͏ͳҙຯΛ΋ͭ
    Y
    @C
    ৗʹ ً౓ ৭౓
    ύϨοτͷ৭
    ً౓
    ৭౓

    View Slide

  101. 116ͷϨδελΛோΊΔ

    View Slide

  102. ΞυϨε ֓ཁ
    Y
    Y
    CJU આ໌
    7#MBOL࣌ʹׂΓࠐΈΛग़ྗ
    ৗʹ̍
    εϓϥΠταΠζYY
    എܠ༻ύλʔϯςʔϒϧΞυϨεYY
    εϓϥΠτύλʔϯςʔϒϧΞυϨεYY
    116ΞυϨεΠϯΫϦϝϯτ
    ωʔϜςʔϒϧࢦఆ
    CJU આ໌
    എܠ৭CࠇC྘C੨C੺

    εϓϥΠτΠωʔϒϧσΟηʔϒϧΠωʔϒϧ
    എܠΠωʔϒϧσΟηʔϒϧΠωʔϒϧ
    εϓϥΠτͷը໘ࠨϐΫηϧඳըඳը͠ͳ͍ඳը͢Δ
    എܠͷը໘ࠨϐΫηϧඳըඳը͠ͳ͍ඳը͢Δ
    σΟεϓϨΠλΠϓΧϥʔϞϊΫϩ
    116ͷϨδελ 8SJUF

    View Slide

  103. ΞυϨε ֓ཁ
    Y
    εϓϥΠτϝϞϦΞυϨε
    YΛܦ༝ͯ͠εϓϥΠτϝϞϦ΁ॻ͖ࠐΉϏοτΞυϨεΛࢦఆ
    Y
    εϓϥΠτϝϞϦσʔλ
    YʹΑͬͯࢦఆ͞ΕͨεϓϥΠτϝϞϦΞυϨε΁σʔλΛॻ͖ࠐΉɻ
    ॻ͖ࠐΉ౓ʹεϓϥΠτϝϞϦΞυϨε͸ΠϯΫϦϝϯτ
    ͞ΕΔɻ
    Y
    എܠεΫϩʔϧΦϑηοτ
    ճϥΠτΛߦ͏͜ͱͰ9ɺ:ͷॱʹεΫϩʔϧ஋͕ઃఆ͞ΕΔ
    Y
    116"%%3 116ϝϞϦΞυϨε

    YΛܦ༝ͯ͠116ϝϞϦ΁ॻ͖ࠐΉϏοτΞυϨεΛࢦఆ͢Δɻ্ҐϏοτɺԼҐϏοτͷॱ
    ʹॻ͖ࠐΉɻ
    Y
    116%"5" 116ϝϞϦσʔλ

    YʹΑͬͯࢦఆ͞Εͨ116ϝϞϦΞυϨε΁σʔλΛॻ͖ࠐΉɻॻ͖ࠐΉ౓ʹϝϞϦΞυϨε͸Π
    ϯΫϦϝϯτ YͷϏοτʹΑͬͯɺ
    ͢Δɻ
    116ͷϨδελ 8SJUF

    View Slide

  104. ΞυϨε ֓ཁ
    Y
    Y
    εϓϥΠτϝϞϦσʔλ
    YʹΑͬͯࢦఆ͞ΕͨεϓϥΠτϝϞϦΞυϨε΁σʔλΛϦʔυ͢Δ
    Ϧʔυ͢Δ౓ʹεϓϥΠτϝϞϦΞυϨε͸ΠϯΫϦϝϯτ
    ͞ΕΔɻ
    Y
    116ϝϞϦσʔλ
    YʹΑͬͯࢦఆ͞Εͨ116ϝϞϦΞυϨεͷσʔλΛϦʔυ͢Δ
    Ϧʔυ͢Δ౓ʹϝϞϦΞυϨε͸ΠϯΫϦϝϯτ YͷϏοτʹΑͬͯɺ
    ͢Δɻ
    CJU આ໌
    7CMBOL࣌ʹ
    εϓϥΠτώοτ࣌ʹ
    εΩϟϯϥΠϯεϓϥΠτ਺ɹݸҎԼݸҎ্
    3FTFSWFE
    116ͷϨδελ 3FBE

    View Slide

  105. ͔͜͜Βॏཁͳ΋ͷΛൈ͖ग़ͯ͠
    ౎౓આ໌͍͖ͯ͠·͢

    View Slide

  106. தͰ΋ॏཁͳͷ͸

    View Slide

  107. 116"%%3116%"5"Ϩδελ

    View Slide

  108. 116ͷϝϞϦۭؒʢ73".ͳͲʣʹ$16͔ΒಡΈॻ͖͢ΔͨΊͷϨδελ
    $16
    116
    116"%%3
    116%"5"
    73".
    ΩϟϥΫλʔ30.
    73".΍ΩϟϥΫλʔ30.͸116όεʹ઀ଓ͞Ε͓ͯΓ
    $16͔Β͸௚઀ΞΫηεͰ͖ͳ͍
    ͦͷͨΊ116"%%3116%"5"Λհͯ͠ಡΈॻ͖͢Δ
    $16όε 116όε
    116"%%3116%"5"Ϩδελ

    View Slide

  109. Ͳ͏΍ͬͯ࢖͏͔

    View Slide

  110. 116ͷϝϞϦۭؒʢ73".ͳͲʣʹ$16͔ΒಡΈॻ͖͢ΔͨΊͷϨδελ
    116"%%3 Y
    ʹ̎ճॻ͖ࠐΈ͜ͱͰ116ϝϞϦۭؒΛࢦఆ
    ྫ͑͹Y' YΛ116"%%3ʹॻ͖ࠐΉ͜ͱͰ
    116ΞυϨε͕Y'ʹηοτ͞ΕΔ
    116%"5" Y
    ʹϦʔυϥΠτ͢Δ͜ͱͰ116"%%3
    Ͱࢦఆͨ͠116ϝϞϦۭؒΛಡΈॻ͖͢Δ͜ͱ͕Ͱ͖Δ
    ʢಡΈॻ͖Λ͢Δͱ116"%%3͸ࣗಈతʹ ·ͨ͸
    ΠϯΫϦϝϯτ͞ΕΔʣ
    116"%%3116%"5"Ϩδελ

    View Slide

  111. ͜͜·Ͱͷ࿩͔͠Β͢Δͱ
    73".ͷ಺༰Λى఺ʹ
    Ճ޻͍͚ͯ͠͹
    ϐΫηϧσʔλΛੜ੒Ͱ͖ͦ͏

    View Slide

  112. ωʔϜςʔϒϧ͔ΒͲͷഎܠεϓϥΠτ͕഑ஔ͞Ε͍ͯΔ͔Ϧʔυ͢Δ
    Ϧʔυ͞ΕͨεϓϥΠτ൪߸ΛݩʹΧηοτ͔Βը૾σʔλΛಡΜͰ͘Δ
    ଐੑςʔϒϧ͔ΒഎܠεϓϥΠτʹద༻͞ΕΔύϨοτ൪߸ΛಡΜͰ͘Δ
    ύϨοτςʔϒϧ͔ΒύϨοτͷ৭ΛಡΜͰ͘Δ
    എܠεϓϥΠτͷCJU৘ใΛݩʹύϨοτ͔Βண৭͢Δ
    ͜ͷखॱͰωʔϜςʔϒϧ͔Β
    YQYͷϐΫηϧσʔλ͕ͭ͘ΕΔ͸ͣ
    116ඳըखॱΠϝʔδ

    View Slide

  113. ΋͏ͪΐͬͱ۩ମతͳྫ

    View Slide

  114. )FMMP 8PSMEͷ)ΛωʔϜςʔϒϧ͔ΒϐΫηϧσʔλʹͯ͠ΈΔྫ
    ωʔϜςʔϒϧͷΛϦʔυ͠εϓϥΠτ൪߸ΛಘΔ
    εϓϥΠτ͸ΩϟϥΫλʔ30.಺ʹ#ZUFͣͭฒΜͰ͍ΔͷͰ
    YYY͔Β#ZUFϦʔυ͠εϓϥΠτΛ૊ΈཱͯΔ
    Y$൪஍








    Y
    ֘౰ͷ࠲ඪ͸ଐੑςʔϒϧͷΞυϨεY%"ʹ֘౰͢ΔͨΊ
    73".ͷ͔ΒΞτϦϏϡʔτ͕Ϧʔυ͞ΕΔ
    Y%"൪஍ Y
    116ඳըखॱΠϝʔδ
    ͜ΜͳεϓϥΠτ
    σʔλ͕ಘΒΕΔ

    View Slide

  115. Ϧʔυ͞ΕͨΞτϦϏϡʔτ͔Β֘౰ϙδγϣϯͷύϨοτ൪߸Λ
    औΓग़͢ͱʹͳΔͷͰύϨοτ͕ద༻͞ΕΔ͜ͱ͕Θ͔Δ
    ύϨοτ͢ͳΘͪ73".ͷ#ZUFಡΉͱ
    ͕ϦʔυͰ͖Δɻ͜ΕΛΧϥʔίʔυදʹద༻͢Δͱ࣍ͷ৭Ͱ͋Δ͜ͱ͕Θ͔Δ
    ͨΊ3(#ʹม׵֤͠ϐΫηϧʹύϨοτΛద༻ͯ͠΍Δͱ׬੒







    ύϨοτ̌
    ׬੒✨
    C
    Y'd Y' Y Y Y
    116ඳըखॱΠϝʔδ
    )FMMP 8PSMEͷ)ΛωʔϜςʔϒϧ͔ΒϐΫηϧσʔλʹͯ͠ΈΔྫ

    View Slide

  116. impl Tile {
    pub fn new(
    vram: &Ram,
    cram: &Ram,
    palette: &P,
    position: &SpritePosition,
    config: &SpriteConfig,
    ) -> Self {
    let block_id = get_block_id(position);
    let sprite_id = get_sprite_id(&vram, position, config);
    let attr = get_attribute(&vram, position, config);
    let palette_id = (attr >> (block_id * 2)) & 0x03;
    let sprite = build(&cram, sprite_id, config.offset_addr_by_background_table);
    Tile { sprite, palette: palette.get(palette_id, PaletteType::Background) }
    }
    }
    pub fn build(cram: &Ram, sprite_id: u8, offset: u16) -> Sprite {
    let mut sprite: Sprite = (0..8).into_iter().map(|_| vec![0; 8]).collect();
    for i in 0..16 {
    for j in 0..8 {
    let addr = (sprite_id as u16) * 16 + i + offset;
    let ram = cram.read(addr);
    if ram & (0x80 >> j) as u8 != 0 {
    sprite[(i % 8) as usize][j] += (0x01 << (i / 8)) as u8;
    }
    }
    }
    sprite
    }
    116ඳըखॱΠϝʔδ
    ࠲ඪ͔ΒϒϩοΫ൪߸
    Λࢉग़
    ࠲ඪͱωʔϜςʔϒϧ͔Β
    εϓϥΠτ൪߸Λࢉग़

    View Slide

  117. impl Tile {
    pub fn new(
    vram: &Ram,
    cram: &Ram,
    palette: &P,
    position: &SpritePosition,
    config: &SpriteConfig,
    ) -> Self {
    let block_id = get_block_id(position);
    let sprite_id = get_sprite_id(&vram, position, config);
    let attr = get_attribute(&vram, position, config);
    let palette_id = (attr >> (block_id * 2)) & 0x03;
    let sprite = build(&cram, sprite_id, config.offset_addr_by_background_table);
    Tile { sprite, palette: palette.get(palette_id, PaletteType::Background) }
    }
    }
    pub fn build(cram: &Ram, sprite_id: u8, offset: u16) -> Sprite {
    let mut sprite: Sprite = (0..8).into_iter().map(|_| vec![0; 8]).collect();
    for i in 0..16 {
    for j in 0..8 {
    let addr = (sprite_id as u16) * 16 + i + offset;
    let ram = cram.read(addr);
    if ram & (0x80 >> j) as u8 != 0 {
    sprite[(i % 8) as usize][j] += (0x01 << (i / 8)) as u8;
    }
    }
    }
    sprite
    }
    116ඳըखॱΠϝʔδ
    ࠲ඪͱଐੑςʔϒϧ͔Β
    ΞτϦϏϡʔτΛࢉग़
    ΞτϦϏϡʔτͱϒϩοΫ൪߸͔Β
    ύϨοτ൪߸Λࢉग़

    View Slide

  118. impl Tile {
    pub fn new(
    vram: &Ram,
    cram: &Ram,
    palette: &P,
    position: &SpritePosition,
    config: &SpriteConfig,
    ) -> Self {
    let block_id = get_block_id(position);
    let sprite_id = get_sprite_id(&vram, position, config);
    let attr = get_attribute(&vram, position, config);
    let palette_id = (attr >> (block_id * 2)) & 0x03;
    let sprite = build(&cram, sprite_id, config.offset_addr_by_background_table);
    Tile { sprite, palette: palette.get(palette_id, PaletteType::Background) }
    }
    }
    pub fn build(cram: &Ram, sprite_id: u8, offset: u16) -> Sprite {
    let mut sprite: Sprite = (0..8).into_iter().map(|_| vec![0; 8]).collect();
    for i in 0..16 {
    for j in 0..8 {
    let addr = (sprite_id as u16) * 16 + i + offset;
    let ram = cram.read(addr);
    if ram & (0x80 >> j) as u8 != 0 {
    sprite[(i % 8) as usize][j] += (0x01 << (i / 8)) as u8;
    }
    }
    }
    sprite
    }
    116ඳըखॱΠϝʔδ
    εϓϥΠτ൪߸͔Β
    YͷϐΫηϧσʔλΛ
    ࡞੒

    View Slide

  119. fn render_tile(&mut self, bg: &BackgroundCtx, x: usize, y: usize) {
    let offset_x = (bg.scroll_x % 8) as i32;
    let offset_y = (bg.scroll_y % 8) as i32;
    for i in 0..8 {
    for j in 0..8 {
    let x = (x + j) as i32 - offset_x;
    let y = (y + i) as i32 - offset_y;
    if x >= 0 as i32 && 0xFF >= x && y >= 0 as i32 && y < 224 {
    let color_id = bg.tile.palette[bg.tile.sprite[i][j] as usize];
    let color = COLORS[color_id as usize];
    let index = ((x + (y * 0x100)) * 4) as usize;
    self.buf[index] = color.0;
    self.buf[index + 1] = color.1;
    self.buf[index + 2] = color.2;
    if x < 8 {
    self.buf[index + 3] = 0;
    }
    }
    }
    }
    }
    pub static COLORS: &'static [(u8, u8, u8)] = &[
    (0x80, 0x80, 0x80), (0x00, 0x3D, 0xA6), (0x00, 0x12, 0xB0), (0x44, 0x00, 0x96), …লུ…
    ];
    116ඳըखॱΠϝʔδ
    ً౓ɺ৭౓ͷσʔλΛ
    3(#ʹม׵͢Δςʔϒϧ
    εϓϥΠτɺύϨοτ
    ͔Β3(#"ͷϐΫηϧσʔλ
    ʹม׵

    View Slide

  120. ϐΫηϧσʔλ͸ಘΒΕ͕ͨ
    Ͳ͏΍ͬͯϒϥ΢βʹදࣔ͢Δ͔

    View Slide

  121. $BOWBT

    View Slide

  122. const canvas = document.querySelector("canvas");
    const ctx = canvas.getContext("2d");
    Module.NES = { ctx, canvas, image: ctx.createImageData(256, 240) };
    mergeInto(LibraryManager.library, {
    canvas_render: function (ptr, len) {
    Module.NES.buf = new Uint8Array(Module.HEAPU8.buffer, ptr, len);
    Module.NES.image.data.set(Module.NES.buf);
    Module.NES.ctx.putImageData(Module.NES.image, 0, 0);
    },
    })
    +BWB4DSJQUଆͷॲཧ
    FNTDSJQUFOΛ࢖༻͍ͯ͠Δ৔߹
    NFSHF*OUPΛ࢖༻ͯ͠+4ؔ਺Λ
    3VTUଆʹެ։Ͱ͖Δ

    View Slide

  123. const canvas = document.querySelector("canvas");
    const ctx = canvas.getContext("2d");
    Module.NES = { ctx, canvas, image: ctx.createImageData(256, 240) };
    mergeInto(LibraryManager.library, {
    canvas_render: function (ptr, len) {
    Module.NES.buf = new Uint8Array(Module.HEAPU8.buffer, ptr, len);
    Module.NES.image.data.set(Module.NES.buf);
    Module.NES.ctx.putImageData(Module.NES.image, 0, 0);
    },
    })
    +BWB4DSJQUଆͷॲཧ
    3VTUଆ͔ΒϐΫηϧσʔλͷ
    ϙΠϯλͱ௕͞Λ΋Βͬͯ
    *NBHF%BUBʹηοτ

    View Slide

  124. extern "C" {
    fn canvas_render(ptr: *const u8, len: usize);
    }
    impl Renderer {
    pub fn render(
    &mut self,
    background: &BackgroundField,
    sprites: &SpritesWithCtx) {
    // …লུ…
    unsafe {
    canvas_render(self.buf.as_ptr(), self.buf.len());
    }
    }
    3VTU XBTN
    ଆͷॲཧ
    ͜Μͳ;͏ʹݺ΂Δ όοϑΝͷϙΠϯλͱ௕͞Λ
    ڭ͑ͯ͋͛Δ

    View Slide

  125. ͜ΕͰ73".ͷ಺༰Λ
    $BOWBTʹॻ͖ग़ͤͦ͏

    View Slide

  126. ͋ͱ͸$16ͱͷಉظͳͲ
    λΠϛϯάपΓ

    View Slide

  127. ͦͷલʹ116ͷϝϞϦۭؒͷ
    ஫ҙ఺Λ͝঺հ
    ׂ
    Ѫ

    View Slide

  128. 116%"5"͔Β116ͷϝϞϦۭؒͷσʔλΛ$16͔ΒϦʔυͰ͖Δ͕
    116಺෦ʹ͸ϦʔυόοϑΝ͕ೖ͍ͬͯͯ116͔Βͷσʔλग़ྗ̍αΠΫϧ஗ΕΔ
    ͨͿΜҟͳΔΫϩοΫͷόε
    Λ·͙ͨͨΊ'*'0ΛೖΕͯಉظΛͱͬͯΔ
    ͨͩ͠ɺεϓϥΠτ3".ɺύϨοτςʔϒϧ͸আ͘
    ʢ΍΍͍͜͠ʜʣ
    ͜Ε͸ʢଟ෼ʣεϓϥΠτ3".ɺύϨοτςʔϒϧ͸116ͷ಺෦ʹߏ੒͞Ε͍ͯͯ
    όεΛ·͍ͨͰ͍ͳ͍ʢ$16όε௚݁ʣ͡Όͳ͍͔ͱਪଌ
    ΤϛϡϨʔλ࡞ऀ͸͜ΕΛݟམͱ͢ͱপʹ͸·Δ
    116ͷϝϞϦۭؒ஫ҙ఺
    ׂ
    Ѫ

    View Slide

  129. 116ͷඳըλΠϛϯά

    View Slide

  130. MJOFQJYFM
    جຊతʹ͸116DZDMFͰQJYFMͣͭඳը
    ࠨ͔Βը໘ͷӈ୺ʹ
    QJYFMͣͭඳը͍ͯ͘͠
    EJTQMBZ
    116ͷඳըλΠϛϯά

    View Slide

  131. MJOFQJYFM
    ࣍ͷϥΠϯ΁ͷඳը४උΛؚΊΔͱMJOF͋ͨΓαΠΫϧඞཁ
    ࣍ͷϥΠϯ΁ͷ४උ
    ը໘ӈ୺·Ͱ౸ୡͨ͠Β
    ࣍ͷϥΠϯͷࠨ୺ʹ໭Δ
    ʢIWMBOL

    EJTQMBZ
    116ͷඳըλΠϛϯά

    View Slide

  132. MJOFQJYFM
    ը໘ͷӈԼ୺ʹ౸ୡ MJOF෼
    ͨ͠Βը໘෼ͷඳը͕׬ྃ
    EJTQMBZ MJOF
    116ඳըλΠϛϯά

    View Slide

  133. MJOFQJYFM
    EJTQMBZ
    ࣍ͷඳըͷͨΊʹઌ಄΁໭Δ
    ͜ͷͨΊͷظؒΛͱݴ͍
    MJOF෼ͷ࣌ؒΛཁ͢Δ
    Ұը໘ͷߋ৽ʹ͸
    Y αΠΫϧ
    ඞཁͱͳΔ
    ͢ͳΘͪ
    7CMBOL
    ը໘ͷӈԼ୺ʹ౸ୡ MJOF෼
    ͨ͠Βը໘෼ͷඳը͕׬ྃ
    116ඳըλΠϛϯά

    View Slide

  134. MJOFQJYFM
    ͜ͷαΠΫϧΛඵؒʹճ '14
    ܁Γฦ͢͜ͱͰ
    Ωϟϥ΍എܠ͕ͳΊΒ͔ʹಈ͖ήʔϜͱͯ͠੒ཱ͢Δ
    EJTQMBZ MJOF
    116ඳըλΠϛϯά

    View Slide

  135. 116ͷσʔλߋ৽ͷ੍໿
    ΤϛϡϨʔλ࡞ऀʹ͸
    ͋·Γؔ܎ͳ͍͔΋

    View Slide

  136. EJTQMBZ
    ඳըதʹ73".Λॻ͖׵͑Δͱը໘͕ΈͩΕͯ͠·͏
    ඳըத
    116ͷσʔλߋ৽ͷ੍໿

    View Slide

  137. ඳըΛߦ͍ͬͯͳ͍7CMBOLதʹ73".Λॻ͖׵͑Δ
    $16͸116εςʔλεϨδελ·ͨ͸/.*ʹͯ
    7MBOLͰ͋Δ͜ͱΛ஌Δ͜ͱ͕Ͱ͖Δ
    EJTQMBZ
    7CMBOLத
    116ͷσʔλߋ৽ͷ੍໿

    View Slide

  138. pub fn run(&mut self, cycle: usize, nmi: &mut bool, mmc: &Mmc) -> bool {
    let cycle = self.cycle + cycle;
    if cycle < 341 {
    self.cycle = cycle;
    return false;
    }
    if self.line == 0 {
    self.background.clear();
    }
    self.cycle = cycle - 341;
    self.line = self.line + 1;
    if self.line <= 240 && self.line % 8 == 0 {
    self.background.build_line(
    &self.ctx.vram,
    &self.ctx.cram,
    &self.ctx.palette,
    (tile_x, tile_y),
    );
    }
    // …লུ…
    }
    116ͷ࣮૷
    116αΠΫϧ਺ΛՃࢉ͍͖ͯ͠
    MJOF׬͔ྃͨ͠Λ൑ఆ

    View Slide

  139. pub fn run(&mut self, cycle: usize, nmi: &mut bool, mmc: &Mmc) -> bool {
    let cycle = self.cycle + cycle;
    if cycle < 341 {
    self.cycle = cycle;
    return false;
    }
    if self.line == 0 {
    self.background.clear();
    }
    self.cycle = cycle - 341;
    self.line = self.line + 1;
    if self.line <= 240 && self.line % 8 == 0 {
    self.background.build_line(
    &self.ctx.vram,
    &self.ctx.cram,
    &self.ctx.palette,
    (tile_x, tile_y),
    );
    }
    // …লུ…
    }
    116ͷ࣮૷
    ඳը۠ؒͰ͋Ε͹
    ϥΠϯຖʹഎܠΛ
    ૊Έཱ͍ͯͯ͘
    MJOFd

    View Slide

  140. pub fn run(&mut self, cycle: usize, nmi: &mut bool, mmc: &Mmc) -> bool {
    //…লུ…
    if self.line == 241 {
    self.registers.set_vblank();
    if self.registers.is_irq_enable() {
    *nmi = true;
    }
    }
    if self.line >= 262 {
    self.registers.clear_vblank();
    self.line = 0;
    self.sprites = build_sprites(
    &self.ctx.cram,
    &self.ctx.sprite_ram,
    &self.ctx.palette,
    );
    return true;
    }
    false
    }
    116ͷ࣮૷
    ׂΓࠐΈ༗ޮͰ͋Ε͹WCMBOL
    ࣌ʹ/.*ΛΞΫςΟϒʹઃఆ
    7#MBOLϑϥάΛηοτ
    MJOF

    View Slide

  141. pub fn run(&mut self, cycle: usize, nmi: &mut bool, mmc: &Mmc) -> bool {
    //…লུ…
    if self.line == 241 {
    self.registers.set_vblank();
    if self.registers.is_irq_enable() {
    *nmi = true;
    }
    }
    if self.line >= 262 {
    self.registers.clear_vblank();
    self.line = 0;
    self.sprites = build_sprites(
    &self.ctx.cram,
    &self.ctx.sprite_ram,
    &self.ctx.palette,
    );
    return true;
    }
    false
    }
    116ͷ࣮૷
    ϥΠϯͰҰը໘෼ͷ
    ඳը͕׬੒
    MJOF

    View Slide

  142. ͋ͱ͸$16ͱ116ɺඳըͷಉظΛ
    ͲͷΑ͏ʹͱΔ͔

    View Slide

  143. ٯࢉͯ͘͠ͱྑͦ͞͏

    View Slide

  144. ϑΝϛίϯ͸'14ɺ͢ͳΘͪNTຖʹ116͕ߋ৽ͨ͠
    ը໘σʔλΛ࡞੒Ͱ͖Ε͹ྑ͍
    લड़ͨ͠Α͏ʹը໘ͷߋ৽͸ 116αΠΫϧ
    ͳͷͰ
    NTຖʹ116͕ը໘ੜ੒͢Δ·Ͱ
    ໿ YαΠΫϧ
    $16Λ࣮ߦͯ͠΍Ε͹Α͍
    116ͷαΠΫϧ͸$16ͷഒ଎ʢഒͷΫϩοΫ͕ೖྗʣ
    $16ͱ116ͷಉظ

    View Slide

  145. ࣌ؒ
    NT NT
    ը໘෼ͷσʔλ͕
    Ͱ͖Δ·Ͱ
    $16116Λ࣮ߦ
    ը໘෼ͷσʔλ͕
    Ͱ͖Δ·Ͱ
    $16116Λ࣮ߦ
    ը໘෼ͷσʔλ͕
    Ͱ͖Δ·Ͱ
    $16116Λ࣮ߦ
    ඳը ඳը ඳը
    ͜ΜͳΠϝʔδͰ࣮ߦ͍ͨ͠
    NT
    $16ͱ116ͷಉظ

    View Slide

  146. SFRVFTU"OJNBUJPO'SBNFΛ࢖͍͍ͨ
    '14Ͱಈ࡞͢ΔΑ͏ʹ͍͍ײ͡ʹ͕Μ͹ͬͯ͘ΕΔ΍ͭ

    View Slide

  147. void emscripten_set_main_loop(
    em_callback_func func,
    int fps,
    int simulate_infinite_loop)
    FNTDSJQUFOΛ࢖༻͍ͯ͠Δ৔߹͍͕ͭ͜࢖͑Δ
    ୈೋҾ਺ʹΛηοτ͢ΔͱΛ
    ࢖ͬͯ͘ΕΔ
    SFRVFTU"OJNBUJPO'SBNF
    [email protected]@[email protected]
    ୈࡾҾ਺Ληοτ͢ΔͱແݶϧʔϓΛ
    γϛϡϨʔτ

    View Slide

  148. [email protected]\
    nes::run(&mut ctx);
    };
    externs::set_main_loop_callback(main_loop);
    pub fn run(ctx: &mut Context) {
    loop {
    // …লུ…
    let cycle: u16 = cpu::run(&mut ctx.cpu_registers, &mut cpu_bus, &mut ctx.nmi) as u16
    let is_ready = ctx.ppu.run((cycle * 3) as usize, &mut ctx.nmi, &ctx.mmc);
    if is_ready {
    if ctx.ppu.background.0.len() != 0 {
    ctx.renderer.render(&ctx.ppu.background.0, &ctx.ppu.sprites);
    }
    break;
    }
    }
    }
    ϝΠϯϧʔϓͷ࣮૷
    NTपظͰOFTSVOΛ࣮ߦ

    View Slide

  149. [email protected]\
    nes::run(&mut ctx);
    };
    externs::set_main_loop_callback(main_loop);
    pub fn run(ctx: &mut Context) {
    loop {
    // …লུ…
    let cycle: u16 = cpu::run(&mut ctx.cpu_registers, &mut cpu_bus, &mut ctx.nmi) as u16
    let is_ready = ctx.ppu.run((cycle * 3) as usize, &mut ctx.nmi, &ctx.mmc);
    if is_ready {
    if ctx.ppu.background.0.len() != 0 {
    ctx.renderer.render(&ctx.ppu.background.0, &ctx.ppu.sprites);
    }
    break;
    }
    }
    }
    ϝΠϯϧʔϓͷ࣮૷
    ߋ৽ͨ͠ը໘ͷϐΫηϧσʔλͷ४උ͕
    Ͱ͖Δ·Ͱ$16ͱ116Λ࣮ߦ͢Δ
    $16ͷ࣮ߦαΠΫϧͷഒͷαΠΫϧΛ
    ౉͢ʢ116αΠΫϧ΁ͷม׵ʣOΛ࣮ߦ

    View Slide

  150. [email protected]\
    nes::run(&mut ctx);
    };
    externs::set_main_loop_callback(main_loop);
    pub fn run(ctx: &mut Context) {
    loop {
    // …লུ…
    let cycle: u16 = cpu::run(&mut ctx.cpu_registers, &mut cpu_bus, &mut ctx.nmi) as u16
    let is_ready = ctx.ppu.run((cycle * 3) as usize, &mut ctx.nmi, &ctx.mmc);
    if is_ready {
    if ctx.ppu.background.0.len() != 0 {
    ctx.renderer.render(&ctx.ppu.background.0, &ctx.ppu.sprites);
    }
    break;
    }
    }
    }
    ϝΠϯϧʔϓͷ࣮૷
    Ұը໘෼४උ͕Ͱ͖ͨΒϨϯμϦϯά

    View Slide

  151. ͜͜·Ͱ͕࣮૷Ͱ͖Ε͹
    )FMMP 8PSME͕ඳըͰ͖ͦ͏

    View Slide

  152. )&--0 803-%ͷαϯϓϧίʔυ
    ΛݟͯΈΔ

    View Slide

  153. IUUQIQWFDUPSDPKQBVUIPST7"OFTTBNQMFIUNMΑΓ
    )&--0 803-%

    View Slide

  154. )FMMP 8PSME
    char NesMain()
    {
    const char palettes[] = {
    0x0f, 0x00, 0x10, 0x20,
    0x0f, 0x06, 0x16, 0x26,
    0x0f, 0x08, 0x18, 0x28,
    0x0f, 0x0a, 0x1a, 0x2a
    };
    const char string[] = "HELLO, WORLD!";
    char i;
    *(char*)0x2000 = 0x00;
    *(char*)0x2001 = 0x00;
    *(char*)0x2006 = 0x3f;
    *(char*)0x2006 = 0x00;
    for (i = 0; i < 0x10; i ++)
    *(char*)0x2007 = palettes[i];
    *(char*)0x2006 = 0x21;
    *(char*)0x2006 = 0xc9;
    for (i = 0; i < 13; i ++)
    *(char*)0x2007 = string[i];
    *(char*)0x2000 = 0x08;
    *(char*)0x2001 = 0x1e;
    while (1);
    return 0;
    }

    View Slide

  155. char NesMain()
    {
    const char palettes[] = {
    0x0f, 0x00, 0x10, 0x20,
    0x0f, 0x06, 0x16, 0x26,
    0x0f, 0x08, 0x18, 0x28,
    0x0f, 0x0a, 0x1a, 0x2a
    };
    const char string[] = "HELLO, WORLD!";
    എܠύϨοτσʔλ
    ৭෼Λࢦఆ
    ॻ͖ࠐΉจࣈྻ
    )FMMP 8PSME

    View Slide

  156. *(char*)0x2000 = 0x00;
    *(char*)0x2001 = 0x00;
    *(char*)0x2006 = 0x3f;
    *(char*)0x2006 = 0x00;
    for (i = 0; i < 0x10; i ++)
    *(char*)0x2007 = palettes[i];
    ඳը΍ׂΓࠐΈΛېࢭ
    Y' YΛYʹॻ͖ࠐΉ
    ͜ͱͰ116ΞυϨεY'Λࢦఆ
    ͭ·ΓഎܠύϨοτςʔϒϧྖҬ
    YʹσʔλΛॻ͖͜ΜͰ͍͘͜ͱͰ
    ઌʹࢦఆͨ͠Y'͔ΒॱʹQBMFUUTͷσʔλΛసૹ͍ͯ͘͠
    116ΞυϨε͸σʔλ͕ॻ͖ࠐ·ΕΔͨͼʹ116ଆͰࣗಈΠϯΫϦϝϯτ͞ΕΔ

    ͜ΕͰύϨοτσʔλͷసૹ͸0,
    )FMMP 8PSME

    View Slide

  157. *(char*)0x2006 = 0x21;
    *(char*)0x2006 = 0xc9;
    for (i = 0; i < 13; i ++)
    *(char*)0x2007 = string[i];
    *(char*)0x2000 = 0x08;
    *(char*)0x2001 = 0x1e;
    while (1);
    return 0;
    }
    Y Y$ΛYʹॻ͖ࠐΉ
    ͜ͱͰ116ΞυϨεY$Λࢦఆ
    Yʹॻ͖ࠐΉ͜ͱͰ
    Y$ʙʹA)&--0 803-%A
    Λసૹ
    ඳը։࢝
    ͜ͷαϯϓϧ͸Ұ౓ը໘Λඳըͨ͠Β
    ߋ৽͞Εͳ͍ͷͰແݶϧʔϓ
    )FMMP 8PSME

    View Slide


  158. )FMMP 8PSME

    View Slide

  159. ͜͜·ͰͰΑ͏΍͘
    )&--0 803-%

    View Slide

  160. ଞͷ30.Λಈ͔͢ʹ͸·ͩ·ͩ
    ػೳΛ࣮૷͠ͳͯ͘͸ͳΒͳ͍

    View Slide

  161. εΫϩʔϧ

    View Slide

  162. 0x2000ʙ0x23BF 0x03C0 ωʔϜςʔϒϧ0
    0x23C0ʙ0x23FF 0x0040 ଐੑςʔϒϧ0
    0x2400ʙ0x27BF 0x03C0 ωʔϜςʔϒϧ1
    0x27C0ʙ0x27FF 0x0040 ଐੑςʔϒϧ1
    0x2800ʙ0x2BBF 0x03C0 ωʔϜςʔϒϧ2
    0x2BC0ʙ0x2BFF 0x0040 ଐੑςʔϒϧ2
    0x2C00ʙ0x2FBF 0x03C0 ωʔϜςʔϒϧ3
    0x2FC0ʙ0x2FFF 0x0040 ଐੑςʔϒϧ3
    116ͷϝϞϦϚοϓΛݟ௚͢ͱҎԼͷΑ͏ʹωʔϜςʔϒϧͱ
    ଐੑςʔϒϧͷηοτΛͭʢ͢ͳΘͪը໘෼ʣ࣋ͯΔΑ͏ʹͳ͍ͬͯΔ
    116ͷϝϞϦϚοϓ ࠶

    View Slide

  163. ը໘෼ͷςʔϒϧ͸ҎԼͷΑ͏ͳ഑ஔʹͳ͍ͬͯΔ
    ωʔϜଐੑςʔϒϧ
    YdY''
    ωʔϜଐੑςʔϒϧ
    YdY''
    ωʔϜଐੑςʔϒϧ
    YdY#''
    ωʔϜଐੑςʔϒϧ
    Y$dY'''
    116ͷωʔϜଐੑςʔϒϧͷ഑ஔ

    View Slide

  164. ԣεΫϩʔϧήʔϜͷྫ

    View Slide

  165. ҎԼͷΑ͏ʹ[email protected]Λࢦఆ͢Δ͜ͱͰσΟεϓϨΠʹ੾Γग़͢ྖҬΛมߋͰ͖Δ
    ωʔϜ
    ଐੑςʔϒϧ
    YdY''
    ωʔϜ
    ଐੑςʔϒϧ
    YdY''
    σΟεϓϨΠʹ͸ҎԼͷ෦෼͕੾Γग़͞Εͯ
    දࣔ͞ΕΔ
    [email protected]
    εΫϩʔϧͱදࣔྖҬͷؔ܎

    View Slide

  166. εΫϩʔϧؔ͢ΔϨδελ͸ͭ
    ׂ
    Ѫ

    View Slide

  167. ΞυϨε ֓ཁ
    Y
    എܠεΫϩʔϧΦϑηοτ
    ճϥΠτΛߦ͏͜ͱͰ9ɺ:ͷॱʹεΫϩʔϧ஋͕ઃఆ͞ΕΔ
    1164$30--Ϩδελ
    αΠζ͕CJUͳͷͰd·ͰͷεΫϩʔϧ͕ઃఆͰ͖Δ
    ͜ͷͻͱͭͷϨδελͰYํ޲ɺZํ޲྆ํઃఆͰ͖ΔΑ͏ʹͳ͍ͬͯΔ
    ࠷ॳͷॻ͖ࠐΈ͕Yํ޲ɺೋճ໨ͷॻ͖ࠐΈ͕Zํ޲ͱͳΔ
    QYͣͭεΫϩʔϧ͍ͨ͠৔߹͸͜ͷϨδελΛ੍ޚ͢Δ
    ͔͠͠ɺ͜ͷϨδελ͚ͩͰ͸QYҎ্ͷεΫϩʔϧ͸ෆՄ
    ׂ
    Ѫ

    View Slide

  168. 116$53-Ϩδελ
    ΞυϨε ֓ཁ
    Y
    CJU આ໌
    ʜ ʜলུʜ
    ωʔϜςʔϒϧࢦఆ
    116$53-Ϩδελ Y
    ͷCJU͸ωʔϜςʔϒϧΛࢦఆ͢Δ͜ͱ͕Ͱ͖Δ
    ωʔϜ
    ଐੑςʔϒϧ
    ωʔϜ
    ଐੑςʔϒϧ
    ωʔϜ
    ଐੑςʔϒϧ
    ωʔϜ
    ଐੑςʔϒϧ
    ྫ͑͹ωʔϜςʔϒϧࢦఆ͕CͰ͋Ε͹͜ͷςʔϒϧ͕ࢦఆ͞Εͨ͜ͱʹͳΓ
    Yํ޲ʹQY෼εΫϩʔϧ͕Φϑηοτͨ͜͠ͱͱಉ౳ͱͳΔ
    ઌͷ1164$30--ͱ߹ΘͤΕ͹
    QYҎ্ͷεΫϩʔϧ͕Մೳ
    ׂ
    Ѫ

    View Slide

  169. ͜ΕΒΛ࢖͏ͱ໘ന͍දݱ͕Մೳʹ

    View Slide

  170. ϥελεΫϩʔϧ

    View Slide

  171. ඳըͷ్தͰεΫϩʔϧ஋Λௐ੔͢Δ͜ͱͰը໘ͷ్த͔ΒεΫϩʔϧ͕Մೳ
    εΫϩʔϧ଎౓Λม͑Δ͜ͱͰͦΕͧΕҧͬͨ଎౓ͰεΫϩʔϧͤ͞Δ͜ͱ΋Մೳ
    ϥελεΫϩʔϧ

    View Slide

  172. εϓϥΠτ

    View Slide

  173. ͜͜·Ͱઆ໌ͨ͠ͷ͸എܠͰ͕͢ɺΩϟϥΫλʔΛಈ͔͢ʹ͸
    εϓϥΠτͱͯ͠ඳը͢Δඞཁ͕͋Δ
    എܠ εϓϥΠτ
    എܠ͸YͷλΠϧΛYݸ
    ը໘ʹෑ͖٧ΊͯεΫϩʔϧ౳Ͱ
    ಈ͔͢͜ͱ͕Ͱ͖Δ
    εϓϥΠτͰ͋Ε͹YZࣗ༝ʹઃఆՄೳ
    8PYJBOHOJÁPOJÁP.PKPO5XJOT
    εϓϥΠτ

    View Slide

  174. εϓϥΠτͷσʔλ͸Ͳ͜ʹॻ͔͘

    View Slide

  175. 116͸εϓϥΠτ༻ͷྖҬεϓϥΠτ3".Λ͍࣋ͬͯΔ
    116ͷϝϞϦϚοϓʹ͸දݱ͞Ε͍ͯͳ͍͓ͦ͠Β͘116಺෦ͷྖҬʁ
    ΞυϨε ֓ཁ
    Y
    εϓϥΠτϝϞϦΞυϨε
    YΛܦ༝ͯ͠εϓϥΠτϝϞϦ΁ϦʔυϥΠτ͢ΔϏοτΞυϨεΛࢦఆ
    Y
    εϓϥΠτϝϞϦσʔλ
    YʹΑͬͯࢦఆ͞ΕͨεϓϥΠτϝϞϦΞυϨεʹ͍ͨͯ͠ϦʔυϥΠτΛߦ͏
    ΞΫηε͢Δͨͼʹ౓ʹεϓϥΠτϝϞϦΞυϨε͸ΠϯΫϦϝϯτ
    ͞ΕΔɻ
    ΞΫηεํ๏͸116"%%3116%"5" YY
    ͱ΄΅ಉ͡
    ҟͳΔ఺͸εϓϥΠτ3".ͷۭؒ͸CJUͰදݱͰ͖ΔͷͰ
    ΞυϨεΛઃఆ͢ΔͨΊʹ̎ճॻ͖ࠐΉඞཁ͸ͳ͍
    #ZUF
    εϓϥΠτ3".

    View Slide

  176. εϓϥΠτͭʹରͯ͠ҎԼͷ#ZUFͷઃఆΛ͍࣋ͬͯΔ
    #ZUF ֓ཁ
    :࠲ඪ

    εϓϥΠτΠϯσοΫε
    ΩϟϥΫλʔ30.಺ͷεϓϥΠτͷԿ൪໨ͷεϓϥΠτΛద༻͢Δ͔Λࢦఆ͢Δ

    9࠲ඪ
    CJU આ໌
    ਨ௚ํ޲൓స൓స͠ͳ͍൓స͢Δ
    ਫฏํ޲൓స൓స͠ͳ͍൓స͢Δ
    දࣔ༏ઌॱҐεϓϥΠτΛ༏ઌഎܠΛ༏ઌ
    ༧໿

    ύϨοτ൪߸CύϨοτCύϨοτ
    CύϨοτCύϨοτ
    εϓϥΠτ3".͸#ZUFͳͷͰηοτͰ͖Δ
    ࠷େεϓϥΠτ
    εϓϥΠτ3".

    View Slide

  177. εϓϥΠτʹؔ͢ΔϢχʔΫͳ࢓༷

    View Slide

  178. εϓϥΠτώοτ
    ʢ௨শʰര஄ʱʣ

    View Slide

  179. ΞυϨε ֓ཁ
    Y
    CJU આ໌
    7CMBOL࣌ʹ
    εϓϥΠτώοτ࣌ʹ
    εΩϟϯϥΠϯεϓϥΠτ਺ɹݸҎԼݸҎ্
    3FTFSWFE
    εϓϥΠτ̌ώοτ
    εϓϥΠτ3".ͷઌ಄ʹઃఆ͞ΕͨεϓϥΠτ͕
    ϥΠϯόοϑΝʹల։͞ΕΔͱ116Ϩδελ Y

    ͷʮεϓϥΠτ̌ώοτʯϑϥάཱ͕ͭVOΛ࣮ߦ

    View Slide

  180. ༻్͸ʁ

    View Slide

  181. ࣮͸͜͜ʹಁ໌ͳ̌ര஄͕഑ஔ͞Ε͍ͯΔ
    8PYJBOHOJÁPOJÁP.PKPO5XJOT
    εϓϥΠτ̌ώοτ

    View Slide

  182. ʮεϓϥΠτ̌ώοτʯϑϥάΛݕग़͔ͯ͠Β
    εΫϩʔϧॲཧΛ։࢝͢Δ͜ͱʹΑΓ
    ݻఆϔομΛ࣮ݱ͍ͯ͠Δ
    ج४ͱͳΔεϓϥΠτʢ̌ര஄ʣ
    ͸͜͜ʹઃஔͯ͋͠Δ
    8PYJBOHOJÁPOJÁP.PKPO5XJOT
    εϓϥΠτ̌ώοτ

    View Slide

  183. εϓϥΠτͷ੍໿

    View Slide

  184. ࣮͸εϓϥΠτ͸ಉҰϥΠϯ্ʹͭ·Ͱ͔͠഑ஔͰ͖ͳ͍
    116͸ϥΠϯόοϑΝΛ͓࣋ͬͯΓ
    ϥΠϯຖʹεϓϥΠτͱഎܠͷ߹੒Λߦ͍ඳը͍ͯ͠Δ
    ͜ͷॲཧ͸ίετ͕ߴ͘࠷େͭ·Ͱ͔͠߹੒Ͱ͖ͳ͍Β͍͠
    ౰࣌ͷϝϞϦͱίετͷؔ܎͔Β
    ϑϨʔϜόοϑΝʹ͸Ͱ͖ͳ͔ͬͨΜͩͱਪଌ
    ΞυϨε ֓ཁ
    Y
    CJU આ໌
    ʜ ʜ
    εΩϟϯϥΠϯεϓϥΠτ਺ɹݸҎԼݸҎ্
    ʜ ʜ
    ͜Ε͸্ه੍໿Λݕग़͢ΔͨΊͷػߏ
    ͕ͩɺόάͬͯΔͱͷӟ΋͋Γ
    Ͳͷఔ౓࢖༻͞Ε͍ͯͨͷ͔͸ෆ໌
    εϓϥΠτͷ੍໿

    View Slide

  185. ൃੜ͢Δ໰୊ͱରࡦʢະݕূʣ

    View Slide

  186. ࠶ݱ؀ڥ͕ͳ͍ͷͰະݕূͰ͕͢ʜ
    υϥΰϯΫΤετͰ͸֗ͷதͰ̐ਓͷύʔςΟͱଜਓ͕
    ԣҰ௚ઢʹฒͿͱϥΠϯ্ͷεϓϥΠτ਺͕ͱͳΓ
    ύʔςΟϝϯόʔ΋͘͠͸ଜਓ͕ফ͑Δ
    ͦͷͨΊɺιϑτ΢ΣΞͰਓΛߴ଎ʹදࣔඇදࣔΛ܁Γฦ͢͜ͱͰ
    Ωϟϥ͕఺໓ͯ͠͠·͏΋ͷͷಉ࣌ʹදࣔ͢Δ͜ͱΛՄೳʹͨ͠
    ͱ͍͏࿩͕͋͠ΔΒ͍͠ʢཁݕূʣ
    ΩϟϥεϓϥΠτͳͷͰ
    ਓͳΒͿͱεϓϥΠτʹ
    ͳͬͯ͠·͏
    ଜਓ
    ਓύʔςΟ
    ൃੜ͢Δ໰୊ͱରࡦʢະݕূʣ

    View Slide

  187. Ͱ΋ɺ͓Ε͸Ͱ͔͍ͬϘεΈͨ͜ͱ͕͋Δͧʂ
    ͱ͍͏ํ΋͍Δ͔΋

    View Slide

  188. IUUQTXXXZPVUVCFDPNXBUDI W1(1EP1T3ΑΓ
    εϓϥΠτͰ͸ͳ͘
    എܠͰඳը
    ͜Ε͸εϓϥΠτͰ͸ͳ͘എܠͰϘεΛදݱͯ͠ΔͬΆ͍
    εϓϥΠτͰ͋Ε͹ෳࡶͳഎܠͷ্ʹ
    ߹੒ʢॏͳΓ͕දݱʣ͞Εͯදࣔ͞ΕΔ͕
    എܠͰఢΛදݱͯ͠͠·͏ͱॏͶΔ͜ͱ͕Ͱ͖ͳ͍
    ͳͷͰɺഎܠ͸ਅͬࠇʹͯ͠ΔͱࢥΘΕΔ
    ௨ৗഎܠͱͯ͠ඳը͢ΔͰ͋Ζ͏
    ଍৔ΛεϓϥΠτͱͯ͠ඳը
    ͔ͭӈ͔Βࠨ΁Ҡಈͤ͞Δ͜ͱ
    ʹΑΓυϥΰϯ͕௥ͬͯ͘ΔΑ͏ʹ
    දݱ
    υϥΰϯͷ্ԼҠಈ͸
    എܠεΫϩʔϧͰ࣮ݱ
    ͜͏͍͏΍ͭ

    View Slide

  189. εϓϥΠτͷసૹύϑΥʔϚϯε

    View Slide

  190. ͨͱ͑͹εϓϥΠτ3".#ZUFΛద౰ͳ஋ͰຒΊΔ
    ؆୯ͳॲཧΛߟ͑ͯΈΔ
    ldy $FF # 2cycle
    copysprites:
    sty $2004 # 4cycle
    dey # 2cycle
    bne copysprites # 2cycle
    YDZDMF
    dΛεϓϥΠτ3".
    ʹॻ͖ࠐΉ
    εϓϥΠτͷసૹύϑΥʔϚϯε

    View Slide

  191. εϓϥΠτ΋എܠಉ༷7CMBOLͷظؒʹసૹ͢Δඞཁ͕͋Δ
    7CMBOLͷظؒ͸$16ͷαΠΫϧ਺ʹ׵ࢉ͢Δͱ
    Y$ZDMF
    116DMPDLMJOF
    7CMBOLظؒʹ૬౰͢ΔMJOF਺
    116ΫϩοΫ͸
    $16ΫϩοΫͷഒͳͷͰ
    ઌͷࢼࢉͰ$ZDMFͳͷͰʜ
    ͘͢͝୯७ͳॲཧͰ΋΄ͱΜͲͷ7CMBOLظؒΛઐ༗ͯ͠͠·͏ʜ
    εϓϥΠτͷసૹύϑΥʔϚϯε

    View Slide

  192. ղܾࡦ͸ʜ

    View Slide

  193. %."
    %JSFDUNFNPSZBDDFTT

    View Slide

  194. ௨ৗ$16͕ϩʔυ໋ྩ΍ετΞ໋ྩΛ࢖༻ͯ͠ϝϞϦؒͷ
    σʔλసૹ౳Λߦ͏ͱ͜ΖΛɺ$16Λհͣ͞σʔλసૹ
    ͯ͘͠ΕΔपลػೳʢϖϦϑΣϥϧʣ
    ૊ΈࠐΈͳͲ௿εϖοΫͳ$16Ͱ΋࢖͍ํ͕͸·Ε͹
    ύϑΥʔϚϯεΛҾ্͖͛ΒΕΔʢ͔΋͠Εͳ͍ʣ௒ॏ
    ཁͳػߏ
    %."ͱ͸

    View Slide

  195. ͜Ε·Ͱʹࣗ෼͕ݟͨͷ͸
    εΩϟφϝϞϦͷసૹ΍ϝϞϦϓϦϯλ
    &UFISOFUίϯτϩʔϥϝϞϦͷసૹͳͲ
    ͨͱ͑͹%."͕ͳ͍ͱҎԼͷΑ͏ͳखॱʹͳͬͨΓ͢Δ
    $16
    εΩϟφ
    όε
    3".
    ᶃεΩϟφ͔ΒϦʔυ
    ᶄ3".΁ϥΠτ
    %."ͱ͸

    View Slide

  196. εΩϟφϝϞϦͷసૹྫ
    %."͕͋Ε͹ҎԼͷΑ͏ʹҰؾʹసૹͰ͖ͨΓ͢Δ
    ʢ৔߹͕͋Δʣ
    $16
    εΩϟφ
    όε
    3".
    ᶃεΩϟφ͔Β3".
    ΁సૹ
    %."ͱ͸

    View Slide

  197. /&4ͷ৔߹Y൪஍ʹ஋Λॻ͖ࠐΉ͜ͱͰ%."͕ىಈ͠
    ॻ͖ࠐΜͩ஋Λ্ҐΞυϨεɺYΛԼҐΞυϨεͱͨ͠ΞυϨ
    εΛى఺ʹ#ZUFΛεϓϥΠτ3".ʹసૹ͢Δ
    ΋͏ͪΐ͍۩ମతʹ͍͏ͱ
    ྫ͑͹YʹYΛॻ͖ࠐΜͩ৔߹
    Y͔ΒY''·Ͱͷ#ZUF͕
    εϓϥΠτ3".ʹసૹ͞ΕΔ
    సૹ͸$16αΠΫϧͰ׬ྃ͢ΔͷͰ
    $16Ͱ#ZUFసૹ͢ΔΑΓߴ଎ʹసૹͰ͖Δ
    ʢόε͕ઐ༗͞ΕΔͷͰ$16͸ͦͷؒఀࢭ͢Δʣ
    %."
    /&4ͷ%."͸͔ͳΓ௿ػೳ

    View Slide

  198. ίϯτϩʔϥ

    View Slide

  199. /&4ͷ৔߹Y൪஍ʹίϯτϩʔϥ͕഑ஔ͞Ε͍ͯΔ
    Y൪஍ʹY YΛॱʹॻ͖ࠐΉͱͦͷॠؒͷίϯτϩʔϥ
    ͷ֤εΠονͷঢ়ଶ͕ϥον͞ΕY൪஍ΛϦʔυ͢Δ͜ͱͰ
    ॱ࣍εΠονঢ়ଶΛಡΉ͜ͱ͕Ͱ͖Δ
    ॳճϦʔυ࣌͸"Ϙλϯͷঢ়ଶɺ࣍ͷϦʔυͰ#Ϙλϯͷঢ়ଶʜ
    ͱ͍ͬͨΑ͏ʹॱ࣍औಘ͢ΔͨΊશϘλϯͷঢ়ଶΛ஌Δʹ͸
    ߹ܭճͷϦʔυ͕ඞཁ
    Ϧʔυ ରԠϘλϯ
    "
    #
    4&-&$5
    45"35

    Լ

    ӈ
    ίϯτϩʔϥ
    ̎1͸Y

    View Slide

  200. ϒϥ΢βͰͷΤϛϡϨʔγϣϯ

    View Slide

  201. const convertKeyCode = keyCode => {
    switch (keyCode) {
    case 88:
    return 0x01; // X A
    case 90:
    return 0x02; // Z B
    case 65:
    return 0x04; // A SELECT
    case 83:
    return 0x08; // S START
    case 38:
    return 0x10; // ↑ ↑
    case 40:
    return 0x20; // ↓ ↓
    case 37:
    return 0x40; // ← ←
    case 39:
    return 0x80; // → →
    }
    };
    document.addEventListener("keydown", e => {
    buf[size - 1] |= convertKeyCode(e.keyCode);
    });
    document.addEventListener("keyup", e => {
    buf[size - 1] &= ~convertKeyCode(e.keyCode);
    });
    +BWB4DSJQUଆͷॲཧ
    LFZEPXOVQΠϕϯτΛ
    MJTUFO
    OFTϑΝΠϧͷத਎Λ౉ͨ͢Ίͷ
    όοϑΝͷ຤ඌʹΩʔೖྗΛ
    ௨஌͢ΔͨΊͷྖҬ#ZUF෼֬
    อͦ͜͠ʹঢ়ଶΛॻ͖ࠐΉ

    View Slide

  202. let main_loop = || {
    let key_state = buf[len - 1];
    keypad.update(key_state);
    // …লུ…
    };
    impl Keypad {
    pub fn new() -> Self {
    // …লུ…
    }
    pub fn update(&mut self, data: Data) {
    self.buffer = data;
    }
    pub fn write(&mut self, data: Data) {
    // …লུ…
    }
    pub fn read(&mut self) -> u8 {
    let v = (0x01 << self.addr) as u8;
    let ret = ((self.register & v) >> self.addr) as u8;
    self.addr += 1;
    ret
    }
    }
    3VTU XBTN
    ଆͷॲཧ
    ϝΠϯϧʔϓͰ+4͔Βड͚औͬͨ
    Ωʔͷঢ়ଶΛ൓ө
    Y͕Πʔυ͞ΕΔͨͼ
    " # 4&-&$5ʜͷॱʹ
    ஋Λฦ͢Α͏ʹ͓ͯ͘͠

    View Slide

  203. "16 α΢ϯυ

    ׂ
    Ѫ

    View Slide

  204. ϑΝϛίϯͷ৔߹"16 ΦʔσΟΦϓϩηογϯάϢχο
    τʣͱ%"$ σΟδλϧΞφϩάίϯόʔλ
    ͕$16ʹ
    ૊Έࠐ·Ε͍ͯΔ
    "16 α΢ϯυ

    νϟωϧ͸ۣܗ೾͕νϟωϧɺࡾ֯೾νϟωϧɺϊ
    Πζνϟωɺ%1$.νϟωϧͷνϟωϧ͕࢖༻Ͱ
    ͖ήʔϜͷԻ͸͜ͷνϟωϧͷ૊Έ߹ΘͤʹΑΓදݱ͞
    ΕΔ
    ׂ
    Ѫ

    View Slide

  205. IUUQTDPEFQFOJPHSFHIQFOYR8XR[
    Πϝʔδ͸͜ͷDPEFQFO͕Θ͔Γ΍͍͢
    "16 α΢ϯυ

    ׂ
    Ѫ

    View Slide

  206. ϨδελΛோΊΔ
    ׂ
    Ѫ

    View Slide

  207. ΞυϨε 38 ༻్
    Y 8 ۣܗ೾$)੍ޚϨδελ
    Y 8 ۣܗ೾$)੍ޚϨδελ
    Y 8 ۣܗ೾$)प೾਺Ϩδελ
    Y 8 ۣܗ೾$)प೾਺Ϩδελ
    Y 8 ۣܗ೾$)੍ޚϨδελ
    Y 8 ۣܗ೾$)੍ޚϨδελ
    Y 8 ۣܗ೾$)प೾਺Ϩδελ
    Y 8 ۣܗ೾$)प೾਺Ϩδελ
    Y 8 ࡾ֯೾੍ޚϨδελ
    Y" 8 ࡾ֯೾प೾਺Ϩδελ
    Y# 8 ࡾ֯೾प೾਺Ϩδελ
    "16ͷϨδελҰཡ
    ׂ
    Ѫ

    View Slide

  208. ΞυϨε 38 ༻్
    Y$ 8 ϊΠζ੍ޚϨδελ
    Y& 8 ϊΠζཚ਺Ϩδελ
    Y' 8 ϊΠζ࣌ؒϨδελ
    Y 8 %1$.੍ޚϨδελ
    Y 8 %1$.੍ޚϨδελ
    Y 8 %1$.੍ޚϨδελ
    Y 8 %1$.੍ޚϨδελ
    Y 38 Ի੠νϟωϧ੍ޚϨδελ
    Y 38 ϑϨʔϜΧ΢ϯλ
    "16ͷϨδελҰཡ
    ׂ
    Ѫ

    View Slide

  209. ۣܗ೾ΛΈ͍ͯ͘
    ׂ
    Ѫ

    View Slide

  210. Τϯϕϩʔϓ
    δΣωϨʔλ
    εΠʔϓ λΠϚʔ
    γʔέϯα
    ௕͞Χ΢ϯλ
    ۣܗ೾ͷߏ੒
    ׂ
    Ѫ

    View Slide

  211. ΞυϨε ֓ཁ
    Y
    CJU આ໌

    σϡʔςΟൺCC
    CC
    ࠶ੜ࣌ؒΧ΢ϯλΠωʔϒϧ
    ΤϯϕϩʔϓσΟηʔϒϧ
    ϘϦϡʔϜ·ͨ͸ΤϯϕϩʔϓσΟόΠμ
    σϡʔςΟൺ
    ݮਰͷ଎౓ͳͲΛ੍ޚ
    ۣܗ೾Ϩδελ
    ׂ
    Ѫ

    View Slide

  212. ΞυϨε ֓ཁ
    Y
    CJU આ໌
    εΠʔϓΠωʔϒϧ
    प೾਺มԽ଎౓
    प೾਺ͷมԽํ޲Լ্߱ঢ
    प೾਺มߋྔͷ৔߹มԽͳ͠
    प೾਺ͷ૿ݮΛ੍ޚ
    ۣܗ೾Ϩδελ
    ׂ
    Ѫ

    View Slide

  213. ΞυϨε ֓ཁ
    Y
    Y
    CJU આ໌
    ύϧελΠϚʔԼҐCJU
    CJU આ໌
    ΩʔΦϑΧ΢ϯλ
    ύϧελΠϚʔ্ҐCJU
    प೾਺ͱ࠶ੜ࣌ؒΛ੍ޚ
    ۣܗ೾Ϩδελ
    ׂ
    Ѫ

    View Slide

  214. Ͳ͏΍ͬͯΤϛϡϨʔτ͢Δ͔
    ׂ
    Ѫ

    View Slide

  215. 8FC"VEJP
    ׂ
    Ѫ

    View Slide

  216. class Oscillator {
    constructor(type) {
    const AudioContext = window.AudioContext || window.webkitAudioContext
    this.context = new AudioContext();
    this.oscillator = this.createOscillator({ kind: type });
    // …লུ…
    }
    createOscillator(options = {}) {
    const oscillator = this.context.createOscillator();
    // …লུ…
    return oscillator;
    }
    setPulseWidth(pulseWidth) {
    this.oscillator.setPeriodicWave(this.waves[`${pulseWidth}`]);
    }
    setFrequency(frequency) {
    this.oscillator.frequency.value = frequency;
    }
    changeFrequency(frequency) {
    this.oscillator.frequency.setValueAtTime(frequency, this.context.currentTime)
    }
    }
    +BWB4DSJQUଆͷॲཧ
    TFU1FSJPEJD8BWFͰ
    ΧελϜ೾ܗΛ࡞੒Ͱ͖Δ
    ׂ
    Ѫ

    View Slide

  217. mergeInto(LibraryManager.library, {
    start_oscillator: function (index) {
    Module.NES.oscs[index].start();
    },
    set_oscillator_frequency: function (index, freq) {
    Module.NES.oscs[index].setFrequency(freq);
    },
    change_oscillator_frequency: function (index, freq) {
    Module.NES.oscs[index].changeFrequency(freq);
    },
    set_oscillator_volume: function (index, volume) {
    Module.NES.oscs[index].setVolume(volume);
    },
    set_oscillator_pulse_width: function (index, width) {
    Module.NES.oscs[index].setPulseWidth(width);
    },
    }
    3VTU XBTN
    ଆ΁ͷϒϦοδ
    ࠶ͼNFSHF*OUPͰ
    3VTUଆ΁ެ։
    ׂ
    Ѫ

    View Slide

  218. ͋ͱ͸)[)[ͷपظͱ
    $16͔ΒͷΞΫηελΠϛϯά
    प೾਺΍ϘϦϡʔϜͷมಈ͕ൃੜ͢Δ
    ͷͰͦͷλΠϛϯάͰݺΜͰ΍Ε͹͍͍
    ׂ
    Ѫ

    View Slide

  219. pub fn update_counters(&mut self) {
    // …লུ…
    self.sweep_unit_counter += 1;
    self.change_frequency();
    }
    pub fn update_envelope(&mut self) {
    // …লུ…
    unsafe {
    set_oscillator_volume(self.index, self.get_volume());
    };
    }
    fn change_frequency(&self) {
    unsafe {
    change_oscillator_frequency(self.index, self.frequency);
    }
    }
    3VTU XBTN
    ଆͷॲཧ
    ׂ
    Ѫ

    View Slide

  220. ͜͜·ͰͰϑΝϛίϯຊମͷ
    ϋʔυ΢ΣΞ͸Ұ௨Γ࣮૷Ͱ͖ͨ͸ͣ

    View Slide

  221. 2͜ΕͰશͯͷ30.͕ಈ࡞͢Δ͔

    View Slide

  222. "͠ͳ͍

    View Slide

  223. ..$
    NFNPSZNBOBHFNFOUDPOUSPMMFS

    View Slide

  224. Χηοτ಺ʹ..$ͱݺ͹ΕΔ
    ϝϞϦ؅ཧ༻ͷిࢠճ࿏Λ͍࣋ͬͯΔ
    Χηοτ͕͋Δ
    ͜ͷػߏʹΑΓϓϩάϥϜ30.࠷େLJ#
    ΩϟϥΫλʔ30.LJ#ͷ੍ݶ͸௒͑ΒΕΔ
    ..$

    View Slide

  225. ..$ʹΑΔϝϞϦͷϚοϐϯά৘ใ
    Λ.BQQFSͱݺͿ
    ..$

    View Slide

  226. .BQQFSͷҰ෦ ·ͩ΄͔ʹ΋͋Δ

    .BQQFS

    View Slide

  227. .BQQFS
    ࣮͸͍͕ͭ͜..$
    ҎԼ͸.BQQFSͷج൘

    View Slide

  228. .BQQFS

    View Slide

  229. ຊདྷϥΠτͰ͖ͳ͍Ydͷۭؒ
    ʹόϯΫ൪߸Λॻ͖ࠐΉ͜ͱͰ࠷େ,J#
    ·Ͱ30.Λ࢖༻͢Δ͜ͱ͕Ͱ͖Δ
    .BQQFS

    View Slide

  230. ͲΜͳճ࿏ʹͳͬͯΔ͔

    View Slide

  231. $)3
    30.
    $/
    )$

    ""
    ""
    %%
    8&
    )$ͰσʔλΛϥον͠
    ΞυϨεʹม׵
    ΩϟϥΫλʔ30.
    όΠφϦΧ΢ϯλ
    .BQQFSͷճ࿏

    View Slide

  232. impl Mmc {
    pub fn new(mapper: u8, bank: u8) -> Self {
    Mmc { bank, mapper }
    }
    pub fn set_bank(&mut self, bank: u8) {
    self.bank = bank;
    }
    pub fn create_chram_addr(&self, addr: u16) -> u16 {
    addr + (self.bank as u16) * 0x2000
    }
    }
    .BQQFSͷ࣮૷
    όϯΫͷઃఆ͔Β
    ΩϟϥΫλʔ30.΁ͷΞυϨε
    Λܭࢉͯ͠ฦ͢

    View Slide

  233. ରԠ30.Λ૿΍͢ʹ͸
    ֤ͭͭ͜͜.BQQFSͷରԠ͕ඞཁ

    View Slide

  234. ͜ΕΛ໢ཏ͢Δͱ͢΂ͯͷ
    30.͕ಈ࡞͢Δ͸ͣ

    View Slide

  235. ύϑΥʔϚϯε

    View Slide

  236. DISPNF

    8FC"TTFNCMZWT+BWB4DSJQU
    DISPNFDBOBSZ

    pSFGPY
    CJU

    pSFGPYEFWFMPQFSFEJUJPO
    C CJU

    TBGBSJ


    NT NT NT NT
    NT NT
    NT NT
    NT
    NT



    UJNF
    TNBMMFSJTCFUUFS
    8FC"TTFNCMZ CPLVXFCSVTUZOFT

    +BWB4DSJQU CPLVXFCqPXOFT

    8FC"VEJP$BOWBTΛσΟηʔϒϧʹͨ͠ঢ়ଶͰ
    ϝΠϯϧʔϓͷॲཧ࣌ؒճͷฏۉ஋Λൺֱ
    .BD#PPL"JS JODI &BSMZ
    ()[*OUFM$PSFJ(#.)[%%3
    HJLPOFT

    View Slide

  237. ͍͞͝ʹ
    !ϑΝϛίϯΤϛϡϨʔλ͸ҰਓͰ࣮૷͢Δͷʹ΋खࠒͳαΠζ
    !$16΍%."ɺׂΓࠐΈͳͲͷಈ࡞Λֶ΂Δ
    !ઌਓͷۤ࿑ͷยྡྷΛຯΘ͑Δ
    !ࣗ෼΋99ݴޠͰ΍ͬͯΈΔ͔ʂͱࢥͬͯ΋Β͑ͨΒخ͍͠Ͱ͢

    View Slide

  238. ͋Γ͕ͱ͏͍͟͝·ͨ͠✨

    View Slide