diff --git a/projects/tzpuPico/src/test/Celestite/celestite_stress.asm b/projects/tzpuPico/src/test/Celestite/celestite_stress.asm new file mode 100644 index 0000000..e2d5b2a --- /dev/null +++ b/projects/tzpuPico/src/test/Celestite/celestite_stress.asm @@ -0,0 +1,541 @@ +;-------------------------------------------------------------------------------------------------------- +;- Celestite LAN Board — Network Stress Test +;- All output on MZ-1500 screen (VRAM D000-D3FF). Loops continuously. +;- Also mirrors summary to debug port (50h). +;- D800-DFFF colour attributes are NOT touched. +;-------------------------------------------------------------------------------------------------------- + +PORT_DBG EQU 050h +PORT_MR EQU 060h +PORT_AR0 EQU 061h +PORT_AR1 EQU 062h +PORT_DR EQU 063h +PORT_PING EQU 067h + +CMD_OPEN EQU 001h +CMD_CLOSE EQU 010h +ST_ESTAB EQU 017h +ST_CLOSED EQU 000h + +TPSTART EQU 010F0h +MEMSTART EQU 01200h +VRAM EQU 0D000h +VL EQU 40 + + ORG TPSTART +ATRB: DB 001h +NAME: DB "CELESTITE STRESS", 0Dh +SIZE: DW MEND - MEMSTART +DTADR: DW MEMSTART +EXADR: DW MEMSTART +COMNT: DS 104 + + ORG MEMSTART + +START: LD SP, 01180h + ;- Init W5100. + LD A, 080h + OUT (PORT_MR), A + LD A, 003h + OUT (PORT_MR), A + ;- Write gateway IP to GAR. + XOR A + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, 192 + OUT (PORT_DR), A + LD A, 168 + OUT (PORT_DR), A + LD A, 1 + OUT (PORT_DR), A + LD A, 1 + OUT (PORT_DR), A + + LD HL, 0 + LD (LOOPCNT), HL + +;- ============================================================ +MAINLP: ;- Clear text VRAM only (D000-D3E7, 1000 bytes). Leave D800 colours alone. + LD HL, VRAM + LD BC, 1000 +CLR: LD (HL), 000h + INC HL + DEC BC + LD A, B + OR C + JR NZ, CLR + + LD HL, (LOOPCNT) + INC HL + LD (LOOPCNT), HL + + ;- Line 0: Title. + LD HL, VRAM + LD DE, S_TITLE + CALL PVRAM + + ;- Line 1: Loop count. + LD HL, VRAM + VL + LD DE, S_LOOP + CALL PVRAM + LD A, (LOOPCNT+1) + CALL PHEXV + LD A, (LOOPCNT) + CALL PHEXV + + ;- ---- PING (line 3) ---- + LD HL, VRAM + VL*3 + LD DE, S_PING + CALL PVRAM + XOR A + OUT (PORT_PING), A + LD B, 250 +PNGW: PUSH BC + IN A, (PORT_PING) + POP BC + CP 0FFh + JR NZ, PNGGOT + LD DE, 12000 +PNGD: DEC DE + LD A, D + OR E + JR NZ, PNGD + DJNZ PNGW + LD HL, VRAM + VL*3 + 28 + LD DE, S_TOUT + CALL PVRAM + JR PNGDN +PNGGOT: LD HL, VRAM + VL*3 + 28 + CALL PDECV + LD DE, S_MS + CALL PVRAM +PNGDN: + + ;- ---- TCP CONNECT (line 4) ---- + LD HL, VRAM + VL*4 + LD DE, S_TCP + CALL PVRAM + ;- Close. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_CLOSE + OUT (PORT_DR), A + ;- Mode = TCP. + LD A, 004h + OUT (PORT_AR0), A + XOR A + OUT (PORT_AR1), A + LD A, 001h + OUT (PORT_DR), A + ;- Dest IP. + LD A, 004h + OUT (PORT_AR0), A + LD A, 00Ch + OUT (PORT_AR1), A + LD A, 192 + OUT (PORT_DR), A + LD A, 168 + OUT (PORT_DR), A + LD A, 1 + OUT (PORT_DR), A + LD A, 1 + OUT (PORT_DR), A + ;- Port 80. + LD A, 004h + OUT (PORT_AR0), A + LD A, 010h + OUT (PORT_AR1), A + XOR A + OUT (PORT_DR), A + LD A, 80 + OUT (PORT_DR), A + ;- OPEN + CONNECT. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_OPEN + OUT (PORT_DR), A + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, 004h + OUT (PORT_DR), A + ;- Wait. + LD B, 250 +TCPW: PUSH BC + LD A, 004h + OUT (PORT_AR0), A + LD A, 003h + OUT (PORT_AR1), A + IN A, (PORT_DR) + POP BC + CP ST_ESTAB + JR Z, TCPOK + CP ST_CLOSED + JP Z, TCPFL + LD DE, 20000 +TCPD: DEC DE + LD A, D + OR E + JR NZ, TCPD + DJNZ TCPW +TCPFL: LD HL, VRAM + VL*4 + 28 + LD DE, S_FAIL + CALL PVRAM + JP HTTPDN +TCPOK: LD HL, VRAM + VL*4 + 28 + LD DE, S_PASS + CALL PVRAM + + ;- ---- HTTP GET (line 5) ---- + LD HL, VRAM + VL*5 + LD DE, S_HTTP + CALL PVRAM + ;- Reset TX pointers (TX_RD=0, TX_WR=0 at 0x0422-0x0425). + LD A, 004h + OUT (PORT_AR0), A + LD A, 022h + OUT (PORT_AR1), A + XOR A + OUT (PORT_DR), A ; TX_RD high = 0. + OUT (PORT_DR), A ; TX_RD low = 0. + OUT (PORT_DR), A ; TX_WR high = 0. + OUT (PORT_DR), A ; TX_WR low = 0. + ;- Write request to TX buffer. + LD A, 040h + OUT (PORT_AR0), A + XOR A + OUT (PORT_AR1), A + LD HL, HTTPREQ +HTTPWR: LD A, (HL) + OR A + JR Z, HTTPWD + OUT (PORT_DR), A + INC HL + JR HTTPWR +HTTPWD: LD DE, HTTPREQ + OR A + SBC HL, DE + LD A, 004h + OUT (PORT_AR0), A + LD A, 024h + OUT (PORT_AR1), A + LD A, H + OUT (PORT_DR), A + LD A, L + OUT (PORT_DR), A + ;- SEND. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, 020h + OUT (PORT_DR), A + ;- Poll RX_RSR. + LD B, 250 +HTTPRW: PUSH BC + LD A, 004h + OUT (PORT_AR0), A + LD A, 026h + OUT (PORT_AR1), A + IN A, (PORT_DR) + LD H, A + IN A, (PORT_DR) + LD L, A + POP BC + LD A, H + OR L + JR NZ, HTTPGOT + LD DE, 20000 +HTTPRD: DEC DE + LD A, D + OR E + JR NZ, HTTPRD + DJNZ HTTPRW + LD HL, VRAM + VL*5 + 28 + LD DE, S_TOUT + CALL PVRAM + JP HTTPDN + +HTTPGOT: ;- Show hex count on line 5. + PUSH HL + LD HL, VRAM + VL*5 + 28 + POP DE + LD A, D + CALL PHEXV + LD A, E + CALL PHEXV + LD DE, S_BYT + CALL PVRAM + + ;- Read HTTP response and display on screen lines 7-24 (18 lines). + LD A, 060h + OUT (PORT_AR0), A + XOR A + OUT (PORT_AR1), A + LD HL, VRAM + VL*7 + LD C, 200 ; Max bytes to display. +HTDISP: IN A, (PORT_DR) + CP 00Dh + JR Z, HTNXT ; Skip CR. + CP 00Ah + JR Z, HTNL ; LF = new line. + ;- Convert and write to VRAM. + PUSH HL + PUSH DE + CALL A2DSP + POP DE + POP HL + LD (HL), A + INC HL + JR HTCHK +HTNL: ;- Advance to next 40-char line. Round HL up to next VL boundary. + ;- New HL = ((HL - VRAM + VL) / VL) * VL + VRAM. + PUSH DE + LD DE, VRAM + OR A + SBC HL, DE ; HL = offset from VRAM. + LD A, L + ADD A, VL + JR NC, HTNL2 + INC H +HTNL2: LD L, A + ;- Round down to VL boundary: offset = (offset / 40) * 40. + ;- Approximate: clear low bits. 40 = 8*5, not power of 2. Use division. + ;- Simple: subtract (offset mod 40). Use repeated subtraction. + LD A, L + LD E, A + LD A, H + LD D, A +HTNL3: LD A, D + OR A + JR NZ, HTNL4 + LD A, E + CP VL + JR C, HTNL5 +HTNL4: LD A, E + SUB VL + LD E, A + JR NC, HTNL3 + DEC D + JR HTNL3 +HTNL5: ;- E = offset mod 40. Subtract from HL. + LD A, L + SUB E + LD L, A + JR NC, HTNL6 + DEC H +HTNL6: LD DE, VRAM + ADD HL, DE + POP DE + JR HTCHK +HTNXT: ;- Just consumed CR — skip, don't advance. +HTCHK: ;- Bounds check. + LD A, H + CP 0D4h + JR NC, HTEND + DEC C + JR NZ, HTDISP +HTEND: + ;- RECV confirm. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, 040h + OUT (PORT_DR), A + +HTTPDN: ;- Close socket. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_CLOSE + OUT (PORT_DR), A + + ;- Debug port summary. + LD HL, DBGLP + CALL PSTR + LD A, (LOOPCNT+1) + CALL PHEX + LD A, (LOOPCNT) + CALL PHEX + LD HL, DBGCR + CALL PSTR + + ;- Delay ~1 second at 3.54MHz (2 × 65535 × 26T ≈ 0.96s). + LD B, 2 +DLY1: LD DE, 0FFFFh +DLY2: DEC DE + LD A, D + OR E + JR NZ, DLY2 + DJNZ DLY1 + + JP MAINLP + +;-------------------------------------------------------------------------------------------------------- +;- PVRAM: Write null-terminated ASCII string at DE to VRAM at HL. Returns HL advanced. +;-------------------------------------------------------------------------------------------------------- +PVRAM: LD A, (DE) + OR A + RET Z + PUSH HL + PUSH DE + CALL A2DSP + POP DE + POP HL + LD (HL), A + INC HL + INC DE + JR PVRAM + +;-------------------------------------------------------------------------------------------------------- +;- PDECV: Print A as decimal to VRAM at HL. Advances HL. +;-------------------------------------------------------------------------------------------------------- +PDECV: PUSH BC + LD B, 0 +PVD100: CP 100 + JR C, PVD10 + SUB 100 + INC B + JR PVD100 +PVD10: PUSH AF + LD A, B + OR A + JR Z, PVD10N + ADD A, 020h + LD (HL), A + INC HL +PVD10N: POP AF + LD B, 0 +PVD10L: CP 10 + JR C, PVD1 + SUB 10 + INC B + JR PVD10L +PVD1: PUSH AF + LD A, B + OR A + JR Z, PVD1N + ADD A, 020h + LD (HL), A + INC HL +PVD1N: POP AF + ADD A, 020h + LD (HL), A + INC HL + POP BC + RET + +;-------------------------------------------------------------------------------------------------------- +;- PHEXV: Print A as 2-digit hex to VRAM at HL. +;-------------------------------------------------------------------------------------------------------- +PHEXV: PUSH AF + RRCA + RRCA + RRCA + RRCA + AND 00Fh + CALL PHXN + POP AF + AND 00Fh +PHXN: CP 00Ah + JR C, PHXN1 + ADD A, 001h - 00Ah + LD (HL), A + INC HL + RET +PHXN1: ADD A, 020h + LD (HL), A + INC HL + RET + +;-------------------------------------------------------------------------------------------------------- +;- A2DSP: Convert ASCII in A to MZ display code via table. +;-------------------------------------------------------------------------------------------------------- +A2DSP: PUSH HL + AND 07Fh + LD L, A + LD H, 0 + LD DE, ATBL + ADD HL, DE + LD A, (HL) + POP HL + RET + +;-------------------------------------------------------------------------------------------------------- +;- Debug port helpers. +;-------------------------------------------------------------------------------------------------------- +PSTR: LD A, (HL) + OR A + RET Z + OUT (PORT_DBG), A + INC HL + JR PSTR + +PHEX: PUSH AF + RRCA + RRCA + RRCA + RRCA + AND 00Fh + ADD A, 030h + CP 03Ah + JR C, PH1 + ADD A, 007h +PH1: OUT (PORT_DBG), A + POP AF + AND 00Fh + ADD A, 030h + CP 03Ah + JR C, PH2 + ADD A, 007h +PH2: OUT (PORT_DBG), A + RET + +;-------------------------------------------------------------------------------------------------------- +;- Strings (ASCII, null-terminated). +;-------------------------------------------------------------------------------------------------------- +S_TITLE: DB "CELESTITE NET STRESS TEST", 0 +S_LOOP: DB "LOOP ", 0 +S_PING: DB "PING 192.168.1.1", 0 +S_TCP: DB "TCP CONNECT GATEWAY 80", 0 +S_HTTP: DB "HTTP GET GATEWAY", 0 +S_PASS: DB "PASS", 0 +S_FAIL: DB "FAIL", 0 +S_TOUT: DB "TOUT", 0 +S_MS: DB "MS", 0 +S_BYT: DB "H", 0 + +HTTPREQ: DB "GET / HTTP/1.0", 0Dh, 0Ah, 0Dh, 0Ah, 00h + +DBGLP: DB 0Dh, 0Ah, "Loop:", 0 +DBGCR: DB 0Dh, 0Ah, 0 + +LOOPCNT: DW 0 + +;- ASCII to MZ display code table (128 bytes). +ATBL: DB 0CCh,0E0h,0F2h,0F3h,0CEh,0CFh,0F6h,0F7h + DB 0F8h,0F9h,0CDh,0FBh,0FCh,0CDh,0FEh,0FFh + DB 0E1h,0C1h,0C2h,0C3h,0C4h,0C5h,0C6h,0E2h + DB 0E3h,0E4h,0E5h,0E6h,0EBh,0EEh,0EFh,0F4h + DB 000h,061h,062h,063h,064h,065h,066h,067h + DB 068h,069h,06Bh,06Ah,02Fh,02Ah,02Eh,02Dh + DB 020h,021h,022h,023h,024h,025h,026h,027h + DB 028h,029h,04Fh,02Ch,051h,02Bh,057h,049h + DB 055h,001h,002h,003h,004h,005h,006h,007h + DB 008h,009h,00Ah,00Bh,00Ch,00Dh,00Eh,00Fh + DB 010h,011h,012h,013h,014h,015h,016h,017h + DB 018h,019h,01Ah,052h,059h,054h,050h,045h + DB 000h,001h,002h,003h,004h,005h,006h,007h + DB 008h,009h,00Ah,00Bh,00Ch,00Dh,00Eh,00Fh + DB 010h,011h,012h,013h,014h,015h,016h,017h + DB 018h,019h,01Ah,053h,000h,058h,000h,000h + +MEND: diff --git a/projects/tzpuPico/src/test/Celestite/celestite_test.asm b/projects/tzpuPico/src/test/Celestite/celestite_test.asm new file mode 100644 index 0000000..f7b618a --- /dev/null +++ b/projects/tzpuPico/src/test/Celestite/celestite_test.asm @@ -0,0 +1,1137 @@ +;-------------------------------------------------------------------------------------------------------- +;- +;- Name: celestite_test.asm +;- Created: May 2026 +;- Author(s): Philip Smart +;- Description: Celestite LAN Board - W5100 Register Test Program +;- For Sharp MZ-700 / MZ-1500 with picoZ80. +;- +;- Tests the W5100 IDM register file and Celestite board-level registers. +;- Output goes to I/O port 50h (picoZ80 debug console - ASCII text). +;- +;- Assemble: java -jar glass.jar celestite_test.asm celestite_test.obj celestite_test.sym +;- The .obj file is an MZF which can be loaded via RFS or tape. +;- +;- Copyright: (c) 2019-2026 Philip Smart +;- +;- History: May 2026 v1.0 - Initial write. +;- +;-------------------------------------------------------------------------------------------------------- +;- This source file is free software: you can redistribute it and-or modify +;- it under the terms of the GNU General Public License as published +;- by the Free Software Foundation, either version 3 of the License, or +;- (at your option) any later version. +;- +;- This source file is distributed in the hope that it will be useful, +;- but WITHOUT ANY WARRANTY; without even the implied warranty of +;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;- GNU General Public License for more details. +;- +;- You should have received a copy of the GNU General Public License +;- along with this program. If not, see . +;-------------------------------------------------------------------------------------------------------- + +;- I/O port constants. +PORT_DBG EQU 050h ; picoZ80 debug output (ASCII). +PORT_MR EQU 060h ; W5100 Mode Register. +PORT_AR0 EQU 061h ; IDM Address high. +PORT_AR1 EQU 062h ; IDM Address low. +PORT_DR EQU 063h ; IDM Data. +PORT_INTV EQU 064h ; Interrupt vector. +PORT_INTC EQU 065h ; Interrupt control/status. +PORT_MEMO EQU 066h ; Memo register. +PORT_UFMA EQU 068h ; UFM address (W) / status (R). +PORT_UFMD EQU 069h ; UFM data. +PORT_PING EQU 067h ; Celestite ping trigger (W) / RTT result (R). +PORT_UNLK EQU 06Fh ; Unlock register. + +;- W5100 internal addresses. +W_MR EQU 00000h ; Mode Register. +W_GAR EQU 00001h ; Gateway IP [0-3]. +W_SUBR EQU 00005h ; Subnet Mask [0-3]. +W_SHAR EQU 00009h ; Source MAC [0-5]. +W_SIPR EQU 0000Fh ; Source IP [0-3]. +W_RMSR EQU 0001Ah ; RX Memory Size. +W_TMSR EQU 0001Bh ; TX Memory Size. +W_S0_MR EQU 00400h ; Socket 0 Mode. +W_S0_CR EQU 00401h ; Socket 0 Command. +W_S0_SR EQU 00403h ; Socket 0 Status. +W_S0_PORT EQU 00404h ; Socket 0 Port [0-1]. + +;- Socket commands. +CMD_OPEN EQU 001h +CMD_LISTEN EQU 002h +CMD_CONN EQU 004h +CMD_CLOSE EQU 010h + +;- Socket status values. +ST_CLOSED EQU 000h +ST_INIT EQU 013h +ST_LISTEN EQU 014h +ST_ESTAB EQU 017h + +;- Monitor entry points (SA-1510). +MONIT EQU 00086h ; Return to monitor. +TPSTART EQU 010F0h ; MZF header start. +MEMSTART EQU 01200h ; Program load/exec address. + +;-------------------------------------------------------------------------------------------------------- +;- MZF Header (at 10F0h) - required for tape/RFS loading. +;-------------------------------------------------------------------------------------------------------- + ORG TPSTART + +ATRB: DB 001h ; Code Type, 01 = Machine Code. +NAME: DB "W5100 TEST V1.0 ", 0Dh ; Title/Name (17 bytes + CR). +SIZE: DW MEND - MEMSTART ; Size of program. +DTADR: DW MEMSTART ; Load address. +EXADR: DW MEMSTART ; Exec address. +COMNT: DS 104 ; Comment (zeroed). + +;-------------------------------------------------------------------------------------------------------- +;- Program start. +;-------------------------------------------------------------------------------------------------------- + ORG MEMSTART + +START: LD SP, 0CFFFh ; Stack below VRAM. + CALL PBANNER + + ;- Test 1: W5100 Software Reset. + LD HL, T1MSG + CALL PSTR + LD A, 080h ; RST bit. + OUT (PORT_MR), A + ;- After reset, MR via IDM should be 01h (IND set, RST cleared). + XOR A + OUT (PORT_AR0), A + OUT (PORT_AR1), A + IN A, (PORT_DR) + CP 001h + CALL RESULT + + ;- Test 2: Enable Auto-Increment. + LD HL, T2MSG + CALL PSTR + LD A, 003h ; AI + IND. + OUT (PORT_MR), A + ;- Verify via IDM read of MR. + XOR A + OUT (PORT_AR0), A + OUT (PORT_AR1), A + IN A, (PORT_DR) + CP 003h + CALL RESULT + + ;- Test 3: Write/Read MAC Address (6 bytes with auto-increment). + LD HL, T3MSG + CALL PSTR + ;- Set IDM address to SHAR (0x0009). + XOR A + OUT (PORT_AR0), A + LD A, 009h + OUT (PORT_AR1), A + ;- Write 6 MAC bytes: DE:AD:BE:EF:CA:FE. + LD A, 0DEh + OUT (PORT_DR), A + LD A, 0ADh + OUT (PORT_DR), A + LD A, 0BEh + OUT (PORT_DR), A + LD A, 0EFh + OUT (PORT_DR), A + LD A, 0CAh + OUT (PORT_DR), A + LD A, 0FEh + OUT (PORT_DR), A + ;- Read back: reset address to 0x0009. + XOR A + OUT (PORT_AR0), A + LD A, 009h + OUT (PORT_AR1), A + IN A, (PORT_DR) + CP 0DEh + JR NZ, T3FAIL + IN A, (PORT_DR) + CP 0ADh + JR NZ, T3FAIL + IN A, (PORT_DR) + CP 0BEh + JR NZ, T3FAIL + IN A, (PORT_DR) + CP 0EFh + JR NZ, T3FAIL + IN A, (PORT_DR) + CP 0CAh + JR NZ, T3FAIL + IN A, (PORT_DR) + CP 0FEh + JR NZ, T3FAIL + XOR A ; Z flag set = PASS. + CALL RESULT + JR T3DONE +T3FAIL: LD A, 001h + OR A ; Clear Z flag = FAIL. + CALL RESULT +T3DONE: + + ;- Test 4: Write/Read Source IP. + LD HL, T4MSG + CALL PSTR + XOR A + OUT (PORT_AR0), A + LD A, 00Fh + OUT (PORT_AR1), A + ;- Write 192.168.1.100. + LD A, 192 + OUT (PORT_DR), A + LD A, 168 + OUT (PORT_DR), A + LD A, 1 + OUT (PORT_DR), A + LD A, 100 + OUT (PORT_DR), A + ;- Read back. + XOR A + OUT (PORT_AR0), A + LD A, 00Fh + OUT (PORT_AR1), A + IN A, (PORT_DR) + CP 192 + JR NZ, T4FAIL + IN A, (PORT_DR) + CP 168 + JR NZ, T4FAIL + IN A, (PORT_DR) + CP 1 + JR NZ, T4FAIL + IN A, (PORT_DR) + CP 100 + JR NZ, T4FAIL + XOR A + CALL RESULT + JR T4DONE +T4FAIL: LD A, 001h + OR A + CALL RESULT +T4DONE: + + ;- Test 5: Socket OPEN (TCP). + LD HL, T5MSG + CALL PSTR + ;- Set socket 0 mode = TCP. + LD A, 004h + OUT (PORT_AR0), A + XOR A + OUT (PORT_AR1), A ; Sn_MR at 0x0400. + LD A, 001h ; TCP mode. + OUT (PORT_DR), A + ;- Write OPEN to Sn_CR (0x0401). + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_OPEN + OUT (PORT_DR), A + ;- Read Sn_SR (0x0403) - expect SOCK_INIT (0x13). + LD A, 004h + OUT (PORT_AR0), A + LD A, 003h + OUT (PORT_AR1), A + IN A, (PORT_DR) + CP ST_INIT + CALL RESULT + + ;- Test 6: Socket LISTEN. + LD HL, T6MSG + CALL PSTR + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_LISTEN + OUT (PORT_DR), A + ;- Read status - expect SOCK_LISTEN (0x14). + LD A, 004h + OUT (PORT_AR0), A + LD A, 003h + OUT (PORT_AR1), A + IN A, (PORT_DR) + CP ST_LISTEN + CALL RESULT + + ;- Test 7: Socket CLOSE. + LD HL, T7MSG + CALL PSTR + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_CLOSE + OUT (PORT_DR), A + ;- Read status - expect SOCK_CLOSED (0x00). + LD A, 004h + OUT (PORT_AR0), A + LD A, 003h + OUT (PORT_AR1), A + IN A, (PORT_DR) + CP ST_CLOSED + CALL RESULT + + ;- Test 8: Socket OPEN (UDP) — verify SOCK_UDP state (0x22). + LD HL, T8MSG + CALL PSTR + ;- Close any prior socket first. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_CLOSE + OUT (PORT_DR), A + ;- Set mode = UDP (0x02). + LD A, 004h + OUT (PORT_AR0), A + XOR A + OUT (PORT_AR1), A + LD A, 002h ; UDP mode. + OUT (PORT_DR), A + ;- OPEN. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_OPEN + OUT (PORT_DR), A + ;- Read status - expect SOCK_UDP (0x22). + LD A, 004h + OUT (PORT_AR0), A + LD A, 003h + OUT (PORT_AR1), A + IN A, (PORT_DR) + CP 022h ; SOCK_UDP. + CALL RESULT + ;- Close for cleanup. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_CLOSE + OUT (PORT_DR), A + + ;- Test 9: Memo Register. + LD HL, T9MSG + CALL PSTR + LD A, 042h + OUT (PORT_MEMO), A + IN A, (PORT_MEMO) + CP 042h + CALL RESULT + + ;- Test 10: Interrupt Vector. + LD HL, T10MSG + CALL PSTR + LD A, 0C7h ; RST 0 opcode as test vector. + OUT (PORT_INTV), A + IN A, (PORT_INTV) + CP 0C7h + CALL RESULT + + ;- Test 11: UFM Write/Read. + LD HL, T11MSG + CALL PSTR + ;- Unlock UFM: write D1h then 0Fh to port 6Fh. + LD A, 0D1h + OUT (PORT_UNLK), A + LD A, 00Fh + OUT (PORT_UNLK), A + ;- Write 0xA5 to UFM address 0. + XOR A + OUT (PORT_UFMA), A ; Address = 0. + LD A, 0A5h + OUT (PORT_UFMD), A ; Write data. + ;- Read back. + XOR A + OUT (PORT_UFMA), A + IN A, (PORT_UFMD) + CP 0A5h + CALL RESULT + + ;- Test 12: TX Buffer Write/Read. + LD HL, T12MSG + CALL PSTR + ;- Write 0x55 to TX buffer at 0x4000. + LD A, 040h + OUT (PORT_AR0), A + XOR A + OUT (PORT_AR1), A + LD A, 055h + OUT (PORT_DR), A + ;- Read back. + LD A, 040h + OUT (PORT_AR0), A + XOR A + OUT (PORT_AR1), A + IN A, (PORT_DR) + CP 055h + CALL RESULT + + ;- ================================================================ + ;- Phase 2: Network tests (require ESP32 WiFi connected). + ;- ================================================================ + LD HL, NETMSG + CALL PSTR + + ;- Test 13: Wait for NET_CFG and show IP. + ;- The Celestite driver auto-requests the ESP32 network config at init. + ;- Poll GAR[0] (gateway, 0x0001) until non-zero — T04 doesn't write GAR so + ;- a non-zero value proves NET_CFG succeeded with real ESP32 WiFi config. + LD HL, T13MSG + CALL PSTR + LD B, 250 ; Retry up to 250 times. +T13WAIT: PUSH BC + ;- Read GAR[0] at W5100 address 0x0001. + XOR A + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + IN A, (PORT_DR) + POP BC + OR A + JR NZ, T13GOT + ;- Small delay (~10ms worth of Z80 cycles at 3.5MHz). + LD DE, 8000 +T13DLY: DEC DE + LD A, D + OR E + JR NZ, T13DLY + DJNZ T13WAIT + ;- Timed out — no IP received. + LD A, 001h + OR A + CALL RESULT + JR T13DONE +T13GOT: XOR A + CALL RESULT +T13DONE: + + ;- Test 14: Display IP address as dotted quad. + LD HL, T14MSG + CALL PSTR + ;- Read 4 bytes of SIPR (0x000F-0x0012). + XOR A + OUT (PORT_AR0), A + LD A, 00Fh + OUT (PORT_AR1), A + IN A, (PORT_DR) ; IP byte 0. + CALL PDEC + LD A, '.' + OUT (PORT_DBG), A + IN A, (PORT_DR) ; IP byte 1. + CALL PDEC + LD A, '.' + OUT (PORT_DBG), A + IN A, (PORT_DR) ; IP byte 2. + CALL PDEC + LD A, '.' + OUT (PORT_DBG), A + IN A, (PORT_DR) ; IP byte 3. + CALL PDEC + LD HL, CRLF + CALL PSTR + + ;- Test 15: Ping gateway. + LD HL, T15MSG + CALL PSTR + ;- Trigger ping via port 67h write (pings the gateway IP). + XOR A + OUT (PORT_PING), A ; Trigger ping. + ;- Wait for result (~3 seconds max). + LD B, 250 +T15WAIT: PUSH BC + IN A, (PORT_PING) ; Read RTT. + POP BC + CP 0FFh ; 0xFF = still pending. + JR NZ, T15GOT + LD DE, 12000 ; ~30ms delay. +T15DLY: DEC DE + LD A, D + OR E + JR NZ, T15DLY + DJNZ T15WAIT + ;- Timeout. + LD HL, TOMSG + CALL PSTR + JR T15DONE +T15GOT: ;- Print RTT value. + LD C, A ; Save RTT. + LD A, C + CALL PDEC + LD HL, MSMSG + CALL PSTR +T15DONE: + + ;- Test 16: TCP Connect to 1.1.1.1 port 80 (Cloudflare DNS, always up). + LD HL, T16MSG + CALL PSTR + ;- First close any open socket 0 and reset. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_CLOSE + OUT (PORT_DR), A + ;- Set mode = TCP. + LD A, 004h + OUT (PORT_AR0), A + XOR A + OUT (PORT_AR1), A + LD A, 001h + OUT (PORT_DR), A ; Sn_MR = TCP. + ;- Set destination IP = 1.1.1.1 (Sn_DIPR at 0x040C). + LD A, 004h + OUT (PORT_AR0), A + LD A, 00Ch + OUT (PORT_AR1), A + LD A, 1 + OUT (PORT_DR), A ; 1. + OUT (PORT_DR), A ; 1. + OUT (PORT_DR), A ; 1. + OUT (PORT_DR), A ; 1. + ;- Set destination port = 80 (0x0050) at Sn_DPORT 0x0410. + LD A, 004h + OUT (PORT_AR0), A + LD A, 010h + OUT (PORT_AR1), A + XOR A + OUT (PORT_DR), A ; Port high = 0. + LD A, 80 + OUT (PORT_DR), A ; Port low = 80. + ;- OPEN socket. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_OPEN + OUT (PORT_DR), A + ;- CONNECT. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_CONN + OUT (PORT_DR), A + ;- Wait for SOCK_ESTABLISHED or timeout. + LD B, 250 ; ~5 seconds. +T16WAIT: PUSH BC + LD A, 004h + OUT (PORT_AR0), A + LD A, 003h + OUT (PORT_AR1), A + IN A, (PORT_DR) ; Read Sn_SR. + POP BC + CP ST_ESTAB + JR Z, T16OK + CP ST_CLOSED + JR Z, T16FAIL + ;- Still connecting — wait. + LD DE, 20000 ; ~50ms delay. +T16DLY: DEC DE + LD A, D + OR E + JR NZ, T16DLY + DJNZ T16WAIT +T16FAIL: LD A, 001h + OR A + CALL RESULT + JR T16DONE +T16OK: XOR A + CALL RESULT + ;- Close the socket. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_CLOSE + OUT (PORT_DR), A +T16DONE: + + ;- ================================================================ + ;- Test 17: HTTP GET — connect, send request, display response on screen. + ;- ================================================================ + LD HL, T17MSG + CALL PSTR + + ;- Close any open socket. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_CLOSE + OUT (PORT_DR), A + + ;- Set mode = TCP. + LD A, 004h + OUT (PORT_AR0), A + XOR A + OUT (PORT_AR1), A + LD A, 001h + OUT (PORT_DR), A + + ;- Set dest IP = 192.168.1.1 (local router — known reachable, has HTTP). + LD A, 004h + OUT (PORT_AR0), A + LD A, 00Ch + OUT (PORT_AR1), A + LD A, 192 + OUT (PORT_DR), A + LD A, 168 + OUT (PORT_DR), A + LD A, 1 + OUT (PORT_DR), A + LD A, 1 + OUT (PORT_DR), A + + ;- Set dest port = 80. + LD A, 004h + OUT (PORT_AR0), A + LD A, 010h + OUT (PORT_AR1), A + XOR A + OUT (PORT_DR), A + LD A, 80 + OUT (PORT_DR), A + + ;- OPEN. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_OPEN + OUT (PORT_DR), A + + ;- CONNECT — wait for ESTABLISHED. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_CONN + OUT (PORT_DR), A + LD B, 250 +T17CW: PUSH BC + LD A, 004h + OUT (PORT_AR0), A + LD A, 003h + OUT (PORT_AR1), A + IN A, (PORT_DR) + POP BC + CP ST_ESTAB + JR Z, T17CONN + CP ST_CLOSED + JP Z, T17FAIL + LD DE, 20000 +T17CD: DEC DE + LD A, D + OR E + JR NZ, T17CD + DJNZ T17CW + JP T17FAIL + +T17CONN: ;- Connected! Write HTTP request to TX buffer at 0x4000. + LD A, 040h + OUT (PORT_AR0), A + XOR A + OUT (PORT_AR1), A + ;- Write "GET / HTTP/1.0\r\nHost: 1.1.1.1\r\n\r\n" + LD HL, HTTPREQ +T17WR: LD A, (HL) + OR A + JR Z, T17WRD + OUT (PORT_DR), A + INC HL + JR T17WR +T17WRD: + ;- Calculate request length. + LD DE, HTTPREQ + OR A + SBC HL, DE ; HL = length of request. + ;- Set TX write pointer (Sn_TX_WR at 0x0424). + ;- TX_WR = request length (high byte, low byte). + LD A, 004h + OUT (PORT_AR0), A + LD A, 024h + OUT (PORT_AR1), A + LD A, H + OUT (PORT_DR), A ; TX_WR high. + LD A, L + OUT (PORT_DR), A ; TX_WR low. + + ;- Issue SEND command. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, 020h ; CMD_SEND. + OUT (PORT_DR), A + + ;- Wait for data to arrive: poll RX_RSR (0x0426) until > 0. + LD HL, RXWMSG + CALL PSTR + LD B, 250 +T17RW: PUSH BC + LD A, 004h + OUT (PORT_AR0), A + LD A, 026h + OUT (PORT_AR1), A + IN A, (PORT_DR) ; RX_RSR high byte. + LD H, A + IN A, (PORT_DR) ; RX_RSR low byte. + LD L, A + POP BC + LD A, H + OR L + JR NZ, T17GOT + LD DE, 20000 +T17RD: DEC DE + LD A, D + OR E + JR NZ, T17RD + DJNZ T17RW + ;- Timeout — no data received. + LD HL, TOMSG + CALL PSTR + JP T17DONE + +T17GOT: ;- HL = 16-bit bytes available (big-endian from W5100). + ;- Print count to debug port. + PUSH HL + LD HL, RXGMSG + CALL PSTR + POP HL + PUSH HL + ;- Print "H.L" in hex to debug (simple, avoids 16-bit decimal). + LD A, H + CALL PHEX + LD A, L + CALL PHEX + LD A, 'h' + OUT (PORT_DBG), A + LD HL, BYTEMSG + CALL PSTR + POP HL + ;- Cap at 200 bytes for screen display. + LD A, H + OR A + JR NZ, T17LIM ; >255: limit. + LD A, L + CP 200 + JR C, T17LOK ; <200: use as-is. +T17LIM: LD L, 200 +T17LOK: LD C, L ; C = display byte count. + + ;- Clear MZ-1500 screen (VRAM at D000-D3FF = 1024 bytes, fill with 0x00 = space). + LD HL, 0D000h + LD BC, 1000 ; 25 lines × 40 chars. +T17CLR: LD (HL), 000h + INC HL + DEC BC + LD A, B + OR C + JR NZ, T17CLR + + ;- Read response from RX buffer at 0x6000 and write directly to VRAM. + LD A, 060h + OUT (PORT_AR0), A + XOR A + OUT (PORT_AR1), A + LD HL, 0D000h ; VRAM write pointer. + + ;- B = line counter (0-24), HL = VRAM pointer. + LD B, 0 ; Line counter. +T17DISP: IN A, (PORT_DR) ; Read byte from W5100 RX buffer. + ;- Skip CR (0x0D) — just consume it. + CP 00Dh + JR Z, T17NXT + ;- LF (0x0A) — advance to next line start. + CP 00Ah + JR Z, T17NL + ;- Regular char: convert ASCII to display code, write to VRAM. + CALL A2DSP + LD (HL), A + INC HL + JR T17NXT +T17NL: ;- Newline: set HL to start of next line (D000 + line*40). + INC B ; Next line. + LD A, B + CP 25 ; Past last line? + JR NC, T17END + ;- Calculate D000 + B*40. B*40 = B*32 + B*8. + LD D, 0 + LD E, B ; DE = line number. + LD H, D + LD L, E ; HL = line. + ADD HL, HL ; ×2. + ADD HL, HL ; ×4. + ADD HL, HL ; ×8. + LD D, H + LD E, L ; DE = line×8. + ADD HL, HL ; ×16. + ADD HL, HL ; ×32. + ADD HL, DE ; HL = line×32 + line×8 = line×40. + LD DE, 0D000h + ADD HL, DE ; HL = D000 + line×40. +T17NXT: ;- Check if past end of visible VRAM. + LD A, H + CP 0D4h + JR NC, T17END + DEC C + JR NZ, T17DISP +T17END: + ;- Issue RECV to confirm read. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, 040h ; CMD_RECV. + OUT (PORT_DR), A + + ;- Print success to debug. + LD HL, CRLF + CALL PSTR + LD HL, OKMSG + CALL PSTR + LD HL, PAUSMSG + CALL PSTR + + ;- Halt here so user can view the screen. Press RESET to continue. +T17HALT: JR T17HALT + +T17FAIL: LD HL, FAILMSG + CALL PSTR + +T17DONE: ;- Close socket. + LD A, 004h + OUT (PORT_AR0), A + LD A, 001h + OUT (PORT_AR1), A + LD A, CMD_CLOSE + OUT (PORT_DR), A + + ;- Done. + LD HL, DONEMSG + CALL PSTR + + ;- Return to monitor. + JP MONIT + +;-------------------------------------------------------------------------------------------------------- +;- RESULT: Print PASS if Z flag set, FAIL otherwise. +;-------------------------------------------------------------------------------------------------------- +RESULT: JR Z, RPASS + LD HL, FAILMSG + CALL PSTR + RET +RPASS: LD HL, PASSMSG + CALL PSTR + RET + +;-------------------------------------------------------------------------------------------------------- +;- PSTR: Print null-terminated ASCII string at HL to debug port 50h. +;-------------------------------------------------------------------------------------------------------- +PSTR: LD A, (HL) + OR A + RET Z + OUT (PORT_DBG), A + INC HL + JR PSTR + +;-------------------------------------------------------------------------------------------------------- +;- PDEC: Print A register as unsigned decimal (0-255) to debug port. +;- Suppresses leading zeros for numbers < 100. +;-------------------------------------------------------------------------------------------------------- +PDEC: PUSH BC + LD B, A ; Save original. + ;- Hundreds digit. + LD C, 0 ; Leading zero suppression flag. + LD A, B + LD B, 0 +PD100: CP 100 + JR C, PD10S + SUB 100 + INC B + JR PD100 +PD10S: PUSH AF ; Save remainder. + LD A, B + OR A + JR Z, PD10N ; Skip leading zero. + ADD A, '0' + OUT (PORT_DBG), A + LD C, 1 ; Had a hundreds digit. +PD10N: POP AF + ;- Tens digit. + LD B, 0 +PD10: CP 10 + JR C, PD1S + SUB 10 + INC B + JR PD10 +PD1S: PUSH AF + LD A, B + OR A + JR NZ, PD1P ; Non-zero tens digit — print. + LD A, C + OR A + JR Z, PD1N ; Skip if no hundreds digit either. +PD1P: LD A, B + ADD A, '0' + OUT (PORT_DBG), A +PD1N: POP AF + ;- Ones digit (always print). + ADD A, '0' + OUT (PORT_DBG), A + POP BC + RET + +;-------------------------------------------------------------------------------------------------------- +;- PHEX: Print A register as 2-digit hex to debug port. +;-------------------------------------------------------------------------------------------------------- +PHEX: PUSH AF + RRCA + RRCA + RRCA + RRCA + AND 00Fh + ADD A, 030h + CP 03Ah + JR C, PHX1 + ADD A, 007h ; A-F. +PHX1: OUT (PORT_DBG), A + POP AF + AND 00Fh + ADD A, 030h + CP 03Ah + JR C, PHX2 + ADD A, 007h +PHX2: OUT (PORT_DBG), A + RET + +;-------------------------------------------------------------------------------------------------------- +;- A2DSP: Convert ASCII code in A to Sharp MZ display code. +;- Uses lookup table. Non-printable chars become space (0x00). +;-------------------------------------------------------------------------------------------------------- +A2DSP: PUSH HL + LD HL, ATBL + AND 07Fh ; Mask to 7-bit ASCII. + LD L, A + LD H, 0 + LD DE, ATBL + ADD HL, DE + LD A, (HL) + POP HL + RET + +;-------------------------------------------------------------------------------------------------------- +;- DPCT: Display character on MZ-1500 screen (display code in A). +;- Calls the SA-1510 monitor's DPCT routine at 0x0DDC. +;-------------------------------------------------------------------------------------------------------- +DPCT EQU 00DDCh + +;-------------------------------------------------------------------------------------------------------- +;- PMSG: Print null-terminated display-code string at DE to MZ-1500 screen. +;-------------------------------------------------------------------------------------------------------- +PMSG: LD A, (DE) + OR A + RET Z + CALL DPCT + INC DE + JR PMSG + +;-------------------------------------------------------------------------------------------------------- +;- PBANNER: Print test banner. +;-------------------------------------------------------------------------------------------------------- +PBANNER: LD HL, BNRMSG + CALL PSTR + RET + +;-------------------------------------------------------------------------------------------------------- +;- String data (null-terminated ASCII). +;-------------------------------------------------------------------------------------------------------- +BNRMSG: DB 0Dh, 0Ah + DB "=== Celestite W5100 Register Test ===", 0Dh, 0Ah + DB "Output: picoZ80 debug port (50h)", 0Dh, 0Ah, 00h + +T1MSG: DB "T01 W5100 Reset........... ", 00h +T2MSG: DB "T02 Auto-Increment Enable. ", 00h +T3MSG: DB "T03 MAC Address W/R....... ", 00h +T4MSG: DB "T04 Source IP W/R......... ", 00h +T5MSG: DB "T05 Socket OPEN (TCP)..... ", 00h +T6MSG: DB "T06 Socket LISTEN......... ", 00h +T7MSG: DB "T07 Socket CLOSE.......... ", 00h +T8MSG: DB "T08 Socket OPEN (UDP)..... ", 00h +T9MSG: DB "T09 Memo Register......... ", 00h +T10MSG: DB "T10 Interrupt Vector...... ", 00h +T11MSG: DB "T11 UFM Write/Read........ ", 00h +T12MSG: DB "T12 TX Buffer Write/Read.. ", 00h + +PASSMSG: DB "PASS", 0Dh, 0Ah, 00h +FAILMSG: DB "FAIL", 0Dh, 0Ah, 00h + +NETMSG: DB 0Dh, 0Ah, "--- Phase 2: Network Tests ---", 0Dh, 0Ah + DB "(Requires ESP32 WiFi connected)", 0Dh, 0Ah, 00h +T13MSG: DB "T13 Wait for NET_CFG...... ", 00h +T14MSG: DB "T14 IP Address: ", 00h +T15MSG: DB "T15 Ping Gateway.......... ", 00h +T16MSG: DB "T16 TCP Connect 1.1.1.1:80 ", 00h + +T17MSG: DB 0Dh, 0Ah, "T17 HTTP GET gateway...... ", 00h +RXWMSG: DB "Waiting for response...", 00h +RXGMSG: DB "Received ", 00h +BYTEMSG: DB " bytes", 0Dh, 0Ah, 00h +OKMSG: DB "HTTP GET OK", 0Dh, 0Ah, 00h +PAUSMSG: DB "Pausing 5s to view screen...", 0Dh, 0Ah, 00h + +CRLF: DB 0Dh, 0Ah, 00h +TOMSG: DB "TIMEOUT", 0Dh, 0Ah, 00h +MSMSG: DB "ms", 0Dh, 0Ah, 00h +DONEMSG: DB 0Dh, 0Ah, "=== All tests complete ===", 0Dh, 0Ah, 00h + +;- HTTP GET request (null-terminated, sent to TX buffer). +;- Uses simple HTTP/1.0 with no Host header — most routers accept this. +HTTPREQ: DB "GET / HTTP/1.0", 0Dh, 0Ah + DB 0Dh, 0Ah, 00h + +;- Screen header string (display codes, null-terminated). +;- "--- HTTP RESPONSE ---" + newline +SCRHDR: DB 02Dh, 02Dh, 02Dh, 000h, 028h, 034h, 034h, 030h ; "--- HTTP" + DB 000h, 032h, 025h, 033h, 030h, 02Fh, 02Eh, 033h ; " RESPONS" + DB 025h, 000h, 02Dh, 02Dh, 02Dh, 0CDh, 00h ; "E ---" + CR + null + +;- ASCII to Sharp MZ display code conversion table (128 bytes). +;- Index = ASCII code, value = display code. +ATBL: DB 0CCh ; 00 NUL -> blank + DB 0E0h ; 01 SOH + DB 0F2h ; 02 STX + DB 0F3h ; 03 ETX + DB 0CEh ; 04 EOT + DB 0CFh ; 05 ENQ + DB 0F6h ; 06 ACK + DB 0F7h ; 07 BEL + DB 0F8h ; 08 BS + DB 0F9h ; 09 HT + DB 0CDh ; 0A LF -> newline display code + DB 0FBh ; 0B VT + DB 0FCh ; 0C FF + DB 0CDh ; 0D CR -> newline display code + DB 0FEh ; 0E SO + DB 0FFh ; 0F SI + DB 0E1h ; 10 DLE + DB 0C1h ; 11 DC1 + DB 0C2h ; 12 DC2 + DB 0C3h ; 13 DC3 + DB 0C4h ; 14 DC4 + DB 0C5h ; 15 NAK + DB 0C6h ; 16 SYN + DB 0E2h ; 17 ETB + DB 0E3h ; 18 CAN + DB 0E4h ; 19 EM + DB 0E5h ; 1A SUB + DB 0E6h ; 1B ESC + DB 0EBh ; 1C FS + DB 0EEh ; 1D GS + DB 0EFh ; 1E RS + DB 0F4h ; 1F US + DB 000h ; 20 SPACE + DB 061h ; 21 ! + DB 062h ; 22 " + DB 063h ; 23 # + DB 064h ; 24 $ + DB 065h ; 25 % + DB 066h ; 26 & + DB 067h ; 27 ' + DB 068h ; 28 ( + DB 069h ; 29 ) + DB 06Bh ; 2A * + DB 06Ah ; 2B + + DB 02Fh ; 2C , + DB 02Ah ; 2D - + DB 02Eh ; 2E . + DB 02Dh ; 2F / + DB 020h ; 30 0 + DB 021h ; 31 1 + DB 022h ; 32 2 + DB 023h ; 33 3 + DB 024h ; 34 4 + DB 025h ; 35 5 + DB 026h ; 36 6 + DB 027h ; 37 7 + DB 028h ; 38 8 + DB 029h ; 39 9 + DB 04Fh ; 3A : + DB 02Ch ; 3B ; + DB 051h ; 3C < + DB 02Bh ; 3D = + DB 057h ; 3E > + DB 049h ; 3F ? + DB 055h ; 40 @ + DB 001h ; 41 A + DB 002h ; 42 B + DB 003h ; 43 C + DB 004h ; 44 D + DB 005h ; 45 E + DB 006h ; 46 F + DB 007h ; 47 G + DB 008h ; 48 H + DB 009h ; 49 I + DB 00Ah ; 4A J + DB 00Bh ; 4B K + DB 00Ch ; 4C L + DB 00Dh ; 4D M + DB 00Eh ; 4E N + DB 00Fh ; 4F O + DB 010h ; 50 P + DB 011h ; 51 Q + DB 012h ; 52 R + DB 013h ; 53 S + DB 014h ; 54 T + DB 015h ; 55 U + DB 016h ; 56 V + DB 017h ; 57 W + DB 018h ; 58 X + DB 019h ; 59 Y + DB 01Ah ; 5A Z + DB 052h ; 5B [ + DB 059h ; 5C yen + DB 054h ; 5D ] + DB 050h ; 5E ^ + DB 045h ; 5F _ + DB 000h ; 60 ` -> space + DB 001h ; 61 a -> A (uppercase on MZ) + DB 002h ; 62 b -> B + DB 003h ; 63 c -> C + DB 004h ; 64 d -> D + DB 005h ; 65 e -> E + DB 006h ; 66 f -> F + DB 007h ; 67 g -> G + DB 008h ; 68 h -> H + DB 009h ; 69 i -> I + DB 00Ah ; 6A j -> J + DB 00Bh ; 6B k -> K + DB 00Ch ; 6C l -> L + DB 00Dh ; 6D m -> M + DB 00Eh ; 6E n -> N + DB 00Fh ; 6F o -> O + DB 010h ; 70 p -> P + DB 011h ; 71 q -> Q + DB 012h ; 72 r -> R + DB 013h ; 73 s -> S + DB 014h ; 74 t -> T + DB 015h ; 75 u -> U + DB 016h ; 76 v -> V + DB 017h ; 77 w -> W + DB 018h ; 78 x -> X + DB 019h ; 79 y -> Y + DB 01Ah ; 7A z -> Z + DB 053h ; 7B { + DB 000h ; 7C | -> space + DB 058h ; 7D } + DB 000h ; 7E ~ -> space + DB 000h ; 7F DEL -> space + +MEND: