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

PHPで学ぶ コンピュータアーキテクチャ

PHPで学ぶ コンピュータアーキテクチャ

PHPカンファレンス福岡2016の発表資料です。

この話は何回しても楽しいので再放送希望の方、お声がけください!

HASEGAWA Tomoki

May 21, 2016
Tweet

More Decks by HASEGAWA Tomoki

Other Decks in Technology

Transcript

  1. 今風のカッコいいPHPの書き方 Modern style PHP coding. クールなライブラリやフレームワーク Cool libraries / frameworks.

    PHPをそんな風に使うのか!という驚き Exciting PHP usage. ゲームボーイの仕様の知識 Knowledge of GAMEBOY specs.
  2. 今風のカッコいいPHPの書き方 Modern style PHP coding. クールなライブラリやフレームワーク Cool libraries / frameworks.

    PHPをそんな風に使うのか!という驚き Exciting PHP usage. ゲームボーイの仕様の知識 Knowledge of GAMEBOY specs.
  3. ライフワーク: Web / iOSアプリ開発, ビール, IoT,
 サッカー観戦, レンタルカートレース, … 長谷川

    智希 Web / iOS App Development, Beer, IoT, Watch soccer match, Rental Kart Racing, … デジタルサーカス株式会社 副団長CTO Digital Circus, Inc. Vice-master CTO Tokyo, Japan Lifework: @tomzoh
  4. WE ARE HIRING!! Web Development Mobile App Development ( )

    (iOS, Android) http://www.dgcircus.com Omotesando, Tokyo
  5. LR35902 CPUのプログラム Program of CPU LR35902 +0 +1 +2 +3

    +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 0200 42 E0 43 E0 A4 E0 41 E0 01 E0 02 EA 00 D0 EA 01 0210 D0 3E 80 E0 40 F0 44 FE 94 20 FA 3E 03 E0 40 3E 0220 E1 E0 47 E0 48 3E E5 E0 49 21 26 FF 3E 80 32 3E 0230 FF 32 36 77 21 06 FF 3E BF 22 3E 04 77 3E 01 EA 0240 00 20 31 FF CF AF 21 FF DF 06 00 32 05 20 FC 21 0250 FF CF 0E 10 06 00 32 05 20 FC 0D 20 F9 21 FF 9F 0260 0E 20 AF 06 00 32 05 20 FC 0D 20 F9 21 FF FE 06
  6. プログラムの実行 Program execution +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0
  7. プログラムの実行 Program execution +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0
  8. プログラムの実行 Program execution AF 21 DF FF 0E 10 06

    00 32 05 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0
  9. プログラムの実行 Program execution AF 21 DF FF 0E 10 06

    00 32 05 XOR A LD HL, 0xFFDF LD C, 0x10 LD B, 0x00 LD (HL-), A DEC B +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0
  10. プログラムの実行 Program execution AF 21 DF FF 0E 10 06

    00 32 05 XOR A LD HL, 0xFFDF LD C, 0x10 LD B, 0x00 LD (HL-), A DEC B +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 AをAでXOR HLに0xffdfを入れる Cに0x10を入れる Bに0x00を入れる HLが指すアドレスにAの値を入れる Bを-1する Load 0xffdf into HL XOR A with A Load 0x10 into C Load 0x00 into B Load a value A has into memory address HL points at Decrement B
  11. SHARP LR35902 のレジスタ SHARP LR35902 registers ʜ ʜ " '

    # $ ) - ʜ ʜ 41 4UBDL1PJOUFS 1$ 1SPHSBN$PVOUFS 8bit / 16bit registers 16bit registers Flag register         ; / ) $     •Z - Zero Flag •N - Subtract Flag •H - Half Carry Flag •C - Carry Flag •0 - Not uses, always zero レジスタ: CPUが持つ、プログラム言語で言う変数 Registers: Variables in programing language.
  12. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. PC
  13. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. PC
  14. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. PC
  15. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. PC
  16. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. PC
  17. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. PC
  18. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. AF 21 DF FF 0E 10 06 00 32 05 XOR A LD HL, 0xFFDF LD C, 0x10 LD B, 0x00 LD (HL-), A DEC B PC
  19. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. AF 21 DF FF 0E 10 06 00 32 05 XOR A LD HL, 0xFFDF LD C, 0x10 LD B, 0x00 LD (HL-), A DEC B PC
  20. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. AF 21 DF FF 0E 10 06 00 32 05 XOR A LD HL, 0xFFDF LD C, 0x10 LD B, 0x00 LD (HL-), A DEC B PC
  21. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. AF 21 DF FF 0E 10 06 00 32 05 XOR A LD HL, 0xFFDF LD C, 0x10 LD B, 0x00 LD (HL-), A DEC B PC
  22. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. AF 21 DF FF 0E 10 06 00 32 05 XOR A LD HL, 0xFFDF LD C, 0x10 LD B, 0x00 LD (HL-), A DEC B PC
  23. プログラムカウンタ Program Counter +0 +1 +2 +3 +4 +5 +6

    +7 +8 +9 +A +B +C +D +E +F 01E0 01 E0 85 E1 D1 C1 F1 D9 AF 21 FF DF 0E 10 06 00 01F0 32 05 20 FC 0D 20 F9 3E 0D F3 E0 0F E0 FF AF E0 現在実行中の命令のアドレスを指す特殊なレジスタ。 A special register that contains the address of the instruction being executed now. AF 21 DF FF 0E 10 06 00 32 05 XOR A LD HL, 0xFFDF LD C, 0x10 LD B, 0x00 LD (HL-), A DEC B PC
  24. LR35902 の命令 - LD LR35902 instructions - LD LD BC,

    0x1234 BCレジスタに0x1234を入れる。 Load BC register with 0x1234. LD (BC), A BCレジスタの指し示すメモリアドレスにAレジスタ の内容を入れる。 Load a value A register has into memory BC register points at.
  25. LR35902 の命令 - JP / CD LR35902 instructions - JP

    / CD JP 0x5678 0x5678番地にジャンプする。 Jump to location 0x5678. CALL 0x8181 スタックに現在のアドレスを入れて0x8181番地に ジャンプする。 Push current address to stack pointer, then jump to 0x8181. RET スタック先頭のアドレスにジャンプする。 Jump to the location of top of stack pointer.
  26. ゲームボーイのハードウェアコンポネント CPU I/O Keys Sound Video Display Com Port Memory

    • RAM • Game 
 Cartridge • Video RAM Hardware components of GAMEBOY
  27. GAMEBOYのメモリマップ Memory map of GAMEBOY $FFFF Interrupt Enable Flag I/O

    $FF80-$FFFE Zero Page - 127 bytes RAM $FF00-$FF7F Hardware I/O Registers I/O $FEA0-$FEFF Unusable Memory $FE00-$FE9F OAM - Object Attribute Memory Video RAM $E000-$FDFF Echo RAM - Reserved, Do Not Use $D000-$DFFF Internal RAM - Bank 1-7 (switchable - CGB only) RAM $C000-$CFFF Internal RAM - Bank 0 (fixed) $A000-$BFFF Cartridge RAM (If Available) Cartridge $9C00-$9FFF BG Map Data 2 Video RAM $9800-$9BFF BG Map Data 1 $8000-$97FF Character RAM $4000-$7FFF Cartridge ROM - Switchable Banks 1-xx Cartridge $0150-$3FFF Cartridge ROM - Bank 0 (fixed) $0100-$014F Cartridge Header Area $0000-$00FF Restart and Interrupt Vectors ROM IUUQXXXIVDLpOHBNFTDPN QJE #Z5SBOTGSPN+1&(WFSTJPOBOESFNPWFXIJUFCBDLHSPVOE0SJHJOBMCZ&WBO"NPT.FEJB(BNF#PZ'-KQH  1VCMJD%PNBJO IUUQTDPNNPOTXJLJNFEJBPSHXJOEFYQIQ DVSJE
  28. GAMEBOYのメモリマップ Memory map of GAMEBOY $FFFF Interrupt Enable Flag I/O

    $FF80-$FFFE Zero Page - 127 bytes RAM $FF00-$FF7F Hardware I/O Registers I/O $FEA0-$FEFF Unusable Memory $FE00-$FE9F OAM - Object Attribute Memory Video RAM $E000-$FDFF Echo RAM - Reserved, Do Not Use $D000-$DFFF Internal RAM - Bank 1-7 (switchable - CGB only) RAM $C000-$CFFF Internal RAM - Bank 0 (fixed) $A000-$BFFF Cartridge RAM (If Available) Cartridge $9C00-$9FFF BG Map Data 2 Video RAM $9800-$9BFF BG Map Data 1 $8000-$97FF Character RAM $4000-$7FFF Cartridge ROM - Switchable Banks 1-xx Cartridge $0150-$3FFF Cartridge ROM - Bank 0 (fixed) $0100-$014F Cartridge Header Area $0000-$00FF Restart and Interrupt Vectors ROM IUUQXXXIVDLpOHBNFTDPN QJE #Z5SBOTGSPN+1&(WFSTJPOBOESFNPWFXIJUFCBDLHSPVOE0SJHJOBMCZ&WBO"NPT.FEJB(BNF#PZ'-KQH  1VCMJD%PNBJO IUUQTDPNNPOTXJLJNFEJBPSHXJOEFYQIQ DVSJE
  29. class Opcode { public static function run(Core $core, $address) {

    $function = 'opcode'.$address; return Opcode::$function($core); } public static function opcode0(Core $core) { // Do Nothing... } public static function opcode1(Core $core) { $core->registerC = $core->memoryRead($core->programCounter); $core->registerB = $core->memoryRead(($core->programCounter + 1) & 0xFFFF); $core->programCounter = ($core->programCounter + 2) & 0xFFFF; } Opcodeの実装 Implementation of opcodes
  30. class Opcode { public static function run(Core $core, $address) {

    $function = 'opcode'.$address; return Opcode::$function($core); } public static function opcode0(Core $core) { // Do Nothing... } public static function opcode1(Core $core) { $core->registerC = $core->memoryRead($core->programCounter); $core->registerB = $core->memoryRead(($core->programCounter + 1) & 0xFFFF); $core->programCounter = ($core->programCounter + 2) & 0xFFFF; } Opcodeの実装 Implementation of opcodes 0x00 NOP
  31. class Opcode { public static function run(Core $core, $address) {

    $function = 'opcode'.$address; return Opcode::$function($core); } public static function opcode0(Core $core) { // Do Nothing... } public static function opcode1(Core $core) { $core->registerC = $core->memoryRead($core->programCounter); $core->registerB = $core->memoryRead(($core->programCounter + 1) & 0xFFFF); $core->programCounter = ($core->programCounter + 2) & 0xFFFF; } Opcodeの実装 Implementation of opcodes 0x01 LD BC, nn
  32. public static function opcode1(Core $core) { $core->registerC =
 $core->memoryRead($core->programCounter); $core->registerB

    = 
 $core->memoryRead(($core->programCounter + 1) & 0xFFFF); $core->programCounter = 
 ($core->programCounter + 2) & 0xFFFF; } LC BC, nn の実装 Implementation of LD BC, nn PC PC + 1 0x01 0x01 0x03 LD BC, nn 0x0301 Data Address
  33. public static function opcode1(Core $core) { $core->registerC =
 $core->memoryRead($core->programCounter); $core->registerB

    = 
 $core->memoryRead(($core->programCounter + 1) & 0xFFFF); $core->programCounter = 
 ($core->programCounter + 2) & 0xFFFF; } LC BC, nn の実装 Implementation of LD BC, nn PC PC + 1 0x01 0x01 0x03 LD BC, nn 0x0301 Data Address BCレジスタに指定したアドレスのメモリの値を入れる。 Load BC register with nn.
  34. public static function opcode1(Core $core) { $core->registerC =
 $core->memoryRead($core->programCounter); $core->registerB

    = 
 $core->memoryRead(($core->programCounter + 1) & 0xFFFF); $core->programCounter = 
 ($core->programCounter + 2) & 0xFFFF; } LC BC, nn の実装 Implementation of LD BC, nn PC PC + 1 0x01 0x01 0x03 LD BC, nn 0x0301 Data Address PCを次の命令まで進める。 Move PC register to next instruction.
  35. public static function opcode1(Core $core) { $core->registerC =
 $core->memoryRead($core->programCounter); $core->registerB

    = 
 $core->memoryRead(($core->programCounter + 1) & 0xFFFF); $core->programCounter = 
 ($core->programCounter + 2) & 0xFFFF; } LC BC, nn の実装 Implementation of LD BC, nn PC PC + 1 0x01 0x01 0x03 LD BC, nn 0x0301 Data Address
  36. $core->memoryRead($core->programCounter); // //Main RAM, MBC RAM, GBC Main RAM, VRAM,

    etc. // //Main Core Memory public $memory = []; Core.php
  37. $core->memoryRead($core->programCounter); // //Main RAM, MBC RAM, GBC Main RAM, VRAM,

    etc. // //Main Core Memory public $memory = []; Core.php メインメモリは配列になっている。 Main memory is defined as array.

  38. $core->memoryRead($core->programCounter); // //Main RAM, MBC RAM, GBC Main RAM, VRAM,

    etc. // //Main Core Memory public $memory = []; Core.php メインメモリは配列になっている。 Main memory is defined as array.
 なぜ $core->memory[$core->programCounter] ではない? Q Why not $core->memory[$core->programCounter] ?
  39. GAMEBOYのメモリマップ Memory map of GAMEBOY $FFFF Interrupt Enable Flag I/O

    $FF80-$FFFE Zero Page - 127 bytes RAM $FF00-$FF7F Hardware I/O Registers I/O $FEA0-$FEFF Unusable Memory $FE00-$FE9F OAM - Object Attribute Memory Video RAM $E000-$FDFF Echo RAM - Reserved, Do Not Use $D000-$DFFF Internal RAM - Bank 1-7 (switchable - CGB only) RAM $C000-$CFFF Internal RAM - Bank 0 (fixed) $A000-$BFFF Cartridge RAM (If Available) Cartridge $9C00-$9FFF BG Map Data 2 Video RAM $9800-$9BFF BG Map Data 1 $8000-$97FF Character RAM $4000-$7FFF Cartridge ROM - Switchable Banks 1-xx Cartridge $0150-$3FFF Cartridge ROM - Bank 0 (fixed) $0100-$014F Cartridge Header Area $0000-$00FF Restart and Interrupt Vectors ROM IUUQXXXIVDLpOHBNFTDPN QJE #Z5SBOTGSPN+1&(WFSTJPOBOESFNPWFXIJUFCBDLHSPVOE0SJHJOBMCZ&WBO"NPT.FEJB(BNF#PZ'-KQH  1VCMJD%PNBJO IUUQTDPNNPOTXJLJNFEJBPSHXJOEFYQIQ DVSJE
  40. GAMEBOYのメモリマップ Memory map of GAMEBOY $FFFF Interrupt Enable Flag I/O

    $FF80-$FFFE Zero Page - 127 bytes RAM $FF00-$FF7F Hardware I/O Registers I/O $FEA0-$FEFF Unusable Memory $FE00-$FE9F OAM - Object Attribute Memory Video RAM $E000-$FDFF Echo RAM - Reserved, Do Not Use $D000-$DFFF Internal RAM - Bank 1-7 (switchable - CGB only) RAM $C000-$CFFF Internal RAM - Bank 0 (fixed) $A000-$BFFF Cartridge RAM (If Available) Cartridge $9C00-$9FFF BG Map Data 2 Video RAM $9800-$9BFF BG Map Data 1 $8000-$97FF Character RAM $4000-$7FFF Cartridge ROM - Switchable Banks 1-xx Cartridge $0150-$3FFF Cartridge ROM - Bank 0 (fixed) $0100-$014F Cartridge Header Area $0000-$00FF Restart and Interrupt Vectors ROM IUUQXXXIVDLpOHBNFTDPN QJE #Z5SBOTGSPN+1&(WFSTJPOBOESFNPWFXIJUFCBDLHSPVOE0SJHJOBMCZ&WBO"NPT.FEJB(BNF#PZ'-KQH  1VCMJD%PNBJO IUUQTDPNNPOTXJLJNFEJBPSHXJOEFYQIQ DVSJE A. メモリアクセスはそのアドレスに よって動作が違うから。 A. Because a result of memory access depends on its location. 

  41. ゲームボーイのハードウェアコンポネント CPU I/O Keys Sound Video Display Com Port Memory

    • RAM • Game 
 Cartridge • Video RAM Hardware components of GAMEBOY
  42. ゲームボーイのハードウェアコンポネント CPU I/O Keys Sound Video Display Com Port Memory

    • RAM • Game 
 Cartridge • Video RAM Hardware components of GAMEBOY CPUはキーにI/O経由でアクセスする CPU accesses keys through the I/O
  43. キー状態の取得 public function __construct(Core $core) { $this->core = $core; exec('stty

    -icanon -echo'); $this->file = fopen('php://stdin', 'r'); stream_set_blocking($this->file, false); } public function check() { $key = fread($this->file, 1); if (!empty($key)) { $this->keyDown($key); } elseif (!empty($this->keyPressing)) { $this->keyUp($this->keyPressing); } $this->keyPressing = $key; } Get key status
  44. キー状態の取得 public function __construct(Core $core) { $this->core = $core; exec('stty

    -icanon -echo'); $this->file = fopen('php://stdin', 'r'); stream_set_blocking($this->file, false); } public function check() { $key = fread($this->file, 1); if (!empty($key)) { $this->keyDown($key); } elseif (!empty($this->keyPressing)) { $this->keyUp($this->keyPressing); } $this->keyPressing = $key; } Get key status 標準入力を開いて… Open standard in and...

  45. キー状態の取得 public function __construct(Core $core) { $this->core = $core; exec('stty

    -icanon -echo'); $this->file = fopen('php://stdin', 'r'); stream_set_blocking($this->file, false); } public function check() { $key = fread($this->file, 1); if (!empty($key)) { $this->keyDown($key); } elseif (!empty($this->keyPressing)) { $this->keyUp($this->keyPressing); } $this->keyPressing = $key; } Get key status 標準入力を開いて… Open standard in and...
 fread()で1文字取る! Get a character with fread!
  46. I/O 読み込み public function memoryRead($address) { if ($address < 0x4000)

    { } elseif ($address >= 0xFF00) { switch ($address) { case 0xFF00: return 0xC0 | $this->memory[0xFF00]; break; I/O read
  47. I/O 書き込み I/O write 7 6 5 4 3 2

    1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00
  48. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00
  49. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00
  50. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00
  51. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00
  52. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00
  53. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00 7 6 5 4 3 2 1 0 A B Select Start → ← ↑ ↓ $this->JoyPad:
  54. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00 7 6 5 4 3 2 1 0 A B Select Start → ← ↑ ↓ $this->JoyPad:
  55. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00 7 6 5 4 3 2 1 0 A B Select Start → ← ↑ ↓ $this->JoyPad:
  56. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00 7 6 5 4 3 2 1 0 A B Select Start → ← ↑ ↓ $this->JoyPad:
  57. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00 7 6 5 4 3 2 1 0 A B Select Start → ← ↑ ↓ $this->JoyPad:
  58. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00 7 6 5 4 3 2 1 0 A B Select Start → ← ↑ ↓ $this->JoyPad:
  59. public function memoryWrite($address, $data) { if ($address < 0x8000) {

    //I/O Registers (GB + GBC): } elseif ($address == 0xFF00) { $this->memory[0xFF00] = ($data & 0x30) | (((($data & 0x20) == 0) ? ($this->JoyPad >> 4) : 0xF) & ((($data & 0x10) == 0) ? ($this->JoyPad & 0xF) : 0xF)); } elseif ($address == 0xFF02) { I/O 書き込み I/O write 7 6 5 4 3 2 1 0 - - P15 out P14 out P13 in P12 in P11 in P10 in - - 0 1 A B Select Start - - 1 0 → ← ↑ ↓ I/O port 0xFF00 7 6 5 4 3 2 1 0 A B Select Start → ← ↑ ↓ $this->JoyPad:
  60. セットアップ How to run $ git clone https://github.com/gabrielrcouto/php- terminal-gameboy-emulator.git $

    cd php-terminal-gameboy-emulator $ composer install -o $ bin/php-gameboy drmario.rom
  61. ストリームの非ブロックモード public function __construct(Core $core) { $this->core = $core; exec('stty

    -icanon -echo'); $this->file = fopen('php://stdin', 'r'); stream_set_blocking($this->file, false); } public function check() { $key = fread($this->file, 1); if (!empty($key)) { $this->keyDown($key); } elseif (!empty($this->keyPressing)) { $this->keyUp($this->keyPressing); } $this->keyPressing = $key; } Non-blocking mode on a stream
  62. ストリームの非ブロックモード public function __construct(Core $core) { $this->core = $core; exec('stty

    -icanon -echo'); $this->file = fopen('php://stdin', 'r'); stream_set_blocking($this->file, false); } public function check() { $key = fread($this->file, 1); if (!empty($key)) { $this->keyDown($key); } elseif (!empty($this->keyPressing)) { $this->keyUp($this->keyPressing); } $this->keyPressing = $key; } Non-blocking mode on a stream
  63. ストリームの非ブロックモード public function __construct(Core $core) { $this->core = $core; exec('stty

    -icanon -echo'); $this->file = fopen('php://stdin', 'r'); stream_set_blocking($this->file, false); } public function check() { $key = fread($this->file, 1); if (!empty($key)) { $this->keyDown($key); } elseif (!empty($this->keyPressing)) { $this->keyUp($this->keyPressing); } $this->keyPressing = $key; } Non-blocking mode on a stream ストリームのモードを非ブロックに設定 Set non-blocking mode on a stream.