2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScript版『FEDORA』リリース

Last updated at Posted at 2025-05-21

fedora.png

5月10日の記事の続きだが、PC-8001向けゲーム『FEDORA』(ASCII, Vol.7, No.7 (1983年7月), pp.143-149)を、JavaScript上で動かしてみた。

5月22日時点でのプログラムリストも、以下に公開しておくことにする。

<!DOCTYPE html><head><meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>FEDORA by Koichi Yasuoka, May 22, 2025</title>
<script>
var pc8001=new Object();
pc8001.memory=new Array(65536);
pc8001.memory.fill(0x76);
["0000 C3 00 E0",
 "0018                         FE 0C CA 3A 09 76",
 "093A                               2A 5A EA EB 21 00",
 "0940 F3 06 50 73 23 10 FC AF 77 23 77 23 36 01 23 72",
 "0950 23 01 50 11 71 23 72 23 10 FA 71 23 77 23 11 00",
 "0960 F3 EB 01 40 0B ED B0 C9",
 "1602       C9",
 "DC00 11 00 02 CD EA E4 21 55 DC DB 01 07 30 3D AF 32",
 "DC10 26 E2 3E 18 32 45 E8 CD ED 52 21 97 DC DB 03 E6",
 "DC20 40 28 13 DB 05 E6 02 20 F4 3E 3A 32 26 E2 3E 20",
 "DC30 32 45 E8 21 66 DC CD ED 52 60 69 23 11 FF FF CD",
 "DC40 EA E4 CD ED 52 11 FF FF CD EA E4 21 9F DC CD ED",
 "DC50 52 C3 81 00 00 46 45 44 4F 52 41 2D 32 20 52 65",
 "DC60 61 64 79 3F 20 00 59 65 73 0D 0A 0A 07 00 50 75",
 "DC70 73 68 97 1E 80 80 1D 1D 1F B6 C5 1D 1D 1F 94 94",
 "DC80 1E 88 77 68 65 6E 20 79 6F 75 20 75 73 65 20 69",
 "DC90 74 2E 0D 1F 1F 00 00 4E 6F 0D 0A 0A 07 00 00 BD",
 "DCA0 C0 B0 C4 CA 20 45 30 30 30 C3 DE BD A1 07 00 0C",
 "DCB0 0C 04 00 C0 44 C0 44 C0 C4 C0 84 C0 44 17 07 07",
 "DCC0 11 50 75 70 44 70 74 70 61 70 45 3A D6 E8 B7 C8",
 "DCD0 3A D8 E8 B7 20 05 3A D7 E8 B7 C0 D9 E5 79 D9 E3",
 "DCE0 4F CD 8D E3 CD 43 E4 54 26 78 CD 32 E4 7A 2B 2B",
 "DCF0 BE 38 FB 23 3E A8 BE E1 C9 00 00 00 3E 20 D3 40",
 "DD00 D9 21 D6 E8 34 7E CD 4C DD 11 31 FA CD 2F DD 23",
 "DD10 3A D1 E8 BE D9 D0 D9 7E 32 D1 E8 11 93 F4 CD 2F",
 "DD20 DD D9 C9 16 00 EB 29 29 29 29 EB C9 00 00 00 21",
 "DD30 D2 E8 0E 03 13 13 23 7E 0D 28 03 B7 28 F6 0E 01",
 "DD40 CD 97 DD 7D FE D5 20 EC C9 00 00 00 47 21 D3 E8",
 "DD50 16 00 72 23 72 23 36 FF 04 3E 0A 21 D6 E8 2B 34",
 "DD60 4E 72 B9 28 F9 71 10 F3 C9 00 00 00 C0 C4 70 74",
 "DD70 40 0C 40 47 40 C4 70 55 40 C4 50 75 C0 C0 10 71",
 "DD80 C0 44 50 75 C0 44 70 75 40 C4 00 70 C0 C4 70 75",
 "DD90 C0 C4 50 75 00 00 00 E5 D5 C5 07 07 C6 6C 6F 26",
 "DDA0 DD ED A0 ED A0 01 76 00 EB 09 EB ED A0 ED A0 C1",
 "DDB0 D1 E1 C9 00 00 00 3E D8 32 BB F4 32 33 F5 21 B3",
 "DDC0 DC 11 27 FA 01 0A 00 ED B0 21 C1 DC 11 9F FA 01",
 "DDD0 0A 00 ED B0 21 AF DC 11 85 F4 01 0E 00 ED B0 11",
 "DDE0 FD F4 01 0E 00 ED B0 AF 32 D6 E8 11 37 FA CD 97",
 "DDF0 DD 3A D1 E8 CD 4C DD 11 93 F4 C3 2F DD 00 00 00",
 "DE00 3A D4 E8 E6 07 C0 21 D6 E8 7E 35 28 18 E6 2F C0",
 "DE10 21 BA F8 0E 02 06 1B 1A AE 77 13 23 10 F9 21 32",
 "DE20 F9 0D 20 F1 C9 21 E0 DF E3 C9 00 DD 7D 0F 0F D6",
 "DE30 2E 6F 26 E0 7E DD 77 00 23 7E DD 77 01 C5 CD 59",
 "DE40 E4 C1 21 D5 E8 7E C6 10 77 D0 36 FF C9 00 00 00",
 "DE50 9F 91 0B F8 F9 08 9F F1 11 0F 9F 99 01 00 00 1F",
 "DE60 31 0F FF 00 0F 9F 99 01 9F F9 08 77 44 07 77 00",
 "DE70 07 77 70 00 07 77 44 04 00 00 47 44 07 70 64 03",
 "DE80 77 44 04 77 00 07 00 00 00 00 8F F0 00 0F 8F F0",
 "DE90 19 F1 F0 19 F1 F0 08 9F 11 0F 9F 91 0B 00 00 00",
 "DEA0 00 00 00 00 00 77 74 44 07 77 70 07 70 70 07 70",
 "DEB0 70 07 77 00 07 77 44 07 00 00 00 00 00 00 00 00",
 "DEC0 00 21 D3 E8 7E B7 28 0E 35 3E 20 D3 40 11 20 00",
 "DED0 CD EA E4 D3 40 C9 21 D8 E8 7E B7 20 24 2B 7E 11",
 "DEE0 50 DE B7 CA 00 DE 3A D4 E8 E6 07 20 14 2B 35 28",
 "DEF0 07 DB 01 07 38 0B 36 00 23 35 DD 21 D8 E8 CD 2B",
 "DF00 DE 3A D2 E8 FE 82 30 20 06 01 0F 38 08 0F 38 05",
 "DF10 0F E6 03 3C 47 DD 21 E0 E8 DD 7E 00 B7 CC 2B DE",
 "DF20 11 08 00 DD 19 10 F2 C9 21 D8 E8 11 86 DE 7E B7",
 "DF30 C8 7D C6 08 6F CA 00 DE 7E B7 18 F5 C9 00 21 D4",
 "DF40 E8 35 C0 23 34 C0 35 C9 00 00 00 FD 66 00 FD 6E",
 "DF50 01 CD 43 E4 CD 32 E4 79 AE 77 C9 00 00 00 FD 21",
 "DF60 00 E9 FD 7E 00 B7 28 1A FD 35 05 20 15 CD 4B DF",
 "DF70 FD 7E 01 FD 86 03 FD 77 01 CD B1 E2 FD 7E 07 FD",
 "DF80 77 05 FD 7D C6 08 FD 6F 20 D8 C9 00 00 00 DD 21",
 "DF90 D8 E8 DD 7E 00 B7 28 39 DD 35 05 20 34 DD 7E 06",
 "DFA0 D6 08 4F CD D0 E1 DD 72 03 DD 73 05 CD C5 E3 DD",
 "DFB0 7E 01 DD 86 03 FE 03 28 04 FE 5C 20 0E 3E 2F DD",
 "DFC0 96 06 DD 77 06 DD 7E 01 DD 96 03 DD 77 01 CD 59",
 "DFD0 E4 DD 7D C6 08 DD 6F 20 B9 C9 31 FF FF CD 7E E8",
 "DFE0 CD 9F E7 CD 24 E5 CD 10 E2 CD 22 E1 CD 40 E0 CD",
 "DFF0 8E DF CD 12 E0 CD 5E DF CD 3E DF CD C1 DE 18 E6",
 "E000 DB 01 07 30 FB 18 D3 00 02 04 99 5B 02 04 02 5B",
 "E010 99 04 FD 21 00 E9 FD 7E 00 B7 28 1A FD 35 04 20",
 "E020 15 CD 4B DF FD 7E 00 FD 86 02 FD 77 00 CD B1 E2",
 "E030 FD 7E 06 FD 77 04 FD 7D C6 08 FD 6F 20 D8 C9 00",
 "E040 DD 21 D8 E8 DD 7E 00 B7 28 36 DD 35 04 20 31 DD",
 "E050 4E 06 CD D0 E1 DD 72 02 DD 73 04 CD C5 E3 DD 7E",
 "E060 00 DD 86 02 FE 01 28 04 FE 9A 20 0E 3E 1F DD 96",
 "E070 06 DD 77 06 DD 7E 00 DD 96 02 DD 77 00 CD 59 E4",
 "E080 DD 7D C6 08 DD 6F 20 BC C9 00 00 00 03 06 0A 10",
 "E090 17 26 50 00 00 00 DD 35 07 C0 DD 36 07 40 3A D8",
 "E0A0 E8 DD 96 00 01 01 08 30 05 ED 44 01 FF 17 57 3A",
 "E0B0 D9 E8 DD 96 01 5F 30 0C ED 44 5F 3E 2F 90 E6 1F",
 "E0C0 47 AF 91 4F 21 8C E0 7E E5 D5 C5 21 00 00 5A 54",
 "E0D0 06 07 0F 30 01 19 EB 29 EB 10 F7 C1 D1 D5 CD 23",
 "E0E0 DD ED 52 D1 E1 30 09 78 81 47 23 7D FE 93 20 D7",
 "E0F0 DD 7E 06 E6 1F 4F 3A DE E8 E6 1F B9 28 0A 30 02",
 "E100 C6 20 D6 10 81 0F E6 1F 90 57 78 92 E6 1F B9 D5",
 "E110 CC 3C E1 D1 DD 34 06 CB 62 C0 DD 35 06 DD 35 06",
 "E120 C9 00 3A D8 E8 B7 C8 DD 21 E0 E8 DD 7E 00 B7 C4",
 "E130 96 E0 DD 7D C6 08 DD 6F 20 F1 C9 00 21 D3 E8 3E",
 "E140 18 BE 38 01 77 CD D0 E1 EB 79 D6 08 4F CD D0 E1",
 "E150 79 C6 08 4F CB 3B CB 3D C3 9B E1 02 FE 03 FE 04",
 "E160 FE 04 FF 05 FF 05 00 06 00 06 01 06 02 06 03 06",
 "E170 04 06 05 06 06 05 06 04 06 03 06 02 06 01 06 00",
 "E180 06 FF 06 FE 06 FE 05 FE 04 FE 03 FE 02 FE 01 FE",
 "E190 00 FF 00 FF FF 00 FF 00 FE 01 FE DD CB 07 D6 79",
 "E1A0 44 4A 55 E6 1F 87 C6 5B 6F 26 E1 7E 23 6E DD 66",
 "E1B0 00 84 C8 67 DD 7E 01 85 6F C3 E2 E2 00 55 1D 12",
 "E1C0 0D 0B 09 09 08 08 09 09 0B 0D 12 1D 55 00 00 00",
 "E1D0 16 01 CB 61 28 02 16 FF 79 E6 0F C6 BD E5 6F 26",
 "E1E0 E1 5E E1 C9 00 00 00 21 D3 E8 3E 30 BE 38 01 77",
 "E1F0 23 23 35 CD D0 E1 EB 79 D6 08 4F CD D0 E1 79 C6",
 "E200 08 4F CB 3B CB 3B CB 3D CB 3D C3 9B E1 00 00 00",
 "E210 3A D8 E8 B7 C8 DD 21 D8 E8 DD 35 07 C0 DD 36 07",
 "E220 20 3A D0 E8 B7 28 3A DB 00 CB 67 20 03 DD 35 06",
 "E230 E6 40 20 03 DD 34 06 3A D5 E8 FE 06 D8 DD 7E 06",
 "E240 D6 04 4F 06 05 DB 09 0F 0F C5 F5 D4 E7 E1 F1 C1",
 "E250 0C 0C 10 F4 0F D8 79 C6 0A 4F 21 D5 E8 35 C3 3C",
 "E260 E1 0E 00 DB 01 0F 30 14 0E 10 DB 00 CB 57 28 0C",
 "E270 0E 18 CB 67 28 06 0E 08 E6 40 20 11 DD 7E 06 91",
 "E280 DD 34 06 E6 10 20 06 DD 35 06 DD 35 06 3A D5 E8",
 "E290 FE 02 D8 DD 4E 06 DB 09 E6 40 CC E7 E1 DB 00 0F",
 "E2A0 D8 21 D5 E8 35 DD 7E 06 C6 10 4F C3 3C E1 00 00",
 "E2B0 00 FD 66 00 FD 6E 01 7C D6 02 FE 9C 30 1C 7D D6",
 "E2C0 04 FE 5C 30 15 CD 43 E4 CD 32 E4 79 AE 77 2F A1",
 "E2D0 C8 FD 66 00 FD 6E 01 C3 3D E3 FD 36 00 00 C9 00",
 "E2E0 00 00 FD E5 FD 21 00 E9 FD 7E 00 B7 28 0B FD 7D",
 "E2F0 C6 08 FD 6F 20 F2 FD E1 C9 FD 74 00 FD 75 01 FD",
 "E300 70 02 FD 71 03 FD 72 04 FD 73 05 FD 72 06 FD 73",
 "E310 07 D9 CD 4B DF D9 FD E1 C9 00 00 00 16 06 01 FF",
 "E320 16 06 FF 01 06 16 01 01 06 16 FF FF 07 0D 01 FF",
 "E330 07 0D FF 01 0D 07 01 01 0D 07 FF FF 00 E5 CD 43",
 "E340 E4 54 26 78 CD 32 E4 7A 2B 2B BE 38 FB 23 7E E6",
 "E350 07 28 37 87 87 87 C6 D0 DD E5 DD 6F DD 26 E8 FE",
 "E360 D8 28 04 21 D2 E8 34 CD C5 E3 DD 36 00 00 DD E1",
 "E370 21 1C E3 56 23 5E 23 46 23 4E 23 E3 CD E2 E2 E3",
 "E380 7D FE 3C 20 EE 3E FF 32 D3 E8 E1 C9 00 11 00 0D",
 "E390 19 06 FF 11 88 FF 04 19 38 FC 7D C6 78 67 3E 0F",
 "E3A0 B9 CB 14 14 CB 03 79 A3 28 F9 78 87 87 82 6F C9",
 "E3B0 00 00 00 E5 23 23 7E B7 28 06 2B 2B 77 23 18 F4",
 "E3C0 E1 C9 00 00 00 CD D2 E4 E5 CD 32 E4 0E 02 06 03",
 "E3D0 1A AE 77 23 13 10 F9 79 01 75 00 09 4F 0D 20 EE",
 "E3E0 E1 E5 CD E7 E3 E1 2C 26 78 CD 32 E4 CD 12 E4 2B",
 "E3F0 BE 28 06 2B 34 35 20 F7 C9 3E B8 77 23 23 BE 2B",
 "E400 CC B3 E3 2B 2B 2B 7E 23 FE B8 CA B3 E3 C9 00 00",
 "E410 00 00 DD 7D 0F 0F 0F C6 5E FE 79 C0 3E 99 C9 00",
 "E420 23 23 E5 7E B7 28 06 70 41 4F 23 18 F6 E1 C9 00",
 "E430 00 00 7D 6C 26 F3 B7 C8 D5 11 78 00 19 3D 20 FC",
 "E440 D1 C9 00 0E 01 CB 3C 30 02 0E 10 CB 3D 30 02 CB",
 "E450 01 CB 3D D0 CB 01 CB 01 C9 CD D2 E4 E5 CD 32 E4",
 "E460 D9 0E 00 D9 0E 02 06 03 1A AE 77 2F EB A6 EB 28",
 "E470 05 E5 D9 E1 4F D9 23 13 10 EE 79 01 75 00 09 4F",
 "E480 0D 20 E3 E1 D9 0C 0D D9 28 05 CD CB DC 30 2F E5",
 "E490 CD 95 E4 E1 2C 54 26 78 CD 32 E4 7A C6 03 2B 2B",
 "E4A0 BE 38 FB 28 0A 47 0E B8 23 7E 2B B9 CC 20 E4 CD",
 "E4B0 12 E4 4F 2B 2B 42 7E B8 DA 20 E4 23 71 C9 D9 CD",
 "E4C0 8D E3 E5 DD 7D C3 58 E3 00 00 00 00 00 00 00 00",
 "E4D0 00 00 DD 66 00 DD 6E 01 CD 43 E4 3E 94 C6 06 CB",
 "E4E0 09 30 FA 5F 16 E5 C9 00 00 00 7A B3 1B 20 FB C9",
 "E4F0 00 00 00 00 00 00 00 00 02 02 04 01 01 20 27 0B",
 "E500 20 00 00 FF FF 20 27 1B 40 00 00 01 01 20 27 0B",
 "E510 40 00 00 01 FF 27 20 03 40 00 00 FF 01 27 20 13",
 "E520 40 00 00 00 21 F3 E4 11 D2 E8 01 2E 00 ED B0 EB",
 "E530 11 08 00 06 20 72 19 10 FC 3E 0C DF 21 00 F3 36",
 "E540 80 06 4E 23 36 88 10 FB 23 36 08 11 78 00 06 17",
 "E550 19 36 0F 10 FB 19 36 01 06 4E 2B 36 11 10 FB 2B",
 "E560 36 10 11 88 FF 06 17 19 36 F0 10 FB DD 21 D8 E8",
 "E570 C3 59 E4 00 00 00 9F 99 01 9F 99 01 9F 11 0F 1F",
 "E580 31 0F 9F F9 08 F8 F9 08 77 00 00 77 44 04 77 44",
 "E590 07 47 44 07 77 00 07 77 00 07 A4 A9 04 01 01 01",
 "E5A0 48 42 08 12 13 02 80 84 00 25 26 05 00 08 00 5A",
 "E5B0 5C 0A 40 9A 4A 10 10 10 80 24 84 20 31 21 00 48",
 "E5C0 08 50 62 52 00 80 00 A0 C5 A5 00 00 00 00 00 00",
 "E5D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 0F",
 "E5E0 E4 45 44 88 00 00 00 00 00 00 00 80 48 44 E5 04",
 "E5F0 5F 0D 00 01 00 01 00 00 11 42 08 00 00 48 12 01",
 "E600 00 00 01 00 11 01 00 00 00 00 00 00 00 00 61 08",
 "E610 68 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
 "E620 00 00 00 0F 0F 00 00 00 00 00 00 00 00 00 00 00",
 "E630 00 00 00 00 00 00 00 83 03 00 00 00 00 00 00 00",
 "E640 00 00 00 00 00 00 00 00 00 00 A0 C5 A5 00 00 00",
 "E650 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
 "E660 00 00 00 00 00 00 00 00 00 00 AE 0A 8E 0E 2E 0E", //SHOT: FGHJK SPACE
 "E670 E2 02 04 00 00 AE 02 00 2E 0A 00 8E 0E 00 08 0E", // E66A-E6B3 37bytes*2
 "E680 00 CE 02 00 00 AE 0A AE 0E 2C 0C 2E 02 AE 02 22",
 "E690 03 03 03 23 03 30 00 01 00 00 03 00 00 23 03 00",
 "E6A0 03 03 00 23 03 00 03 03 00 00 22 03 03 00 13 03",
 "E6B0 23 02 23 02 00 00 00 00 00 00 00 00 00 5F 0F 00",
 "E6C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
 "E6D0 00 D1 01 00 00 00 00 00 00 00 00 00 00 00 00 00",
 "E6E0 00 00 00 00 00 F0 00 00 00 00 00 00 00 00 00 00",
 "E6F0 00 00 00 8E 0E 88 88 88 80 24 84 80 88 88 08 AE",
 "E700 0A 00 00 00 00 00 00 00 03 00 00 00 20 B1 21 00",
 "E710 00 00 00 23 03 00 00 00 00 00 00 00 00 00 00 00",
 "E720 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
 "E730 00 00 00 00 00 54 0C 00 00 00 00 00 00 00 00 00",
 "E740 00 00 00 00 00 00 00 00 00 57 05 00 00 00 00 00",
 "E750 00 00 00 00 AE 0A 8E 0E 2E 0E E2 02 04 00 AE 0A",
 "E760 AE 0E 2C 0C 2E 02 AE 02 00 00 2E 0E 1E 20 0E E0",
 "E770 E2 E0 2C E0 2A E0 E0 10 0E 22 03 03 03 23 03 30",
 "E780 00 01 00 22 03 03 00 13 03 23 02 23 02 06 00 23",
 "E790 03 43 20 23 30 32 30 30 30 22 00 03 40 03 00 3E",
 "E7A0 0C DF 21 98 18 22 53 F3 22 CB F3 21 AB F5 11 78",
 "E7B0 00 06 0C 36 78 19 10 FB 06 08 36 F8 19 10 FB 21",
 "E7C0 76 E5 11 02 F3 01 12 00 ED B0 11 7A F3 01 12 00",
 "E7D0 ED B0 21 C8 E8 7E FE 72 20 10 11 A5 F3 01 16 00",
 "E7E0 ED B8 11 2D F3 01 16 00 ED B8 CD B6 DD 3A D2 E8",
 "E7F0 B7 28 48 FE 83 38 02 3E 82 4F 21 59 F5 06 1A EB",
 "E800 21 A6 E5 79 C6 06 4F ED A0 ED A0 ED A0 7B C6 75",
 "E810 5F 30 01 14 ED A0 ED A0 ED A0 EB CD FC DC 11 00",
 "E820 20 CD EA E4 D3 40 11 00 10 CD EA E4 0D 28 0C 11",
 "E830 88 FF 19 10 CA 11 A2 00 19 18 C2 21 CA E5 DB 08",
 "E840 E6 20 32 D0 E8 20 03 21 B4 E6 3E 08 11 02 FB 01",
 "E850 14 00 ED B0 EB 01 64 00 09 EB 3D 20 F2 11 88 FC",
 "E860 01 25 00 ED B0 11 00 FD 01 25 00 ED B0 21 D0 E8",
 "E870 DB 08 E6 20 AE 20 C4 DB 01 07 38 F4 C9 00 21 00",
 "E880 00 22 D1 E8 21 5A EA 11 05 00 01 19 50 72 23 36",
 "E890 B8 19 72 23 36 FF 19 CB 8E C3 3A 09 00 4C 08 0C",
 "E8A0 0C 00 C0 48 00 C0 C0 80 84 C0 44 C0 C0 C0 C4 C0",
 "E8B0 48 80 84 57 02 61 01 00 70 61 40 10 16 70 72 50",
 "E8C0 75 70 74 70 74 70 61 70 72 00 00 DA DF 00 00 00"
].forEach(function(v){
  var t=v.split(/ +/);
  var a=parseInt(t[0],16);
  var i;
  for(i=1;i<t.length;i++)
    pc8001.memory[a+i-1]=parseInt(t[i],16);
});
pc8001.initDisplay80x25=function(svg){
  var d=pc8001.display=new Object();
  var t=d.textArray=new Array(80);
  var x,y,e;
  d.svg=svg;
  d.colors=new Array(256);
  d.colors.fill("none");
  for(x=0;x<8;x++){
    d.colors[0x18+x]="#000000";
    d.colors[0x38+x]="#0000ff";
    d.colors[0x58+x]="#ff0000";
    d.colors[0x78+x]="#ff00ff";
    d.colors[0x98+x]="#00ff00";
    d.colors[0xb8+x]="#00ffff";
    d.colors[0xd8+x]="#ffff00";
    d.colors[0xf8+x]="#ffffff";
  }
  d.colors[0x00]="#00ffff";
  for(x=0;x<80;x++)
    t[x]=new Array(25);
  d.start=d.end=0xf300;
  for(y=0;y<25;y++){
    for(x=0;x<80;x++){
      pc8001.memory[d.end]=0;
      d.end++;
      t[x][y]=new Object();
      e=document.createElementNS("http://www.w3.org/2000/svg","text");
      e.setAttribute("y",x*2);
      e.setAttribute("x",y*4);
      e.setAttribute("font-family","monospace");
      e.setAttribute("font-size",2.1);
      e.setAttribute("transform","matrix(0 1 1 0 1.8 0)");
      e.setAttribute("fill","#00ffff");
      e.setAttribute("stroke","none");
      d.svg.appendChild(e);
      t[x][y].element=e;
      t[x][y].attribute="#00ffff";
    }
    pc8001.memory[d.end]=0;
    d.end++;
    for(x=1;x<39;x++){
      pc8001.memory[d.end]=(x%2==0)?80:0xb8;
      d.end++;
    }
    pc8001.memory[d.end]=0;
    d.end++;
  }
  d.end--;
  e=[[0x3000,0x2598,0x259d,0x2580],
     [0x2596,0x258c,0x259e,0x259b],
     [0x2597,0x259a,0x2590,0x259c],
     [0x2584,0x2599,0x259f,0x2588]];
  d.blocks=new Array(256);
  d.blocks[0]="";
  for(x=1;x<256;x++){
    if((x&0xcc)>0)
      d.blocks[x]=String.fromCodePoint(e[(x>>4)&3][x&3],e[(x>>6)&3][(x>>2)&3]);
    else
      d.blocks[x]=String.fromCodePoint(e[(x>>4)&3][x&3]);
  }
  pc8001.writeMemory(d.start,0xff);
  y=t[0][0].element.getBBox();
  pc8001.writeMemory(d.start,0);
  if(y.width<4){
    e[0][0]=0x2003;
    for(x=1;x<256;x++){
      if((x&0xcc)>0)
        d.blocks[x]=String.fromCodePoint(e[(x>>4)&3][x&3],e[(x>>6)&3][(x>>2)&3]);
      else
        d.blocks[x]=String.fromCodePoint(e[(x>>4)&3][x&3]);
    }
    e=4/y.width;
    for(y=0;y<25;y++){
      for(x=0;x<80;x++){
        t[x][y].element.setAttribute("x",y*4/e);
        t[x][y].element.setAttribute("transform","matrix(0 "+e+" 1 0 1.8 0)");
      }
    }
  }
}
pc8001.writeMemory=function(address,data){
  var t=pc8001.memory[address];
  var d=pc8001.display;
  var x,y,i,j;
  pc8001.memory[address]=data;
  if(address<d.start||d.end<address||t==data)
    return;
  x=(address-d.start)%120;
  y=Math.floor((address-d.start)/120);
  if(x<80){
    d.textArray[x][y].element.textContent=d.blocks[data];
    return;
  }
  i=d.start+80+y*120;
  j="#00ffff";
  for(x=0;x<80;x++){
    if(pc8001.memory[i]==x){
      i++;
      j=d.colors[pc8001.memory[i]];
      i++;
    }
    t=d.textArray[x][y];
    if(t.attribute!=j){
      t.element.setAttribute("fill",j);
      t.attribute=j;
    }
  }
}
pc8001.inports=new Array(256);
pc8001.inports.fill(0xff);
pc8001.keymap=new Array(256);
pc8001.keymap.fill([-1,0xff]);
pc8001.keymap[13]=[1,0x7f];                    // enter-key
pc8001.keymap[100]=pc8001.keymap[37]=[0,0xef]; // ten-key 4 = leftarrow
pc8001.keymap[102]=pc8001.keymap[39]=[0,0xbf]; // ten-key 6 = rightarrow
pc8001.keymap[32]=[9,0xbf];                    // space-key
pc8001.keymap[112]=pc8001.keymap[70]=[9,0xfd]; // function-key F1 = key F
pc8001.keymap[113]=pc8001.keymap[71]=[9,0xfb]; // function-key F2 = key G
pc8001.keymap[114]=pc8001.keymap[72]=[9,0xf7]; // function-key F3 = key H
pc8001.keymap[115]=pc8001.keymap[74]=[9,0xef]; // function-key F4 = key J
pc8001.keymap[116]=pc8001.keymap[75]=[9,0xdf]; // function-key F5 = key K
pc8001.keydown=function(event){
  var k=pc8001.keymap[event.keyCode]
  if(k[0]<0)
    return;
  pc8001.inports[k[0]]&=k[1];
}
pc8001.keyup=function(event){
  var k=pc8001.keymap[event.keyCode]
  if(k[0]<0)
    return;
  pc8001.inports[k[0]]|=(k[1]^0xff);
  if(pc8001.keybeep==0){
    pc8001.keybeep=1;
    pc8001.beep.gain.value=0;
    pc8001.oscillator.start();
  }
}
pc8001.z80=new Object();
pc8001.z80.regs={"PC":0,"SP":0,"A":0,"B":0,"C":0,"D":0,"E":0,"H":0,"L":0,"J":0,"X":0,"K":0,"Y":0,"a":0,"b":0,"c":0,"d":0,"e":0,"h":0,"l":0};
pc8001.z80.flags={"Z":0,"C":0,"z":0,"c":0};
pc8001.z80.mnemonics={};
pc8001.z80.halt=pc8001.z80.states=0;
pc8001.z80.ops=new Array(256);
pc8001.z80.ops.fill(["UNDEF","",0]);
pc8001.z80.ops[0xcb]=new Array(257);
pc8001.z80.ops[0xcb].fill(["UNDEF","CB",0]);
pc8001.z80.ops[0xcb][256]=-1;
pc8001.z80.ops[0xdd]=new Array(257);
pc8001.z80.ops[0xdd].fill(["UNDEF","DD",0]);
pc8001.z80.ops[0xdd][256]=-1;
pc8001.z80.ops[0xed]=new Array(257);
pc8001.z80.ops[0xed].fill(["UNDEF","ED",0]);
pc8001.z80.ops[0xed][256]=-1;
pc8001.z80.ops[0xfd]=new Array(257);
pc8001.z80.ops[0xfd].fill(["UNDEF","FD",0]);
pc8001.z80.ops[0xfd][256]=-1;
pc8001.z80.mnemonics["UNDEF"]=function(v,m){
  pc8001.z80.regs["PC"]=(pc8001.z80.regs["PC"]+0xffff)&0xffff;
  pc8001.z80.halt=1;
  console.log(performance.now()-pc8001.z80.millitimer,"milliseconds");
  console.log(pc8001.z80.states,"states");
  console.log(m[0],m[1],v.toString(16).toUpperCase().padStart(2,"0"));
  Object.keys(pc8001.z80.regs).forEach(function(v){
    console.log(" reg",v,pc8001.z80.regs[v].toString(16).toUpperCase().padStart(v.length*2,"0"));
  });
  console.log(" flags",pc8001.z80.flags);
}
pc8001.params=["B","C","D","E","H","L","(HL)","A"];
pc8001.params.forEach(function(v,i,a){
  var j;
  for(j=0;j<8;j++)
    pc8001.z80.ops[i*8+j+0x40]=["LD",v,a[j],(i==6||j==6)?7:4];
  pc8001.z80.ops[i*8+4]=["INC",v,(i==6)?11:4];
  pc8001.z80.ops[i*8+5]=["DEC",v,(i==6)?11:4];
  pc8001.z80.ops[i*8+6]=["LD",v,"n",(i==6)?10:7];
  pc8001.z80.ops[i+0x80]=["ADD","A",v,(i==6)?7:4];
  pc8001.z80.ops[i+0x90]=["SUB","A",v,(i==6)?7:4];
  pc8001.z80.ops[i+0xa0]=["AND","A",v,(i==6)?7:4];
  pc8001.z80.ops[i+0xa8]=["XOR","A",v,(i==6)?7:4];
  pc8001.z80.ops[i+0xb0]=["OR","A",v,(i==6)?7:4];
  pc8001.z80.ops[i+0xb8]=["CP","A",v,(i==6)?7:4];
  if(i!=6){
    pc8001.z80.ops[0xdd][i*8+0x46]=["LD",v,"(JX+d)",19];
    pc8001.z80.ops[0xdd][i+0x70]=["LD","(JX+d)",v,19];
    pc8001.z80.ops[0xdd][i*8+0x44]=["LD",v,"J",8];
    pc8001.z80.ops[0xdd][i*8+0x45]=["LD",v,"X",8];
    pc8001.z80.ops[0xdd][i+0x60]=["LD","J",v,8];
    pc8001.z80.ops[0xdd][i+0x68]=["LD","X",v,8];
    pc8001.z80.ops[0xfd][i*8+0x46]=["LD",v,"(KY+d)",19];
    pc8001.z80.ops[0xfd][i+0x70]=["LD","(KY+d)",v,19];
    pc8001.z80.ops[0xfd][i*8+0x44]=["LD",v,"K",8];
    pc8001.z80.ops[0xfd][i*8+0x45]=["LD",v,"Y",8];
    pc8001.z80.ops[0xfd][i+0x60]=["LD","K",v,8];
    pc8001.z80.ops[0xfd][i+0x68]=["LD","Y",v,8];
    pc8001.z80.ops[0xed][i*8+0x40]=["IN",v,"(C)",12];
    pc8001.z80.ops[0xed][i*8+0x41]=["OUT","(C)",v,12];
  }
  pc8001.z80.ops[0xcb][i+0x00]=["RLC",v,(i==6)?15:8];
  pc8001.z80.ops[0xcb][i+0x08]=["RRC",v,(i==6)?15:8];
  pc8001.z80.ops[0xcb][i+0x10]=["RL",v,(i==6)?15:8];
  pc8001.z80.ops[0xcb][i+0x38]=["SRL",v,(i==6)?15:8];
  for(j=0;j<8;j++){
    pc8001.z80.ops[0xcb][i+j*8+0x40]=["BIT",j,v,(i==6)?12:8];
    pc8001.z80.ops[0xcb][i+j*8+0x80]=["RES",j,v,(i==6)?15:8];
    pc8001.z80.ops[0xcb][i+j*8+0xc0]=["SET",j,v,(i==6)?15:8];
  }
});
pc8001.z80.ops[0x76]=["HALT","",4];
pc8001.z80.mnemonics["HALT"]=pc8001.z80.mnemonics["UNDEF"];
pc8001.z80.ops[0x02]=["LD","(BC)","A",7];
pc8001.z80.ops[0x0a]=["LD","A","(BC)",7];
pc8001.z80.ops[0x12]=["LD","(DE)","A",7];
pc8001.z80.ops[0x1a]=["LD","A","(DE)",7];
pc8001.z80.ops[0x32]=["LD","(nn)","A",13];
pc8001.z80.ops[0x3a]=["LD","A","(nn)",13];
pc8001.z80.ops[0xdd][0x26]=["LD","J","n",11];
pc8001.z80.ops[0xdd][0x2e]=["LD","X","n",11];
pc8001.z80.ops[0xdd][0x36]=["LD","(JX+d)","n",19];
pc8001.z80.ops[0xdd][0x64]=["LD","J","J",8];
pc8001.z80.ops[0xdd][0x65]=["LD","J","X",8];
pc8001.z80.ops[0xdd][0x6c]=["LD","X","J",8];
pc8001.z80.ops[0xdd][0x6d]=["LD","X","X",8];
pc8001.z80.ops[0xfd][0x26]=["LD","K","n",11];
pc8001.z80.ops[0xfd][0x2e]=["LD","Y","n",11];
pc8001.z80.ops[0xfd][0x36]=["LD","(KY+d)","n",19];
pc8001.z80.ops[0xfd][0x64]=["LD","K","K",8];
pc8001.z80.ops[0xfd][0x65]=["LD","K","Y",8];
pc8001.z80.ops[0xfd][0x6c]=["LD","Y","K",8];
pc8001.z80.ops[0xfd][0x6d]=["LD","Y","Y",8];
pc8001.z80.mnemonics["LD"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var a=-1;
  var b,c;
  switch(m[1].length){
    case 4:
      if(m[1]=="(nn)"){
        a=pc8001.memory[pc]+pc8001.memory[(pc+1)&0xffff]*256;
        pc8001.z80.regs["PC"]=pc=(pc+2)&0xffff;
      }
      else
        a=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      break;
    case 6:
      a=pc8001.memory[pc];
      pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      a&=0xffff;
  }
  switch(m[2].length){
    case 1:
      if(m[2]=="n"){
        c=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        c=pc8001.z80.regs[m[2]];
      break;
    case 4:
      if(m[2]=="(nn)"){
        b=pc8001.memory[pc]+pc8001.memory[(pc+1)&0xffff]*256;
        pc8001.z80.regs["PC"]=pc=(pc+2)&0xffff;
      }
      else
        b=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      c=pc8001.memory[b];
      break;
    case 6:
      b=pc8001.memory[pc];
      pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      if(b>0x7f)
        b+=0xff00;
      b+=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      c=pc8001.memory[b&0xffff];
  }
  if(a<0)
    pc8001.z80.regs[m[1]]=c;
  else
    pc8001.writeMemory(a,c);
}
pc8001.z80.ops[0x01]=["LD16","BC","nn",10];
pc8001.z80.ops[0x11]=["LD16","DE","nn",10];
pc8001.z80.ops[0x21]=["LD16","HL","nn",10];
pc8001.z80.ops[0x22]=["LD16","(nn)","HL",16];
pc8001.z80.ops[0x2a]=["LD16","HL","(nn)",16];
pc8001.z80.ops[0x31]=["LD16","SP","nn",10];
pc8001.z80.ops[0xf9]=["LD16","SP","HL",6];
pc8001.z80.ops[0xed][0x43]=["LD16","(nn)","BC",20];
pc8001.z80.ops[0xed][0x4b]=["LD16","BC","(nn)",20];
pc8001.z80.ops[0xed][0x53]=["LD16","(nn)","DE",20];
pc8001.z80.ops[0xed][0x5b]=["LD16","DE","(nn)",20];
pc8001.z80.ops[0xdd][0x21]=["LD16","JX","nn",14];
pc8001.z80.ops[0xdd][0xf9]=["LD16","SP","JX",10];
pc8001.z80.ops[0xfd][0x21]=["LD16","KY","nn",14];
pc8001.z80.ops[0xfd][0xf9]=["LD16","SP","KY",10];
pc8001.z80.mnemonics["LD16"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var h,l,a;
  switch(m[2]){
    case "nn":
      l=pc8001.memory[pc];
      h=pc8001.memory[(pc+1)&0xffff];
      pc=pc8001.z80.regs["PC"]=(pc+2)&0xffff;
      break;
    case "(nn)":
      a=pc8001.memory[pc]+pc8001.memory[(pc+1)&0xffff]*256;
      pc=pc8001.z80.regs["PC"]=(pc+2)&0xffff;
      l=pc8001.memory[a];
      h=pc8001.memory[(a+1)&0xffff];
      break;
    default:
      h=pc8001.z80.regs[m[2].substr(0,1)];
      l=pc8001.z80.regs[m[2].substr(1)];
  }
  switch(m[1]){
    case "(nn)":
      a=pc8001.memory[pc]+pc8001.memory[(pc+1)&0xffff]*256;
      pc=pc8001.z80.regs["PC"]=(pc+2)&0xffff;
      pc8001.writeMemory(a,l);
      pc8001.writeMemory((a+1)&0xffff,h);
      return;
    case "SP":
      pc8001.z80.regs["SP"]=h*256+l;
      return;
    default:
      pc8001.z80.regs[m[1].substr(0,1)]=h;
      pc8001.z80.regs[m[1].substr(1)]=l;
  }
}
pc8001.z80.ops[0x08]=["EX","AF","af",4];
pc8001.z80.ops[0xe3]=["EX","(SP)","HL",19];
pc8001.z80.ops[0xeb]=["EX","DE","HL",4];
pc8001.z80.mnemonics["EX"]=function(v,m){
  var a,t;
  if(m[1]=="(SP)"){
    a=pc8001.z80.regs["SP"]
    t=pc8001.memory[a];
    pc8001.writeMemory(a,pc8001.z80.regs[m[2].substr(1)]);
    pc8001.z80.regs[m[2].substr(1)]=t;
    a=(a+1)&0xffff;
    t=pc8001.memory[a];
    pc8001.writeMemory(a,pc8001.z80.regs[m[2].substr(0,1)]);
    pc8001.z80.regs[m[2].substr(0,1)]=t;
    return;
  }
  t=pc8001.z80.regs[m[1].substr(0,1)];
  pc8001.z80.regs[m[1].substr(0,1)]=pc8001.z80.regs[m[2].substr(0,1)];
  pc8001.z80.regs[m[2].substr(0,1)]=t;
  if(m[1].substr(1)=="F"){
    a=["Z","C"];
    a.forEach(function(v){
      var b=pc8001.z80.flags[v];
      pc8001.z80.flags[v]=pc8001.z80.flags[v.toLowerCase()];
      pc8001.z80.flags[v.toLowerCase()]=b;
    });
    return;
  }
  t=pc8001.z80.regs[m[1].substr(1)];
  pc8001.z80.regs[m[1].substr(1)]=pc8001.z80.regs[m[2].substr(1)];
  pc8001.z80.regs[m[2].substr(1)]=t;
}
pc8001.z80.ops[0xd9]=["EXX",4];
pc8001.z80.mnemonics["EXX"]=function(v,m){
  var r=["B","C","D","E","H","L"];
  r.forEach(function(v){
    var t=pc8001.z80.regs[v];
    pc8001.z80.regs[v]=pc8001.z80.regs[v.toLowerCase()];
    pc8001.z80.regs[v.toLowerCase()]=t;
  });
}
pc8001.z80.ops[0xdd][0x34]=["INC","(JX+d)",23];
pc8001.z80.ops[0xfd][0x34]=["INC","(KY+d)",23];
pc8001.z80.mnemonics["INC"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var a=-1;
  var c;
  switch(m[1].length){
    case 1:
      c=pc8001.z80.regs[m[1]];
      break;
    case 4:
      a=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      c=pc8001.memory[a];
      break;
    case 6:
      a=pc8001.memory[pc];
      pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      a&=0xffff;
      c=pc8001.memory[a];
  }
  c=(c+1)&0xff;
  pc8001.z80.flags["Z"]=(c==0)?1:0;
  if(a<0)
    pc8001.z80.regs[m[1]]=c;
  else
    pc8001.writeMemory(a,c);
}
pc8001.z80.ops[0x03]=["INC16","BC",6];
pc8001.z80.ops[0x13]=["INC16","DE",6];
pc8001.z80.ops[0x23]=["INC16","HL",6];
pc8001.z80.ops[0x33]=["INC16","SP",6];
pc8001.z80.mnemonics["INC16"]=function(v,m){
  var c;
  if(m[1]=="SP")
    pc8001.z80.regs["SP"]=(pc8001.z80.regs["SP"]+1)&0xffff;
  else{
    pc8001.z80.regs[m[1].substr(1)]=c=(pc8001.z80.regs[m[1].substr(1)]+1)&0xff;
    if(c==0)
      pc8001.z80.regs[m[1].substr(0,1)]=(pc8001.z80.regs[m[1].substr(0,1)]+1)&0xff;
  }
}
pc8001.z80.ops[0xdd][0x35]=["DEC","(JX+d)",23];
pc8001.z80.ops[0xfd][0x35]=["DEC","(KY+d)",23];
pc8001.z80.mnemonics["DEC"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var a=-1;
  var c;
  switch(m[1].length){
    case 1:
      c=pc8001.z80.regs[m[1]];
      break;
    case 4:
      a=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      c=pc8001.memory[a];
      break;
    case 6:
      a=pc8001.memory[pc];
      pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      a&=0xffff;
      c=pc8001.memory[a];
  }
  c=(c+0xff)&0xff;
  pc8001.z80.flags["Z"]=(c==0)?1:0;
  if(a<0)
    pc8001.z80.regs[m[1]]=c;
  else
    pc8001.writeMemory(a,c);
}
pc8001.z80.ops[0x0b]=["DEC16","BC",6];
pc8001.z80.ops[0x1b]=["DEC16","DE",6];
pc8001.z80.ops[0x2b]=["DEC16","HL",6];
pc8001.z80.ops[0x3b]=["DEC16","SP",6];
pc8001.z80.mnemonics["DEC16"]=function(v,m){
  var c;
  if(m[1]=="SP")
    pc8001.z80.regs["SP"]=(pc8001.z80.regs["SP"]+0xffff)&0xffff;
  else{
    pc8001.z80.regs[m[1].substr(1)]=c=(pc8001.z80.regs[m[1].substr(1)]+0xff)&0xff;
    if(c==0xff)
      pc8001.z80.regs[m[1].substr(0,1)]=(pc8001.z80.regs[m[1].substr(0,1)]+0xff)&0xff;
  }
}
pc8001.z80.ops[0x09]=["ADD16","HL","BC",11];
pc8001.z80.ops[0x19]=["ADD16","HL","DE",11];
pc8001.z80.ops[0x29]=["ADD16","HL","HL",11];
pc8001.z80.ops[0x39]=["ADD16","HL","SP",11];
pc8001.z80.ops[0xdd][0x09]=["ADD16","JX","BC",15];
pc8001.z80.ops[0xdd][0x19]=["ADD16","JX","DE",15];
pc8001.z80.ops[0xdd][0x29]=["ADD16","JX","JX",15];
pc8001.z80.ops[0xdd][0x39]=["ADD16","JX","SP",15];
pc8001.z80.ops[0xfd][0x09]=["ADD16","KY","BC",15];
pc8001.z80.ops[0xfd][0x19]=["ADD16","KY","DE",15];
pc8001.z80.ops[0xfd][0x29]=["ADD16","KY","KY",15];
pc8001.z80.ops[0xfd][0x39]=["ADD16","KY","SP",15];
pc8001.z80.mnemonics["ADD16"]=function(v,m){
  var c;
  c=pc8001.z80.regs[m[1].substr(0,1)]*256+pc8001.z80.regs[m[1].substr(1)];
  if(m[2]=="SP")
    c+=pc8001.z80.regs["SP"];
  else
    c+=pc8001.z80.regs[m[2].substr(0,1)]*256+pc8001.z80.regs[m[2].substr(1)];
  if(c>0xffff){
    pc8001.z80.flags["C"]=1;
    c&=0xffff;
  }
  else
    pc8001.z80.flags["C"]=0;
  pc8001.z80.regs[m[1].substr(0,1)]=c>>8;
  pc8001.z80.regs[m[1].substr(1)]=c&0xff;
}
pc8001.z80.ops[0xc6]=["ADD","A","n",7];
pc8001.z80.ops[0xdd][0x86]=["ADD","A","(JX+d)",19];
pc8001.z80.ops[0xfd][0x86]=["ADD","A","(KY+d)",19];
pc8001.z80.mnemonics["ADD"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var c,a;
  switch(m[2].length){
    case 4:
      c=pc8001.memory[pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)]];
      break;
    case 6:
      a=pc8001.memory[pc];
      pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      a&=0xffff;
      c=pc8001.memory[a];
      break;
    default:
      if(m[2]=="n"){
        c=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        c=pc8001.z80.regs[m[2]];
  }
  c+=pc8001.z80.regs[m[1]];
  pc8001.z80.flags["C"]=(c>0xff)?1:0;
  c&=0xff;
  pc8001.z80.regs[m[1]]=c;
  pc8001.z80.flags["Z"]=(c==0)?1:0;
}
pc8001.z80.ops[0xed][0x44]=["NEG","A",8];
pc8001.z80.mnemonics["NEG"]=function(v,m){
  var c=(256-pc8001.z80.regs[m[1]])&0xff;
  pc8001.z80.regs[m[1]]=c;
  pc8001.z80.flags["Z"]=(c==0)?1:0;
  pc8001.z80.flags["C"]=(c==0)?0:1;
}
pc8001.z80.ops[0xd6]=["SUB","A","n",7];
pc8001.z80.ops[0xdd][0x96]=["SUB","A","(JX+d)",19];
pc8001.z80.ops[0xfd][0x96]=["SUB","A","(KY+d)",19];
pc8001.z80.mnemonics["SUB"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var c,a;
  switch(m[2].length){
    case 4:
      c=pc8001.memory[pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)]];
      break;
    case 6:
      a=pc8001.memory[pc];
      pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      a&=0xffff;
      c=pc8001.memory[a];
      break;
    default:
      if(m[2]=="n"){
        c=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        c=pc8001.z80.regs[m[2]];
  }
  c=pc8001.z80.regs[m[1]]-c;
  pc8001.z80.flags["C"]=(c<0)?1:0;
  c=(c+256)&0xff;
  pc8001.z80.regs[m[1]]=c;
  pc8001.z80.flags["Z"]=(c==0)?1:0;
}
pc8001.z80.ops[0xed][0x42]=["SBC16","HL","BC",15]
pc8001.z80.ops[0xed][0x52]=["SBC16","HL","DE",15]
pc8001.z80.ops[0xed][0x62]=["SBC16","HL","HL",15]
pc8001.z80.ops[0xed][0x72]=["SBC16","HL","SP",15]
pc8001.z80.mnemonics["SBC16"]=function(v,m){
  var c;
  c=pc8001.z80.regs[m[1].substr(0,1)]*256+pc8001.z80.regs[m[1].substr(1)];
  if(m[2]=="SP")
    c-=pc8001.z80.regs["SP"];
  else
    c-=pc8001.z80.regs[m[2].substr(0,1)]*256+pc8001.z80.regs[m[2].substr(1)];
  c-=pc8001.z80.flags["C"]
  if(c<0){
    pc8001.z80.flags["C"]=1;
    c=(c+65536)&0xffff;
  }
  else
    pc8001.z80.flags["C"]=0;
  pc8001.z80.regs[m[1].substr(0,1)]=c>>8;
  pc8001.z80.regs[m[1].substr(1)]=c&0xff;
  pc8001.z80.flags["Z"]=(c==0)?1:0;
}
pc8001.z80.ops[0xe6]=["AND","A","n",7];
pc8001.z80.mnemonics["AND"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var c;
  switch(m[2].length){
    case 4:
      c=pc8001.memory[pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)]];
      break;
    default:
      if(m[2]=="n"){
        c=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        c=pc8001.z80.regs[m[2]];
  }
  c&=pc8001.z80.regs[m[1]];
  pc8001.z80.regs[m[1]]=c;
  pc8001.z80.flags["Z"]=(c==0)?1:0;
  pc8001.z80.flags["C"]=0;
}
pc8001.z80.ops[0x2f]=["CPL","A",4];
pc8001.z80.mnemonics["CPL"]=function(v,m){
  pc8001.z80.regs[m[1]]^=0xff;
}
pc8001.z80.ops[0xee]=["XOR","A","n",7];
pc8001.z80.mnemonics["XOR"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var c;
  switch(m[2].length){
    case 4:
      c=pc8001.memory[pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)]];
      break;
    default:
      if(m[2]=="n"){
        c=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        c=pc8001.z80.regs[m[2]];
  }
  c^=pc8001.z80.regs[m[1]];
  pc8001.z80.regs[m[1]]=c;
  pc8001.z80.flags["Z"]=(c==0)?1:0;
  pc8001.z80.flags["C"]=0;
}
pc8001.z80.ops[0xf6]=["OR","A","n",7];
pc8001.z80.mnemonics["OR"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var c;
  switch(m[2].length){
    case 4:
      c=pc8001.memory[pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)]];
      break;
    default:
      if(m[2]=="n"){
        c=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        c=pc8001.z80.regs[m[2]];
  }
  c|=pc8001.z80.regs[m[1]];
  pc8001.z80.regs[m[1]]=c;
  pc8001.z80.flags["Z"]=(c==0)?1:0;
  pc8001.z80.flags["C"]=0;
}
pc8001.z80.ops[0xfe]=["CP","A","n",7];
pc8001.z80.mnemonics["CP"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var c;
  switch(m[2].length){
    case 4:
      c=pc8001.memory[pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)]];
      break;
    default:
      if(m[2]=="n"){
        c=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        c=pc8001.z80.regs[m[2]];
  }
  c=pc8001.z80.regs[m[1]]-c;
  pc8001.z80.flags["C"]=(c<0)?1:0;
  c=(c+256)&0xff;
  pc8001.z80.flags["Z"]=(c==0)?1:0;
}
pc8001.z80.ops[0xc2]=["JP","NZ","nn",10];
pc8001.z80.ops[0xc3]=["JP","","nn",10];
pc8001.z80.ops[0xca]=["JP","Z","nn",10];
pc8001.z80.ops[0xd2]=["JP","NC","nn",10];
pc8001.z80.ops[0xda]=["JP","C","nn",10];
pc8001.z80.ops[0xe9]=["JP","","(HL)",4];
pc8001.z80.mnemonics["JP"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var c=1;
  switch(m[1].length){
    case 1:
      c=pc8001.z80.flags[m[1]];
      break;
    case 2:
      c=1-pc8001.z80.flags[m[1].substr(1)];
  }
  if(c==0){
    if(m[2]=="nn")
      pc8001.z80.regs["PC"]=(pc+2)&0xffff;
    return;
  }
  switch(m[2].length){
    case 2:
      pc8001.z80.regs["PC"]=pc8001.memory[pc]+pc8001.memory[(pc+1)&0xffff]*256;
      return;
    case 4:
      pc8001.z80.regs["PC"]=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      return;
  }
}
pc8001.z80.ops[0x10]=["JR","DJNZ","e",13];
pc8001.z80.ops[0x18]=["JR","","e",12];
pc8001.z80.ops[0x20]=["JR","NZ","e",12];
pc8001.z80.ops[0x28]=["JR","Z","e",12];
pc8001.z80.ops[0x30]=["JR","NC","e",12];
pc8001.z80.ops[0x38]=["JR","C","e",12];
pc8001.z80.mnemonics["JR"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var c=1;
  switch(m[1].length){
    case 1:
      c=pc8001.z80.flags[m[1]];
      break;
    case 2:
      c=1-pc8001.z80.flags[m[1].substr(1)];
      break;
    case 4:
      pc8001.z80.regs["B"]=c=(pc8001.z80.regs["B"]+0xff)&0xff;
  }
  if(c==0){
    if(m[2]=="e")
      pc8001.z80.regs["PC"]=(pc+1)&0xffff;
    return;
  }
  c=pc8001.memory[pc];
  pc8001.z80.regs["PC"]=((c>0x7f)?pc+0xff01+c:pc+1+c)&0xffff;
}
pc8001.z80.ops[0xc4]=["CALL","NZ","nn",17];
pc8001.z80.ops[0xc7]=["CALL","","0000",11];
pc8001.z80.ops[0xcc]=["CALL","Z","nn",17];
pc8001.z80.ops[0xcd]=["CALL","","nn",17];
pc8001.z80.ops[0xcf]=["CALL","","0008",11];
pc8001.z80.ops[0xd4]=["CALL","NC","nn",17];
pc8001.z80.ops[0xd7]=["CALL","","0010",11];
pc8001.z80.ops[0xdc]=["CALL","C","nn",17];
pc8001.z80.ops[0xdf]=["CALL","","0018",11];
pc8001.z80.ops[0xe7]=["CALL","","0020",11];
pc8001.z80.ops[0xef]=["CALL","","0028",11];
pc8001.z80.ops[0xf7]=["CALL","","0030",11];
pc8001.z80.ops[0xff]=["CALL","","0038",11];
pc8001.z80.mnemonics["CALL"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var sp=pc8001.z80.regs["SP"];
  var c=1;
  switch(m[1].length){
    case 1:
      c=pc8001.z80.flags[m[1]];
      break;
    case 2:
      c=1-pc8001.z80.flags[m[1].substr(1)];
  }
  if(c==0){
    if(m[2]=="nn")
      pc8001.z80.regs["PC"]=(pc+2)&0xffff;
    return;
  }
  if(m[2]=="nn"){
    a=pc8001.memory[pc]+pc8001.memory[(pc+1)&0xffff]*256;
    pc=(pc+2)&0xffff;
  }
  else
    a=parseInt(m[2],16);
  pc8001.writeMemory((sp+0xffff)&0xffff,pc>>8);
  pc8001.z80.regs["SP"]=sp=(sp+0xfffe)&0xffff;
  pc8001.writeMemory(sp,pc&0xff);
  pc8001.z80.regs["PC"]=a;
}
pc8001.z80.ops[0xc0]=["RET","NZ",11];
pc8001.z80.ops[0xc8]=["RET","Z",11];
pc8001.z80.ops[0xc9]=["RET","",10];
pc8001.z80.ops[0xd0]=["RET","NC",11];
pc8001.z80.ops[0xd8]=["RET","C",11];
pc8001.z80.mnemonics["RET"]=function(v,m){
  var sp=pc8001.z80.regs["SP"];
  var c=1;
  switch(m[1].length){
    case 1:
      c=pc8001.z80.flags[m[1]];
      break;
    case 2:
      c=1-pc8001.z80.flags[m[1].substr(1)];
  }
  if(c==0)
    return;
  pc8001.z80.regs["PC"]=pc8001.memory[sp]+pc8001.memory[(sp+1)&0xffff]*256;
  pc8001.z80.regs["SP"]=(sp+2)&0xffff;
}
pc8001.z80.ops[0xc5]=["PUSH","BC",11];
pc8001.z80.ops[0xd5]=["PUSH","DE",11];
pc8001.z80.ops[0xe5]=["PUSH","HL",11];
pc8001.z80.ops[0xf5]=["PUSH","AF",11];
pc8001.z80.ops[0xdd][0xe5]=["PUSH","JX",15];
pc8001.z80.ops[0xfd][0xe5]=["PUSH","KY",15];
pc8001.z80.mnemonics["PUSH"]=function(v,m){
  var sp=pc8001.z80.regs["SP"];
  pc8001.writeMemory((sp+0xffff)&0xffff,pc8001.z80.regs[m[1].substr(0,1)]);
  pc8001.z80.regs["SP"]=sp=(sp+0xfffe)&0xffff;
  if(m[1]=="AF")
    pc8001.writeMemory(sp,pc8001.z80.flags["C"]+(pc8001.z80.flags["Z"]<<6));
  else
    pc8001.writeMemory(sp,pc8001.z80.regs[m[1].substr(1)]);
}
pc8001.z80.ops[0xc1]=["POP","BC",10];
pc8001.z80.ops[0xd1]=["POP","DE",10];
pc8001.z80.ops[0xe1]=["POP","HL",10];
pc8001.z80.ops[0xf1]=["POP","AF",10];
pc8001.z80.ops[0xdd][0xe1]=["POP","JX",14];
pc8001.z80.ops[0xfd][0xe1]=["POP","KY",14];
pc8001.z80.mnemonics["POP"]=function(v,m){
  var sp=pc8001.z80.regs["SP"];
  var c=pc8001.memory[sp];
  if(m[1]=="AF"){
    pc8001.z80.flags["Z"]=((c&0x40)==0)?0:1;
    pc8001.z80.flags["C"]=((c&1)==0)?0:1;
  }
  else
    pc8001.z80.regs[m[1].substr(1)]=c;
  pc8001.z80.regs[m[1].substr(0,1)]=pc8001.memory[(sp+1)&0xffff];
  pc8001.z80.regs["SP"]=(sp+2)&0xffff;
}
pc8001.z80.ops[0x07]=["RLCA",4];
pc8001.z80.mnemonics["RLCA"]=function(v,m){
  var t=pc8001.z80.regs["A"];
  var c=(t>0x7f)?1:0;
  pc8001.z80.regs["A"]=((t<<1)+c)&0xff;
  pc8001.z80.flags["C"]=c;
}
pc8001.z80.mnemonics["RLC"]=function(v,m){
  var a,t,c;
  switch(m[1].length){
    case 4:
      a=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      t=pc8001.memory[a];
      c=(t>0x7f)?1:0;
      t=((t<<1)+c)&0xff;
      pc8001.writeMemory(a,t);
      break;
    case 7:
      a=parseInt(m[1].substr(4,2),16);
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      a&=0xffff;
      t=pc8001.memory[a];
      c=(t>0x7f)?1:0;
      t=((t<<1)+c)&0xff;
      pc8001.writeMemory(a,t);
      break;
    default:
      t=pc8001.z80.regs[m[1]];
      c=(t>0x7f)?1:0;
      t=((t<<1)+c)&0xff;
      pc8001.z80.regs[m[1]]=t;
  }
  pc8001.z80.flags["C"]=c;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
}
pc8001.z80.ops[0x0f]=["RRCA",4];
pc8001.z80.mnemonics["RRCA"]=function(v,m){
  var t=pc8001.z80.regs["A"];
  var c=t&1;
  pc8001.z80.regs["A"]=(t>>1)+c*0x80;
  pc8001.z80.flags["C"]=c;
}
pc8001.z80.mnemonics["RRC"]=function(v,m){
  var a,t,c;
  switch(m[1].length){
    case 4:
      a=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      t=pc8001.memory[a];
      c=t&1;
      t=(t>>1)+c*0x80;
      pc8001.writeMemory(a,t);
      break;
    case 7:
      a=parseInt(m[1].substr(4,2),16);
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      a&=0xffff;
      t=pc8001.memory[a];
      c=t&1;
      t=(t>>1)+c*0x80;
      pc8001.writeMemory(a,t);
      break;
    default:
      t=pc8001.z80.regs[m[1]];
      c=t&1;
      t=(t>>1)+c*0x80;
      pc8001.z80.regs[m[1]]=t;
  }
  pc8001.z80.flags["C"]=c;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
}
pc8001.z80.ops[0x17]=["RLA",4];
pc8001.z80.mnemonics["RLA"]=function(v,m){
  var t=pc8001.z80.regs["A"];
  var c=(t>0x7f)?1:0;
  pc8001.z80.regs["A"]=((t<<1)+pc8001.z80.flags["C"])&0xff;
  pc8001.z80.flags["C"]=c;
}
pc8001.z80.mnemonics["RL"]=function(v,m){
  var a,t,c;
  switch(m[1].length){
    case 4:
      a=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      t=pc8001.memory[a];
      c=(t>0x7f)?1:0;
      t=((t<<1)+pc8001.z80.flags["C"])&0xff;
      pc8001.writeMemory(a,t);
      break;
    case 7:
      a=parseInt(m[1].substr(4,2),16);
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      a&=0xffff;
      t=pc8001.memory[a];
      c=(t>0x7f)?1:0;
      t=((t<<1)+pc8001.z80.flags["C"])&0xff;
      pc8001.writeMemory(a,t);
      break;
    default:
      t=pc8001.z80.regs[m[1]];
      c=(t>0x7f)?1:0;
      pc8001.z80.regs[m[1]]=t=((t<<1)+pc8001.z80.flags["C"])&0xff;
  }
  pc8001.z80.flags["C"]=c;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
}
pc8001.z80.ops[0x1f]=["RRA",4];
pc8001.z80.mnemonics["RRA"]=function(v,m){
  var t=pc8001.z80.regs["A"];
  pc8001.z80.regs["A"]=(t>>1)+pc8001.z80.flags["C"]*0x80;
  pc8001.z80.flags["C"]=t&1;
}
pc8001.z80.mnemonics["SRL"]=function(v,m){
  var a,t;
  switch(m[1].length){
    case 4:
      a=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      t=pc8001.memory[a];
      pc8001.writeMemory(a,t>>1);
      break;
    case 7:
      a=parseInt(m[1].substr(4,2),16);
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
      a&=0xffff;
      t=pc8001.memory[a];
      pc8001.writeMemory(a,t>>1);
      break;
    default:
      t=pc8001.z80.regs[m[1]];
      pc8001.z80.regs[m[1]]=(t>>1);
  }
  pc8001.z80.flags["C"]=t&1;
  pc8001.z80.flags["Z"]=(t<2)?1:0;
}
pc8001.z80.mnemonics["BIT"]=function(v,m){
  var a,c;
  switch(m[2].length){
    case 4:
      a=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      c=pc8001.memory[a];
      break;
    case 7:
      a=parseInt(m[2].substr(4,2),16);
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      a&=0xffff;
      c=pc8001.memory[a];
      break;
    default:
      c=pc8001.z80.regs[m[2]];
  }
  pc8001.z80.flags["Z"]=((c&(1<<m[1]))==0)?1:0;
}
pc8001.z80.mnemonics["RES"]=function(v,m){
  var a;
  switch(m[2].length){
    case 1:
      pc8001.z80.regs[m[2]]&=(1<<m[1])^0xff;
      break;
    case 4:
      a=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      pc8001.writeMemory(a,pc8001.memory[a]&((1<<m[1])^0xff));
      break;
    case 7:
      a=parseInt(m[2].substr(4,2),16);
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      a&=0xffff;
      pc8001.writeMemory(a,pc8001.memory[a]&((1<<m[1])^0xff));
      break;
  }
}
pc8001.z80.mnemonics["SET"]=function(v,m){
  var a;
  switch(m[2].length){
    case 4:
      a=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      pc8001.writeMemory(a,pc8001.memory[a]|(1<<m[1]));
      break;
    case 7:
      a=parseInt(m[2].substr(4,2),16);
      if(a>0x7f)
        a+=0xff00;
      a+=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      a&=0xffff;
      pc8001.writeMemory(a,pc8001.memory[a]|(1<<m[1]));
      break;
    default:
      pc8001.z80.regs[m[2]]|=1<<m[1];
  }
}
pc8001.z80.ops[0xed][0xa0]=["LDI",16];
pc8001.z80.mnemonics["LDI"]=function(v,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var de=pc8001.z80.regs["D"]*256+pc8001.z80.regs["E"];
  var bc=pc8001.z80.regs["B"]*256+pc8001.z80.regs["C"];
  pc8001.writeMemory(de,pc8001.memory[hl]);
  hl=(hl+1)&0xffff;
  de=(de+1)&0xffff;
  bc=(bc+0xffff)&0xffff;
  pc8001.z80.regs["H"]=hl>>8;
  pc8001.z80.regs["L"]=hl&0xff;
  pc8001.z80.regs["D"]=de>>8;
  pc8001.z80.regs["E"]=de&0xff;
  pc8001.z80.regs["B"]=bc>>8;
  pc8001.z80.regs["C"]=bc&0xff;
}
pc8001.z80.ops[0xed][0xb0]=["LDIR",21];
pc8001.z80.mnemonics["LDIR"]=function(v,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var de=pc8001.z80.regs["D"]*256+pc8001.z80.regs["E"];
  var bc=pc8001.z80.regs["B"]*256+pc8001.z80.regs["C"];
  pc8001.writeMemory(de,pc8001.memory[hl]);
  hl=(hl+1)&0xffff;
  de=(de+1)&0xffff;
  bc=(bc+0xffff)&0xffff;
  pc8001.z80.regs["H"]=hl>>8;
  pc8001.z80.regs["L"]=hl&0xff;
  pc8001.z80.regs["D"]=de>>8;
  pc8001.z80.regs["E"]=de&0xff;
  pc8001.z80.regs["B"]=bc>>8;
  pc8001.z80.regs["C"]=bc&0xff;
  if(bc!=0)
    pc8001.z80.regs["PC"]=(pc8001.z80.regs["PC"]+0xfffe)&0xffff;
}
pc8001.z80.ops[0xed][0xa8]=["LDD",16];
pc8001.z80.mnemonics["LDD"]=function(v,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var de=pc8001.z80.regs["D"]*256+pc8001.z80.regs["E"];
  var bc=pc8001.z80.regs["B"]*256+pc8001.z80.regs["C"];
  pc8001.writeMemory(de,pc8001.memory[hl]);
  hl=(hl+0xffff)&0xffff;
  de=(de+0xffff)&0xffff;
  bc=(bc+0xffff)&0xffff;
  pc8001.z80.regs["H"]=hl>>8;
  pc8001.z80.regs["L"]=hl&0xff;
  pc8001.z80.regs["D"]=de>>8;
  pc8001.z80.regs["E"]=de&0xff;
  pc8001.z80.regs["B"]=bc>>8;
  pc8001.z80.regs["C"]=bc&0xff;
}
pc8001.z80.ops[0xed][0xb8]=["LDDR",21];
pc8001.z80.mnemonics["LDDR"]=function(v,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var de=pc8001.z80.regs["D"]*256+pc8001.z80.regs["E"];
  var bc=pc8001.z80.regs["B"]*256+pc8001.z80.regs["C"];
  pc8001.writeMemory(de,pc8001.memory[hl]);
  hl=(hl+0xffff)&0xffff;
  de=(de+0xffff)&0xffff;
  bc=(bc+0xffff)&0xffff;
  pc8001.z80.regs["H"]=hl>>8;
  pc8001.z80.regs["L"]=hl&0xff;
  pc8001.z80.regs["D"]=de>>8;
  pc8001.z80.regs["E"]=de&0xff;
  pc8001.z80.regs["B"]=bc>>8;
  pc8001.z80.regs["C"]=bc&0xff;
  if(bc!=0)
    pc8001.z80.regs["PC"]=(pc8001.z80.regs["PC"]+0xfffe)&0xffff;
}
pc8001.z80.ops[0xdb]=["IN","A","(n)",11];
pc8001.z80.mnemonics["IN"]=function(v,m){
  var c,pc;
  if(m[2]=="(n)"){
    pc=pc8001.z80.regs["PC"];
    c=pc8001.memory[pc];
    pc8001.z80.regs["PC"]=(pc+1)&0xffff;
  }
  else
    c=pc8001.z80.regs[m[2].substr(1,1)];
  pc8001.z80.regs[m[1]]=pc8001.inports[c];
}
pc8001.z80.ops[0xd3]=["OUT","(n)","A",11];
pc8001.z80.mnemonics["OUT"]=function(v,m){
  var c,pc;
  if(m[1]=="(n)"){
    pc=pc8001.z80.regs["PC"];
    c=pc8001.memory[pc];
    pc8001.z80.regs["PC"]=(pc+1)&0xffff;
  }
  else
    c=pc8001.z80.regs[m[1].substr(1,1)];
  pc8001.outports(c,pc8001.z80.regs[m[2]]);
}
pc8001.outports=function(p,d){
  if(p!=0x40){
    pc8001.z80.mnemonics["UNDEF"](p,["UNDEF","OUT",0]);
    return;
  }
  pc8001.beep.gain.value=((d&0x20)==0)?0:1;
}
pc8001.z80.ops[0xdd][0xcb]=["EXTCB","DD CB dd","JX",20];
pc8001.z80.ops[0xfd][0xcb]=["EXTCB","FD CB dd","KY",20];
pc8001.z80.mnemonics["EXTCB"]=function(v,m){
  var pc=pc8001.z80.regs["PC"];
  var d=pc8001.memory[pc];
  var e=pc8001.memory[(pc+1)&0xffff];
  var f=pc8001.z80.ops[0xcb][e].slice();
  pc8001.z80.regs["PC"]=(pc+2)&0xffff;
  if(f[f.length-2]=="(HL)"){
    f[f.length-2]="("+m[2]+"+"+d.toString(16).padStart(2,"0")+")";
    pc8001.z80.mnemonics[f[0]](e,f);
    return;
  }
  pc8001.z80.mnemonics["UNDEF"](e,["UNDEF",m[1],0]);
}
pc8001.z80.run=function(){
  var i,pc,v,m,s;
  for(i=0;i<4000;i++){
    pc=pc8001.z80.regs["PC"];
    v=pc8001.memory[pc];
    m=pc8001.z80.ops[v];
    pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
    s=m[m.length-1];
    if(s<0){
      v=pc8001.memory[pc];
      m=m[v];
      pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      s=m[m.length-1];
    }
    pc8001.z80.states+=s;
    pc8001.z80.lastop=m;
    pc8001.z80.mnemonics[m[0]](v,m);
    if(pc8001.z80.halt==1)
      return;
  }
  i=performance.now()-pc8001.z80.millitimer;
  s=pc8001.z80.states-i*4000;
  pc8001.z80.timer=setTimeout("clearTimeout(pc8001.z80.timer);pc8001.z80.run()",(s>8000)?s/4000:0);
}
pc8001.run=function(){
  pc8001.audio=new(window.AudioContext||window.webkitAudioContext)();
  pc8001.oscillator=pc8001.audio.createOscillator();
  pc8001.beep=pc8001.audio.createGain();
  pc8001.oscillator.connect(pc8001.beep);
  pc8001.beep.connect(pc8001.audio.destination);
  pc8001.oscillator.frequency.setValueAtTime(2400,pc8001.audio.currentTime);
  pc8001.oscillator.type="sine";
  pc8001.keybeep=0;
  document.addEventListener("keydown",pc8001.keydown);
  document.addEventListener("keyup",pc8001.keyup);
  pc8001.z80.millitimer=performance.now()
  pc8001.z80.run();
}
</script>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink"
 width=984 height=624 viewBox="-2 -2 164 104"
 style="background-color:black"
 onload="pc8001.initDisplay80x25(this);pc8001.run()">
</svg>
</body>
</html>

端的に言えば、PC-8001の160×100ドット画面をSVGでエミュレートして、その上でZ80エミュレータを動かしている。ただし、Z80エミュレータは、かなり手抜きで、命令セットは必要な分しか作ってないし、フラグはZeroとCarryしか実装していない。キーボードは、さすがにファンクションキーは難しいので、F G H J KとスペースでCannon発射とした。また、テンキーの4と6に加え、左右の矢印キーも使えるようにした。どうにもならなかったのがビープ音で、とりあえず2400Hzのoscillatorを、gainの上げ下げで実装してみたのだが、なかなかうまい感じの音にならない。まだ、あちこちバグが残ってると思うので、ぜひ試しに遊んでみてほしい。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?