0
1

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によるPC-8001エミュレータにおける「tan関数の有理数近似」直線

Last updated at Posted at 2025-06-24

PC-8001の160×100ドット画面において、画面中心を(0,0)とする時、HLレジスタで始点のXY座標(いずれも符号付き整数)、Cレジスタで角度(2π/256刻み)を渡すと、直線の描画をおこなうZ80プログラム(6月17日18日23日記事参照)を、もう少し高速化してみよう。キーとなるアイデアは、tan関数の有理数近似である。

  • tan(0π/128)=0/1
  • tan(1π/128)≒1/41
  • tan(2π/128)≒1/20
  • tan(3π/128)≒1/14
  • tan(4π/128)≒1/10
  • tan(5π/128)≒1/8
  • tan(6π/128)≒1/7
  • tan(7π/128)≒1/6
  • tan(8π/128)≒1/5
  • tan(9π/128)≒2/9
  • tan(10π/128)≒1/4
  • tan(11π/128)≒2/7
  • tan(12π/128)≒3/10
  • tan(13π/128)≒1/3
  • tan(14π/128)≒5/14
  • tan(15π/128)≒5/13
  • tan(16π/128)≒5/12
  • tan(17π/128)≒4/9
  • tan(18π/128)≒9/19
  • tan(19π/128)≒1/2
  • tan(20π/128)≒8/15
  • tan(21π/128)≒4/7
  • tan(22π/128)≒3/5
  • tan(23π/128)≒5/8
  • tan(24π/128)≒2/3
  • tan(25π/128)≒7/10
  • tan(26π/128)≒3/4
  • tan(27π/128)≒4/5
  • tan(28π/128)≒5/6
  • tan(29π/128)≒6/7
  • tan(30π/128)≒9/10
  • tan(31π/128)≒20/21
  • tan(32π/128)=1/1

C=00Hについては、画面番地変換(HLレジスタにPC-8001での画面番地、Bレジスタにバイト内ドット位置を返す)と右1ドット移動を使えば、以下のように書ける。

DC00 E5     PUSH HL        # 直線描画(C=00H)
DC01 D9      EXX
DC02 E1      POP HL
DC03 CDC0E6 CALL E6C0H
DC06 D9      EXX
DC07 D8      RET C
DC08 D9      EXX
DC09 7E       LD A,(HL)
DC0A B0       OR A,B
DC0B 77       LD (HL),A
DC0C D9      EXX
DC0D 7C       LD A,H
DC0E BA       CP A,D
DC0F C8      RET Z
DC10 24      INC H
DC11 D9      EXX
DC12 CD30E7 CALL E730H
DC15 18F2     JR DC09H

E6C0 7C       LD A,H       # 画面番地変換
E6C1 C6B0    ADD A,B0H
E6C3 D660    SUB A,60H
E6C5 D8      RET C
E6C6 1F      RRA
E6C7 5F       LD E,A
E6C8 9F      SBC A,A
E6C9 E60F    AND A,0FH
E6CB 3C      INC A
E6CC 47       LD B,A
E6CD 3ECE     LD A,CEH
E6CF 95      SUB A,L
E6D0 D69C    SUB A,9CH
E6D2 D8      RET C
E6D3 CB47    BIT 0,A
E6D5 2802     JR Z,E6D9H
E6D7 CB20    SLA B
E6D9 CB4F    BIT 1,A
E6DB 2804     JR Z,E6E1H
E6DD CB20    SLA B
E6DF CB20    SLA B
E6E1 E67C    AND A,7CH
E6E3 57       LD D,A
E6E4 CB22    SLA D
E6E6 0F     RRCA
E6E7 0F     RRCA
E6E8 1F      RRA
E6E9 67       LD H,A
E6EA 9F      SBC A,A
E6EB E680    AND A,80H
E6ED 92      SUB A,D
E6EE 6F       LD L,A
E6EF 3001     JR NC,E6F2H
E6F1 25      DEC H
E6F2 16F3     LD D,F3H
E6F4 19      ADD HL,DE
E6F5 C9      RET

E730 78       LD A,B       # 右1ドット移動
E731 07     RLCA
E732 07     RLCA
E733 07     RLCA
E734 07     RLCA
E735 47       LD B,A
E736 E60F    AND A,0FH
E738 C8      RET Z
E739 23      INC HL
E73A C9      RET

C=20Hについては、画面番地変換と右上1ドット移動を使えば、以下のように書ける。

DD00 E5     PUSH HL        # 直線描画(C=20H)
DD01 D9      EXX
DD02 E1      POP HL
DD03 CDC0E6 CALL E6C0H
DD06 D9      EXX
DD07 D8      RET C
DD08 D9      EXX
DD09 7E       LD A,(HL)
DD0A B0       OR A,B
DD0B 77       LD (HL),A
DD0C D9      EXX
DD0D 7C       LD A,H
DD0E BA       CP A,D
DD0F C8      RET Z
DD10 7D       LD A,L
DD11 BB       CP A,E
DD12 C8      RET Z
DD13 24      INC H
DD14 2C      INC L
DD15 D9      EXX
DD16 CD80E7 CALL E780H
DD19 18EE     JR DD09H

E780 78       LD A,B       # 右上1ドット移動
E781 E611    AND A,11H
E783 200A     JR NZ,E78FH
E785 78       LD A,B
E786 07     RLCA
E787 07     RLCA
E788 07     RLCA
E789 47       LD B,A
E78A E60F    AND A,0FH
E78C C8      RET Z
E78D 23      INC HL
E78E C9      RET
E78F 0F     RRCA
E790 017700   LD BC,0077H
E793 ED42    SBC HL,BC
E795 47       LD B,A
E796 C9      RET

tan(C)≒1/kを満たす01H≦C≦08HおよびC=0AH,0DH,13Hは、k回に1回の割合で右上1ドット移動して、残るk-1回は右1ドット移動すればいい。

DC20 0E29     LD C,29H     # 直線描画(C=01H)
DC22 1815     JR DC39H
DC24 0E14     LD C,14H     # 直線描画(C=02H)
DC26 1811     JR DC39H
DC28 0E0E     LD C,0EH     # 直線描画(C=03H)
DC2A 180D     JR DC39H
DC2C 0D      DEC C         # 直線描画(C=04H,0AH)
DC2D 3E0D     LD A,0DH     # 直線描画(C=05H,06H,07H,08H)
DC2F 91      SUB A,C
DC30 4F       LD C,A
DC31 1806     JR DC39H
DC33 0E03     LD C,03H     # 直線描画(C=0DH)
DC35 1802     JR DC39H
DC37 0E02     LD C,02H     # 直線描画(C=13H)
DC39 E5     PUSH HL
DC3A D9      EXX
DC3B E1      POP HL
DC3C CDC0E6 CALL E6C0H
DC3F D9      EXX
DC40 D8      RET C
DC41 41       LD B,C
DC42 CB38    SRL B
DC44 D9      EXX
DC45 7E       LD A,(HL)
DC46 B0       OR A,B
DC47 77       LD (HL),A
DC48 D9      EXX
DC49 7D       LD A,L
DC4A BB       CP A,E
DC4B C8      RET Z
DC4C 7C       LD A,H
DC4D BA       CP A,D
DC4E C8      RET Z
DC4F 24      INC H
DC50 1008   DJNZ DC5AH
DC52 2C      INC L
DC53 41       LD B,C
DC54 D9      EXX
DC55 CD80E7 CALL E780H
DC58 18EB     JR DC45H
DC5A D9      EXX
DC5B CD30E7 CALL E730H
DC5E 7E       LD A,(HL)
DC5F B0       OR A,B
DC60 77       LD (HL),A
DC61 D9      EXX
DC62 18E8     JR DC4CH

tan(C)≒(k-1)/kを満たすC=18Hおよび1AH≦C≦1FHは、k回に1回の割合で右1ドット移動して、残るk-1回は右上1ドット移動すればいい。

DC70 0C      INC C         # 直線描画(C=18H)
DC71 79       LD A,C       # 直線描画(C=1AH,1BH,1CH,1DH)
DC72 D616    SUB A,16H
DC74 4F       LD C,A
DC75 1806     JR DC7DH
DC77 0E0A     LD C,0AH     # 直線描画(C=1EH)
DC79 1802     JR DC7DH
DC7B 0E15     LD C,15H     # 直背描画(C=1FH)
DC7D E5     PUSH HL
DC7E D9      EXX
DC7F E1      POP HL
DC80 CDC0E6 CALL E6C0H
DC83 D9      EXX
DC84 D8      RET C
DC85 41       LD B,C
DC86 CB38    SRL B
DC88 D9      EXX
DC89 7E       LD A,(HL)
DC8A B0       OR A,B
DC8B 77       LD (HL),A
DC8C D9      EXX
DC8D 7D       LD A,L
DC8E BB       CP A,E
DC8F C8      RET Z
DC90 7C       LD A,H
DC91 BA       CP A,D
DC92 C8      RET Z
DC93 24      INC H
DC94 100B   DJNZ DCA1H
DC96 41       LD B,C
DC97 D9      EXX
DC98 CD30E7 CALL E730H
DC9B 7E       LD A,(HL)
DC9C B0       OR A,B
DC9D 77       LD (HL),A
DC9E D9      EXX
DC9F 18EF     JR DC90H
DCA1 2C      INC L
DCA2 D9      EXX
DCA3 CD80E7 CALL E780H
DCA6 18E1     JR DC89H

