JavaScript版『SIGNAL ALIEN』リリース

![sgnalien.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/5b09bfb6-bc13-46fd-b6f2-58cca6aa1f81.gif)

[5月11日の記事](https://qiita.com/KoichiYasuoka/items/0f8f8089bb3e76839204)の続きだが、PC-8001向けゲーム『[SIGNAL ALIEN](http://kanji.zinbun.kyoto-u.ac.jp/~yasuoka/publications/1983-04ASCII.pdf)』(ASCII, Vol.7, No.4 (1983年4月), pp.140-143)を、JavaScript上で動かすことに挑戦してみた。しかし『SIGNAL ALIEN』は、PC-8001の40×25キャラクタモードで動いており、SVGでエミュレートするには、8×8ドットフォントを「目作業」で作成する必要があった。しかも、N-BASICのルーチンのうち

> * 0018 1文字出力(メッセージ出力用)
> * 093A 画面幅設定
> * 1602 時計読み込み(ランダムのモト)
> * 52ED 文字列出力

を独自実装する必要があったため、かなり作業が難航した。結論として「1602 時計読み込み(ランダムのモト)」は実装しきれなかったが、それでも何とか動くところまで漕ぎ着けたので、とりあえずリリースすることにする。

http://kanji.zinbun.kyoto-u.ac.jp/~yasuoka/sgnalien/sgnalien.html

5月29日時点のプログラムリストも、以下に公開しておく。

```
<!DOCTYPE html><head><meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>SIGNAL ALIEN by Koichi Yasuoka, May 29, 2025</title>
<script>
var pc8001=new Object();
pc8001.memory=new Array(65536);
pc8001.memory.fill(0x76);
["0000 C3 D0 DF",
 "0018                         C3 A6 40",
 "093A                               79 32 62 EA 78 32", // display init
 "0940 65 EA C6 B0 3E 14 8F 32 66 EA D3 30 ED 5B 5A EA",
 "0950 21 00 F3 06 50 73 23 10 FC 70 23 70 23 3A 65 EA",
 "0960 C6 B0 9F C6 02 77 23 72 23 01 50 11 71 23 72 23",
 "0970 10 FA 71 23 70 23 11 00 F3 EB 01 B8 0B ED B0 21",
 "0980 01 01 22 63 EA C9",
 "1602       C9",                                        // "date" unsupport
 "40A6                   F5 E5 D5 C5 FE 0C 20 08 CD 4C", // print one-char
 "40B0 09 C1 D1 E1 F1 C9 FE 1C 20 06 21 64 EA 34 18 F1",
 "40C0 FE 1D 20 06 21 64 EA 35 18 E7 FE 1E 20 06 21 63",
 "40D0 EA 35 18 DD FE 1F 20 10 21 63 EA 34 18 D3 DF 3A",
 "40E0 64 EA E6 07 3E 20 20 F6 FE 09 28 F3 4F 3A 63 EA",
 "40F0 3D 67 87 87 87 6F AF CB 3C 1F 95 6F 9F 84 67 EB",
 "4100 21 64 EA 7E 34 23 CB 76 20 01 87 6F 26 F3 19 71",
 "4110 21 50 F3 19 E5 F5 11 D8 F2 01 28 00 ED B0 21 0B",
 "4120 FF 4E 21 D8 F2 54 5D 06 50 2D 71 10 FC 06 50 1A",
 "4130 80 FE 50 20 08 1C 1A 4F 1C 20 02 1D 1D 71 2C 10",
 "4140 EE F1 C6 88 5F 3A 5B EA 12 21 65 EA CB 76 20 02",
 "4150 1C 12 21 08 FF 11 D8 F2 01 28 00 ED B0 21 88 F2",
 "4160 11 D8 F2 4E 0C 06 50 7E B9 28 0D 3E 50 90 12 1C",
 "4170 4E 79 12 1C 20 02 1D 1D 2C 10 EC 21 D8 F2 D1 01",
 "4180 28 00 ED B0 C1 D1 E1 F1 C9",
 "52ED                                        3A 5B EA", // print string
 "52F0 E6 E8 32 5B EA 44 4D 0A B7 C8 DF 03 18 F9",
 "DFD0 31 FF FF 21 00 E8 22 5A EA 21 19 01 22 62 EA 21",
 "DFE0 01 28 22 64 EA C3 00 E0 00 00 00 00 00 00 00 00",
 "DFF0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
 "E000 3A CB E8 FE 08 CC A0 E8 CD 7A E8 CD DE E7 31 FF",
 "E010 FF CD 01 E6 CD 3D E4 CD BB E1 18 F8 00 00 00 00",
 "E020 9F 99 0B 8F F0 19 B9 F0 19 F1 80 9F 8F F0 08 00",
 "E030 00 F8 F9 08 8F 00 00 8F F0 99 19 F0 19 F1 46 74",
 "E040 07 77 70 47 74 70 07 70 70 07 70 70 47 44 00 77",
 "E050 00 07 77 44 04 77 70 47 44 70 07 70 06 00 04 05",
 "E060 C8 CD 52 E6 E6 0E C6 05 6F CD 52 E6 E6 3C C6 09",
 "E070 67 CD B0 E6 EB B6 20 E6 36 87 10 E5 C9 2B 7E 23",
 "E080 23 77 23 23 D6 10 5F 7E D6 10 2B BB CC 51 E5 2B",
 "E090 30 01 2B C3 51 E5 CD F0 E0 DD 6E 00 DD 66 01 DD",
 "E0A0 4E 02 CD 76 E2 CD 3A E6 DD 75 00 DD 74 01 E5 26",
 "E0B0 50 CD B0 E6 E1 EB 7A 23 23 BE 30 FB 2B 7E EB 01",
 "E0C0 A8 40 FE E8 28 02 0E 18 C3 79 E5 00 00 21 EA E0",
 "E0D0 E5 CD F0 E0 E1 DD 6E 00 DD 66 01 DD 4E 02 CD 76",
 "E0E0 E2 CD 3A E6 DD 75 00 DD 74 01 01 C8 40 C3 79 E5",
 "E0F0 1E 00 CD 2B E1 38 1A DD 71 02 DD E5 DD 21 FE DF",
 "E100 22 FE DF 1E EC CD 2B E1 DD E1 D8 DD 34 02 DD 34",
 "E110 02 F1 DD 6E 00 DD 66 01 C9 DD 6E 00 DD 66 01 CD",
 "E120 3A E6 D5 CD B0 E6 1A D1 C9 00 00 CD 52 E6 07 9F",
 "E130 CB 37 57 DD 86 02 06 04 4F CD 19 E1 BB C8 79 92",
 "E140 10 F6 37 C9 00 00 00 2A E0 E8 7C DD BE 01 DD 7E",
 "E150 00 20 05 BD 9F 87 18 0A BD 20 19 7C DD BE 01 9F",
 "E160 CB 37 4F DD 96 02 E6 03 FE 02 28 08 CD 19 E1 3D",
 "E170 FE EB 30 06 1E 00 CD 2B E1 D8 DD 6E 00 DD 66 01",
 "E180 DD 71 02 CD 76 E2 CD 3A E6 DD 75 00 DD 74 01 01",
 "E190 68 40 C3 79 E5 00 00 00 DD 46 03 10 0A DD 6E 00",
 "E1A0 DD 66 01 CD AE E5 05 DD 70 03 78 FE 48 D2 96 E0",
 "E1B0 FE 40 D2 CD E0 C3 47 E1 00 00 00 DD 21 E4 E8 CD",
 "E1C0 98 E1 11 04 00 DD 19 DD 7E 00 B7 20 F2 11 0F 17",
 "E1D0 DD 19 38 02 3E 02 32 91 FE CD 40 E3 11 00 20 C3",
 "E1E0 1E E8 00 00 00 11 19 E8 09 00 10 19 E8 47 41 4D",
 "E1F0 45 FF 4F 56 45 52 00 00 00 00 2A E0 E8 1E F8 01",
 "E200 88 EC CD 79 E5 4B 16 00 CD 95 E2 7B D6 30 5F 01",
 "E210 68 40 CD 79 E5 4B 16 00 CD 95 E2 7B D6 30 5F 30",
 "E220 DE 21 E5 E1 CD 43 E8 CD 24 E8 CD 1E E8 CD 1E E8",
 "E230 C3 0B E0 00 00 00 10 19 00 09 09 00 02 19 02 20",
 "E240 00 03 19 48 45 58 54 45 52 4D 49 4E 41 54 45 44",
 "E250 00 1C 19 C8 42 6F 6E 75 73 20 35 30 30 30 00 00",
 "E260 06 04 21 36 E2 CD 24 E8 10 FB 0E 32 CD A9 E2 CD",
 "E270 E3 E6 C3 0E E0 00 CD B0 E6 1A B7 C8 AF 12 E5 7C",
 "E280 26 50 08 CD B0 E6 08 EB 5F 23 23 7E BB 38 FA CC",
 "E290 7D E0 E1 C9 00 3E 20 D3 40 41 10 FE AF D3 40 41",
 "E2A0 10 FE 15 20 F0 C9 00 00 00 06 0A 21 16 F3 CD 3F",
 "E2B0 E5 10 F8 21 0E F3 11 42 F3 06 0B 3A E2 E8 B7 20",
 "E2C0 0D 1A BE 20 0F 13 23 10 F8 32 E2 E8 18 06 7E 12",
 "E2D0 13 23 10 FA 0D 20 D2 16 05 CD 95 E2 0C 20 F8 C9",
 "E2E0 00 00 00 10 19 88 50 6F 69 6E 74 FF FF FF 30 00",
 "E2F0 00 00 AF 32 91 FE 79 07 07 07 07 C6 58 32 E5 E2",
 "E300 21 10 19 22 F1 DF 21 F3 DF 11 60 FE 72 06 0A 23",
 "E310 1A 77 13 13 10 F9 D9 21 E3 E2 CD 43 E8 D9 51 06",
 "E320 0A 21 6E FE CD 3F E5 10 F8 15 20 F3 CD A9 E2 21",
 "E330 F1 DF CD 43 E8 2B 2B 7E 3C CA 60 E2 C9 00 00 00",
 "E340 ED 4B E0 E8 21 E4 E8 5E 1C 1D C8 23 56 23 23 23",
 "E350 EB B7 ED 42 EB 20 F0 54 5D 1B 1A 1B 1B 1B 47 0E",
 "E360 34 7E ED A0 ED A0 ED A0 ED A0 B7 20 F2 21 72 FE",
 "E370 2B 2B 35 7E 36 39 B9 38 F7 77 20 0A 2B 2B 7E 3C",
 "E380 20 04 23 23 36 FF 78 FE 40 DA FA E1 0E 14 FE 48",
 "E390 DA F2 E2 CD 52 E6 E6 03 4F C2 F2 E2 CD 52 E6 E6",
 "E3A0 07 C6 03 4F C3 F2 E2 00 00 00 D9 2A E0 E8 44 05",
 "E3B0 05 4C 0C 0C 0C 0C 11 08 E8 7D 3D 3D 28 05 CD 6D",
 "E3C0 E4 18 F8 3E 18 2C 3D BD D9 C8 D9 CD 6D E4 18 F6",
 "E3D0 00 00 00 D9 ED 4B E0 E8 79 04 04 04 04 0E 50 11",
 "E3E0 08 E8 3D CD 6D E4 3C CD 6D E4 3C CD 6D E4 48 0D",
 "E3F0 0D 0D 0D 0D 0D 06 02 CD 6D E4 3D CD 6D E4 3D CD",
 "E400 6D E4 D9 C9 00 00 00 CD 19 E1 FE 87 C8 47 2A E0",
 "E410 E8 CD 76 E2 CD 3A E6 59 C5 01 88 EC CD 79 E5 CB",
 "E420 43 CC D3 E3 CB 43 C4 AA E3 22 E0 E8 CB 43 CC FF",
 "E430 E4 CD C2 E4 C1 04 05 C4 40 E3 C9 00 00 DD 21 E0",
 "E440 E8 0E 00 DB 01 0F D4 07 E4 0E 02 DB 00 E6 04 CC",
 "E450 07 E4 0E 01 DB 00 E6 40 CC 07 E4 0E 03 DB 00 E6",
 "E460 10 CC 07 E4 DB 08 E6 20 CC D1 E8 C9 00 E5 F5 6F",
 "E470 26 50 D5 CD B0 E6 EB D1 C5 78 23 23 BE 28 1E 30",
 "E480 F9 2B 7E 23 BA 20 20 C5 4B CD 67 E5 C1 47 7B 2B",
 "E490 BE 23 CC 51 E5 23 23 23 BE 2B CC 51 E5 7E B7 28",
 "E4A0 1A B9 30 0C 23 7E 23 47 BA 20 F2 2B 73 2B 18 DE",
 "E4B0 28 09 78 BA 20 05 41 4A CD 67 E5 C1 F1 E1 C9 00",
 "E4C0 00 00 2A E0 E8 CD B0 E6 EB E5 53 01 88 FF 15 09",
 "E4D0 7E FE 87 20 F9 E1 01 78 00 1C 09 7E FE 87 20 F9",
 "E4E0 EB 3A E1 E8 47 05 05 C6 04 4F 7C 11 E8 08 CD 6D",
 "E4F0 E4 11 A8 18 CD 6D E4 BD C8 3C 18 EF 00 00 00 2A",
 "E500 E0 E8 CD B0 E6 EB E5 42 05 05 2B 2B 7E FE 87 20",
 "E510 F7 E1 4A 0C 0C 0C 0C 23 23 7E FE 87 20 F7 7B 11",
 "E520 E8 08 3D CD 6D E4 3C CD 6D E4 3C CD 6D E4 11 A8",
 "E530 18 CD 6D E4 3D CD 6D E4 3D C3 6D E4 00 00 00 34",
 "E540 20 02 36 31 7E FE 3A C0 36 30 2B 2B 18 F1 00 00",
 "E550 00 08 E5 23 23 7E 2B 2B 77 23 B7 20 F6 2B 36 E8",
 "E560 E1 08 2B 2B C9 00 00 08 E5 7E B7 28 06 70 41 4F",
 "E570 23 18 F6 E1 08 C9 00 00 00 D5 CD B0 E6 78 12 E5",
 "E580 26 78 CD B0 E6 E1 C5 7C EB C6 02 2B 2B BE 38 FB",
 "E590 28 09 47 23 4E 23 CD 67 E5 C1 C5 7A 2B 2B 47 BE",
 "E5A0 28 05 23 23 CD 67 E5 23 C1 71 EB D1 C9 00 11 E0",
 "E5B0 E8 13 13 13 13 1A B7 20 F8 CD 52 E6 F6 80 EB 73",
 "E5C0 23 72 23 23 77 23 36 00 21 70 FE CD 3F E5 EB C9",
 "E5D0 00 10 19 E8 41 4C 49 45 4E FF FF FF FF 00 00 00",
 "E5E0 00 21 79 F3 3E 18 06 27 4E 23 71 23 10 FA 23 EB",
 "E5F0 21 08 FF 01 28 00 ED B0 EB 23 3D 20 E9 32 E4 E8",
 "E600 C9 CD E1 E5 21 D1 E5 CD 43 E8 06 04 CD 52 E6 E6",
 "E610 0E C6 04 6F CD 52 E6 E6 3C C6 08 67 CD AE E5 10",
 "E620 EB 21 0C 28 22 E0 E8 01 88 EC CD 79 E5 CD FF E4",
 "E630 CD C2 E4 3E E8 32 53 F3 C9 00 CB 41 28 0A 24 24",
 "E640 CB 49 C8 25 25 25 25 C9 2C CB 49 C0 2D 2D C9 00",
 "E650 00 00 E5 D5 C5 21 00 00 ED 5B 76 EA 01 03 0A 3E",
 "E660 83 CB 39 1F 30 01 19 EB 29 EB 10 F5 22 76 EA 7C",
 "E670 85 C1 D1 E1 C9 00 00 00 E5 3C 12 CD 52 E6 4F CD",
 "E680 3A E6 CD B0 E6 D5 CD 3A E6 CD B0 E6 1A 47 3E 01",
 "E690 12 D1 05 28 E6 04 28 E2 12 21 79 F3 11 4F 05 46",
 "E6A0 10 02 36 87 23 23 1B 7A B3 20 F4 E1 C9 00 00 00",
 "E6B0 E5 7D 6C 26 F3 11 78 00 19 3D 20 FC EB E1 C9 11",
 "E6C0 2C 00 06 27 77 23 23 10 FB 2B 2B 19 77 23 23 06",
 "E6D0 25 72 23 23 10 FB 77 19 0D 20 F1 06 27 77 23 23",
 "E6E0 10 FB C9 21 79 F3 3E 87 0E 15 CD BF E6 CD 5C E0",
 "E6F0 26 05 2E 03 CD B0 E6 1A B7 CC 78 E6 2C 2C 7D FE",
 "E700 17 20 F1 7C C6 04 67 FE 4D 20 E7 C9 07 01 08 FF",
 "E710 FF FF FF FF 30 00 03 03 88 53 49 47 4E 41 4C 20",
 "E720 41 4C 49 45 4E 00 05 0A A8 40 FF FF 1D 1D A5 A5",
 "E730 A5 A5 4C 41 52 56 41 FF 28 53 61 66 65 2E 20 54",
 "E740 72 79 20 74 6F 20 63 61 74 63 68 29 00 05 0B C8",
 "E750 40 FF FF 1D 1D A5 A5 A5 A5 50 55 50 41 FF 20 28",
 "E760 54 75 72 6E 73 00 17 0B 68 40 00 19 0B E8 69 6E",
 "E770 20 61 20 77 68 69 6C 65 29 00 05 0C 68 40 FF FF",
 "E780 1D 1D A5 A5 A5 A5 49 4D 41 47 4F FF 28 41 76 6F",
 "E790 69 64 2C 20 6F 72 20 62 65 20 65 61 74 65 6E 29",
 "E7A0 00 23 13 E8 38 1F 1D 96 1F 1D 1D 1D 34 95 8F 95",
 "E7B0 36 1F 1D 1D 1D 96 1F 1D 32 00 0D 19 A8 50 75 73",
 "E7C0 68 00 11 19 88 20 00 12 19 00 09 00 12 19 22 52",
 "E7D0 45 54 55 52 4E 00 19 19 A8 6B 65 79 00 00 CD 02",
 "E7E0 16 21 76 EA CB C6 CD E3 E6 3E 08 32 53 F3 CD E1",
 "E7F0 E5 21 78 F3 AF 0E 16 CD BF E6 21 0C E7 CD 43 E8",
 "E800 06 06 CD 24 E8 32 E2 E8 DB 01 07 D0 10 F4 CD 43",
 "E810 E8 06 05 CD 24 E8 10 FB DB 01 07 38 FB C9 7A B3",
 "E820 1B 20 FB C9 56 23 5E 23 7E 23 ED 53 63 EA 32 5B",
 "E830 EA 7E 23 B7 C8 DF 11 00 40 FE 21 D4 1E E8 18 F1",
 "E840 00 00 00 46 23 4E 23 7E 23 ED 43 63 EA 32 5B EA",
 "E850 CD ED 52 60 69 23 C9 01 01 08 0C 00 02 01 08 53",
 "E860 43 4F 52 45 09 09 09 48 69 2D 53 43 4F 52 45 FF",
 "E870 FF 35 30 30 30 00 00 00 00 00 21 5A EA 11 05 00",
 "E880 01 19 28 72 23 19 72 23 36 FF 19 CB 8E CD 3A 09",
 "E890 21 57 E8 CD 43 E8 CD 43 E8 3E 08 32 2F FF C9 00",
 "E8A0 CD 7A E8 01 19 50 CD 3A 09 3E 98 32 5B EA 3E 0C",
 "E8B0 DF 21 20 E0 11 40 F8 01 1E 00 ED B0 11 B8 F8 01",
 "E8C0 1E 00 ED B0 CD 1E E8 CD 1E E8 C3 08 E0 00 00 00",
 "E8D0 00 1E 40 CD 2B E1 D8 1E 00 CD 2B E1 D4 07 E4 C9"
].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.font=[
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "2300 2000 2300 0211 2311 0031 0011 0011",
  "2300 2000 2300 0201 2320 0010 0220 0101",
  "2300 2000 2300 2001 2320 0010 0220 0101",
  "2300 2000 2300 2000 2331 0020 0020 0020",
  "3100 1000 3100 1030 3301 0201 0201 0032",
  "0100 2200 2300 2201 2220 0210 0220 0201",
  "2300 2010 2300 2010 2320 0020 0020 0023",
  "2300 2010 2300 2033 2320 0023 0002 0023",
  "2200 2200 2300 2200 2231 0020 0020 0020",
  "2000 2000 2000 2031 2310 0030 0010 0010",
  "2200 2200 2300 2200 2202 0213 0222 0202",
  "0330 2000 2000 2020 0310 0010 0010 0033",
  "0310 2000 2000 0331 0012 0031 0011 0012",
  "2300 2000 2300 0200 2330 0201 0201 0030",
  "2300 2000 2300 0200 2331 0020 0020 0031",
  "2300 2010 2010 2033 2320 0023 0020 0023",
  "2300 2010 2010 2011 2321 0001 0001 0023",
  "2300 2010 2010 2031 2302 0021 0010 0033",
  "2300 2010 2010 2033 2302 0023 0002 0033",
  "2300 2010 2010 2011 2321 0011 0233 0001",
  "2010 2110 2210 2012 2011 0030 0011 0012",
  "2300 2000 2300 0200 2312 0032 0013 0012",
  "2300 2000 2300 2031 2312 0031 0012 0031",
  "0310 2000 2000 0310 0012 0032 0013 0012",
  "2300 2000 2300 2000 2302 0213 0222 0202",
  "2300 2000 2300 0230 2301 0230 0201 0230",
  "2300 2000 2300 2000 2331 0200 0200 0031",
  "0000 0010 0020 2331 0020 0010 0000 0000",
  "0000 0200 0100 2331 0100 0200 0000 0000",
  "0000 0010 0230 0111 0010 0010 0010 0000",
  "0000 0010 0010 0010 0111 0230 0010 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "0010 0010 0010 0010 0000 0000 0010 0000",
  "0120 0120 0120 0000 0000 0000 0000 0000",
  "0120 0120 2331 0120 2331 0120 0120 0000",
  "0010 0231 0110 0230 0011 0330 0010 0000",
  "0000 2101 2120 0010 0200 0121 2021 0000",
  "0300 2010 2010 0300 2011 2020 0311 0000",
  "0020 0010 0200 0000 0000 0000 0000 0000",
  "0020 0010 0200 0200 0200 0010 0020 0000",
  "0100 0200 0010 0010 0010 0200 0100 0000",
  "0010 0111 0230 0331 0230 0111 0010 0000",
  "0000 0010 0010 0331 0010 0010 0000 0000",
  "0000 0000 0000 0000 0000 0010 0010 0200",
  "0000 0000 0000 2331 0000 0000 0000 0000",
  "0000 0000 0000 0000 0000 0210 0210 0000",
  "0000 0001 0020 0010 0200 0100 2000 0000",
  "0330 2001 2021 2211 2101 2001 0330 0000",
  "0010 0210 0110 0010 0010 0010 0331 0000",
  "0330 2001 0001 0030 0300 2000 2331 0000",
  "0330 2001 0001 0230 0001 2001 0330 0000",
  "0020 0030 0220 0120 2331 0020 0020 0000",
  "2331 2000 2310 0020 0001 2020 0310 0000",
  "0230 0100 2000 2330 2001 2001 0330 0000",
  "2331 2001 0020 0010 0200 0200 0200 0000",
  "0330 2001 2001 0330 2001 2001 0330 0000",
  "0330 2001 2001 0331 0001 0020 0310 0000",
  "0000 0000 0010 0000 0000 0010 0000 0000",
  "0000 0000 0010 0000 0000 0010 0010 0200",
  "0031 0210 0300 2100 0300 0210 0031 0000",
  "0000 0000 2331 0000 2331 0000 0000 0000",
  "2300 0210 0030 0021 0030 0210 2300 0000",
  "0330 2001 0001 0030 0200 0000 0200 0000",
  "0230 0101 2011 2221 2030 0100 0231 0000",
  "0210 0120 2001 2331 2001 2001 2001 0000",
  "2330 0101 0101 0330 0101 0101 2330 0000",
  "0230 0101 2000 2000 2000 0101 0230 0000",
  "2310 0120 0101 0101 0101 0120 2310 0000",
  "2331 2000 2000 2310 2000 2000 2331 0000",
  "2331 2000 2000 2310 2000 2000 2000 0000",
  "0230 0101 2000 2031 2001 0101 0230 0000",
  "2001 2001 2001 2331 2001 2001 2001 0000",
  "0230 0010 0010 0010 0010 0010 0230 0000",
  "0031 0020 0020 0020 0020 2020 0310 0000",
  "2001 2020 2010 2300 2010 2020 2001 0000",
  "2000 2000 2000 2000 2000 2000 2331 0000",
  "2001 2121 2211 2211 2001 2001 2001 0000",
  "2001 2101 2201 2011 2021 2001 2001 0000",
  "0210 0120 2001 2001 2001 0120 0210 0000",
  "2330 2001 2001 2330 2000 2000 2000 0000",
  "0210 0120 2001 2001 2011 0120 0211 0000",
  "2330 2001 2001 2330 2010 2020 2001 0000",
  "0330 2001 2000 0330 0001 2001 0330 0000",
  "0331 0010 0010 0010 0010 0010 0010 0000",
  "2001 2001 2001 2001 2001 2001 0330 0000",
  "2001 2001 2001 0120 0120 0210 0210 0000",
  "2001 2001 2001 2211 2211 2121 2001 0000",
  "2001 2001 0120 0210 0120 2001 2001 0000",
  "0101 0101 0101 0230 0010 0010 0010 0000",
  "2331 0001 0020 0210 0100 2000 2331 0000",
  "0330 0100 0100 0100 0100 0100 0330 0000",
  "0101 0101 0220 0331 0010 0331 0010 0000",
  "0330 0020 0020 0020 0020 0020 0330 0000",
  "0010 0220 0101 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 0000 0000 2331 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "0000 0000 0330 0020 0330 2020 0311 0000",
  "2000 2000 2230 2101 2001 2101 2230 0000",
  "0000 0000 0330 2001 2000 2001 0330 0000",
  "0001 0001 0311 2021 2001 2021 0311 0000",
  "0000 0000 0330 2001 2331 2000 0330 0000",
  "0030 0201 0200 2330 0200 0200 0200 0000",
  "0000 0000 0311 2021 2021 0311 0001 0330",
  "2000 2000 2230 2101 2001 2001 2001 0000",
  "0010 0000 0210 0010 0010 0010 0230 0000",
  "0020 0000 0030 0020 0020 0020 2020 0310",
  "2000 2000 2020 2010 2200 2110 2020 0000",
  "0210 0010 0010 0010 0010 0010 0230 0000",
  "0000 0000 2321 2012 2012 2012 2012 0000",
  "0000 0000 2230 2101 2001 2001 2001 0000",
  "0000 0000 0330 2001 2001 2001 0330 0000",
  "0000 0000 2230 2101 2101 2230 2000 2000",
  "0000 0000 0311 2021 2021 0311 0001 0001",
  "0000 0000 2230 2101 2000 2000 2000 0000",
  "0000 0000 0331 2000 0330 0001 2330 0000",
  "0200 0200 2330 0200 0200 0201 0030 0000",
  "0000 0000 2001 2001 2001 2021 0311 0000",
  "0000 0000 2001 2001 2001 0120 0210 0000",
  "0000 0000 2002 2012 2012 2012 0321 0000",
  "0000 0000 2001 0120 0210 0120 2001 0000",
  "0000 0000 2001 2001 2021 0311 0001 0330",
  "0000 0000 2331 0020 0210 0100 2331 0000",
  "0031 0200 0200 0100 0200 0200 0031 0000",
  "0010 0010 0000 0000 0000 0010 0010 0000",
  "2300 0010 0010 0020 0010 0010 2300 0000",
  "0300 2012 0021 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 0000 0000 0000 3333",
  "0000 0000 0000 0000 0000 0000 3333 3333",
  "0000 0000 0000 0000 0000 3333 3333 3333",
  "0000 0000 0000 0000 3333 3333 3333 3333",
  "0000 0000 0000 3333 3333 3333 3333 3333",
  "0000 0000 3333 3333 3333 3333 3333 3333",
  "0000 3333 3333 3333 3333 3333 3333 3333",
  "3333 3333 3333 3333 3333 3333 3333 3333",
  "1000 1000 1000 1000 1000 1000 1000 1000",
  "3000 3000 3000 3000 3000 3000 3000 3000",
  "3100 3100 3100 3100 3100 3100 3100 3100",
  "3300 3300 3300 3300 3300 3300 3300 3300",
  "3310 3310 3310 3310 3310 3310 3310 3310",
  "3330 3330 3330 3330 3330 3330 3330 3330",
  "3331 3331 3331 3331 3331 3331 3331 3331",
  "0010 0010 0010 0010 3333 0010 0010 0010",
  "0010 0010 0010 0010 3333 0000 0000 0000",
  "0000 0000 0000 0000 3333 0010 0010 0010",
  "0010 0010 0010 0010 3310 0010 0010 0010",
  "0010 0010 0010 0010 0033 0010 0010 0010",
  "3333 0000 0000 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 3333 0000 0000 0000",
  "0010 0010 0010 0010 0010 0010 0010 0010",
  "0002 0002 0002 0002 0002 0002 0002 0002",
  "0000 0000 0000 0000 0033 0010 0010 0010",
  "0000 0000 0000 0000 3310 0010 0010 0010",
  "0010 0010 0010 0010 0033 0000 0000 0000",
  "0010 0010 0010 0010 3310 0000 0000 0000",
  "0000 0000 0000 0000 0003 0020 0010 0010",
  "0000 0000 0000 0000 3100 0200 0010 0010",
  "0010 0010 0010 0020 0003 0000 0000 0000",
  "0010 0010 0010 0200 3100 0000 0000 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 0310 0110 0310 0000",
  "0230 0200 0200 0200 0000 0000 0000 0000",
  "0000 0000 0000 0010 0010 0010 0310 0000",
  "0000 0000 0000 0000 0100 0200 0010 0000",
  "0000 0000 0000 0210 0210 0000 0000 0000",
  "0000 2331 0001 2331 0001 0020 0310 0000",
  "0000 0000 0331 0001 0030 0010 0200 0000",
  "0000 0000 0020 0010 0210 0110 0010 0000",
  "0000 0000 0010 0331 0101 0001 0030 0000",
  "0000 0000 0000 0331 0010 0010 0331 0000",
  "0000 0000 0020 0331 0030 0220 0120 0000",
  "0000 0000 0200 0331 0201 0220 0200 0000",
  "0000 0000 0000 0230 0020 0020 0331 0000",
  "0000 0000 0330 0020 0330 0020 0330 0000",
  "0000 0000 0000 0111 0111 0001 0030 0000",
  "0000 0000 0000 0331 0000 0000 0000 0000",
  "2331 0001 0001 0220 0210 0200 0100 0000",
  "0001 0020 0010 0210 0110 2010 0010 0000",
  "0010 2331 2001 2001 0001 0020 0310 0000",
  "0000 0331 0010 0010 0010 0010 0331 0000",
  "0010 2331 0010 0210 0110 2010 0010 0000",
  "0200 2331 0201 0201 0201 0201 0120 0000",
  "0010 0331 0010 0331 0010 0010 0010 0000",
  "0231 0101 2001 0020 0010 0200 2100 0000",
  "0100 0331 2010 0010 0010 0010 0200 0000",
  "0000 2331 0001 0001 0001 0001 2331 0000",
  "0120 2331 0120 0120 0020 0010 0200 0000",
  "0000 2300 0000 2301 0001 0020 2310 0000",
  "2331 0001 0020 0010 0210 0120 2001 0000",
  "0100 2331 0101 0120 0100 0100 0231 0000",
  "2001 2001 0101 0001 0020 0010 0300 0000",
  "0231 0101 2101 0220 0010 0200 2100 0000",
  "0020 0310 0010 2331 0010 0010 2300 0000",
  "0000 2201 2201 2201 0020 0010 2300 0000",
  "0330 0000 2331 0010 0010 0200 0100 0000",
  "0200 0200 0200 0210 0220 0200 0200 0000",
  "0010 0010 2331 0010 0010 0200 0100 0000",
  "0000 0330 0000 0000 0000 0000 2331 0000",
  "0000 0331 0001 0220 0010 0220 0100 0000",
  "0010 0331 0020 0010 0230 0111 0010 0000",
  "0001 0001 0001 0020 0010 0200 0100 0000",
  "0200 0010 0020 2001 2001 2001 2001 0000",
  "2000 2000 2331 2000 2000 2000 0331 0000",
  "0000 2331 0001 0001 0020 0010 0300 0000",
  "0000 0200 0110 2020 0001 0001 0000 0000",
  "0010 0331 0010 0010 0111 0111 0010 0000",
  "2331 0001 0001 0020 0110 0200 0010 0000",
  "0000 0330 0000 0330 0000 2330 0001 0000",
  "0020 0010 0200 0100 2010 2330 0001 0000",
  "0000 0001 0001 0220 0010 0220 2100 0000",
  "0000 2331 0200 2331 0200 0200 0231 0000",
  "0100 0100 2331 0101 0120 0100 0100 0000",
  "0000 0310 0010 0010 0010 0010 2331 0000",
  "2331 0001 0001 2331 0001 0001 2331 0000",
  "0330 0000 2331 0001 0020 0010 0200 0000",
  "2001 2001 2001 2001 0001 0020 0210 0000",
  "0110 0110 0110 0111 0111 0130 2010 0000",
  "0100 0100 0100 0101 0120 0110 0300 0000",
  "0000 2331 2001 2001 2001 2001 2331 0000",
  "0000 2331 2001 2001 0001 0020 0210 0000",
  "0000 2300 0001 0001 0020 0010 2300 0000",
  "0200 2010 0100 0000 0000 0000 0000 0000",
  "2300 2200 2300 0000 0000 0000 0000 0000",
  "0000 0000 3333 0000 0000 3333 0000 0000",
  "0010 0010 0033 0010 0010 0033 0010 0010",
  "0010 0010 3333 0010 0010 3333 0010 0010",
  "0010 0010 3310 0010 0010 3310 0010 0010",
  "0002 0003 0023 0033 0233 0333 2333 3333",
  "1000 3000 3100 3300 3310 3330 3331 3333",
  "3333 2333 0333 0233 0033 0023 0003 0002",
  "3333 3331 3330 3310 3300 3100 3000 1000",
  "0010 0230 0331 2333 2333 0230 0331 0000",
  "0321 2333 2333 2333 0331 0230 0010 0000",
  "0010 0230 0331 2333 0331 0230 0010 0000",
  "0230 0230 2333 2333 2113 0010 0331 0000",
  "0000 0330 2331 2331 2331 2331 0330 0000",
  "0000 0330 2001 2001 2001 2001 0330 0000",
  "0002 0001 0020 0010 0200 0100 2000 1000",
  "1000 2000 0100 0200 0010 0020 0001 0002",
  "1002 2001 0120 0210 0210 0120 2001 1002",
  "2333 2012 2012 2333 2002 2002 2002 0000",
  "2000 2331 2010 0330 0110 2331 0010 0000",
  "0333 0102 0333 0102 0333 0102 2002 0000",
  "2333 2002 2002 2333 2002 2002 2333 0000",
  "0020 3131 1120 3133 1101 3133 0011 0001",
  "0000 0210 0120 2001 0330 0220 0120 0000",
  "0311 0201 2333 0223 0313 2201 0220 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000",
  "0000 0000 0000 0000 0000 0000 0000 0000"];
pc8001.display=new Object();
pc8001.display.columns=80;
pc8001.display.initColor=0x98;
pc8001.initDisplay=function(svg){
  var d=pc8001.display;
  var x,y,e,t,c;
  d.svg=svg;
  d.lines=25;
  d.colors=new Array(256);
  d.colors.fill("control");
  for(x=0;x<8;x++){
    d.colors[0x08+x]="rgb(0 0 0)";
    d.colors[0x18+x]="#000000";
    d.colors[0x28+x]="rgb(0 0 255)";
    d.colors[0x38+x]="#0000ff";
    d.colors[0x48+x]="rgb(255 0 0)";
    d.colors[0x58+x]="#ff0000";
    d.colors[0x68+x]="rgb(255 0 255)";
    d.colors[0x78+x]="#ff00ff";
    d.colors[0x88+x]="rgb(0 255 0)";
    d.colors[0x98+x]="#00ff00";
    d.colors[0xa8+x]="rgb(0 255 255)";
    d.colors[0xb8+x]="#00ffff";
    d.colors[0xc8+x]="rgb(255 255 0)";
    d.colors[0xd8+x]="#ffff00";
    d.colors[0xe8+x]="rgb(255 255 255)";
    d.colors[0xf8+x]="#ffffff";
  }
  e=document.createElementNS("http://www.w3.org/2000/svg","text");
  e.setAttribute("font-family","monospace");
  e.setAttribute("font-size",2);
  e.setAttribute("fill","none");
  d.svg.appendChild(e);
  e.textContent=String.fromCodePoint(0x2588);
  d.monowidth=(e.getBBox().width<2)?1:2;
  e=document.createElementNS("http://www.w3.org/2000/svg","path");
  e=[[0x3000,0x2598,0x259d,0x2580],
     [0x2596,0x258c,0x259e,0x259b],
     [0x2597,0x259a,0x2590,0x259c],
     [0x2584,0x2599,0x259f,0x2588]];
  if(pc8001.display.monowidth<2)
    e[0][0]=0xa0;
  d.font=new Array(pc8001.font.length);
  d.font.fill("");
  d.font.forEach(function(v,x,a){
    var t=pc8001.font[x].split(" ");
    var i,j
    for(i=j=0;i<8;i++){
      if(t[i]=="0000")
        j++;
    }
    if(j!=8){
      for(i=0;i<8;i+=2){
        for(j=0;j<4;j++)
           a[x]+=String.fromCodePoint(e[t[i+1].substr(j,1)][t[i].substr(j,1)]);
      }
    }
  });
  d.blocks=new Array(256);
  d.blocks.fill("");
  for(x=1;x<256;x++){
    for(y=1;y<16;y*=2){
      t=((x&y)==0)?0:3;
      c=((x&(y<<4))==0)?0:3;
      d.blocks[x]+=String.fromCodePoint(e[t][t],e[t][t],e[c][c],e[c][c]);
    }
  }
  d.bgchars=new Array(56);
  d.bgchars.fill("");
  for(x=0;x<4;x++){
    d.bgchars[0x04+x]=d.bgchars[0x14+x]=d.bgchars[0x24+x]=d.bgchars[0x34+x]=String.fromCodePoint(0x2588);
    d.bgchars[0x10+x]=String.fromCodePoint(0x258f);
    d.bgchars[0x20+x]=String.fromCodePoint(0x2595);
    d.bgchars[0x30+x]=String.fromCodePoint(0x258c,e[0][0],e[0][0],0x2590);
  }
  e=document.createElementNS("http://www.w3.org/2000/svg","path");
  e.setAttribute("id","charpath");
  t=(d.monowidth<2)?"2.4":"4";
  e.setAttribute("d","M 0 1 h "+t+" m -"+t+" 1 h "+t+" m -"+t+" 1 h "+t+" m -"+t+" 1 h "+t);
  d.svg.appendChild(e);
  e=document.createElementNS("http://www.w3.org/2000/svg","g");
  e.setAttribute("class","blink");
  d.svg.appendChild(e);
  d.blinker=e;
  d.textArray=t=new Array(80);
  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();
      t[x][y].color=d.colors[d.initColor];
      c=(x%2==0||d.columns==80)?d.colors[d.initColor]:"none";
      e=document.createElementNS("http://www.w3.org/2000/svg","text");
      e.setAttribute("y",x*2);
      e.setAttribute("x",y*4);
      e.setAttribute("font-size",160/d.columns);
      e.setAttribute("font-family","monospace"); 
      e.setAttribute("fill",c);
      e.setAttribute("transform","matrix(0 1 1 0 "+((d.monowidth<2)?128:144)/d.columns+" 0)");
      e.setAttribute("textLength",4);
      e.setAttribute("lengthAdjust","spacingAndGlyphs");
      d.svg.appendChild(e);
      t[x][y].controlbox=e;
      t[x][y].control=0;
      e=document.createElementNS("http://www.w3.org/2000/svg","text");
      e.setAttribute("font-size",1);
      e.setAttribute("font-family","monospace");
      e.setAttribute("fill",c);
      e.setAttribute("transform","matrix("+((d.monowidth<2)?66:40)/d.columns+" 0 0 1 "+x*2+" "+y*4+")");
      d.svg.appendChild(e);
      t[x][y].textbox=e;
      e=document.createElementNS("http://www.w3.org/2000/svg","textPath");
      e.setAttribute("href","#charpath");
      t[x][y].textbox.appendChild(e);
      t[x][y].textpath=e;
      t[x][y].data=0;
    }
    pc8001.memory[d.end]=0;
    d.end++;
    pc8001.memory[d.end]=0;
    d.end++;
    pc8001.memory[d.end]=(d.columns==40)?2:1;
    d.end++;
    for(x=3;x<39;x++){
      pc8001.memory[d.end]=(x%2==0)?80:d.initColor;
      d.end++;
    }
    pc8001.memory[d.end]=0;
    d.end++;
  }
  d.end--;
}
pc8001.resizeDisplay=function(columns,lines){
  var d=pc8001.display;
  var x,y,t;
  if((columns!=40&&columns!=80)||lines<20||lines>25){
    console.log("Unable resizeDisplay",columns,lines);
    return;
  }
  if(columns!=d.columns||lines!=d.lines){
    for(y=0;y<25;y++){
      for(x=0;x<80;x++){
        t=d.textArray[x][y];
        t.controlbox.setAttribute("x",y*100/lines);
        t.controlbox.setAttribute("font-size",160/columns);
        t.controlbox.setAttribute("transform","matrix(0 1 1 0 "+(d.monowidth<2?128:144)/columns+" 0)");
        t.textbox.setAttribute("transform","matrix("+((d.monowidth<2)?66:40)/columns+" 0 0 1 "+x*2+" "+y*100/lines+")");
        t.controlbox.textContent=d.bgchars[t.control];
        t.textpath.textContent=(t.color.substr(0,1)=="#")?d.blocks[t.data]:d.font[t.data];
        if(y>=lines||(x%2==1&&columns==40)){
          t.controlbox.setAttribute("fill","none");
          t.textbox.setAttribute("fill","none");
        }
        else{
          t.controlbox.setAttribute("fill",t.color);
          t.textbox.setAttribute("fill",((t.control&1)==1)?"none":((t.control&4)==4)?"black":t.color);
          if((t.control&2)==2)
            d.blinker.appendChild(t.textbox);
          else
            d.svg.appendChild(t.textbox);
        }
      }
    }
  }
  d.columns=columns;
  d.lines=lines;
}
pc8001.writeMemory=function(address,data){
  var t=pc8001.memory[address];
  var d=pc8001.display;
  var x,y,f,i,j,k;
  if(data<0||data>0xff){
    console.log("writeMemory",address.toString(16),data);
    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);
    data=(data+65536)&0xff;
  }
  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){
    t=d.textArray[x][y];
    if(y<d.lines&&(x%2==0||d.columns==80))
      t.textpath.textContent=(t.color.substr(0,1)=="#")?d.blocks[data]:d.font[data];
    t.data=data;
    return;
  }
  for(f=1;f==1;y=(y>d.lines-2)?0:y+1){
    i=d.start+80+y*120;
    j=d.textArray[79][(y==0)?d.lines-1:y-1].control;
    k=d.textArray[79][(y==0)?d.lines-1:y-1].color;
    for(x=0;x<80;x++){
      if(pc8001.memory[i]==x){
        i++;
        t=d.colors[pc8001.memory[i]];
        if(t=="control")
          j=pc8001.memory[i]&0x3f;
        else
          k=t;
        i++;
      }
      t=d.textArray[x][y];
      f=0;
      if(t.color!=k){
        if(x%2==0||d.columns==80){
          t.controlbox.setAttribute("fill",k);
          t.textbox.setAttribute("fill",k);
          if(t.color.substr(0,1)!=k.substr(0,1))
            t.textpath.textContent=(k.substr(0,1)=="#")?d.blocks[t.data]:d.font[t.data];
        }
        t.color=k;
        f=1;
      }
      if(t.control!=j){
        if(x%2==0||d.columns==80){
          t.textbox.setAttribute("fill",((j&1)==1)?"none":((j&4)==4)?"black":k);
          if(((t.control^j)&2)==2){
            if((j&2)==2)
              d.blinker.appendChild(t.textbox);
            else
              d.svg.appendChild(t.textbox);
          }
          t.controlbox.textContent=d.bgchars[j];
        }
        t.control=j;
        f=1;
      }
    }
  }
}
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[98]=pc8001.keymap[40]=[0,0xfb];  // ten-key 2 = downarrow
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[104]=pc8001.keymap[38]=[1,0xfe]; // ten-key 8 = uparrow
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.beep.counter<0){
    pc8001.beep.counter=pc8001.beep.on=0;
    pc8001.beep.start=pc8001.z80.states;
    pc8001.beep.oscillator.start();
  }
}
pc8001.beep=new Object();
pc8001.beep.audio=new(window.AudioContext||window.webkitAudioContext)();
pc8001.beep.buffer=pc8001.beep.audio.createBuffer(1,Math.floor(pc8001.beep.audio.sampleRate/60),pc8001.beep.audio.sampleRate);
pc8001.beep.oscillator=pc8001.beep.audio.createBufferSource();
pc8001.beep.oscillator.buffer=pc8001.beep.buffer;
pc8001.beep.wave=pc8001.beep.buffer.getChannelData(0);
pc8001.beep.wave.fill(0);
pc8001.beep.counter=-1;
pc8001.beep.oscillator.loop=true;
pc8001.beep.oscillator.connect(pc8001.beep.audio.destination);
pc8001.beep.refWave=new Array(pc8001.beep.wave.length);
pc8001.beep.refWave.fill(0);
pc8001.beep.refWave.forEach(function(v,i,a){
  a[i]=Math.sin(i*Math.PI*2/pc8001.beep.audio.sampleRate*2400);
});
pc8001.z80=new Object();
pc8001.z80.frequency=3000000;                  // down to 3MHz
pc8001.z80.millistates=pc8001.z80.frequency/1000;
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,"V":0,"M":0,"DUMMY":0,"z":0,"c":0,"v":0,"m":0,"dummy":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(x,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],x.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.z80.ops[0x00]=["NOP",4];
pc8001.z80.mnemonics["NOP"]=function(x,m){
}
pc8001.operators=["ADD","ADC","SUB","SBC","AND","XOR","OR","CP"];
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.operators.forEach(function(w,j){
    pc8001.z80.ops[i+j*8+0x80]=[w,"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+0x18]=["RR",v,(i==6)?15:8];
  pc8001.z80.ops[0xcb][i+0x20]=["SLA",v,(i==6)?15:8];
  pc8001.z80.ops[0xcb][i+0x28]=["SRA",v,(i==6)?15:8];
  pc8001.z80.ops[0xcb][i+0x30]=["SLL",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.operators.forEach(function(v,i){
  pc8001.z80.ops[i*8+0xc6]=[v,"A","n",7];
  pc8001.z80.ops[0xdd][i*8+0x84]=[v,"A","J",8];
  pc8001.z80.ops[0xdd][i*8+0x85]=[v,"A","X",8];
  pc8001.z80.ops[0xdd][i*8+0x86]=[v,"A","(JX+d)",19];
  pc8001.z80.ops[0xfd][i*8+0x84]=[v,"A","K",8];
  pc8001.z80.ops[0xfd][i*8+0x85]=[v,"A","Y",8];
  pc8001.z80.ops[0xfd][i*8+0x86]=[v,"A","(KY+d)",19];
});
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(x,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 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];
      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]];
  }
  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[0xed][0x63]=["LD16","(nn)","HL",20];
pc8001.z80.ops[0xed][0x6b]=["LD16","HL","(nn)",20];
pc8001.z80.ops[0xed][0x73]=["LD16","(nn)","SP",20];
pc8001.z80.ops[0xed][0x7b]=["LD16","SP","(nn)",20];
pc8001.z80.ops[0xdd][0x21]=["LD16","JX","nn",14];
pc8001.z80.ops[0xdd][0x22]=["LD16","(nn)","JX",20];
pc8001.z80.ops[0xdd][0x2a]=["LD16","JX","(nn)",20];
pc8001.z80.ops[0xdd][0xf9]=["LD16","SP","JX",10];
pc8001.z80.ops[0xfd][0x21]=["LD16","KY","nn",14];
pc8001.z80.ops[0xfd][0x22]=["LD16","(nn)","KY",20];
pc8001.z80.ops[0xfd][0x2a]=["LD16","KY","(nn)",20];
pc8001.z80.ops[0xfd][0xf9]=["LD16","SP","KY",10];
pc8001.z80.mnemonics["LD16"]=function(x,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;
    case "SP":
      a=pc8001.z80.regs["SP"];
      h=a>>8;
      l=a&0xff;
      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(x,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","V","M","DUMMY"];
    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(x,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(x,m){
  var pc=pc8001.z80.regs["PC"];
  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];
      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;
      t=pc8001.memory[a];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[1]];
  }
  t=(t+1)&0xff;
  if(a<0)
    pc8001.z80.regs[m[1]]=t;
  else
    pc8001.writeMemory(a,t);
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  pc8001.z80.flags["V"]=(t==0x80)?1:0;
}
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.ops[0xdd][0x23]=["INC16","JX",10];
pc8001.z80.ops[0xfd][0x23]=["INC16","KY",10];
pc8001.z80.mnemonics["INC16"]=function(x,m){
  var t;
  if(m[1]=="SP")
    pc8001.z80.regs["SP"]=(pc8001.z80.regs["SP"]+1)&0xffff;
  else{
    pc8001.z80.regs[m[1].substr(1)]=t=(pc8001.z80.regs[m[1].substr(1)]+1)&0xff;
    if(t==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(x,m){
  var pc=pc8001.z80.regs["PC"];
  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];
      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;
      t=pc8001.memory[a];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[1]];
  }
  t=(t+0xff)&0xff;
  if(a<0)
    pc8001.z80.regs[m[1]]=t;
  else
    pc8001.writeMemory(a,t);
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  pc8001.z80.flags["V"]=(t==0x7f)?1:0;
}
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.ops[0xdd][0x2b]=["DEC16","JX",6];
pc8001.z80.ops[0xfd][0x2b]=["DEC16","KY",6];
pc8001.z80.mnemonics["DEC16"]=function(x,m){
  var t;
  if(m[1]=="SP")
    pc8001.z80.regs["SP"]=(pc8001.z80.regs["SP"]+0xffff)&0xffff;
  else{
    pc8001.z80.regs[m[1].substr(1)]=t=(pc8001.z80.regs[m[1].substr(1)]+0xff)&0xff;
    if(t==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(x,m){
  var t;
  t=pc8001.z80.regs[m[1].substr(0,1)]*256+pc8001.z80.regs[m[1].substr(1)];
  if(m[2]=="SP")
    t+=pc8001.z80.regs["SP"];
  else
    t+=pc8001.z80.regs[m[2].substr(0,1)]*256+pc8001.z80.regs[m[2].substr(1)];
  if(t>0xffff){
    pc8001.z80.flags["C"]=1;
    t&=0xffff;
  }
  else
    pc8001.z80.flags["C"]=0;
  pc8001.z80.regs[m[1].substr(0,1)]=t>>8;
  pc8001.z80.regs[m[1].substr(1)]=t&0xff;
}
pc8001.z80.mnemonics["ADD"]=function(x,m){
  var pc=pc8001.z80.regs["PC"];
  var a,t,u,v;
  switch(m[2].length){
    case 4:
      t=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;
      t=pc8001.memory[a];
      break;
    default:
      if(m[2]=="n"){
        t=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        t=pc8001.z80.regs[m[2]];
  }
  u=pc8001.z80.regs[m[1]];
  v=t+u;
  pc8001.z80.flags["C"]=(v>0xff)?1:0;
  v&=0xff;
  pc8001.z80.regs[m[1]]=v;
  pc8001.z80.flags["Z"]=(v==0)?1:0;
  pc8001.z80.flags["M"]=(v>0x7f)?1:0;
  pc8001.z80.flags["V"]=((t>0x7f&&u>0x7f&&v<0x80)||(t<0x80&&u<0x80&&v>0x7f))?1:0;
}
pc8001.z80.ops[0xed][0x4a]=["ADC16","HL","BC",15]
pc8001.z80.ops[0xed][0x5a]=["ADC16","HL","DE",15]
pc8001.z80.ops[0xed][0x6a]=["ADC16","HL","HL",15]
pc8001.z80.ops[0xed][0x7a]=["ADC16","HL","SP",15]
pc8001.z80.mnemonics["ADC16"]=function(x,m){
  var t,u,v;
  t=pc8001.z80.regs[m[1].substr(0,1)]*256+pc8001.z80.regs[m[1].substr(1)];
  if(m[2]=="SP")
    u=pc8001.z80.regs["SP"];
  else
    u=pc8001.z80.regs[m[2].substr(0,1)]*256+pc8001.z80.regs[m[2].substr(1)];
  v=t+u+pc8001.z80.flags["C"]
  if(v>0xffff){
    pc8001.z80.flags["C"]=1;
    v&=0xffff;
  }
  else
    pc8001.z80.flags["C"]=0;
  pc8001.z80.regs[m[1].substr(0,1)]=v>>8;
  pc8001.z80.regs[m[1].substr(1)]=v&0xff;
  pc8001.z80.flags["Z"]=(v==0)?1:0;
  pc8001.z80.flags["M"]=(v>0x7fff)?1:0;
  pc8001.z80.flags["V"]=((u<0x8000&&t<0x8000&&v>0x7fff)||(u>0x7fff&&t>0x7fff&&v<0x8000))?1:0;
}
pc8001.z80.mnemonics["ADC"]=function(x,m){
  var pc=pc8001.z80.regs["PC"];
  var a,t,u,v;
  switch(m[2].length){
    case 4:
      t=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;
      t=pc8001.memory[a];
      break;
    default:
      if(m[2]=="n"){
        t=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        t=pc8001.z80.regs[m[2]];
  }
  u=pc8001.z80.regs[m[1]];
  v=t+u+pc8001.z80.flags["C"];
  pc8001.z80.flags["C"]=(v>0xff)?1:0;
  v&=0xff;
  pc8001.z80.regs[m[1]]=v;
  pc8001.z80.flags["Z"]=(v==0)?1:0;
  pc8001.z80.flags["M"]=(v>0x7f)?1:0;
  pc8001.z80.flags["V"]=((t>0x7f&&u>0x7f&&v<0x80)||(t<0x80&&u<0x80&&v>0x7f))?1:0;
}
pc8001.z80.ops[0xed][0x44]=["NEG","A",8];
pc8001.z80.mnemonics["NEG"]=function(x,m){
  var t=(256-pc8001.z80.regs[m[1]])&0xff;
  pc8001.z80.regs[m[1]]=t;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["C"]=(t==0)?0:1;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  pc8001.z80.flags["V"]=(t==0x80)?1:0;
}
pc8001.z80.mnemonics["SUB"]=function(x,m){
  var pc=pc8001.z80.regs["PC"];
  var a,t,u,v;
  switch(m[2].length){
    case 4:
      t=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;
      t=pc8001.memory[a];
      break;
    default:
      if(m[2]=="n"){
        t=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        t=pc8001.z80.regs[m[2]];
  }
  u=pc8001.z80.regs[m[1]];
  v=u-t;
  pc8001.z80.flags["C"]=(v<0)?1:0;
  v=(v+256)&0xff;
  pc8001.z80.regs[m[1]]=v;
  pc8001.z80.flags["Z"]=(v==0)?1:0;
  pc8001.z80.flags["M"]=(v>0x7f)?1:0;
  pc8001.z80.flags["V"]=((u<0x80&&t>0x7f&&v>0x7f)||(u>0x7f&&t<0x80&&v<0x80))?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(x,m){
  var t,u,v;
  t=pc8001.z80.regs[m[1].substr(0,1)]*256+pc8001.z80.regs[m[1].substr(1)];
  if(m[2]=="SP")
    u=pc8001.z80.regs["SP"];
  else
    u=pc8001.z80.regs[m[2].substr(0,1)]*256+pc8001.z80.regs[m[2].substr(1)];
  v=t-u-pc8001.z80.flags["C"]
  if(v<0){
    pc8001.z80.flags["C"]=1;
    v=(v+65536)&0xffff;
  }
  else
    pc8001.z80.flags["C"]=0;
  pc8001.z80.regs[m[1].substr(0,1)]=v>>8;
  pc8001.z80.regs[m[1].substr(1)]=v&0xff;
  pc8001.z80.flags["Z"]=(v==0)?1:0;
  pc8001.z80.flags["M"]=(v>0x7fff)?1:0;
  pc8001.z80.flags["V"]=((u<0x8000&&t>0x7fff&&v>0x7fff)||(u>0x7fff&&t<0x8000&&v<0x8000))?1:0;
}
pc8001.z80.mnemonics["SBC"]=function(x,m){
  var pc=pc8001.z80.regs["PC"];
  var a,t,u,v;
  switch(m[2].length){
    case 4:
      t=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;
      t=pc8001.memory[a];
      break;
    default:
      if(m[2]=="n"){
        t=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        t=pc8001.z80.regs[m[2]];
  }
  u=pc8001.z80.regs[m[1]];
  v=u-t-pc8001.z80.flags["C"];
  pc8001.z80.flags["C"]=(v<0)?1:0;
  v=(v+256)&0xff;
  pc8001.z80.regs[m[1]]=v;
  pc8001.z80.flags["Z"]=(v==0)?1:0;
  pc8001.z80.flags["M"]=(v>0x7f)?1:0;
  pc8001.z80.flags["V"]=((u<0x80&&t>0x7f&&v>0x7f)||(u>0x7f&&t<0x80&&v<0x80))?1:0;
}
pc8001.z80.mnemonics["AND"]=function(x,m){
  var pc=pc8001.z80.regs["PC"];
  var a,t;
  switch(m[2].length){
    case 4:
      t=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;
      t=pc8001.memory[a];
      break;
    default:
      if(m[2]=="n"){
        t=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        t=pc8001.z80.regs[m[2]];
  }
  t&=pc8001.z80.regs[m[1]];
  pc8001.z80.regs[m[1]]=t;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  pc8001.z80.flags["C"]=0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.ops[0x2f]=["CPL","A",4];
pc8001.z80.mnemonics["CPL"]=function(x,m){
  pc8001.z80.regs[m[1]]^=0xff;
}
pc8001.z80.mnemonics["XOR"]=function(x,m){
  var pc=pc8001.z80.regs["PC"];
  var a,t;
  switch(m[2].length){
    case 4:
      t=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;
      t=pc8001.memory[a];
      break;
    default:
      if(m[2]=="n"){
        t=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        t=pc8001.z80.regs[m[2]];
  }
  t^=pc8001.z80.regs[m[1]];
  pc8001.z80.regs[m[1]]=t;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  pc8001.z80.flags["C"]=0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.mnemonics["OR"]=function(x,m){
  var pc=pc8001.z80.regs["PC"];
  var a,t;
  switch(m[2].length){
    case 4:
      t=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;
      t=pc8001.memory[a];
      break;
    default:
      if(m[2]=="n"){
        t=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        t=pc8001.z80.regs[m[2]];
  }
  t|=pc8001.z80.regs[m[1]];
  pc8001.z80.regs[m[1]]=t;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  pc8001.z80.flags["C"]=0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.mnemonics["CP"]=function(x,m){
  var pc=pc8001.z80.regs["PC"];
  var a,t,u,v;
  switch(m[2].length){
    case 4:
      t=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;
      t=pc8001.memory[a];
      break;
    default:
      if(m[2]=="n"){
        t=pc8001.memory[pc];
        pc8001.z80.regs["PC"]=pc=(pc+1)&0xffff;
      }
      else
        t=pc8001.z80.regs[m[2]];
  }
  u=pc8001.z80.regs[m[1]];
  v=u-t;
  pc8001.z80.flags["C"]=(v<0)?1:0;
  v=(v+256)&0xff;
  pc8001.z80.flags["Z"]=(v==0)?1:0;
  pc8001.z80.flags["M"]=(v>0x7f)?1:0;
  pc8001.z80.flags["V"]=((u<0x80&&t>0x7f&&v>0x7f)||(u>0x7f&&t<0x80&&v<0x80))?1:0;
}
pc8001.z80.ops[0x37]=["SCF",4];
pc8001.z80.mnemonics["SCF"]=function(x,m){
  pc8001.z80.flags["C"]=1;
}
pc8001.z80.ops[0x3f]=["CCF",4];
pc8001.z80.mnemonics["CCF"]=function(x,m){
  pc8001.z80.flags["C"]^=1;
}
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[0xe2]=["JP","NV","nn",10];
pc8001.z80.ops[0xea]=["JP","V","nn",10];
pc8001.z80.ops[0xf2]=["JP","NM","nn",10];
pc8001.z80.ops[0xfa]=["JP","M","nn",10];
pc8001.z80.ops[0xe9]=["JP","","(HL)",4];
pc8001.z80.ops[0xdd][0xe9]=["JP","","(JX)",8];
pc8001.z80.ops[0xfd][0xe9]=["JP","","(KY)",8];
pc8001.z80.mnemonics["JP"]=function(x,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(x,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[0xe4]=["CALL","NV","nn",17];
pc8001.z80.ops[0xe7]=["CALL","","0020",11];
pc8001.z80.ops[0xec]=["CALL","V","nn",17];
pc8001.z80.ops[0xef]=["CALL","","0028",11];
pc8001.z80.ops[0xf4]=["CALL","NM","nn",17];
pc8001.z80.ops[0xf7]=["CALL","","0030",11];
pc8001.z80.ops[0xfc]=["CALL","M","nn",17];
pc8001.z80.ops[0xff]=["CALL","","0038",11];
pc8001.z80.mnemonics["CALL"]=function(x,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.ops[0xe0]=["RET","NV",11];
pc8001.z80.ops[0xe8]=["RET","V",11];
pc8001.z80.ops[0xf0]=["RET","NM",11];
pc8001.z80.ops[0xf8]=["RET","M",11];
pc8001.z80.mnemonics["RET"]=function(x,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(x,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["DUMMY"]&0x3a)|pc8001.z80.flags["C"]|(pc8001.z80.flags["V"]<<2)|(pc8001.z80.flags["Z"]<<6)|(pc8001.z80.flags["M"]<<7));
  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(x,m){
  var sp=pc8001.z80.regs["SP"];
  var t=pc8001.memory[sp];
  if(m[1]=="AF"){
    pc8001.z80.flags["C"]=((t&1)==0)?0:1;
    pc8001.z80.flags["V"]=((t&4)==0)?0:1;
    pc8001.z80.flags["Z"]=((t&0x40)==0)?0:1;
    pc8001.z80.flags["M"]=((t&0x80)==0)?0:1;
    pc8001.z80.flags["DUMMY"]=t;
  }
  else
    pc8001.z80.regs[m[1].substr(1)]=t;
  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(x,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(x,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];
      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];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[1]];
  }
  c=(t>0x7f)?1:0;
  t=((t<<1)+c)&0xff;
  if(a<0)
    pc8001.z80.regs[m[1]]=t;
  else
    pc8001.writeMemory(a,t);
  pc8001.z80.flags["C"]=c;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.ops[0x0f]=["RRCA",4];
pc8001.z80.mnemonics["RRCA"]=function(x,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(x,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];
      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];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[1]];
  }
  c=t&1;
  t=(t>>1)+c*0x80;
  if(a<0)
    pc8001.z80.regs[m[1]]=t;
  else
    pc8001.writeMemory(a,t);
  pc8001.z80.flags["C"]=c;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.ops[0x17]=["RLA",4];
pc8001.z80.mnemonics["RLA"]=function(x,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(x,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];
      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];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[1]];
  }
  c=(t>0x7f)?1:0;
  t=((t<<1)+pc8001.z80.flags["C"])&0xff;
  if(a<0)
    pc8001.z80.regs[m[1]]=t;
  else
    pc8001.writeMemory(a,t);
  pc8001.z80.flags["C"]=c;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.ops[0x1f]=["RRA",4];
pc8001.z80.mnemonics["RRA"]=function(x,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["RR"]=function(x,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];
      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];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[1]];
  }
  c=t&1;
  t=(t>>1)+pc8001.z80.flags["C"]*0x80;
  if(a<0)
    pc8001.z80.regs[m[1]]=t;
  else
    pc8001.writeMemory(a,t);
  pc8001.z80.flags["C"]=c;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.mnemonics["SLA"]=function(x,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];
      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];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[1]];
  }
  t=t<<1;
  pc8001.z80.flags["C"]=(t>0xff)?1:0;
  t&=0xff;
  if(a<0)
    pc8001.z80.regs[m[1]]=t;
  else
    pc8001.writeMemory(a,t);
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.mnemonics["SRA"]=function(x,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];
      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];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[1]];
  }
  pc8001.z80.flags["C"]=t&1;
  t=((t>>1)|(t&0x80));
  if(a<0)
    pc8001.z80.regs[m[1]]=t;
  else
    pc8001.writeMemory(a,t);
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.mnemonics["SLL"]=function(x,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];
      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];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[1]];
  }
  t=(t<<1)|1;
  pc8001.z80.flags["C"]=(t>0xff)?1:0;
  t&=0xff;
  if(a<0)
    pc8001.z80.regs[m[1]]=t;
  else
    pc8001.writeMemory(a,t);
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.mnemonics["SRL"]=function(x,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];
      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];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[1]];
  }
  pc8001.z80.flags["C"]=t&1;
  t=t>>1;
  if(a<0)
    pc8001.z80.regs[m[1]]=t;
  else
    pc8001.writeMemory(a,t);
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.mnemonics["BIT"]=function(x,m){
  var a,t;
  switch(m[2].length){
    case 4:
      a=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      t=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;
      t=pc8001.memory[a];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[2]];
  }
  pc8001.z80.flags["Z"]=((t&(1<<m[1]))==0)?1:0;
}
pc8001.z80.mnemonics["RES"]=function(x,m){
  var a,t
  switch(m[2].length){
    case 4:
      a=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      t=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;
      t=pc8001.memory[a];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[2]]
  }
  t&=(1<<m[1])^0xff;
  if(a<0)
    pc8001.z80.regs[m[2]]=t;
  else
    pc8001.writeMemory(a,t);
}
pc8001.z80.mnemonics["SET"]=function(x,m){
  var a,t;
  switch(m[2].length){
    case 4:
      a=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
      t=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;
      t=pc8001.memory[a];
      break;
    default:
      a=-1;
      t=pc8001.z80.regs[m[2]]
  }
  t|=1<<m[1];
  if(a<0)
    pc8001.z80.regs[m[2]]=t;
  else
    pc8001.writeMemory(a,t);
}
pc8001.z80.ops[0xed][0xa0]=["LDI",16];
pc8001.z80.mnemonics["LDI"]=function(x,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.flags["V"]=(bc==0)?0:1;
}
pc8001.z80.ops[0xed][0xb0]=["LDIR",21];
pc8001.z80.mnemonics["LDIR"]=function(x,m){
  pc8001.z80.mnemonics["LDI"](x,m);
  if(pc8001.z80.flags["V"]==1)
    pc8001.z80.regs["PC"]=(pc8001.z80.regs["PC"]+0xfffe)&0xffff;
}
pc8001.z80.ops[0xed][0xa8]=["LDD",16];
pc8001.z80.mnemonics["LDD"]=function(x,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.flags["V"]=(bc==0)?0:1;
}
pc8001.z80.ops[0xed][0xb8]=["LDDR",21];
pc8001.z80.mnemonics["LDDR"]=function(x,m){
  pc8001.z80.mnemonics["LDD"](x,m);
  if(pc8001.z80.flags["V"]==1)
    pc8001.z80.regs["PC"]=(pc8001.z80.regs["PC"]+0xfffe)&0xffff;
}
pc8001.z80.ops[0xed][0xa1]=["CPI",16];
pc8001.z80.mnemonics["CPI"]=function(x,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var bc=pc8001.z80.regs["B"]*256+pc8001.z80.regs["C"];
  var t=(pc8001.z80.regs["A"]-pc8001.memory[hl]+256)&0xff;
  hl=(hl+1)&0xffff;
  bc=(bc+0xffff)&0xffff;
  pc8001.z80.regs["H"]=hl>>8;
  pc8001.z80.regs["L"]=hl&0xff;
  pc8001.z80.regs["B"]=bc>>8;
  pc8001.z80.regs["C"]=bc&0xff;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  pc8001.z80.flags["V"]=(bc==0)?0:1;
}
pc8001.z80.ops[0xed][0xb1]=["CPIR",21];
pc8001.z80.mnemonics["CPIR"]=function(x,m){
  pc8001.z80.mnemonics["CPI"](x,m);
  if(pc8001.z80.flags["V"]==1&&pc8001.z80.flags["Z"]==0)
    pc8001.z80.regs["PC"]=(pc8001.z80.regs["PC"]+0xfffe)&0xffff;
}
pc8001.z80.ops[0xed][0xa9]=["CPD",16];
pc8001.z80.mnemonics["CPD"]=function(x,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var bc=pc8001.z80.regs["B"]*256+pc8001.z80.regs["C"];
  var t=(pc8001.z80.regs["A"]-pc8001.memory[hl]+256)&0xff;
  hl=(hl+0xffff)&0xffff;
  bc=(bc+0xffff)&0xffff;
  pc8001.z80.regs["H"]=hl>>8;
  pc8001.z80.regs["L"]=hl&0xff;
  pc8001.z80.regs["B"]=bc>>8;
  pc8001.z80.regs["C"]=bc&0xff;
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  pc8001.z80.flags["V"]=(bc==0)?0:1;
}
pc8001.z80.ops[0xed][0xb9]=["CPDR",21];
pc8001.z80.mnemonics["CPDR"]=function(x,m){
  pc8001.z80.mnemonics["CPD"](x,m);
  if(pc8001.z80.flags["V"]==1&&pc8001.z80.flags["Z"]==0)
    pc8001.z80.regs["PC"]=(pc8001.z80.regs["PC"]+0xfffe)&0xffff;
}
pc8001.z80.ops[0xdb]=["IN","A","(n)",11];
pc8001.z80.mnemonics["IN"]=function(x,m){
  var c,t,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]]=t=pc8001.inports[c];
  if(m[2]!="(n)"){
    pc8001.z80.flags["Z"]=(t==0)?1:0;
    pc8001.z80.flags["M"]=(t>0x7f)?1:0;
    t=(((t>>6)|4)^(t>>3)^t)&3;
    pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
  }
}
pc8001.z80.ops[0xed][0xa2]=["INI",16];
pc8001.z80.mnemonics["INI"]=function(x,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var b=pc8001.z80.regs["B"];
  pc8001.writeMemory(hl,pc8001.inports(pc8001.z80.regs["C"]));
  hl=(hl+1)&0xffff;
  b=(b+0xff)&0xff;
  pc8001.z80.regs["H"]=hl>>8;
  pc8001.z80.regs["L"]=hl&0xff;
  pc8001.z80.regs["B"]=b;
  pc8001.z80.flags["Z"]=(b==0)?1:0;
}
pc8001.z80.ops[0xed][0xb2]=["INIR",21];
pc8001.z80.mnemonics["INIR"]=function(x,m){
  pc8001.z80.mnemonics["INI"](x,m);
  if(pc8001.z80.flags["Z"]==0)
    pc8001.z80.regs["PC"]=(pc8001.z80.regs["PC"]+0xfffe)&0xffff;
}
pc8001.z80.ops[0xed][0xaa]=["IND",16];
pc8001.z80.mnemonics["IND"]=function(x,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var b=pc8001.z80.regs["B"];
  pc8001.writeMemory(hl,pc8001.inports(pc8001.z80.regs["C"]));
  hl=(hl+0xffff)&0xffff;
  b=(b+0xff)&0xff;
  pc8001.z80.regs["H"]=hl>>8;
  pc8001.z80.regs["L"]=hl&0xff;
  pc8001.z80.regs["B"]=b;
  pc8001.z80.flags["Z"]=(b==0)?1:0;
}
pc8001.z80.ops[0xed][0xb2]=["INDR",21];
pc8001.z80.mnemonics["INDR"]=function(x,m){
  pc8001.z80.mnemonics["IND"](x,m);
  if(pc8001.z80.flags["Z"]==0)
    pc8001.z80.regs["PC"]=(pc8001.z80.regs["PC"]+0xfffe)&0xffff;
}
pc8001.z80.ops[0xd3]=["OUT","(n)","A",11];
pc8001.z80.mnemonics["OUT"]=function(x,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.z80.ops[0xed][0xa3]=["OUTI",16];
pc8001.z80.mnemonics["OUTI"]=function(x,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var b=pc8001.z80.regs["B"];
  pc8001.outports(pc8001.z80.regs["C"],pc8001.memory[hl]);
  hl=(hl+1)&0xffff;
  b=(b+0xff)&0xff;
  pc8001.z80.regs["H"]=hl>>8;
  pc8001.z80.regs["L"]=hl&0xff;
  pc8001.z80.regs["B"]=b;
  pc8001.z80.flags["Z"]=(b==0)?1:0;
}
pc8001.z80.ops[0xed][0xb3]=["OTIR",21];
pc8001.z80.mnemonics["OTIR"]=function(x,m){
  pc8001.z80.mnemonics["OUTI"](x,m);
  if(pc8001.z80.flags["Z"]==0)
    pc8001.z80.regs["PC"]=(pc8001.z80.regs["PC"]+0xfffe)&0xffff;
}
pc8001.z80.ops[0xed][0xab]=["OUTD",16];
pc8001.z80.mnemonics["OUTD"]=function(x,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var b=pc8001.z80.regs["B"];
  pc8001.outports(pc8001.z80.regs["C"],pc8001.memory[hl]);
  hl=(hl+0xffff)&0xffff;
  b=(b+0xff)&0xff;
  pc8001.z80.regs["H"]=hl>>8;
  pc8001.z80.regs["L"]=hl&0xff;
  pc8001.z80.regs["B"]=b;
  pc8001.z80.flags["Z"]=(b==0)?1:0;
}
pc8001.z80.ops[0xed][0xbb]=["OTDR",21];
pc8001.z80.mnemonics["OTDR"]=function(x,m){
  pc8001.z80.mnemonics["OUTD"](x,m);
  if(pc8001.z80.flags["Z"]==0)
    pc8001.z80.regs["PC"]=(pc8001.z80.regs["PC"]+0xfffe)&0xffff;
}
pc8001.outports=function(p,d){
  switch(p){
    case 0x30:
      pc8001.resizeDisplay(((d&1)==1)?80:40,25);
      return;
    case 0x40:
      pc8001.beep.on=((d&0x20)==0)?0:1;
      return;
  }
  pc8001.z80.mnemonics["UNDEF"](p,["UNDEF","OUT",0]);
}
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(x,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.mnemonics[m[0]](v,m);
    if(pc8001.z80.halt==1)
      return;
    if(pc8001.beep.counter!=-1){
      v=Math.floor(pc8001.z80.states*pc8001.beep.audio.sampleRate/pc8001.z80.frequency)%pc8001.beep.refWave.length;
      if(v==pc8001.beep.counter){
        pc8001.beep.wave[v]=pc8001.beep.on*pc8001.beep.refWave[v];
        pc8001.beep.counter=(pc8001.beep.counter+1)%pc8001.beep.refWave.length;
      }
    }
    s=pc8001.z80.states-(performance.now()-pc8001.z80.millitimer)*pc8001.z80.millistates;
    if(s>1000)
      break;
  }
  if(s<0){
    pc8001.z80.states%=pc8001.z80.frequency;
    pc8001.z80.millitimer=performance.now()-pc8001.z80.states/pc8001.z80.millistates;
  }
  pc8001.z80.timer=setTimeout("clearTimeout(pc8001.z80.timer);pc8001.z80.run()",(s>1000)?s/pc8001.z80.millistates:0);
}
pc8001.run=function(){
  document.addEventListener("keydown",pc8001.keydown);
  document.addEventListener("keyup",pc8001.keyup);
  pc8001.z80.millitimer=performance.now();
  pc8001.z80.run();
}
</script>
<style>
.blink{
  animation: blink 1.5s step-end infinite
}
@keyframes blink{
  0% {opacity:1}
  75% {opacity:0}
}
</style>
</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.initDisplay(this);pc8001.run()">
</svg>
</body>
</html>
```

キーボードは、テンキーの2 4 6 8を、下左右上のカーソルキーにも割り当てておいた。まだ、あちこちバグが残ってると思うので、ぜひ試しに遊んでみてほしい。