Movatterモバイル変換


[0]ホーム

URL:


Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker DeckSpeaker Deck
Speaker Deck

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

Avatar for bokuweb bokuweb
September 07, 2018
45k

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

Avatar for bokuweb

bokuweb

September 07, 2018
Tweet

More Decks by bokuweb

See All by bokuweb

Featured

See All Featured

Transcript

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

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

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

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

  5. %&.0 IUUQTHJUIVCDPNCPLVXFCSVTUZOFT

  6. $16 31" 3*$0)੡ CJU.)[ 116 ϐΫνϟʔϓϩηοαϢχοτ31$ 30. ࠷େϓϩάϥϜ30.,J# ΩϟϥΫλ30.,J# 83".

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

    .)[ .)[ /.* CJU116CVT CJU$16CVT "16 ϑΝϛίϯ σΟεϓϨΠ α΢ϯυ ίϯτϩʔϥ ϑΝϛίϯͷϒϩοΫਤ
  8. ΤϛϡϨʔλΛ࡞Δʹ͸ ͜ΕΒͷσόΠεΛҰͭҰͭ ࣮૷͍ͯ͘͠ඞཁ͕͋Δ

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

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

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

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

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

  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ͷόε৴߸
  15. ΩϟϥΫλʔ 30. 116 $16 ϑΝϛίϯຊମ ϓϩάϥϜ 30. Χηοτ $16όεΛհͯ͠ Ϧʔυ͞ΕΔ

    116όεΛհͯ͠ Ϧʔυ͞ΕΔ Χηοτͱຊମͱͷόε઀ଓ
  16. ϓϩάϥϜ30.ͱ͸

  17. ήʔϜϓϩάϥϜ͕֨ೲ͞Εͨ30. $16͸ϓϩάϥϜ30.͔Β໋ྩϑΣονͯ͠ϓϩάϥϜ Λ࣮ߦ͢Δ void main() { char i; *(char*)0x2000 =

    0x00; *(char*)0x2001 = 0x00; ͜Μͳͷ͕ "'''"ʜ ͜Μͳײ͡Ͱ٧·ͬͯΔ ϓϩάϥϜ30.ͱ͸
  18. ΩϟϥΫλʔ30.ͱ͸

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

  20. ՄࢹԽͯ͠ΈΔͱ

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

  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.ͷσʔλ
  23. ΤϛϡϨʔλͰ͸͜ΕΒͷ৘ใΛ Ͳ͏औΓѻ͑͹͍͍͔

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

  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.ͷϒϩοΫαΠζ͕ ֨ೲ͞Ε͍ͯΔ
  26. ·ͣ͸ OFTΛಡΜͰղੳͯ͠ ֤30.Λ੾Γग़ͯ͠΍Δඞཁ͕͋Δ

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

  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 ͔Βݺ΂ΔΑ͏ʹ ͜Ε͸Ҿ਺
  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ʹม׵
  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σʔλͷઌ಄ ʢ͢ͳΘͪϙΠϯλʣͱͯ͠αΠζͱҰॹʹڭ͑ ͯ΍Δ
  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. ͷ಺༰Λ࣮ߦ͢Ε͹ήʔϜ͕։࢝͢Δʣ
  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.Λ੾Γग़͢
  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͢Δؔ਺Λ ࢦఆͯ͠΍Δඞཁ͕͋Δ
  34. ϝϞϦʢ3".30.ʣ

  35. pub struct Ram { pub field: Vec<u8>, } impl Ram

    { pub fn new(buf: Vec<u8>) -> 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".ͷ࣮૷
  36. $16͕ϝϞϦʹͲͷΑ͏ʹ ΞΫηε͢Δ͔஌ͬͯ·͔͢ʁ ׂ Ѫ

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

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

    νοϓηϨΫτɺΞυϨεɺϦʔυ৴߸ͳͲ Ϧʔυʹඞཁͳ৴߸͕ଗ͏ͱ3".͔Βσʔλ ׂ Ѫ
  39. ΞυϨε νοϓηϨΫτ Ϧʔυ σʔλ Y%&"% Y#& 43".ͷY%&"%൪஍ʹϦʔυΞΫηεΛߦ͍Y#&͕ಡΈग़͞ΕΔྫ 43".ͷϦʔυλΠϛϯάྫ ͜ͷλΠϛϯάͰY#&Λϥον͢Δ σʔλ͸Ϧʔυ৴߸ͷ্ཱ͕ͪΓ΍ͦͷޙͷ

    $16ΫϩοΫͷ্ཱ͕ͪΓͰऔΓࠐ·ΕΔ΋ͷ͕ଟ͍ σόΠεʹϓϦϯτ͞Ε͍ͯΔ਺ࣈ͸͍͍ͩͨ͜͜ͷ਺ࣈ ʢDZDMF खݩͷ30.͸ͳͷͰ DZDMFOTҎ্ʹͯ͠Ͷͱ͍͏ҙຯ ׂ Ѫ
  40. ͢ͳΘͪɺ͜ΕΒͷ৴߸ΛλΠϛϯάΛकΓͭͭ ༩͑ͯ΍Ε͹Χηοτͷ30.͔Βσʔλ͕ಡΊΔ ׂ Ѫ

  41. $16

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

  43. $16ͷϨδελҰཡ ໊শ αΠζ ৄࡉ " CJU ΞΩϡϜϨʔλ 9 CJU ΠϯσοΫεϨδελ

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

  44. εςʔλεϨδελ CJU ໊শ ৄࡉ ಺༰ CJU / ωΨςΟϒ ԋࢉ݁ՌͷCJU͕ͷ࣌ʹηοτ CJU

    7 Φʔόʔϑϩʔ 1ԋࢉ݁Ռ͕ΦʔόʔϑϩʔΛىͨ࣌͜͠ʹηο τ CJU 3 ༧໿ࡁΈ ৗʹηοτ͞Ε͍ͯΔ CJU # ϒϨʔΫϞʔυ #3,ൃੜ࣌ʹηοτɺ*32ൃੜ࣌ʹΫϦΞ CJU % σγϚϧϞʔυ σϑΥϧτɺ#$%Ϟʔυ ະ࣮૷ CJU * *32ېࢭ *32ڐՄɺ*32ېࢭ CJU ; θϩ ԋࢉ݁Ռ͕ͷ࣌ʹηοτ CJU $ ΩϟϦʔ ΩϟϦʔൃੜ࣌ʹηοτ εςʔλεϨδελͷৄࡉ CJU͸ৗʹͰɺCJU͸/&4Ͱ͸ະ࣮૷
 *32͸ׂΓࠐΈɺ#3,͸ιϑτ΢ΤΞׂΓࠐΈ
  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ͷϨδελͷ࣮૷
  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.
  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όεͷ࣮૷ ϝϞϦϚοϓΛ൓ө
  48. $16͸Ͳͷ൪஍͔Β ͲͷλΠϛϯάͰىಈ͢Δ͔

  49. ׂΓࠐΈ

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

  51. ͨͱ͑͹ɺϦηοτʢϑΝϛίϯͷ࢛֯ͷϘλϯͰ͢Ͷʣ΋ׂΓࠐΈͷҰछͰ Ϧηοτ͕ൃੜͨ͠৔߹Y'''$ɺY'''%͔ΒCJUͷΞυϨεΛϦʔυ͠ 1$ʢϓϩάϥϜΧ΢ϯλʣʹηοτ͠ɺηοτ͞ΕͨΞυϨε͔Β࣮ߦ͠·͢ ׂΓࠐΈ ԼҐόΠτ ্ҐόΠτ ֓ཁ /.* Y'''" Y'''#

    ϊϯϚεΧϥϒϧׂΓࠐΈͱݴͬͯ$16͸ଆͰϚεΫͰ͖ͳ ׂ͍ΓࠐΈͰ͢ɻ116ͷׂΓࠐΈग़ྗ৴߸͕઀ଓ͞Ε͍ͯ· ͢ 3&4&5 Y'''$ Y'''% ϦηοτϘλϯԡԼ࣌΍ిݯ౤ೖ࣌ʹ͔͔ΔׂΓࠐΈͰ͢ *32ɺ#3, Y'''& Y'''' #3,͸ιϑτ΢ΣΞׂΓࠐΈͰ#3,໋ྩΛ࣮ߦͨ͠ͱ͖ʹൃ ੜ͠·͢ɻ*32͸"16΍Χηοτʹ઀ଓ͞Ε͍ͯ·͢ ͷ৔߹ҎԼͷΑ͏ͳׂΓࠐΈཁҼ͕༻ҙ͞Ε͍ͯ·͢ ͷׂΓࠐΈ
  52. ϦηοτׂΓࠐΈͷ৔߹

  53. pub fn reset<T: CpuRegisters, U: CpuBus>(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$ʢϓϩάϥϜΧ΢ϯλʣʹηοτ ࣍αΠΫϧ͸ηοτͨ͠ΞυϨε͔Β࣮ߦ͞ΕΔ
  54. /.*ͷ৔߹

  55. pub fn process_nmi<T: CpuRegisters, U: CpuBus>(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)
  56. pub fn process_nmi<T: CpuRegisters, U: CpuBus>(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)
  57. pub fn process_nmi<T: CpuRegisters, U: CpuBus>(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$ʹηοτ
  58. ྫ͑͹/.*લͷ1$͕YɺεςʔλεϨδελ͕Y"" ελοΫϙΠϯλ͕Y''ͩͱ͢Δͱ/.*ޙͷελοΫ͸ҎԼͷΠϝʔδ Y'' Y'&' Y'&& Y'&% Y'& ελοΫϙΠϯλ ʜ Y

    Y Y"" 1$ͷ্ҐΞυϨε 1$ͷԼҐΞυϨε εςʔλεϨδελ ࣍ճͷ164)͸͜͜ʹੵ·ΕΔ /.*ͷ࣮ߦޙͷελοΫΠϝʔδ
  59. ͷ໋ྩ

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

  61. ͨͱ͑͹

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

  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ͰಘΒΕΔ൪஍ʹ֨ೲ͞Ε͍ͯΔ஋ΛԼҐΞυϨεɺͦͷ࣍ͷ൪஍ʹ֨ೲ͞ Ε͍ͯΔ஋Λ্ҐΞυϨεͱͨ͠൪஍Λԋࢉର৅ͱ͢Δ ΞυϨογϯάϞʔυ
  64. ໋ྩද

  65. ଟ͍

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

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

  68. Yʹͱ͍͏໋ྩ͕֨ೲ͞Ε͍ͯΔ৔߹ ϝϞϦͱ࣮ߦखॱҎԼͷΑ͏ʹͳΔʢ1$΋Yͱ͢Δʣ -%" ʢY"ʣ Y Y" Y ʜ Y -%""

    $16͸1$ ͢ͳΘͪY ͔Β໋ྩΛϑΣον͠1$Λ  ϑΣον݁ՌY"͔Β-%"JNNͰ͋Δͱ൑ผ͞ΕΔ $16͸Y͔ΒΦϖϥϯυY"ΛϑΣον͠1$Λ  Ϩδελ"ʹY"Λ֨ೲ͠ɺ࣍ͷ໋ྩ΁ -%"JNN ࣍ͷ໋ྩ ͜ͷ஋Λ"Ϩδελ ʹϩʔυ͢Δ 1$
  69. pub fn lda_imm<T: CpuRegisters>(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 "ϨδελʹΦϖϥϯυ ʹηοτ ηοτ͞Εͨ஋ʹରԠ͢Δ εςʔλεϑϥάΛηοτ
  70. -%"[QH ্ҐΛYԼҐΛΦϖϥϯυͱͨ͠ΞυϨεʹ ֨ೲ͞Ε͍ͯΔ஋Λ"Ϩδελʹϩʔυ͢Δ

  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$
  72. pub fn lda<T: CpuRegisters, U: CpuBus>(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ԼҐΛΦϖϥϯυͱͨ͠ΞυϨεʹ ֨ೲ͞Ε͍ͯΔ஋Λ"Ϩδελʹϩʔυ͢Δϩʔυ͢Δ Φϖϥϯυͷ஋ΞυϨεͱͯ͠Ϧʔυ Ϧʔυ͞Εͨ஋Λ"Ϩδελʹηοτ
  73. ͜͜·Ͱͷ$16ͷಈ࡞Λ·ͱΊΔͱ

  74. Ϧηοτ ແ͠ ແ͠ ༗Γ ༗Γ ׂΓࠐΈ ༗ແ Φϖϥϯυ ༗ແ Ϩδελͷ

    ঢ়ଶΛୀආ 1$͔Β໋ྩ ΛϑΣον 1$ 1$͔ΒΦϖϥϯυΛ ϑΣον 1$ ໋ྩΛ࣮ߦ ׂΓࠐΈϕΫλ ͷ஋Λ1$ ʹηοτ $16ͷಈ࡞Πϝʔδ Y'''$'''%ʹ ֨ೲ͞Εͨ൪஍͔Β։࢝
  75. pub fn run<T: CpuRegisters + Debug, U: CpuBus>( 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ͷ࣮૷ ׂΓࠐΈͷνΣοΫ
  76. pub fn run<T: CpuRegisters + Debug, U: CpuBus>( 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$͔Β໋ྩΛϑΣον σίʔυ ࣙॻ͔Β໋ྩͷछผɾΞυϨογϯά ϞʔυɺαΠΫϧ਺ͳͲΛҾ͍ͯ͘Δ
  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] }); // …লུ… ΞυϨογϯάϞʔυ΍αΠΫϧ਺ Λ൑ผ
  78. pub fn run<T: CpuRegisters + Debug, U: CpuBus>( 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໋ྩ
  79. ͋ͱ͸໋֤ͭͭ͜͜ྩΛ࣮૷$

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

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

  82. OFTUFTUOFT

  83. 116

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

  85. 116ͷϝϞϦϚοϓ

  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.
  87. Α͘Θ͔Βͳ͍ςʔϒϧ ͕͍ͬͺ͍

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

  89. ωʔϜςʔϒϧ

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

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

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

  93. ଐੑςʔϒϧ

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

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

     ͜ͷϒϩοΫ Y ͸ ͳͷͰ͕ ࢖༻Ͱ͖Δ ύϨοτ  ͜ͷϒϩοΫ͸ ͜ͷϒϩοΫ͸ ͜ͷϒϩοΫ͸ ଐੑςʔϒϧͱ͸
  96. ύϨοτςʔϒϧ

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

  98. ͨͱ͑͹εύʔϚϦΦϒϥβʔεͷΦʔϓχϯάը໘͸ҎԼͷΑ͏ͳ ύϨοτ͕ઃఆ͞Ε͍ͯΔ ύϨοτY' ύϨοτY' ύϨοτY' ύϨοτY'$ ύϨοτY' ύϨοτY' ύϨοτY' ύϨοτY'$

    എܠ༻ύϨοτʢഎܠ৭৭ ৭YύϨοτͰ৭ʣ εϓϥΠτ༻ύϨοτʢ৭͸ಁ໌৭ͳͷͰ৭YύϨοτͰ৭ʣ ֤ςʔϒϧͷઌ಄ ͸ಁ໌৭ͱͯ͠ ѻΘΕΔ ಁ໌৭ ಁ໌৭ ಁ໌৭ ֤ςʔϒϧͷઌ಄ ͸എܠ৭ എܠ৭ എܠ৭ എܠ৭ ϚϦΦ͸ӈଆͷ৭Ͱදݱ͞Ε͍ͯΔ ύϨοτςʔϒϧͱ͸
  99. ஋ͱ৭ͱͷରԠ͸ʁ

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

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

  102. ΞυϨε ֓ཁ Y Y CJU આ໌  7#MBOL࣌ʹׂΓࠐΈΛग़ྗ  ৗʹ̍

     εϓϥΠταΠζYY  എܠ༻ύλʔϯςʔϒϧΞυϨεYY  εϓϥΠτύλʔϯςʔϒϧΞυϨεYY  116ΞυϨεΠϯΫϦϝϯτ    ωʔϜςʔϒϧࢦఆ CJU આ໌  എܠ৭CࠇC྘C੨C੺
  εϓϥΠτΠωʔϒϧσΟηʔϒϧΠωʔϒϧ  എܠΠωʔϒϧσΟηʔϒϧΠωʔϒϧ  εϓϥΠτͷը໘ࠨϐΫηϧඳըඳը͠ͳ͍ඳը͢Δ  എܠͷը໘ࠨϐΫηϧඳըඳը͠ͳ͍ඳը͢Δ  σΟεϓϨΠλΠϓΧϥʔϞϊΫϩ 116ͷϨδελ 8SJUF
  103. ΞυϨε ֓ཁ Y εϓϥΠτϝϞϦΞυϨε YΛܦ༝ͯ͠εϓϥΠτϝϞϦ΁ॻ͖ࠐΉϏοτΞυϨεΛࢦఆ Y εϓϥΠτϝϞϦσʔλ YʹΑͬͯࢦఆ͞ΕͨεϓϥΠτϝϞϦΞυϨε΁σʔλΛॻ͖ࠐΉɻ ॻ͖ࠐΉ౓ʹεϓϥΠτϝϞϦΞυϨε͸ΠϯΫϦϝϯτ 

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

    116ϝϞϦσʔλ YʹΑͬͯࢦఆ͞Εͨ116ϝϞϦΞυϨεͷσʔλΛϦʔυ͢Δ Ϧʔυ͢Δ౓ʹϝϞϦΞυϨε͸ΠϯΫϦϝϯτ YͷϏοτʹΑͬͯ ɺ  ͢Δɻ CJU આ໌  7CMBOL࣌ʹ  εϓϥΠτώοτ࣌ʹ  εΩϟϯϥΠϯεϓϥΠτ਺ɹݸҎԼݸҎ্  3FTFSWFE 116ͷϨδελ 3FBE
  105. ͔͜͜Βॏཁͳ΋ͷΛൈ͖ग़ͯ͠ ౎౓આ໌͍͖ͯ͠·͢

  106. தͰ΋ॏཁͳͷ͸

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

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

    $16όε 116όε 116"%%3116%"5"Ϩδελ
  109. Ͳ͏΍ͬͯ࢖͏͔

  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"Ϩδελ
  111. ͜͜·Ͱͷ࿩͔͠Β͢Δͱ 73".ͷ಺༰Λى఺ʹ Ճ޻͍͚ͯ͠͹ ϐΫηϧσʔλΛੜ੒Ͱ͖ͦ͏

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

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

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

                                                                Y ֘౰ͷ࠲ඪ͸ଐੑςʔϒϧͷΞυϨεY%"ʹ֘౰͢ΔͨΊ 73".ͷ͔ΒΞτϦϏϡʔτ͕Ϧʔυ͞ΕΔ Y%"൪஍ Y 116ඳըखॱΠϝʔδ ͜ΜͳεϓϥΠτ σʔλ͕ಘΒΕΔ
  115.  Ϧʔυ͞ΕͨΞτϦϏϡʔτ͔Β֘౰ϙδγϣϯͷύϨοτ൪߸Λ औΓग़͢ͱʹͳΔͷͰύϨοτ͕ద༻͞ΕΔ͜ͱ͕Θ͔Δ  ύϨοτ͢ͳΘͪ73".ͷ#ZUFಡΉͱ ͕ϦʔυͰ͖Δɻ͜ΕΛΧϥʔίʔυදʹద༻͢Δͱ࣍ͷ৭Ͱ͋Δ͜ͱ͕Θ͔Δ ͨΊ3(#ʹม׵֤͠ϐΫηϧʹύϨοτΛద༻ͯ͠΍Δͱ׬੒   

                                ύϨοτ̌ ׬੒✨ C Y'd Y' Y Y Y 116ඳըखॱΠϝʔδ )FMMP 8PSMEͷ)ΛωʔϜςʔϒϧ͔ΒϐΫηϧσʔλʹͯ͠ΈΔྫ
  116. impl Tile { pub fn new<P: PaletteRam>( 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ඳըखॱΠϝʔδ ࠲ඪ͔ΒϒϩοΫ൪߸ Λࢉग़ ࠲ඪͱωʔϜςʔϒϧ͔Β εϓϥΠτ൪߸Λࢉग़
  117. impl Tile { pub fn new<P: PaletteRam>( 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ඳըखॱΠϝʔδ ࠲ඪͱଐੑςʔϒϧ͔Β ΞτϦϏϡʔτΛࢉग़ ΞτϦϏϡʔτͱϒϩοΫ൪߸͔Β ύϨοτ൪߸Λࢉग़
  118. impl Tile { pub fn new<P: PaletteRam>( 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ͷϐΫηϧσʔλΛ ࡞੒
  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(#"ͷϐΫηϧσʔλ ʹม׵
  120. ϐΫηϧσʔλ͸ಘΒΕ͕ͨ Ͳ͏΍ͬͯϒϥ΢βʹදࣔ͢Δ͔

  121. $BOWBT

  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ଆʹެ։Ͱ͖Δ
  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ʹηοτ
  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 ଆͷॲཧ ͜Μͳ;͏ʹݺ΂Δ όοϑΝͷϙΠϯλͱ௕͞Λ ڭ͑ͯ͋͛Δ
  125. ͜ΕͰ73".ͷ಺༰Λ $BOWBTʹॻ͖ग़ͤͦ͏

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

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

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

    ׂ Ѫ
  129. 116ͷඳըλΠϛϯά

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

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

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

  133. MJOFQJYFM EJTQMBZ ࣍ͷඳըͷͨΊʹઌ಄΁໭Δ ͜ͷͨΊͷظؒΛͱݴ͍ MJOF෼ͷ࣌ؒΛཁ͢Δ Ұը໘ͷߋ৽ʹ͸ Y αΠΫϧ ඞཁͱͳΔ ͢ͳΘͪ

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

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

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

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

  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׬͔ྃͨ͠Λ൑ఆ
  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
  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
  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
  142. ͋ͱ͸$16ͱ116ɺඳըͷಉظΛ ͲͷΑ͏ʹͱΔ͔

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

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

    $16ͱ116ͷಉظ
  145. ࣌ؒ NT NT ը໘෼ͷσʔλ͕ Ͱ͖Δ·Ͱ $16116Λ࣮ߦ ը໘෼ͷσʔλ͕ Ͱ͖Δ·Ͱ $16116Λ࣮ߦ ը໘෼ͷσʔλ͕

    Ͱ͖Δ·Ͱ $16116Λ࣮ߦ ඳը ඳը ඳը ͜ΜͳΠϝʔδͰ࣮ߦ͍ͨ͠ NT $16ͱ116ͷಉظ
  146. SFRVFTU"OJNBUJPO'SBNFΛ࢖͍͍ͨ '14Ͱಈ࡞͢ΔΑ͏ʹ͍͍ײ͡ʹ͕Μ͹ͬͯ͘ΕΔ΍ͭ

  147. void emscripten_set_main_loop( em_callback_func func, int fps, int simulate_infinite_loop) FNTDSJQUFOΛ࢖༻͍ͯ͠Δ৔߹͍͕ͭ͜࢖͑Δ ୈೋҾ਺ʹΛηοτ͢ΔͱΛ

    ࢖ͬͯ͘ΕΔ SFRVFTU"OJNBUJPO'SBNF FNTDSJQUFO@TFU@NBJO@MPPQ ୈࡾҾ਺Ληοτ͢ΔͱແݶϧʔϓΛ γϛϡϨʔτ
  148. MFUNBJO@MPPQcc\ 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Λ࣮ߦ
  149. MFUNBJO@MPPQcc\ 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Λ࣮ߦ
  150. MFUNBJO@MPPQcc\ 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; } } } ϝΠϯϧʔϓͷ࣮૷ Ұը໘෼४උ͕Ͱ͖ͨΒϨϯμϦϯά
  151. ͜͜·Ͱ͕࣮૷Ͱ͖Ε͹ )FMMP 8PSME͕ඳըͰ͖ͦ͏

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

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

  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; }
  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
  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
  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
  158. )FMMP 8PSME

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

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

  161. εΫϩʔϧ

  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ͷϝϞϦϚοϓ ࠶
  163. ը໘෼ͷςʔϒϧ͸ҎԼͷΑ͏ͳ഑ஔʹͳ͍ͬͯΔ ωʔϜଐੑςʔϒϧ YdY'' ωʔϜଐੑςʔϒϧ YdY'' ωʔϜଐੑςʔϒϧ YdY#'' ωʔϜଐੑςʔϒϧ Y$dY''' 116ͷωʔϜଐੑςʔϒϧͷ഑ஔ

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

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

    εΫϩʔϧͱදࣔྖҬͷؔ܎
  166. εΫϩʔϧؔ͢ΔϨδελ͸ͭ ׂ Ѫ

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

    ͔͠͠ɺ͜ͷϨδελ͚ͩͰ͸QYҎ্ͷεΫϩʔϧ͸ෆՄ ׂ Ѫ
  168. 116$53-Ϩδελ ΞυϨε ֓ཁ Y CJU આ໌ ʜ ʜলུʜ  ωʔϜςʔϒϧࢦఆ

    116$53-Ϩδελ Y ͷCJU͸ωʔϜςʔϒϧΛࢦఆ͢Δ͜ͱ͕Ͱ͖Δ ωʔϜ ଐੑςʔϒϧ ωʔϜ ଐੑςʔϒϧ ωʔϜ ଐੑςʔϒϧ ωʔϜ ଐੑςʔϒϧ ྫ͑͹ωʔϜςʔϒϧࢦఆ͕CͰ͋Ε͹͜ͷςʔϒϧ͕ࢦఆ͞Εͨ͜ͱʹͳΓ Yํ޲ʹQY෼εΫϩʔϧ͕Φϑηοτͨ͜͠ͱͱಉ౳ͱͳΔ ઌͷ1164$30--ͱ߹ΘͤΕ͹ QYҎ্ͷεΫϩʔϧ͕Մೳ ׂ Ѫ
  169. ͜ΕΒΛ࢖͏ͱ໘ന͍දݱ͕Մೳʹ

  170. ϥελεΫϩʔϧ

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

  172. εϓϥΠτ

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

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

  175. 116͸εϓϥΠτ༻ͷྖҬεϓϥΠτ3".Λ͍࣋ͬͯΔ 116ͷϝϞϦϚοϓʹ͸දݱ͞Ε͍ͯͳ͍͓ͦ͠Β͘116಺෦ͷྖҬʁ ΞυϨε ֓ཁ Y εϓϥΠτϝϞϦΞυϨε YΛܦ༝ͯ͠εϓϥΠτϝϞϦ΁ϦʔυϥΠτ͢ΔϏοτΞυϨεΛࢦఆ Y εϓϥΠτϝϞϦσʔλ YʹΑͬͯࢦఆ͞ΕͨεϓϥΠτϝϞϦΞυϨεʹ͍ͨͯ͠ϦʔυϥΠτΛߦ͏

    ΞΫηε͢Δͨͼʹ౓ʹεϓϥΠτϝϞϦΞυϨε͸ΠϯΫϦϝϯτ  ͞ΕΔɻ ΞΫηεํ๏͸116"%%3116%"5" YY ͱ΄΅ಉ͡ ҟͳΔ఺͸εϓϥΠτ3".ͷۭؒ͸CJUͰදݱͰ͖ΔͷͰ ΞυϨεΛઃఆ͢ΔͨΊʹ̎ճॻ͖ࠐΉඞཁ͸ͳ͍ #ZUF εϓϥΠτ3".
  176. εϓϥΠτͭʹରͯ͠ҎԼͷ#ZUFͷઃఆΛ͍࣋ͬͯΔ #ZUF ֓ཁ  :࠲ඪ  εϓϥΠτΠϯσοΫε ΩϟϥΫλʔ30.಺ͷεϓϥΠτͷԿ൪໨ͷεϓϥΠτΛద༻͢Δ͔Λࢦఆ͢Δ  

    9࠲ඪ CJU આ໌  ਨ௚ํ޲൓స൓స͠ͳ͍൓స͢Δ  ਫฏํ޲൓స൓స͠ͳ͍൓స͢Δ  දࣔ༏ઌॱҐεϓϥΠτΛ༏ઌഎܠΛ༏ઌ  ༧໿  ύϨοτ൪߸CύϨοτCύϨοτ CύϨοτCύϨοτ εϓϥΠτ3".͸#ZUFͳͷͰηοτͰ͖Δ ࠷େεϓϥΠτ εϓϥΠτ3".
  177. εϓϥΠτʹؔ͢ΔϢχʔΫͳ࢓༷

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

  179. ΞυϨε ֓ཁ Y CJU આ໌  7CMBOL࣌ʹ  εϓϥΠτώοτ࣌ʹ 

    εΩϟϯϥΠϯεϓϥΠτ਺ɹݸҎԼݸҎ্  3FTFSWFE εϓϥΠτ̌ώοτ εϓϥΠτ3".ͷઌ಄ʹઃఆ͞ΕͨεϓϥΠτ͕ ϥΠϯόοϑΝʹల։͞ΕΔͱ116Ϩδελ Y  ͷʮεϓϥΠτ̌ώοτʯϑϥάཱ͕ͭVOΛ࣮ߦ
  180. ༻్͸ʁ

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

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

  183. εϓϥΠτͷ੍໿

  184. ࣮͸εϓϥΠτ͸ಉҰϥΠϯ্ʹͭ·Ͱ͔͠഑ஔͰ͖ͳ͍ 116͸ϥΠϯόοϑΝΛ͓࣋ͬͯΓ ϥΠϯຖʹεϓϥΠτͱഎܠͷ߹੒Λߦ͍ඳը͍ͯ͠Δ ͜ͷॲཧ͸ίετ͕ߴ͘࠷େͭ·Ͱ͔͠߹੒Ͱ͖ͳ͍Β͍͠ ౰࣌ͷϝϞϦͱίετͷؔ܎͔Β ϑϨʔϜόοϑΝʹ͸Ͱ͖ͳ͔ͬͨΜͩͱਪଌ ΞυϨε ֓ཁ Y CJU

    આ໌ ʜ ʜ  εΩϟϯϥΠϯεϓϥΠτ਺ɹݸҎԼݸҎ্ ʜ ʜ ͜Ε͸্ه੍໿Λݕग़͢ΔͨΊͷػߏ ͕ͩɺόάͬͯΔͱͷӟ΋͋Γ Ͳͷఔ౓࢖༻͞Ε͍ͯͨͷ͔͸ෆ໌ εϓϥΠτͷ੍໿
  185. ൃੜ͢Δ໰୊ͱରࡦʢະݕূʣ

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

    ଜਓ ਓύʔςΟ ൃੜ͢Δ໰୊ͱରࡦʢະݕূʣ
  187. Ͱ΋ɺ͓Ε͸Ͱ͔͍ͬϘεΈͨ͜ͱ͕͋Δͧʂ ͱ͍͏ํ΋͍Δ͔΋

  188. IUUQTXXXZPVUVCFDPNXBUDI W1(1EP1T3ΑΓ εϓϥΠτͰ͸ͳ͘ എܠͰඳը ͜Ε͸εϓϥΠτͰ͸ͳ͘എܠͰϘεΛදݱͯ͠ΔͬΆ͍ εϓϥΠτͰ͋Ε͹ෳࡶͳഎܠͷ্ʹ ߹੒ʢॏͳΓ͕දݱʣ͞Εͯදࣔ͞ΕΔ͕ എܠͰఢΛදݱͯ͠͠·͏ͱॏͶΔ͜ͱ͕Ͱ͖ͳ͍ ͳͷͰɺഎܠ͸ਅͬࠇʹͯ͠ΔͱࢥΘΕΔ ௨ৗഎܠͱͯ͠ඳը͢ΔͰ͋Ζ͏

    ଍৔ΛεϓϥΠτͱͯ͠ඳը ͔ͭӈ͔Βࠨ΁Ҡಈͤ͞Δ͜ͱ ʹΑΓυϥΰϯ͕௥ͬͯ͘ΔΑ͏ʹ දݱ υϥΰϯͷ্ԼҠಈ͸ എܠεΫϩʔϧͰ࣮ݱ ͜͏͍͏΍ͭ
  189. εϓϥΠτͷసૹύϑΥʔϚϯε

  190. ͨͱ͑͹εϓϥΠτ3".#ZUFΛద౰ͳ஋ͰຒΊΔ ؆୯ͳॲཧΛߟ͑ͯΈΔ ldy $FF # 2cycle copysprites: sty $2004 #

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

  192. ղܾࡦ͸ʜ

  193. %." %JSFDUNFNPSZBDDFTT

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

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

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

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

    %." /&4ͷ%."͸͔ͳΓ௿ػೳ
  198. ίϯτϩʔϥ

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

     "  #  4&-&$5  45"35  ্  Լ  ࠨ  ӈ ίϯτϩʔϥ ̎1͸Y
  200. ϒϥ΢βͰͷΤϛϡϨʔγϣϯ

  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෼֬ อͦ͜͠ʹঢ়ଶΛॻ͖ࠐΉ
  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ʜͷॱʹ ஋Λฦ͢Α͏ʹ͓ͯ͘͠
  203. "16 α΢ϯυ ׂ Ѫ

  204. ϑΝϛίϯͷ৔߹"16 ΦʔσΟΦϓϩηογϯάϢχο τʣͱ%"$ σΟδλϧΞφϩάίϯόʔλ ͕$16ʹ ૊Έࠐ·Ε͍ͯΔ "16 α΢ϯυ νϟωϧ͸ۣܗ೾͕νϟωϧɺࡾ֯೾νϟωϧɺϊ Πζνϟωɺ%1$.νϟωϧͷνϟωϧ͕࢖༻Ͱ

    ͖ήʔϜͷԻ͸͜ͷνϟωϧͷ૊Έ߹ΘͤʹΑΓදݱ͞ ΕΔ ׂ Ѫ
  205. IUUQTDPEFQFOJPHSFHIQFOYR8XR[ Πϝʔδ͸͜ͷDPEFQFO͕Θ͔Γ΍͍͢ "16 α΢ϯυ ׂ Ѫ

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

  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ͷϨδελҰཡ ׂ Ѫ
  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ͷϨδελҰཡ ׂ Ѫ
  209. ۣܗ೾ΛΈ͍ͯ͘ ׂ Ѫ

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

  211. ΞυϨε ֓ཁ Y CJU આ໌  σϡʔςΟൺCC CC  ࠶ੜ࣌ؒΧ΢ϯλΠωʔϒϧ

     ΤϯϕϩʔϓσΟηʔϒϧ  ϘϦϡʔϜ·ͨ͸ΤϯϕϩʔϓσΟόΠμ σϡʔςΟൺ ݮਰͷ଎౓ͳͲΛ੍ޚ ۣܗ೾Ϩδελ ׂ Ѫ
  212. ΞυϨε ֓ཁ Y CJU આ໌  εΠʔϓΠωʔϒϧ  प೾਺มԽ଎౓ 

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

     ΩʔΦϑΧ΢ϯλ  ύϧελΠϚʔ্ҐCJU प೾਺ͱ࠶ੜ࣌ؒΛ੍ޚ ۣܗ೾Ϩδελ ׂ Ѫ
  214. Ͳ͏΍ͬͯΤϛϡϨʔτ͢Δ͔ ׂ Ѫ

  215. 8FC"VEJP ׂ Ѫ

  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Ͱ ΧελϜ೾ܗΛ࡞੒Ͱ͖Δ ׂ Ѫ
  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ଆ΁ެ։ ׂ Ѫ
  218. ͋ͱ͸)[)[ͷपظͱ $16͔ΒͷΞΫηελΠϛϯά प೾਺΍ϘϦϡʔϜͷมಈ͕ൃੜ͢Δ ͷͰͦͷλΠϛϯάͰݺΜͰ΍Ε͹͍͍ ׂ Ѫ

  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 ଆͷॲཧ ׂ Ѫ
  220. ͜͜·ͰͰϑΝϛίϯຊମͷ ϋʔυ΢ΣΞ͸Ұ௨Γ࣮૷Ͱ͖ͨ͸ͣ

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

  222. "͠ͳ͍

  223. ..$ NFNPSZNBOBHFNFOUDPOUSPMMFS

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

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

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

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

  228. .BQQFS

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

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

  231. $)3 30. $/ )$  "" "" %% 8& )$ͰσʔλΛϥον͠

    ΞυϨεʹม׵ ΩϟϥΫλʔ30. όΠφϦΧ΢ϯλ .BQQFSͷճ࿏
  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.΁ͷΞυϨε Λܭࢉͯ͠ฦ͢
  233. ରԠ30.Λ૿΍͢ʹ͸ ֤ͭͭ͜͜.BQQFSͷରԠ͕ඞཁ

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

  235. ύϑΥʔϚϯε

  236. DISPNF  8FC"TTFNCMZWT+BWB4DSJQU DISPNFDBOBSZ  pSFGPY  CJU pSFGPYEFWFMPQFSFEJUJPO C

    CJU TBGBSJ    NT NT NT NT NT NT NT NT NT NT    UJNF<NT> TNBMMFSJTCFUUFS 8FC"TTFNCMZ CPLVXFCSVTUZOFT +BWB4DSJQU CPLVXFCqPXOFT 8FC"VEJP$BOWBTΛσΟηʔϒϧʹͨ͠ঢ়ଶͰ ϝΠϯϧʔϓͷॲཧ࣌ؒճͷฏۉ஋Λൺֱ .BD#PPL"JS JODI &BSMZ ()[*OUFM$PSFJ(#.)[%%3 HJLPOFT
  237. ͍͞͝ʹ !ϑΝϛίϯΤϛϡϨʔλ͸ҰਓͰ࣮૷͢Δͷʹ΋खࠒͳαΠζ !$16΍%."ɺׂΓࠐΈͳͲͷಈ࡞Λֶ΂Δ !ઌਓͷۤ࿑ͷยྡྷΛຯΘ͑Δ !ࣗ෼΋99ݴޠͰ΍ͬͯΈΔ͔ʂͱࢥͬͯ΋Β͑ͨΒخ͍͠Ͱ͢

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


[8]ページ先頭

©2009-2025 Movatter.jp