悩ましいのはC=09H,0BH,0EH,0FH,10H,11H,12H,14H,15H,16H,17H,19Hだが、これらについてはtan表を引いて、256を分母とする有理数で近似することにする。

DCB0 E5     PUSH HL        # 直線描画(01H≦C≦1FH)
DCB1 D9      EXX
DCB2 E1      POP HL
DCB3 CDC0E6 CALL E6C0H
DCB6 D9      EXX
DCB7 D8      RET C
DCB8 CB21    SLA C
DCBA 06E8     LD B,E8H
DCBC 0A       LD A,(BC)
DCBD 4F       LD C,A
DCBE 0680     LD B,80H
DCC0 D9      EXX
DCC1 7E       LD A,(HL)
DCC2 B0       OR A,B
DCC3 77       LD (HL),A
DCC4 D9      EXX
DCC5 7D       LD A,L
DCC6 BB       CP A,E
DCC7 C8      RET Z
DCC8 7C       LD A,H
DCC9 BA       CP A,D
DCCA C8      RET Z
DCCB 24      INC H
DCCC 78       LD A,B
DCCD 81      ADD A,C
DCCE 47       LD B,A
DCCF 3007     JR NC,DCD8H
DCD1 2C      INC L
DCD2 D9      EXX
DCD3 CD80E7 CALL E780H
DCD6 18E9     JR DCC1H
DCD8 D9      EXX
DCD9 CD30E7 CALL E730H
DCDC 7E       LD A,(HL)
DCDD B0       OR A,B
DCDE 77       LD (HL),A
DCDF D9      EXX
DCE0 18E6     JR DCC8H

E800 00 00 06 00 0D 00 13 00 19 00 20 00 26 00 2C 00
E810 33 00 39 00 40 00 47 00 4E 00 55 00 5C 00 63 00
E820 6A 00 71 00 79 00 81 00 89 00 91 00 99 00 A2 00
E830 AB 00 B4 00 BE 00 C8 00 D2 00 DD 00 E8 00 F4 00
E840 00 01 0D 01 1A 01 29 01 38 01 48 01 59 01 6B 01
E850 7F 01 94 01 AB 01 C4 01 DF 01 FD 01 1D 02 42 02
E860 6A 02 98 02 CB 02 07 03 4C 03 9D 03 FE 03 74 04
E870 07 05 C3 05 BE 06 1C 08 27 0A 8F 0D 5B 14 BC 28
E880 FF 7F

E890 26E8     LD H,E8H     # tan関数
E892 CB71    BIT 6,C
E894 280D     JR Z,E8A3H
E896 AF      XOR A,A
E897 91      SUB A,C
E898 87      ADD A,A
E899 6F       LD L,A
E89A 7E       LD A,(HL)
E89B 2F      CPL
E89C 5F       LD E,A
E89D 2C      INC L
E89E 7E       LD A,(HL)
E89F 2F      CPL
E8A0 57       LD D,A
E8A1 13      INC DE
E8A2 C9      RET
E8A3 69       LD L,C
E8A4 CB25    SLA L
E8A6 5E       LD E,(HL)
E8A7 2C      INC L
E8A8 56       LD D,(HL)
E8A9 C9      RET

この手法を21H≦C≦FFHにも拡張して、以下のPC-8001エミュレータに実装してみた。1ドット描くのに平均180ステートかかるので、長さ50の直線を1本引くだけで9000ステートほど必要である。テンキーの4と6(あるいは左右の矢印キー)で、実際の動作速度を確かめてみてほしい。

<!DOCTYPE html><head><meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>PC-8001 Emulator by Koichi Yasuoka, June 25, 2025</title>
<script>
var pc8001=new Object();
pc8001.memory=new Array(65536);
pc8001.memory.fill(0x76);
["0000 C3 00 DA",
 "045A                               C3 50 09",          // clear display
 "093A                               79 32 62 EA 78 32", // init display
 "0940 65 EA C6 B0 3E 14 8F 32 66 EA D3 30 3E 20 D3 51",
 "0950 ED 5B 5A EA 21 00 F3 06 50 73 23 10 FC 70 23 70",
 "0960 23 3A 65 EA C6 B0 9F C6 02 77 23 72 23 01 50 11",
 "0970 71 23 72 23 10 FA 71 23 70 23 11 00 F3 EB 01 B8",
 "0980 0B ED B0 21 01 01 22 63 EA C9",

 "DA00 31 FF FF 21 00 B8 22 5A EA 26 FF 22 60 EA AF 32",
 "DA10 5F EA 3E 05 32 66 EA 01 19 50 CD 3A 09 3E E0 32",
 "DA20 D0 E8 CD 80 DB CD 50 DA DB 00 F6 AF FE BF 28 0F",
 "DA30 FE EF 20 F4 3A D0 E8 FE 20 28 ED C6 02 18 E0 3A",
 "DA40 D0 E8 FE E0 28 E2 D6 02 18 D5",

 "DA50 3A D0 E8 4F CB 2F 32 D1 E8 CD 90 E8 62 6B 29 29",
 "DA60 29 19 29 29 2E 2C 22 D2 E8 11 D4 80 0E C0 CD 40",
 "DA70 E7 3A D1 E8 D6 10 4F 2A D2 E8 11 00 4F CD 40 E7",
 "DA80 3A D1 E8 2F C6 11 4F 2A D2 E8 2E D4 11 00 4F CD",
 "DA90 40 E7 7D B7 20 1B E5 3A D1 E8 C6 30 4F 11 32 4F",
 "DAA0 CD 40 E7 E1 3A D1 E8 2F D6 2F 4F 11 CF 4F CD 40",
 "DAB0 E7 3A D1 E8 D6 70 4F 2A D2 E8 11 00 B0 CD 40 E7",
 "DAC0 3A D1 E8 2F C6 71 4F 2A D2 E8 2E D4 11 00 B0 CD",
 "DAD0 40 E7 7D B7 C0 E5 3A D1 E8 C6 50 4F 11 32 B0 CD",
 "DAE0 40 E7 E1 3A D1 E8 2F D6 4F 4F 11 CF B0 C3 40 E7",

 "DB80 21 00 00 39 D9 31 50 F3 11 00 00 06 19 D5 D5 D5",
 "DB90 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5",
 "DBA0 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5 D5",
 "DBB0 D5 D5 D5 D5 D5 21 C8 00 39 F9 10 D1 D9 F9 C9",

 "DC00 E5 D9 E1 CD C0 E6 D9 D8 D9 7E B0 77 D9 7C BA C8",
 "DC10 24 D9 CD 30 E7 18 F2",
 "DC20 0E 29 18 15 0E 14 18 11 0E 0E 18 0D 0D 3E 0D 91",
 "DC30 4F 18 06 0E 03 18 02 0E 02 E5 D9 E1 CD C0 E6 D9",
 "DC40 D8 41 CB 38 D9 7E B0 77 D9 7D BB C8 7C BA C8 24",
 "DC50 10 08 2C 41 D9 CD 80 E7 18 EB D9 CD 30 E7 7E B0",
 "DC60 77 D9 18 E8",
 "DC70 0C 79 D6 16 4F 18 06 0E 0A 18 02 0E 15 E5 D9 E1",
 "DC80 CD C0 E6 D9 D8 41 CB 38 D9 7E B0 77 D9 7D BB C8",
 "DC90 7C BA C8 24 10 0B 41 D9 CD 30 E7 7E B0 77 D9 18",
 "DCA0 EF 2C D9 CD 80 E7 18 E1",
 "DCB0 E5 D9 E1 CD C0 E6 D9 D8 CB 21 06 E8 0A 4F 06 80",
 "DCC0 D9 7E B0 77 D9 7D BB C8 7C BA C8 24 78 81 47 30",
 "DCD0 07 2C D9 CD 80 E7 18 E9 D9 CD 30 E7 7E B0 77 D9",
 "DCE0 18 E6",

 "DD00 E5 D9 E1 CD C0 E6 D9 D8 D9 7E B0 77 D9 7C BA C8",
 "DD10 7D BB C8 24 2C D9 CD 80 E7 18 EE",
 "DD20 0E 29 18 15 0E 14 18 11 0E 0E 18 0D 0C 79 D6 33",
 "DD30 4F 18 06 0E 03 18 02 0E 02 E5 D9 E1 CD C0 E6 D9",
 "DD40 D8 41 CB 38 D9 7E B0 77 D9 7C BA C8 7D BB C8 2C",
 "DD50 10 08 24 41 D9 CD 80 E7 18 EB D9 CD 00 E7 7E B0",
 "DD60 77 D9 18 E8",
 "DD70 0D 3E 2A 91 4F 18 06 0E 0A 18 02 0E 15 E5 D9 E1",
 "DD80 CD C0 E6 D9 D8 41 CB 38 D9 7E B0 77 D9 7C BA C8",
 "DD90 7D BB C8 2C 10 0B 41 D9 CD 00 E7 7E B0 77 D9 18",
 "DDA0 EF 24 D9 CD 80 E7 18 E1",
 "DDB0 E5 D9 E1 CD C0 E6 D9 D8 3E 40 91 87 4F 06 E8 0A",
 "DDC0 4F 06 80 D9 7E B0 77 D9 7C BA C8 7D BB C8 2C 78",
 "DDD0 81 47 30 07 24 D9 CD 80 E7 18 E9 D9 CD 00 E7 7E",
 "DDE0 B0 77 D9 18 E6",

 "DE00 E5 D9 E1 CD C0 E6 D9 D8 D9 7E B0 77 D9 7D BB C8",
 "DE10 2C D9 CD 00 E7 18 F2",
 "DE20 0E 29 18 15 0E 14 18 11 0E 0E 18 0D 0D 3E 4D 91",
 "DE30 4F 18 06 0E 03 18 02 0E 02 E5 D9 E1 CD C0 E6 D9",
 "DE40 D8 41 CB 38 D9 7E B0 77 D9 7C BA C8 7D BB C8 2C",
 "DE50 10 08 25 41 D9 CD A0 E7 18 EB D9 CD 00 E7 7E B0",
 "DE60 77 D9 18 E8",
 "DE70 0C 79 D6 56 4F 18 06 0E 0A 18 02 0E 15 E5 D9 E1",
 "DE80 CD C0 E6 D9 D8 41 CB 38 D9 7E B0 77 D9 7C BA C8",
 "DE90 7D BB C8 2C 10 0B 41 D9 CD 00 E7 7E B0 77 D9 18",
 "DEA0 EF 25 D9 CD A0 E7 18 E1",
 "DEB0 E5 D9 E1 CD C0 E6 D9 D8 CB 21 CB B9 06 E8 0A 4F",
 "DEC0 06 80 D9 7E B0 77 D9 7C BA C8 7D BB C8 2C 78 81",
 "DED0 47 30 07 25 D9 CD A0 E7 18 E9 D9 CD 00 E7 7E B0",
 "DEE0 77 D9 18 E6",

 "DF00 E5 D9 E1 CD C0 E6 D9 D8 D9 7E B0 77 D9 7C BA C8",
 "DF10 7D BB C8 25 2C D9 CD A0 E7 18 EE",
 "DF20 0E 29 18 15 0E 14 18 11 0E 0E 18 0D 0C 79 D6 73",
 "DF30 4F 18 06 0E 03 18 02 0E 02 E5 D9 E1 CD C0 E6 D9",
 "DF40 D8 41 CB 38 D9 7E B0 77 D9 7D BB C8 7C BA C8 25",
 "DF50 10 08 2C 41 D9 CD A0 E7 18 EB D9 CD 20 E7 7E B0",
 "DF60 77 D9 18 E8",
 "DF70 0D 3E 6A 91 4F 18 06 0E 0A 18 02 0E 15 E5 D9 E1",
 "DF80 CD C0 E6 D9 D8 41 CB 38 D9 7E B0 77 D9 7D BB C8",
 "DF90 7C BA C8 25 10 0B 41 D9 CD 20 E7 7E B0 77 D9 18",
 "DFA0 EF 2C D9 CD A0 E7 18 E1",
 "DFB0 E5 D9 E1 CD C0 E6 D9 D8 AF 91 87 4F 06 E8 0A 4F",
 "DFC0 06 80 D9 7E B0 77 D9 7D BB C8 7C BA C8 25 78 81",
 "DFD0 47 30 07 2C D9 CD A0 E7 18 E9 D9 CD 20 E7 7E B0",
 "DFE0 77 D9 18 E6",

 "E000 E5 D9 E1 CD C0 E6 D9 D8 D9 7E B0 77 D9 7C BA C8",
 "E010 25 D9 CD 20 E7 18 F2",
 "E020 0E 29 18 15 0E 14 18 11 0E 0E 18 0D 0D 3E 8D 91",
 "E030 4F 18 06 0E 03 18 02 0E 02 E5 D9 E1 CD C0 E6 D9",
 "E040 D8 41 CB 38 D9 7E B0 77 D9 7D BB C8 7C BA C8 25",
 "E050 10 08 2D 41 D9 CD C0 E7 18 EB D9 CD 20 E7 7E B0",
 "E060 77 D9 18 E8",
 "E070 0C 79 D6 96 4F 18 06 0E 0A 18 02 0E 15 E5 D9 E1",
 "E080 CD C0 E6 D9 D8 41 CB 38 D9 7E B0 77 D9 7D BB C8",
 "E090 7C BA C8 25 10 0B 41 D9 CD 20 E7 7E B0 77 D9 18",
 "E0A0 EF 2D D9 CD C0 E7 18 E1",
 "E0B0 E5 D9 E1 CD C0 E6 D9 D8 CB 21 06 E8 0A 4F 06 80",
 "E0C0 D9 7E B0 77 D9 7D BB C8 7C BA C8 25 78 81 47 30",
 "E0D0 07 2D D9 CD C0 E7 18 E9 D9 CD 20 E7 7E B0 77 D9",
 "E0E0 18 E6",

 "E100 E5 D9 E1 CD C0 E6 D9 D8 D9 7E B0 77 D9 7C BA C8",
 "E110 7D BB C8 25 2D D9 CD C0 E7 18 EE",
 "E120 0E 29 18 15 0E 14 18 11 0E 0E 18 0D 0C 79 D6 B3",
 "E130 4F 18 06 0E 03 18 02 0E 02 E5 D9 E1 CD C0 E6 D9",
 "E140 D8 41 CB 38 D9 7E B0 77 D9 7C BA C8 7D BB C8 2D",
 "E150 10 08 25 41 D9 CD C0 E7 18 EB D9 CD 10 E7 7E B0",
 "E160 77 D9 18 E8",
 "E170 0D 3E AA 91 4F 18 06 0E 0A 18 02 0E 15 E5 D9 E1",
 "E180 CD C0 E6 D9 D8 41 CB 38 D9 7E B0 77 D9 7C BA C8",
 "E190 7D BB C8 2D 10 0B 41 D9 CD 10 E7 7E B0 77 D9 18",
 "E1A0 EF 25 D9 CD C0 E7 18 E1",
 "E1B0 E5 D9 E1 CD C0 E6 D9 D8 3E C0 91 87 4F 06 E8 0A",
 "E1C0 4F 06 80 D9 7E B0 77 D9 7C BA C8 7D BB C8 2D 78",
 "E1D0 81 47 30 07 25 D9 CD C0 E7 18 E9 D9 CD 10 E7 7E",
 "E1E0 B0 77 D9 18 E6",

 "E200 E5 D9 E1 CD C0 E6 D9 D8 D9 7E B0 77 D9 7D BB C8",
 "E210 2D D9 CD 10 E7 18 F2",
 "E220 0E 29 18 15 0E 14 18 11 0E 0E 18 0D 0D 3E CD 91",
 "E230 4F 18 06 0E 03 18 02 0E 02 E5 D9 E1 CD C0 E6 D9",
 "E240 D8 41 CB 38 D9 7E B0 77 D9 7C BA C8 7D BB C8 2D",
 "E250 10 08 24 41 D9 CD E0 E7 18 EB D9 CD 10 E7 7E B0",
 "E260 77 D9 18 E8",
 "E270 0C 79 D6 D6 4F 18 06 0E 0A 18 02 0E 15 E5 D9 E1",
 "E280 CD C0 E6 D9 D8 41 CB 38 D9 7E B0 77 D9 7C BA C8",
 "E290 7D BB C8 2D 10 0B 41 D9 CD 10 E7 7E B0 77 D9 18",
 "E2A0 EF 24 D9 CD E0 E7 18 E1",
 "E2B0 E5 D9 E1 CD C0 E6 D9 D8 CB 21 CB B9 06 E8 0A 4F",
 "E2C0 06 80 D9 7E B0 77 D9 7C BA C8 7D BB C8 2D 78 81",
 "E2D0 47 30 07 24 D9 CD E0 E7 18 E9 D9 CD 10 E7 7E B0",
 "E2E0 77 D9 18 E6",

 "E300 E5 D9 E1 CD C0 E6 D9 D8 D9 7E B0 77 D9 7C BA C8",
 "E310 7D BB C8 24 2D D9 CD E0 E7 18 EE",
 "E320 0E 29 18 15 0E 14 18 11 0E 0E 18 0D 0C 79 D6 F3",
 "E330 4F 18 06 0E 03 18 02 0E 02 E5 D9 E1 CD C0 E6 D9",
 "E340 D8 41 CB 38 D9 7E B0 77 D9 7D BB C8 7C BA C8 24",
 "E350 10 08 2D 41 D9 CD E0 E7 18 EB D9 CD 30 E7 7E B0",
 "E360 77 D9 18 E8",
 "E370 0D 3E EA 91 4F 18 06 0E 0A 18 02 0E 15 E5 D9 E1",
 "E380 CD C0 E6 D9 D8 41 CB 38 D9 7E B0 77 D9 7D BB C8",
 "E390 7C BA C8 24 10 0B 41 D9 CD 30 E7 7E B0 77 D9 18",
 "E3A0 EF 2D D9 CD E0 E7 18 E1",
 "E3B0 E5 D9 E1 CD C0 E6 D9 D8 AF 91 87 4F 06 E8 0A 4F",
 "E3C0 06 80 D9 7E B0 77 D9 7D BB C8 7C BA C8 24 78 81",
 "E3D0 47 30 07 2D D9 CD E0 E7 18 E9 D9 CD 30 E7 7E B0",
 "E3E0 77 D9 18 E6",

 "E400 00 20 24 28 2C 2D 2D 2D 2D B0 2C B0 B0 33 B0 B0",
 "E410 B0 B0 B0 37 B0 B0 B0 B0 70 B0 71 71 71 71 77 7B",
 "E420 00 7B 77 71 71 71 71 B0 70 B0 B0 B0 B0 37 B0 B0",
 "E430 B0 B0 B0 33 B0 B0 2C B0 2D 2D 2D 2D 2C 28 24 20",
 "E440 00 20 24 28 2C 2D 2D 2D 2D B0 2C B0 B0 33 B0 B0",
 "E450 B0 B0 B0 37 B0 B0 B0 B0 70 B0 71 71 71 71 77 7B",
 "E460 00 7B 77 71 71 71 71 B0 70 B0 B0 B0 B0 37 B0 B0",
 "E470 B0 B0 B0 33 B0 B0 2C B0 2D 2D 2D 2D 2C 28 24 20",
 "E480 00 20 24 28 2C 2D 2D 2D 2D B0 2C B0 B0 33 B0 B0",
 "E490 B0 B0 B0 37 B0 B0 B0 B0 70 B0 71 71 71 71 77 7B",
 "E4A0 00 7B 77 71 71 71 71 B0 70 B0 B0 B0 B0 37 B0 B0",
 "E4B0 B0 B0 B0 33 B0 B0 2C B0 2D 2D 2D 2D 2C 28 24 20",
 "E4C0 00 20 24 28 2C 2D 2D 2D 2D B0 2C B0 B0 33 B0 B0",
 "E4D0 B0 B0 B0 37 B0 B0 B0 B0 70 B0 71 71 71 71 77 7B",
 "E4E0 00 7B 77 71 71 71 71 B0 70 B0 B0 B0 B0 37 B0 B0",
 "E4F0 B0 B0 B0 33 B0 B0 2C B0 2D 2D 2D 2D 2C 28 24 20",
 "E500 DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC",
 "E510 DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC",
 "E520 DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD",
 "E530 DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD",
 "E540 DE DE DE DE DE DE DE DE DE DE DE DE DE DE DE DE",
 "E550 DE DE DE DE DE DE DE DE DE DE DE DE DE DE DE DE",
 "E560 DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF",
 "E570 DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF",
 "E580 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0",
 "E590 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0",
 "E5A0 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1",
 "E5B0 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1",
 "E5C0 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2",
 "E5D0 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2",
 "E5E0 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3",
 "E5F0 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3 E3",

 "E6C0 7C C6 B0 D6 60 D8 1F 5F 9F E6 0F 3C 47 3E CE 95",
 "E6D0 D6 9C D8 CB 47 28 02 CB 20 CB 4F 28 04 CB 20 CB",
 "E6E0 20 E6 7C 57 CB 22 0F 0F 1F 67 9F E6 80 92 6F 30",
 "E6F0 01 25 16 F3 19 C9",

 "E700 78 CB 08 E6 11 C8 01 88 FF 09 07 07 07 47 C9",
 "E710 78 CB 00 E6 88 C8 01 78 00 09 0F 0F 0F 47 C9",
 "E720 78 0F 0F 0F 0F 47 E6 F0 C8 2B C9",
 "E730 78 07 07 07 07 47 E6 0F C8 23 C9",

 "E740 06 E4 0A DD 6F 04 0A DD 67 DD E9",

 "E780 78 E6 11 20 0A 78 07 07 07 47 E6 0F C8 23 C9 0F",
 "E790 01 77 00 ED 42 47 C9",
 "E7A0 78 E6 11 20 0A 78 07 07 07 47 E6 F0 C8 2B C9 0F",
 "E7B0 01 78 00 ED 42 47 C9",
 "E7C0 78 E6 88 20 0A 78 0F 0F 0F 47 E6 F0 C8 2B C9 07",
 "E7D0 01 77 00 ED 4A 47 C9",
 "E7E0 78 E6 88 20 0A 78 0F 0F 0F 47 E6 0F C8 23 C9 07",
 "E7F0 01 78 00 ED 4A 47 C9",

 "E800 00 00 06 00 0D 00 13 00 19 00 20 00 26 00 2C 00",
 "E810 33 00 39 00 40 00 47 00 4E 00 55 00 5C 00 63 00",
 "E820 6A 00 71 00 79 00 81 00 89 00 91 00 99 00 A2 00",
 "E830 AB 00 B4 00 BE 00 C8 00 D2 00 DD 00 E8 00 F4 00",
 "E840 00 01 0D 01 1A 01 29 01 38 01 48 01 59 01 6B 01",
 "E850 7F 01 94 01 AB 01 C4 01 DF 01 FD 01 1D 02 42 02",
 "E860 6A 02 98 02 CB 02 07 03 4C 03 9D 03 FE 03 74 04",
 "E870 07 05 C3 05 BE 06 1C 08 27 0A 8F 0D 5B 14 BC 28",
 "E880 FF 7F",

 "E890 26 E8 CB 71 28 0D AF 91 87 6F 7E 2F 5F 2C 7E 2F",
 "E8A0 57 13 C9 69 CB 25 5E 2C 56 C9",

 "E8C0 00 00 00 00 00 00 00 00 00 00 00 00 DA 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.font=[
// 0x00 - 0x07
  "-------- -###---- -###---- -###---- -###---- ###----- --#----- -###----",
  "-------- -#------ -#------ -#------ -#------ #------- -#-#---- -#--#---",
  "-------- -###---- -###---- -###---- -###---- ###----- -###---- -###----",
  "-------- ---##-#- ---#--#- -#----#- -#------ #---##-- -#-#--#- -#--#---",
  "-------- -####-#- -###-#-- -###-#-- -######- ####--#- -#-#-#-- -###-#--",
  "-------- ----###- ----#--- ----#--- -----#-- ---#--#- ---##--- -----#--",
  "-------- ----#-#- ---#-#-- ---#-#-- -----#-- ---#--#- ---#-#-- -----#--",
  "-------- ----#-#- --#---#- --#---#- -----#-- ----##-# ---#--#- -----###",
// 0x08 - 0x0f
  "-###---- -#-#---- -#------ -#-#---- --####-- --###--- -###---- -###----",
  "-#--#--- -#-#---- -#------ -#-#---- -#------ -#------ -#------ -#------",
  "-###---- -###---- -#------ -###---- -#------ -#------ -###---- -###----",
  "-#--#### -#-#---- -#--###- -#-#---- -#---#-- --#####- ---#---- ---#----",
  "-###-#-- -#-####- -####--- -#-#---# --###--- ----#--# -#####-- -######-",
  "-----### -----#-- ----##-- ---##-## ----#--- ----###- ---#--#- -----#--",
  "-------# -----#-- ----#--- ---#-#-# ----#--- ----#-#- ---#--#- -----#--",
  "-----### -----#-- ----#--- ---#---# ----#### ----#--# ----##-- ----###-",
// 0x10 - 0x17
  "-###---- -###---- -###---- -###---- -###---- -#--#--- -###---- -###----",
  "-#--#--- -#--#--- -#--#--- -#--#--- -#--#--- -##-#--- -#------ -#------",
  "-#--#--- -#--#--- -#--#--- -#--#--- -#--#--- -#-##--- -###---- -###----",
  "-#--#### -#--#-#- -#--###- -#--#### -#--#-#- -#--#--# ---#---- -#--###-",
  "-###-#-- -###-##- -###---# -###---# -###-##- -#--#-#- -####--# -####--#",
  "-----### ------#- -----##- -----### ----#-#- ----##-- ----##-# ----###-",
  "-----#-- ------#- ----#--- -------# ---##### ----#-#- ----#-## ----#--#",
  "-----### -----### ----#### ----#### ------#- ----#--# ----#--# ----###-",
// 0x18 - 0x1f
  "--###--- -###---- -###---- -###---- -------- -------- -------- --------",
  "-#------ -#------ -#------ -#------ ----#--- ---#---- ----#--- ----#---",
  "-#------ -###---- -###---- -###---- -----#-- --#----- ---###-- ----#---",
  "--###--- -#------ ---###-- -#------ -######- -######- --#-#-#- ----#---",
  "----#--# -###---# -###--#- -######- -----#-- --#----- ----#--- --#-#-#-",
  "----##-# ---##-## ---###-- ---#---- ----#--- ---#---- ----#--- ---###--",
  "----#-## ---#-#-# ---#--#- ---#---- -------- -------- ----#--- ----#---",
  "----#--# ---#---# ---###-- ----###- -------- -------- -------- --------",
// 0x20 - 0x27
  "-------- ----#--- --#--#-- --#--#-- ----#--- -------- --##---- -----#--",
  "-------- ----#--- --#--#-- --#--#-- ---####- -##---#- -#--#--- ----#---",
  "-------- ----#--- --#--#-- -######- --#-#--- -##--#-- -#--#--- ---#----",
  "-------- ----#--- -------- --#--#-- ---###-- ----#--- --##---- --------",
  "-------- -------- -------- -######- ----#-#- ---#---- -#--#-#- --------",
  "-------- -------- -------- --#--#-- --####-- --#--##- -#---#-- --------",
  "-------- ----#--- -------- --#--#-- ----#--- -#---##- --###-#- --------",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0x28 - 0x2f
  "-----#-- --#----- ----#--- -------- -------- -------- -------- --------",
  "----#--- ---#---- --#-#-#- ----#--- -------- -------- -------- ------#-",
  "---#---- ----#--- ---###-- ----#--- -------- -------- -------- -----#--",
  "---#---- ----#--- --#####- --#####- -------- -######- -------- ----#---",
  "---#---- ----#--- ---###-- ----#--- -------- -------- -------- ---#----",
  "----#--- ---#---- --#-#-#- ----#--- ----#--- -------- ---##--- --#-----",
  "-----#-- --#----- ----#--- -------- ----#--- -------- ---##--- -#------",
  "-------- -------- -------- -------- ---#---- -------- -------- --------",
// 0x30 - 0x37
  "--####-- ----#--- --####-- --####-- -----#-- -######- ---###-- -######-",
  "-#----#- ---##--- -#----#- -#----#- ----##-- -#------ --#----- -#----#-",
  "-#---##- --#-#--- ------#- ------#- ---#-#-- -####--- -#------ -----#--",
  "-#-##-#- ----#--- ----##-- ---###-- --#--#-- -----#-- -#####-- ----#---",
  "-##---#- ----#--- --##---- ------#- -######- ------#- -#----#- ---#----",
  "-#----#- ----#--- -#------ -#----#- -----#-- -#---#-- -#----#- ---#----",
  "--####-- --#####- -######- --####-- -----#-- --###--- --####-- ---#----",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0x38 - 0x3f
  "--####-- --####-- -------- -------- ----###- -------- -###---- --####--",
  "-#----#- -#----#- -------- -------- ---##--- -------- ---##--- -#----#-",
  "-#----#- -#----#- ----#--- ----#--- --##---- -######- ----##-- ------#-",
  "--####-- --#####- -------- -------- -##----- -------- -----##- ----##--",
  "-#----#- ------#- -------- -------- --##---- -######- ----##-- ---#----",
  "-#----#- -----#-- ----#--- ----#--- ---##--- -------- ---##--- --------",
  "--####-- --###--- -------- ----#--- ----###- -------- -###---- ---#----",
  "-------- -------- -------- ---#---- -------- -------- -------- --------",
// 0x40 - 0x47
  "---###-- ---##--- -#####-- ---###-- -####--- -######- -######- ---###--",
  "--#---#- --#--#-- --#---#- --#---#- --#--#-- -#------ -#------ --#---#-",
  "-#--#-#- -#----#- --#---#- -#------ --#---#- -#------ -#------ -#------",
  "-#-#-##- -######- --####-- -#------ --#---#- -####--- -####--- -#--###-",
  "-#--##-- -#----#- --#---#- -#------ --#---#- -#------ -#------ -#----#-",
  "--#----- -#----#- --#---#- --#---#- --#--#-- -#------ -#------ --#---#-",
  "---####- -#----#- -#####-- ---###-- -####--- -######- -#------ ---###--",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0x48 - 0x4f
  "-#----#- ---###-- ----###- -#----#- -#------ -#----#- -#----#- ---##---",
  "-#----#- ----#--- -----#-- -#---#-- -#------ -##--##- -##---#- --#--#--",
  "-#----#- ----#--- -----#-- -#--#--- -#------ -#-##-#- -#-#--#- -#----#-",
  "-######- ----#--- -----#-- -###---- -#------ -#-##-#- -#--#-#- -#----#-",
  "-#----#- ----#--- -----#-- -#--#--- -#------ -#----#- -#---##- -#----#-",
  "-#----#- ----#--- -#---#-- -#---#-- -#------ -#----#- -#----#- --#--#--",
  "-#----#- ---###-- --###--- -#----#- -######- -#----#- -#----#- ---##---",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0x50 - 0x57
  "-#####-- ---##--- -#####-- --####-- --#####- -#----#- -#----#- -#----#-",
  "-#----#- --#--#-- -#----#- -#----#- ----#--- -#----#- -#----#- -#----#-",
  "-#----#- -#----#- -#----#- -#------ ----#--- -#----#- -#----#- -#----#-",
  "-#####-- -#----#- -#####-- --####-- ----#--- -#----#- --#--#-- -#-##-#-",
  "-#------ -#--#-#- -#--#--- ------#- ----#--- -#----#- --#--#-- -#-##-#-",
  "-#------ --#--#-- -#---#-- -#----#- ----#--- -#----#- ---##--- -##--##-",
  "-#------ ---##-#- -#----#- --####-- ----#--- --####-- ---##--- -#----#-",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0x58 - 0x5f
  "-#----#- --#---#- -######- --####-- --#---#- --####-- ----#--- --------",
  "-#----#- --#---#- ------#- --#----- --#---#- -----#-- ---#-#-- --------",
  "--#--#-- --#---#- -----#-- --#----- ---#-#-- -----#-- --#---#- --------",
  "---##--- ---###-- ---##--- --#----- --#####- -----#-- -------- --------",
  "--#--#-- ----#--- --#----- --#----- ----#--- -----#-- -------- --------",
  "-#----#- ----#--- -#------ --#----- --#####- -----#-- -------- --------",
  "-#----#- ----#--- -######- --####-- ----#--- --####-- -------- -######-",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0x60 - 0x67
  "-------- -------- -#------ -------- ------#- -------- ----##-- --------",
  "-------- -------- -#------ -------- ------#- -------- ---#--#- --------",
  "-------- --####-- -#-###-- --####-- --###-#- --####-- ---#---- --###-#-",
  "-------- -----#-- -##---#- -#----#- -#---##- -#----#- -#####-- -#---##-",
  "-------- --####-- -#----#- -#------ -#----#- -######- ---#---- -#---##-",
  "-------- -#---#-- -##---#- -#----#- -#---##- -#------ ---#---- --###-#-",
  "-------- --###-#- -#-###-- --####-- --###-#- --####-- ---#---- ------#-",
  "-------- -------- -------- -------- -------- -------- -------- --####--",
// 0x68 - 0x6f
  "-#------ ----#--- -----#-- -#------ ---##--- -------- -------- --------",
  "-#------ -------- -------- -#------ ----#--- -------- -------- --------",
  "-#-###-- ---##--- ----##-- -#---#-- ----#--- -###-##- -#-###-- --####--",
  "-##---#- ----#--- -----#-- -#--#--- ----#--- -#--#--# -##---#- -#----#-",
  "-#----#- ----#--- -----#-- -#-#---- ----#--- -#--#--# -#----#- -#----#-",
  "-#----#- ----#--- -----#-- -##-#--- ----#--- -#--#--# -#----#- -#----#-",
  "-#----#- ---###-- -#---#-- -#---#-- ---###-- -#--#--# -#----#- --####--",
  "-------- -------- --###--- -------- -------- -------- -------- --------",
// 0x70 - 0x77
  "-------- -------- -------- -------- ---#---- -------- -------- --------",
  "-------- -------- -------- -------- ---#---- -------- -------- --------",
  "-#-###-- --###-#- -#-###-- --#####- -#####-- -#----#- -#----#- -#-----#",
  "-##---#- -#---##- -##---#- -#------ ---#---- -#----#- -#----#- -#--#--#",
  "-##---#- -#---##- -#------ --####-- ---#---- -#----#- -#----#- -#--#--#",
  "-#-###-- --###-#- -#------ ------#- ---#--#- -#---##- --#--#-- -#--#--#",
  "-#------ ------#- -#------ -#####-- ----##-- --###-#- ---##--- --##-##-",
  "-#------ ------#- -------- -------- -------- -------- -------- --------",
// 0x78 - 0x7f
  "-------- -------- -------- ----###- ----#--- -###---- --##---- --------",
  "-------- -------- -------- ---#---- ----#--- ----#--- -#--#--# --------",
  "-#----#- -#----#- -######- ---#---- -------- ----#--- -----##- --------",
  "--#--#-- -#----#- -----#-- --#----- -------- -----#-- -------- --------",
  "---##--- -#---##- ---##--- ---#---- -------- ----#--- -------- --------",
  "--#--#-- --###-#- --#----- ---#---- ----#--- ----#--- -------- --------",
  "-#----#- ------#- -######- ----###- ----#--- -###---- -------- --------",
  "-------- --####-- -------- -------- -------- -------- -------- --------",
// 0x80 - 0x87
  "-------- -------- -------- -------- -------- -------- -------- ########",
  "-------- -------- -------- -------- -------- -------- ######## ########",
  "-------- -------- -------- -------- -------- ######## ######## ########",
  "-------- -------- -------- -------- ######## ######## ######## ########",
  "-------- -------- -------- ######## ######## ######## ######## ########",
  "-------- -------- ######## ######## ######## ######## ######## ########",
  "-------- ######## ######## ######## ######## ######## ######## ########",
  "######## ######## ######## ######## ######## ######## ######## ########",
// 0x88 - 0x8f
  "#------- ##------ ###----- ####---- #####--- ######-- #######- ----#---",
  "#------- ##------ ###----- ####---- #####--- ######-- #######- ----#---",
  "#------- ##------ ###----- ####---- #####--- ######-- #######- ----#---",
  "#------- ##------ ###----- ####---- #####--- ######-- #######- ----#---",
  "#------- ##------ ###----- ####---- #####--- ######-- #######- ########",
  "#------- ##------ ###----- ####---- #####--- ######-- #######- ----#---",
  "#------- ##------ ###----- ####---- #####--- ######-- #######- ----#---",
  "#------- ##------ ###----- ####---- #####--- ######-- #######- ----#---",
// 0x90 - 0x97
  "----#--- -------- ----#--- ----#--- ######## -------- ----#--- -------#",
  "----#--- -------- ----#--- ----#--- -------- -------- ----#--- -------#",
  "----#--- -------- ----#--- ----#--- -------- -------- ----#--- -------#",
  "----#--- -------- ----#--- ----#--- -------- -------- ----#--- -------#",
  "######## ######## #####--- ----#### -------- ######## ----#--- -------#",
  "-------- ----#--- ----#--- ----#--- -------- -------- ----#--- -------#",
  "-------- ----#--- ----#--- ----#--- -------- -------- ----#--- -------#",
  "-------- ----#--- ----#--- ----#--- -------- -------- ----#--- -------#",
// 0x98 - 0x9f
  "-------- -------- ----#--- ----#--- -------- -------- ----#--- ----#---",
  "-------- -------- ----#--- ----#--- -------- -------- ----#--- ----#---",
  "-------- -------- ----#--- ----#--- -------- -------- ----#--- ----#---",
  "-------- -------- ----#--- ----#--- -------- -------- -----#-- ---#----",
  "----#### #####--- ----#### #####--- ------## ###----- ------## ###-----",
  "----#--- ----#--- -------- -------- -----#-- ---#---- -------- --------",
  "----#--- ----#--- -------- -------- ----#--- ----#--- -------- --------",
  "----#--- ----#--- -------- -------- ----#--- ----#--- -------- --------",
// 0xa0 - 0xa7
  "-------- -------- ---###-- -------- -------- -------- -------- --------",
  "-------- -------- ---#---- -------- -------- -------- -######- --------",
  "-------- -------- ---#---- -------- -------- -------- ------#- --#####-",
  "-------- -------- ---#---- ----#--- -------- ---##--- -######- ------#-",
  "-------- --###--- -------- ----#--- --#----- ---##--- ------#- ----##--",
  "-------- --#-#--- -------- ----#--- ---#---- -------- -----#-- ----#---",
  "-------- --###--- -------- --###--- ----#--- -------- --###--- ---#----",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0xa8 - 0xaf
  "-------- -------- -------- -------- -------- -------- -------- --------",
  "-------- -------- -------- -------- -------- -------- -------- --------",
  "-----#-- ----#--- -------- -----#-- ---#---- -------- --####-- --------",
  "----#--- --#####- --#####- --#####- --#####- ---###-- -----#-- --#-#-#-",
  "---##--- --#---#- ----#--- ----##-- ---#--#- -----#-- --####-- --#-#-#-",
  "--#-#--- ------#- ----#--- ---#-#-- ---#-#-- -----#-- -----#-- ------#-",
  "----#--- ----##-- --#####- --#--#-- ---#---- --#####- --####-- ----##--",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0xb0 - 0xb7
  "-------- -######- ------#- ----#--- -------- ----#--- ---#---- ----#---",
  "-------- ------#- -----#-- -######- --#####- -######- -######- --#####-",
  "-------- ------#- ----#--- -#----#- ----#--- ----#--- ---#--#- ----#---",
  "--#####- ---#-#-- ---##--- -#----#- ----#--- ---##--- ---#--#- --#####-",
  "-------- ---##--- --#-#--- ------#- ----#--- --#-#--- ---#--#- ----#---",
  "-------- ---#---- -#--#--- -----#-- ----#--- -#--#--- ---#--#- ----#---",
  "-------- --#----- ----#--- --###--- --#####- ----#--- --#--#-- ----#---",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0xb8 - 0xbf
  "---####- --#----- -------- --#--#-- -------- -######- --#----- -#----#-",
  "--#---#- --#####- -######- -######- -###---- ------#- -######- -#----#-",
  "-#----#- -#--#--- ------#- --#--#-- -------- -----#-- --#---#- --#---#-",
  "-----#-- ----#--- ------#- --#--#-- -###--#- ----#--- --#--#-- ------#-",
  "----#--- ----#--- ------#- -----#-- ------#- ---##--- --#----- -----#--",
  "---#---- ----#--- ------#- ----#--- -----#-- --#--#-- --#----- ----#---",
  "-##----- ---#---- -######- ---#---- -####--- -#----#- ---####- --##----",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0xc0 - 0xc7
  "---####- -----#-- -------- --####-- ---#---- ----#--- -------- --------",
  "--#---#- --###--- -#-#--#- -------- ---#---- ----#--- --####-- --#####-",
  "-##---#- ----#--- -#-#--#- -######- ---#---- -######- -------- ------#-",
  "---#-#-- -######- -#-#--#- ----#--- ---##--- ----#--- -------- ---#-#--",
  "----#--- ----#--- -----#-- ----#--- ---#-#-- ----#--- -------- ----#---",
  "---#---- ----#--- ----#--- ---#---- ---#---- ---#---- -------- ---#-#--",
  "-##----- -###---- -###---- --#----- ---#---- --#----- -######- --#-----",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0xc8 - 0xcf
  "----#--- ------#- ---#---- -#------ -------- -------- ----#--- -######-",
  "--#####- ------#- ----#--- -#------ -######- ---#---- --#####- ------#-",
  "-----#-- ------#- -----#-- -######- ------#- --#-#--- ----#--- ------#-",
  "----#--- -----#-- -#----#- -#------ ------#- -#---#-- ----#--- -----#--",
  "---###-- ----#--- -#----#- -#------ -----#-- ------#- --#-#-#- --#-#---",
  "--#-#-#- ---#---- -#----#- -#------ ----#--- ------#- --#-#-#- ---#----",
  "----#--- --#----- -#----#- --#####- --##---- -------- ----#--- ----#---",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0xd0 - 0xd7
  "-------- -----#-- -------- -------- --#----- -------- -######- --####--",
  "--####-- ----#--- ------#- -######- --#----- --###--- ------#- --------",
  "-------- ---#---- ------#- ---#---- -######- ----#--- ------#- -######-",
  "--####-- --#----- ---#-#-- -######- --#---#- ----#--- -######- ------#-",
  "-------- -#--#--- ----#--- ---#---- --#--#-- ----#--- ------#- -----#--",
  "-#####-- -#####-- ---#-#-- ---#---- --#----- ----#--- ------#- ----#---",
  "------#- ------#- -##----- ---####- --#----- -######- -######- ---#----",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0xd8 - 0xdf
  "-#----#- --#-#--- --#----- -------- -------- -------- ---#---- -###----",
  "-#----#- --#-#--- --#----- -######- -######- -###---- -#--#--- -#-#----",
  "-#----#- --#-#--- --#----- -#----#- -#----#- ------#- --#----- -###----",
  "-#----#- --#-#-#- --#---#- -#----#- -#----#- ------#- -------- --------",
  "------#- --#-#-#- --#--#-- -#----#- ------#- -----#-- -------- --------",
  "-----#-- --#-##-- --#-#--- -#----#- -----#-- ----#--- -------- --------",
  "---##--- -#--#--- --##---- -######- ---##--- -###---- -------- --------",
  "-------- -------- -------- -------- -------- -------- -------- --------",
// 0xe0 - 0xe7
  "-------- ----#--- ----#--- ----#--- -------# #------- ######## ########",
  "-------- ----#--- ----#--- ----#--- ------## ##------ -####### #######-",
  "######## ----#### ######## #####--- -----### ###----- --###### ######--",
  "-------- ----#--- ----#--- ----#--- ----#### ####---- ---##### #####---",
  "-------- ----#--- ----#--- ----#--- ---##### #####--- ----#### ####----",
  "######## ----#### ######## #####--- --###### ######-- -----### ###-----",
  "-------- ----#--- ----#--- ----#--- -####### #######- ------## ##------",
  "-------- ----#--- ----#--- ----#--- ######## ######## -------# #-------",
// 0xe8 - 0xef
  "----#--- --##-##- ----#--- ---###-- -------- -------- -------# #-------",
  "---###-- -####### ---###-- ---###-- --####-- --####-- ------#- -#------",
  "--#####- -####### --#####- -####### -######- -#----#- -----#-- --#-----",
  "-####### -####### -####### -####### -######- -#----#- ----#--- ---#----",
  "-####### --#####- --#####- -##-#-## -######- -#----#- ---#---- ----#---",
  "---###-- ---###-- ---###-- ----#--- -######- -#----#- --#----- -----#--",
  "--#####- ----#--- ----#--- --#####- --####-- --####-- -#------ ------#-",
  "-------- -------- -------- -------- -------- -------- #------- -------#",
// 0xf0 - 0xf7
  "#------# -####### -#------ --###### -####### -----#-- -------- --###-#-",
  "-#----#- -#--#--# -######- --#----# -#-----# ###-###- ---##--- ---#--#-",
  "--#--#-- -#--#--# -#--#--- --###### -#-----# #-#--#-- --#--#-- -#######",
  "---##--- -####### --####-- --#----# -####### ###-#### -#----#- ---#-###",
  "---##--- -#-----# --#-#--- --###### -#-----# #-#---#- --####-- --###-##",
  "--#--#-- -#-----# -######- --#----# -#-----# ###-#### ---#-#-- -#-#--#-",
  "-#----#- -#-----# ----#--- -#-----# -####### ----#-#- --#--#-- ---#-#--",
  "#------# -------- -------- -------- -------- ------#- -------- --------",
// 0xf8 - 0xff
  "-------- -------- -------- -------- -------- -------- -------- --------",
  "-------- -------- -------- -------- -------- -------- -------- --------",
  "-------- -------- -------- -------- -------- -------- -------- --------",
  "-------- -------- -------- -------- -------- -------- -------- --------",
  "-------- -------- -------- -------- -------- -------- -------- --------",
  "-------- -------- -------- -------- -------- -------- -------- --------",
  "-------- -------- -------- -------- -------- -------- -------- --------",
  "-------- -------- -------- -------- -------- -------- -------- --------"];
pc8001.display=new Object();
pc8001.display.columns=80;
pc8001.display.initColor=0xb8;
pc8001.initDisplay=function(svg){
  var d=pc8001.display;
  var x,y,e,t,c;
  d.svg=svg;
  d.lines=25;
  d.reverse=0;
  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=[[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(256);
  d.font.fill("");
  d.font.forEach(function(v,x,a){
    var t=new Array(8);
    var i,j
    for(i=j=0;i<8;i++){
      t[i]=pc8001.font[(x&0xf8)+i].split(" ")[x%8].replace(/-/g,"0").replace(/#/g,"1");
      if(t[i]=="00000000")
        j++;
    }
    if(j!=8){
      for(i=0;i<8;i+=2){
        for(j=0;j<8;j+=2)
          a[x]+=String.fromCodePoint(e[parseInt(t[j+1].substr(i+1,1)+t[j].substr(i+1,1),2)][parseInt(t[j+1].substr(i,1)+t[j].substr(i,1),2)]);
      }
    }
  });
  d.blocks=new Array(256);
  d.blocks.fill("");
  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]);
  }
  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=d.reverse;
      e=document.createElementNS("http://www.w3.org/2000/svg","text");
      e.setAttribute("font-family","monospace");
      if(d.colors[d.initColor].substr(0,1)=="#"){
        e.setAttribute("font-size",2);
        e.setAttribute("transform","matrix(0 "+((d.monowidth<2)?5/3:1)+" "+80/d.columns+" 0 "+(x*2+72/d.columns)+" "+y*100/d.lines+")");
      }
      else{
        e.setAttribute("font-size",1);
        e.setAttribute("transform","matrix(0 "+((d.monowidth<2)?5/3:1)+" "+40/d.columns+" 0 "+x*2+" "+y*100/d.lines+")");
      }
      e.setAttribute("fill",c);
      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.outports[0x30]=(d.columns==80)?0x29:0x28;
}
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.controlbox.textContent=d.bgchars[t.control];
        if(t.color.substr(0,1)=="#"){
          t.textbox.setAttribute("font-size",2);
          t.textbox.setAttribute("transform","matrix(0 "+((d.monowidth<2)?5/3:1)+" "+80/columns+" 0 "+(x*2+72/columns)+" "+y*100/lines+")");
          t.textpath.textContent=d.blocks[t.data];
        }
        else{
          t.textbox.setAttribute("font-size",1);
          t.textbox.setAttribute("transform","matrix(0 "+((d.monowidth<2)?5/3:1)+" "+40/columns+" 0 "+x*2+" "+y*100/lines+")");
          t.textpath.textContent=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.reverseDisplay=function(rev){
  var d=pc8001.display;
  var x,y,t;
  if(rev!=0)
    rev=4;
  if(d.reverse==rev)
    return;
  for(y=0;y<25;y++){
    for(x=0;x<80;x++){
      t=d.textArray[x][y];
      t.control^=4;
      t.controlbox.textContent=d.bgchars[t.control];
      if(y<d.lines&&(x%2==0||d.columns==80))
        t.textbox.setAttribute("fill",((t.control&1)==1)?"none":((t.control&4)==4)?"black":t.color);
    }
  }
  d.reverse=rev;
}
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;
  }
  if(address<0x6000)
    console.log("write",data,"to ROM",address.toString(16).toUpperCase().padStart(4,"0"),"at",pc8001.z80.regs["PC"].toString(16).toUpperCase().padStart(4,"0"));
  else
    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)^d.reverse;
        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)){
            if(k.substr(0,1)=="#"){
              t.textbox.setAttribute("font-size",2);
              t.textbox.setAttribute("transform","matrix(0 "+((d.monowidth<2)?5/3:1)+" "+80/d.columns+" 0 "+(x*2+72/d.columns)+" "+y*100/d.lines+")");
              t.textpath.textContent=d.blocks[t.data];
            }
            else{
              t.textbox.setAttribute("font-size",1);
              t.textbox.setAttribute("transform","matrix(0 "+((d.monowidth<2)?5/3:1)+" "+40/d.columns+" 0 "+x*2+" "+y*100/d.lines+")");
              t.textpath.textContent=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.outports=new Array(256);
pc8001.outports.fill(0);
pc8001.keymap=new Array(256);
pc8001.keymap.fill([]);
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.keydown=function(event){
  var k=pc8001.keymap[event.keyCode]
  var i;
  if(k.length<2)
    return;
  for(i=0;i<k.length;i+=2)
    pc8001.inports[k[i]]&=k[i+1];
}
pc8001.keyup=function(event){
  var k=pc8001.keymap[event.keyCode]
  var i;
  if(k.length<2)
    return;
  for(i=0;i<k.length;i+=2)
    pc8001.inports[k[i]]|=(k[i+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.calendar=new Object();
pc8001.calendar.command=function(com){
  var d,j,k;
  switch(com){
    case 4:
      pc8001.calendar.differential=0;
    case 3:
      pc8001.calendar.readreg="00000000";
      pc8001.calendar.writereg="";
      pc8001.calendar.date=new Date();
      return 0;
    case 2:
      d=new Date();
      k=pc8001.calendar.writereg;
      if(k.length>40){
        j=parseInt(parseInt(k.slice(0,-40),2).toString(16),10);
        if(!isNaN(j))
          d.setFullYear(j);
      }
      if(k.length>39){
        j=parseInt(k.slice(-40,-36),2);
        if(!isNaN(j))
          d.setMonth(j-1);
      }
      if(k.length>31){
        j=parseInt(parseInt(k.slice(-32,-24),2).toString(16),10);
        if(!isNaN(j))
          d.setDate(j);
      }
      if(k.length>23){
        j=parseInt(parseInt(k.slice(-24,-16),2).toString(16),10);
        if(!isNaN(j))
          d.setHours(j);
      }
      if(k.length>15){
        j=parseInt(parseInt(k.slice(-16,-8),2).toString(16),10);
        if(!isNaN(j))
          d.setMinutes(j);
      }
      if(k.length>7){
        j=parseInt(parseInt(k.slice(-8),2).toString(16),10);
        if(!isNaN(j))
          d.setSeconds(j);
      }
      pc8001.calendar.date=new Date();
      pc8001.calendar.differential=pc8001.calendar.date-d;
    case 1:
      d=new Date(pc8001.calendar.date-pc8001.calendar.differential);
      j=d.getFullYear().toString()+(d.getMonth()+1).toString(16)+d.getDay().toString()
      k=parseInt(j,16).toString(2).padStart(32,"0");
      j=(d.getDate()*1000000+d.getHours()*10000+d.getMinutes()*100+d.getSeconds()).toString();
      k+=parseInt(j,16).toString(2).padStart(32,"0");
      pc8001.calendar.readreg=k;
      pc8001.calendar.writereg="";
  }
  return (pc8001.calendar.readreg.slice(-1)=="1")?0x10:0;
}
pc8001.calendar.command(4);
pc8001.calendar.shift=function(b){
  var t;
  pc8001.calendar.writereg=(((b&8)==0)?"0":"1")+pc8001.calendar.writereg;
  t=pc8001.calendar.readreg.slice(-1)+pc8001.calendar.readreg.slice(0,-1);
  pc8001.calendar.readreg=t;
  return (t.slice(-1)=="1")?0x10:0;
}
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,"H":0,"N":0,"DUMMY":0,"z":0,"c":0,"v":0,"m":0,"h":0,"n":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,"(BC)",12];
    pc8001.z80.ops[0xed][i*8+0x41]=["OUT","(BC)",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","H","N","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.flags["H"]=((t&0x0f)==0)?1:0;
  pc8001.z80.flags["N"]=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.flags["H"]=((t&0x0f)==0x0f)?1:0;
  pc8001.z80.flags["N"]=1;
}
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.flags["H"]=((t&0x0f)+(u&0x0f)>0x0f)?1:0;
  pc8001.z80.flags["N"]=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,c;
  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]];
  c=pc8001.z80.flags["C"];
  v=t+u+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.flags["H"]=((t&0x0f)+(u&0x0f)+c>0x0f)?1:0;
  pc8001.z80.flags["N"]=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.flags["H"]=((t&0x0f)==0)?0:1;
  pc8001.z80.flags["N"]=1;
}
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.flags["H"]=((u&0x0f)-(t&0x0f)<0)?1:0;
  pc8001.z80.flags["N"]=1;
}
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,c;
  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]];
  c=pc8001.z80.flags["C"];
  v=u-t-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.flags["H"]=((u&0x0f)-(t&0x0f)-c<0)?1:0;
  pc8001.z80.flags["N"]=1;
}
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;
  pc8001.z80.flags["H"]=1
  pc8001.z80.flags["N"]=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.flags["H"]=1;
  pc8001.z80.flags["N"]=1;
}
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;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=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;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=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.flags["H"]=((u&0x0f)-(t&0x0f)<0)?1:0;
  pc8001.z80.flags["N"]=1;
}
pc8001.z80.ops[0x37]=["SCF",4];
pc8001.z80.mnemonics["SCF"]=function(x,m){
  pc8001.z80.flags["C"]=1;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=0;
}
pc8001.z80.ops[0x3f]=["CCF",4];
pc8001.z80.mnemonics["CCF"]=function(x,m){
  pc8001.z80.flags["C"]^=1;
  pc8001.z80.flags["N"]=0;
}
pc8001.z80.ops[0x27]=["DAA",4];
pc8001.z80.mnemonics["DAA"]=function(x,m){
  var t=pc8001.z80.regs["A"];
  var v;
  if(pc8001.z80.flags["N"]==0){
    if(pc8001.z80.flags["C"]==0){
      v=((t>0x99)?0x60:0)+(((pc8001.z80.flags["H"]==1||(t&0x0f)>9))?6:0);
      pc8001.z80.flags["C"]=(t>0x99)?1:0;
    }
    else
      v=((pc8001.z80.flags["H"]==1)||((t&0x0f)>9)?0x66:0x60);
    pc8001.z80.flags["H"]=((t&0x0f)>9)?1:0;
  }
  else{
    if(pc8001.z80.flags["C"]==0){
      if(pc8001.z80.flags["H"]==0)
        v=((t>0x99)?0xa0:0)+(((t&0x0f)>9)?0xfa:0);
      else{
        v=(t>0x99)?0x9a:0xfa;
        pc8001.z80.flags["H"]=((t&0x0f)<6)?1:0;
      }
      pc8001.z80.flags["C"]=(t>0x99)?1:0;
    }
    else{
      v=(pc8001.z80.flags["H"]==0&&((t&0x0f)<10))?0xa0:0x9a;
      pc8001.z80.flags["H"]&=((t&0x0f)<6)?1:0;
    }
  }
  pc8001.z80.regs["A"]=(t+v)&0xff;
}
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"]&0x28)|pc8001.z80.flags["C"]|(pc8001.z80.flags["N"]<<1)|(pc8001.z80.flags["V"]<<2)|(pc8001.z80.flags["H"]<<4)|(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["N"]=((t&2)==0)?0:1;
    pc8001.z80.flags["V"]=((t&4)==0)?0:1;
    pc8001.z80.flags["H"]=((t&0x10)==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.flags["H"]=0;
  pc8001.z80.flags["N"]=0;
}
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;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=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.flags["H"]=0;
  pc8001.z80.flags["N"]=0;
}
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;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=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.flags["H"]=0;
  pc8001.z80.flags["N"]=0;
}
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;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=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.flags["H"]=0;
  pc8001.z80.flags["N"]=0;
}
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;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=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;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=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;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=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;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=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;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=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.flags["H"]=1;
  pc8001.z80.flags["N"]=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][0x67]=["RRD",18];
pc8001.z80.mnemonics["RRD"]=function(x,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var c=pc8001.memory[hl];
  var t=pc8001.z80.regs["A"];
  pc8001.writeMemory(hl,(c>>4)|((t<<4)&0xf0))
  pc8001.z80.regs["A"]=t=(t&0xf0)|(c&0x0f);
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
pc8001.z80.ops[0xed][0x6f]=["RLD",18];
pc8001.z80.mnemonics["RLD"]=function(x,m){
  var hl=pc8001.z80.regs["H"]*256+pc8001.z80.regs["L"];
  var c=pc8001.memory[hl];
  var t=pc8001.z80.regs["A"];
  pc8001.writeMemory(hl,((c<<4)&0xf0)|(t&0x0f))
  pc8001.z80.regs["A"]=t=(t&0xf0)|(c>>4);
  pc8001.z80.flags["Z"]=(t==0)?1:0;
  pc8001.z80.flags["M"]=(t>0x7f)?1:0;
  pc8001.z80.flags["H"]=0;
  pc8001.z80.flags["N"]=0;
  t=(((t>>6)|4)^(t>>3)^t)&3;
  pc8001.z80.flags["V"]=((t>>2)^(t>>1)^t)&1;
}
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.flags["H"]=0;
  pc8001.z80.flags["N"]=0;
}
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.flags["H"]=0;
  pc8001.z80.flags["N"]=0;
}
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"];
  var u=pc8001.memory[hl];
  var v=(t-u+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"]=(v==0)?1:0;
  pc8001.z80.flags["M"]=(v>0x7f)?1:0;
  pc8001.z80.flags["V"]=(bc==0)?0:1;
  pc8001.z80.flags["H"]=((t&0x0f)-(u&0x0f)<0)?1:0;
  pc8001.z80.flags["N"]=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"];
  var u=pc8001.memory[hl];
  var v=(t-u+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"]=(v==0)?1:0;
  pc8001.z80.flags["M"]=(v>0x7f)?1:0;
  pc8001.z80.flags["V"]=(bc==0)?0:1;
  pc8001.z80.flags["H"]=((t&0x0f)-(u&0x0f)<0)?1:0;
  pc8001.z80.flags["N"]=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[m[1]]*256;
    pc8001.z80.regs["PC"]=(pc+1)&0xffff;
  }
  else
    c=pc8001.z80.regs[m[2].substr(1,1)]*256+pc8001.z80.regs[m[2].substr(2,1)];
  pc8001.z80.regs[m[1]]=t=pc8001.inport16(c);
  if(m[2]!="(n)"){
    pc8001.z80.flags["Z"]=(t==0)?1:0;
    pc8001.z80.flags["M"]=(t>0x7f)?1:0;
    pc8001.z80.flags["H"]=0;
    pc8001.z80.flags["N"]=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"]+0xff)&0xff;
  pc8001.writeMemory(hl,pc8001.inport16(b*256+pc8001.z80.regs["C"]));
  hl=(hl+1)&0xffff;
  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.flags["N"]=1;
}
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"]+0xff)&0xff;
  pc8001.writeMemory(hl,pc8001.inport16(b*256+pc8001.z80.regs["C"]));
  hl=(hl+0xffff)&0xffff;
  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.flags["N"]=1;
}
pc8001.z80.ops[0xed][0xba]=["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.inport16=function(p){
  return pc8001.inports[p&0xff];
}
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[m[2]]*256;
    pc8001.z80.regs["PC"]=(pc+1)&0xffff;
  }
  else
    c=pc8001.z80.regs[m[1].substr(1,1)]*256+pc8001.z80.regs[m[1].substr(2,1)];
  pc8001.outport16(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"]+0xff)&0xff;
  pc8001.outport16(b*256+pc8001.z80.regs["C"],pc8001.memory[hl]);
  hl=(hl+1)&0xffff;
  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.flags["N"]=1;
}
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"]+0xff)&0xff;
  pc8001.outport16(b*256+pc8001.z80.regs["C"],pc8001.memory[hl]);
  hl=(hl+0xffff)&0xffff;
  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.flags["N"]=1;
}
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.outport16=function(p,d){
  var t=pc8001.outports[p&0xff];
  pc8001.outports[p&0xff]=d;
  switch(p&0xff){
    case 0x10:
      return;
    case 0x30:
      if((d^t)==1)
        pc8001.resizeDisplay(((d&1)==1)?80:40,25);
      return;
    case 0x40:
      pc8001.beep.on=((d&0x20)==0)?0:1;
      if(((d^t)&6)!=0){
        switch(d&6){
          case 2:
            t=pc8001.calendar.command(pc8001.outports[0x10]);
            break;
          case 4:
            t=pc8001.calendar.shift(pc8001.outports[0x10]);
            break;
          default:
            return;
        }
        if(t==0)
          pc8001.inports[0x40]&=0xef;
        else
          pc8001.inports[0x40]|=0x10;
      }
      return;
    case 0x51:
      switch(d){
        case 0x20:
          pc8001.reverseDisplay(0);
          return;
        case 0x21:
          pc8001.reverseDisplay(1);
          return;
      }
      console.log("OUT (51H),",d);
      return;
  }
  pc8001.z80.mnemonics["UNDEF"](p&0xff,["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>
0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?