From 9cc53483ad886118ef15518b95ee1197ddbd1640 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Sat, 21 Apr 2018 15:30:26 -0400 Subject: [PATCH] rewrite vt100 and telnet. --- GNUmakefile | 32 + ansi.asm | 1539 ++++++++++++++++++++------------------- chars.asm | 2002 +++++++++++++++++++++++++-------------------------- display.c | 464 ++---------- fctelnet.c | 897 ++++++++++------------- makefile | 47 +- marinetti.c | 248 +++---- marinetti.h | 278 +++---- telnet.h | 166 ++--- vt100.c | 1081 ++++++++++++++++++++------- 10 files changed, 3395 insertions(+), 3359 deletions(-) create mode 100644 GNUmakefile diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 0000000..9a4c2d4 --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,32 @@ +PROG = fctelnet +OBJS = o/fctelnet.a o/vt100.a o/telnet.a o/ansi.a o/chars.a o/marinetti.a o/display.a + +OPTIMIZE ?= 79 + +CFLAGS = -w-1 -O $(OPTIMIZE) +CC = occ --gno + +$(PROG): $(OBJS) + $(RM) o/ansi.root + $(RM) o/chars.root + $(CC) $(OBJS) -o $@ + + +fctelnet.o: fctelnet.c marinetti.h +vt100.o: vt100.c CLAGS+=-r +ansi.o: ansi.asm +chars.o: chars.asm +marinetti.o: marinetti.c CLAGS+=-r +telnet.o: telnet.c CLAGS+=-r + +o/%.a : %.c + $(CC) -c $(CFLAGS) -o $@ $^ + +o/%.a : %.asm + $(CC) -c $(CFLAGS) -o $@ $^ + + +clean: + $(RM) -f *.o *.root *.a *.r +clobber: clean + $(RM) -f $(PROG) diff --git a/ansi.asm b/ansi.asm index a7115f7..14d86b7 100644 --- a/ansi.asm +++ b/ansi.asm @@ -1,774 +1,765 @@ - case on - -dummy start - end - -; -;ReverseScrollRegion(line1, line2) -; -ReverseScrollRegion START -line2 equ 9 -line1 equ 7 -_rtlb equ 3 -_d equ 1 - -; brk $ea - - phb - phd - tsc - tcd - - lda 23*8*160 - ldx #$e12000+1920 ; src address - ldy #$e12000+640 ; dest address - -; ldx #$2000+1280 -; ldy #$2000 - - mvn $e10000,$e10000 - -; -; now empty outline #24 -; - pea 23 - jsl ClearLine - - - plb - rtl - - END - -; -; ClearLine(int line_no); clears the line -; -ClearLine START - -line equ 9 -_rtlb equ 5 -tmp equ 3 -_d equ 1 - - -; brk $ea - phb - pha - - phd - tsc - tcd - -; line * 8 * 160 + 4*160 -; = line * 1024 + line * 256 + 4*160 - lda $e10000,x ; stick a 0 in there - txy ; destination address (src + 2) - iny - iny - - - lda #8*160-3 ; length -1 - mvn $e10000,$e10000 - - lda <_rtlb+2 - sta <_rtlb+4 - lda <_rtlb - sta <_rtlb+2 - - pld - pla - pla - plb - rtl - - END - - -;extern void ClearScreenFrom(int Y); -; -; -; -ClearScreenFrom START - -Y equ 9 -_rtlb equ 5 -tmp equ 3 -_d equ 1 - - -; brk $ea - phb - pha - - phd - tsc - tcd - -; line * 8 * 160 + 4*160 -; = line * 1024 + line * 256 + 4*160 - lda $e10000,x ; stick a 0 in there - txy ; destination address (src + 2) - iny - iny - - - phy - lda #$9d00-2 ; end of graphics + $2000 - sec - sbc 1,s - ply - -; a now equals length to clear - - mvn $e10000,$e10000 - - lda <_rtlb+2 - sta <_rtlb+4 - lda <_rtlb - sta <_rtlb+2 - - pld - pla - pla - plb - rtl - - END - -; -;extern void ClearLineFrom(int Y, int X); -; - -; -; clear the end of the line from a given x & y -; -ClearLineFrom START - -X equ 11 -Y equ 9 -_rtlb equ 5 -tmp equ 3 -_d equ 1 - - phb - pha - phd - tsc - tcd - - pea $e1e1 - plb - plb - - -; -; if X is >= 80, skip it... -; - lda $e12000,x - - - - pld - pla ;tmp - pla - sta 5,s - pla - sta 5,s - pla - plb - rtl - - END - - - -; -; clear the screen to black (or whatnot) -; - -ClearScreen START - - phb - pea $e1e1 - plb - plb - lda #0 - ldy #0 -loop anop - sta $2000,y - iny - iny - cpy #32000 - bcc loop - plb - rtl - -; -; this will, in 1 atomic action, blast the screen with 0 -; - - phb - lda #0 - sta >$e12000 - lda #32000-3 ;length - ldx #$2000 - ldy #$2002 - mvn $e10000,$e10000 - - plb - rtl - END -; -; draw a character at the current Xpos & Ypos -; -; - -PrintChar START - -andMask equ 11 -char equ 9 -_rtlb equ 5 -pos equ 3 -_d equ 1 - -; brk $ea - phb - pha - - phd - tsc - tcd - -; sanity check on Xpos && Ypos - lda Xpos - cmp #80 - bcc _ok - lda Ypos - cmp #24 - bcc _ok - brl exit -_ok anop - - - pea $e1e1 - plb - plb - -; -; each line has a width of 160 pixels -; -; start drawing the letter at $e12000 + (Ypos x 160 x 8) + Xpos - - -; 160 * 8 = 1240 = 1024 + 256 - lda >Ypos - and #$00ff - xba ; x 256 - sta Xpos - asl a ; x 2 - clc - adc CHAR_SPACE,x - eor >xor_mask - and CHAR_SPACE+2,x - eor >xor_mask - and CHAR_SPACE+4,x - eor >xor_mask - and CHAR_SPACE+6,x - eor >xor_mask - and CHAR_SPACE+8,x - eor >xor_mask - and CHAR_SPACE+10,x - eor >xor_mask - and CHAR_SPACE+12,x - eor >xor_mask - and CHAR_SPACE+14,x - eor >xor_mask - and rows,x + clc ; dec a + ldx rows,x + pha + + +; +; mvn: +; while (--a != -1) +; dest[y++] = dest[x++]; +; +; mvp: +; while(--a != -1) +; dest[y--] = dest[x--]; + + + +; y = dest address = $2000 + 640 + (line2 + 1) * 8 * 160 -1 +; x = src address = dest - 160*8 + + + ldx rows,x + dec a + tay + sec + sbc #160*8 + tax + + pla ; length + + mvp $e10000,$e10000 + +; +; now empty first line +; + ldx rows,x + clc ; dec a + ldx rows,x + pha + + +; src address = $2000 + line1 + + +; ldx #$e12000+1920 ; src address +; ldy #$e12000+640 ; dest address + +; dest = $2000 + 640 + line1 * 8 * 160 +; src = dest + 1280 + + ldx rows,x + tay + clc + adc #8*160 + tax + + pla ; length + + mvn $e10000,$e10000 + +; +; now empty last line +; + ldx line2 + dex + dex + jsr _ClearLine + +exit anop + + lda <_rtlb + sta 23*8*160 + ldx #$e12000+1920 ; src address + ldy #$e12000+640 ; dest address + +; ldx #$2000+1280 +; ldy #$2000 + + mvn $e10000,$e10000 + +; +; now empty outline #24 +; + ldx #23 + jsr _ClearLine + + + plb + rtl + + END + + +; clear line in X (which has been pre-multiplied) +_ClearLine PRIVATE + + using tables + + lda >rows,x + tax + lda #0 + sta >$e10000,x ; stick a 0 in there + txy ; destination address (src + 2) + iny + iny + + lda #8*160-3 ; length -1 + mvn $e10000,$e10000 + rts + END +; +; ClearLine(int line_no); clears the line +; +ClearLine START + +line equ 7 +_rtlb equ 3 +_d equ 1 + + +; brk $ea + phb + + phd + tsc + tcd + + lda rows,x + clc + ldx rows,x + dec a + dec a + pha ; save length + + + ldx rows,x + tax + tay + iny + iny + + lda #0 + sta >$e1000,x + pla ; restore length + + mvn $e10000,$e10000 + + +exit anop + lda <_rtlb+2 + sta rows,x + + clc + adc start + tax + + +loop anop + + stz |0,x + stz |160,x + stz |320,x + stz |480,x + stz |640,x + stz |800,x + stz |960,x + stz |1120,x + inx + inx + dey + bne loop + +exit anop + + lda <_rtlb+2 + sta $e12000,x + + + + pld + pla ;tmp + pla + sta 5,s + pla + sta 5,s + pla + plb + rtl + + END + + + +; +; clear the screen to black (or whatnot) +; + +ClearScreen START + + phb + pea $e1e1 + plb + plb + lda #0 + ldy #32000 +loop anop + sta |$2000-2,y + dey + dey + bne loop + plb + rtl + + END +; +; draw a character at the current Xpos & Ypos +; +; +; PrintChar(x, y, char, andMask, xorMask) +PrintChar START + + using tables + +xorMask equ 15 +andMask equ 13 +char equ 11 +yy equ 9 +xx equ 7 +_rtlb equ 3 +_d equ 1 + +; brk $ea + phb + + phd + tsc + tcd + +; sanity check on Xpos && Ypos + + ldx xx + cpx #80 + bcc ok2 + +exit2 anop + brl exit + +ok2 anop + ldy yy + cpy #24 + bcs exit2 + + lda rows,x + clc + adc xx + tay + + +; +; $e12000 + pos = location to start drawing the character +; + +; +; each char takes up 16 bytes :. the offset is (char - $20) * 16 +; + + ldx char + lda >CHAR_SPACE,x + eor CHAR_SPACE+2,x + eor CHAR_SPACE+4,x + eor CHAR_SPACE+6,x + eor CHAR_SPACE+8,x + eor CHAR_SPACE+10,x + eor CHAR_SPACE+12,x + eor CHAR_SPACE+14,x + eor - dc b'0000110000000000' - dc b'0000001100000000' - dc b'0000000011000000' - dc b'0000000000110000' - dc b'0000000011000000' - dc b'0000001100000000' - dc b'0000110000000000' - dc b'0000000000000000' - -;? - dc b'0000111111000000' - dc b'0011000000110000' - dc b'0000000011000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000000000000000' - dc b'0000001100000000' - dc b'0000000000000000' - - -;@ - - dc b'0000111111000000' - dc b'0011000000110000' - dc b'0011001100110000' - dc b'0011001100110000' - dc b'0011001111000000' - dc b'0011000000000000' - dc b'0000111111110000' - dc b'0000000000000000' - - - -;CHAR_A START - dc b'0000001100000000' - dc b'0000110011000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011111111110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000000000000000' - - -;CHAR_B START - dc b'0011111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011111111000000' - dc b'0000000000000000' - -;CHAR_C START - dc b'0000111111000000' - dc b'0011000000110000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000110000' - dc b'0000111111000000' - dc b'0000000000000000' - -;CHAR_D START - dc b'0011111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011111111000000' - dc b'0000000000000000' - -;CHAR_E START - dc b'0011111111110000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011111111000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011111111110000' - dc b'0000000000000000' - -;CHAR_F START - dc b'0011111111110000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011111111000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0000000000000000' - -;CHAR_G START - dc b'0000111111110000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000011110000' - dc b'0011000000110000' - dc b'0000111111110000' - dc b'0000000000000000' - -;CHAR_H START - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011111111110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000000000000000' - -;CHAR_I START - dc b'0000111111000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000111111000000' - dc b'0000000000000000' - -;CHAR_J START - dc b'0000000000110000' - dc b'0000000000110000' - dc b'0000000000110000' - dc b'0000000000110000' - dc b'0000000000110000' - dc b'0011000000110000' - dc b'0000111111000000' - dc b'0000000000000000' - -;CHAR_K START - dc b'0011000011000000' - dc b'0011001100000000' - dc b'0011110000000000' - dc b'0011000000000000' - dc b'0011110000000000' - dc b'0011001100000000' - dc b'0011000011000000' - dc b'0000000000000000' - - -;CHAR_L START - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011111111110000' - dc b'0000000000000000' - -;CHAR_M START - dc b'0011000000110000' - dc b'0011110011110000' - dc b'0011001100110000' - dc b'0011001100110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000000000000000' - -;CHAR_N START - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011110000110000' - dc b'0011001100110000' - dc b'0011000011110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000000000000000' - -;CHAR_O START - dc b'0000111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000111111000000' - dc b'0000000000000000' - -;CHAR_P START - dc b'0011111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011111111000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0000000000000000' - - -;CHAR_Q START - dc b'0000111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011001100110000' - dc b'0011000011000000' - dc b'0000111100110000' - dc b'0000000000000000' - -;CHAR_R START - dc b'0011111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011111111000000' - dc b'0011001100000000' - dc b'0011000011000000' - dc b'0011000000110000' - dc b'0000000000000000' -;CHAR_S START - dc b'0000111111000000' - dc b'0011000000110000' - dc b'0011000000000000' - dc b'0000111111000000' - dc b'0000000000110000' - dc b'0011000000110000' - dc b'0000111111000000' - dc b'0000000000000000' -;CHAR_T START - dc b'0011111111110000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000000000000000' - -;CHAR_U START - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000111111000000' - dc b'0000000000000000' - -;CHAR_V START - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000110011000000' - dc b'0000001100000000' - dc b'0000000000000000' - -;CHAR_W START - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011001100110000' - dc b'0011001100110000' - dc b'0011110011110000' - dc b'0011000000110000' - dc b'0000000000000000' - -;CHAR_X START - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000110011000000' - dc b'0000001100000000' - dc b'0000110011000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000000000000000' - -;CHAR_Y START - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000110011000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000000000000000' -;CHAR_Z START - dc b'0011111111110000' - dc b'0000000000110000' - dc b'0000000011000000' - dc b'0000001100000000' - dc b'0000110000000000' - dc b'0011000000000000' - dc b'0011111111110000' - dc b'0000000000000000' - -; _[_ - dc b'0011111111110000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011111111110000' - dc b'0000000000000000' - -; \ - dc b'0000000000000000' - dc b'0011000000000000' - dc b'0000110000000000' - dc b'0000001100000000' - dc b'0000000011000000' - dc b'0000000000110000' - dc b'0000000000000000' - dc b'0000000000000000' - -; ] - dc b'0011111111110000' - dc b'0000000000110000' - dc b'0000000000110000' - dc b'0000000000110000' - dc b'0000000000110000' - dc b'0000000000110000' - dc b'0011111111110000' - dc b'0000000000000000' - -; ^ - - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000001100000000' - dc b'0000110011000000' - dc b'0011000000110000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - -;CHAR__ START - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'1111111111111111' - -; ` - dc b'0000110000000000' - dc b'0000001100000000' - dc b'0000000011000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - - -; a - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000111111000000' - dc b'0000000000110000' - dc b'0000111111110000' - dc b'0011000000110000' - dc b'0000111111110000' - dc b'0000000000000000' - -;b - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011111111000000' - dc b'0000000000000000' - -;c - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000111111110000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0000111111110000' - dc b'0000000000000000' - -;d - - dc b'0000000000110000' - dc b'0000000000110000' - dc b'0000111111110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000111111110000' - dc b'0000000000000000' - -;e - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000111111000000' - dc b'0011000000110000' - dc b'0011111111110000' - dc b'0011000000000000' - dc b'0000111111110000' - dc b'0000000000000000' - -;f - - dc b'0000001111000000' - dc b'0000110000110000' - dc b'0000110000000000' - dc b'0011111111000000' - dc b'0000110000000000' - dc b'0000110000000000' - dc b'0000110000000000' - dc b'0000000000000000' - - -; g - - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000111111110000' - dc b'0000000000110000' - dc b'0000111111000000' - -;h - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000000000000000' - -;i - dc b'0000001100000000' - dc b'0000000000000000' - dc b'0000111100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000111111000000' - dc b'0000000000000000' - -; j - - dc b'0000000011000000' - dc b'0000000000000000' - dc b'0000001111000000' - dc b'0000000011000000' - dc b'0000000011000000' - dc b'0000000011000000' - dc b'0000110011000000' - dc b'0000001100000000' - -; k - - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000011000000' - dc b'0011001100000000' - dc b'0011111100000000' - dc b'0011000011000000' - dc b'0011000000110000' - dc b'0000000000000000' - -;l - dc b'0000111100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000111111000000' - dc b'0000000000000000' - -;m - - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0011110011110000' - dc b'0011001100110000' - dc b'0011001100110000' - dc b'0011001100110000' - dc b'0011000000110000' - dc b'0000000000000000' - -;n - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0011111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000000000000000' - - -;o - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000111111000000' - dc b'0000000000000000' - -;p - - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0011111111000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011111111000000' - dc b'0011000000000000' - dc b'0011000000000000' - -;q - - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000111111110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000111111110000' - dc b'0000000000110000' - dc b'0000000000110000' - -;r - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0011001111110000' - dc b'0011110000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0011000000000000' - dc b'0000000000000000' - -;s - - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000111111110000' - dc b'0011000000000000' - dc b'0000111111000000' - dc b'0000000000110000' - dc b'0011111111000000' - dc b'0000000000000000' - -;t - dc b'0000110000000000' - dc b'0000110000000000' - dc b'0011111111000000' - dc b'0000110000000000' - dc b'0000110000000000' - dc b'0000110000110000' - dc b'0000001111000000' - dc b'0000000000000000' - -;u - - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000011110000' - dc b'0000111100110000' - dc b'0000000000000000' - -;v - - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000110011000000' - dc b'0000001100000000' - dc b'0000000000000000' - -; w - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011001100110000' - dc b'0011001100110000' - dc b'0011110011110000' - dc b'0000000000000000' - -;x - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0011000000110000' - dc b'0000110011000000' - dc b'0000001100000000' - dc b'0000110011000000' - dc b'0011000000110000' - dc b'0000000000000000' - -;y - - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0011000000110000' - dc b'0000111111110000' - dc b'0000000000110000' - dc b'0000111111000000' - -;z - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0011111111110000' - dc b'0000000011000000' - dc b'0000001100000000' - dc b'0000110000000000' - dc b'0011111111110000' - dc b'0000000000000000' - -;{ - - dc b'0000001111110000' - dc b'0000111100000000' - dc b'0000111100000000' - dc b'0011110000000000' - dc b'0000111100000000' - dc b'0000111100000000' - dc b'0000001111110000' - dc b'0000000000000000' - - -;| - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - dc b'0000001100000000' - -;} - dc b'0011111100000000' - dc b'0000001111000000' - dc b'0000001111000000' - dc b'0000000011110000' - dc b'0000001111000000' - dc b'0000001111000000' - dc b'0011111100000000' - dc b'0000000000000000' - -;~ - - dc b'0000111100110000' - dc b'0011001111000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - dc b'0000000000000000' - - END - + case on + +dummy start + end + +; +; these are bitmaps for the characters +; +; +; + +CHAR_SPACE START + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + +;CHAR_BANG START + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000000000000000' + +;CHAR_DQ START + dc b'0000110011000000' + dc b'0000110011000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + +; # + dc b'0000110011000000' + dc b'0000110011000000' + dc b'0011111111110000' + dc b'0000110011000000' + dc b'0011111111110000' + dc b'0000110011000000' + dc b'0000110011000000' + dc b'0000000000000000' + +; $ + dc b'0000001100000000' + dc b'0000111111110000' + dc b'0011001100000000' + dc b'0000111111000000' + dc b'0000001100110000' + dc b'0011111111000000' + dc b'0000001100000000' + dc b'0000000000000000' + +;% + dc b'0011110000000000' + dc b'0011110000110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0011000011110000' + dc b'0000000011110000' + dc b'0000000000000000' + + +; & + dc b'0000110000000000' + dc b'0011001100000000' + dc b'0011001100000000' + dc b'0000110000000000' + dc b'0011001100110000' + dc b'0011000011000000' + dc b'0000111100110000' + dc b'0000000000000000' + +;' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' +; ( + + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0000110000000000' + dc b'0000001100000000' + dc b'0000000000000000' + +; ) + + dc b'0000001100000000' + dc b'0000000011000000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000000000000000' + + +;* + + dc b'0000001100000000' + dc b'0011001100110000' + dc b'0000111111000000' + dc b'0000001100000000' + dc b'0000111111000000' + dc b'0011001100110000' + dc b'0000001100000000' + dc b'0000000000000000' + +;+ + + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0011111111110000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000000000000000' + dc b'0000000000000000' + +;, + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0000000000000000' + + + +;- + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + +;. + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000000000000000' + +;/ + + dc b'0000000000000000' + dc b'0000000000110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0011000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + + +;0 + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000011110000' + dc b'0011001100110000' + dc b'0011110000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;1 + dc b'0000001100000000' + dc b'0000111100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000111111000000' + dc b'0000000000000000' + +;2 + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0000000000110000' + dc b'0000001111000000' + dc b'0000110000000000' + dc b'0011000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + + +;3 + dc b'0011111111110000' + dc b'0000000000110000' + dc b'0000000011000000' + dc b'0000001111000000' + dc b'0000000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;4 + dc b'0000000011000000' + dc b'0000001111000000' + dc b'0000110011000000' + dc b'0011000011000000' + dc b'0011111111110000' + dc b'0000000011000000' + dc b'0000000011000000' + dc b'0000000000000000' + +;5 + dc b'0011111111110000' + dc b'0011000000000000' + dc b'0011111111000000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;6 + + dc b'0000001111110000' + dc b'0000110000000000' + dc b'0011000000000000' + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;7 + dc b'0011111111110000' + dc b'0000000000110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0000110000000000' + dc b'0000110000000000' + dc b'0000000000000000' + +;8 + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;9 + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000110000' + dc b'0000000011000000' + dc b'0011111100000000' + dc b'0000000000000000' + +;: + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + +;; + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0000000000000000' + +;< + + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0011000000000000' + dc b'0000110000000000' + dc b'0000001100000000' + dc b'0000000011000000' + dc b'0000000000000000' + +;= + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + +;> + dc b'0000110000000000' + dc b'0000001100000000' + dc b'0000000011000000' + dc b'0000000000110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0000000000000000' + +;? + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000000000000000' + + +;@ + + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011001111000000' + dc b'0011000000000000' + dc b'0000111111110000' + dc b'0000000000000000' + + + +;CHAR_A START + dc b'0000001100000000' + dc b'0000110011000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + + +;CHAR_B START + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0000000000000000' + +;CHAR_C START + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;CHAR_D START + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0000000000000000' + +;CHAR_E START + dc b'0011111111110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + +;CHAR_F START + dc b'0011111111110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0000000000000000' + +;CHAR_G START + dc b'0000111111110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000011110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000000000' + +;CHAR_H START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;CHAR_I START + dc b'0000111111000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000111111000000' + dc b'0000000000000000' + +;CHAR_J START + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;CHAR_K START + dc b'0011000011000000' + dc b'0011001100000000' + dc b'0011110000000000' + dc b'0011000000000000' + dc b'0011110000000000' + dc b'0011001100000000' + dc b'0011000011000000' + dc b'0000000000000000' + + +;CHAR_L START + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + +;CHAR_M START + dc b'0011000000110000' + dc b'0011110011110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;CHAR_N START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011110000110000' + dc b'0011001100110000' + dc b'0011000011110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;CHAR_O START + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;CHAR_P START + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0000000000000000' + + +;CHAR_Q START + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011001100110000' + dc b'0011000011000000' + dc b'0000111100110000' + dc b'0000000000000000' + +;CHAR_R START + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0011001100000000' + dc b'0011000011000000' + dc b'0011000000110000' + dc b'0000000000000000' +;CHAR_S START + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000000000' + dc b'0000111111000000' + dc b'0000000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' +;CHAR_T START + dc b'0011111111110000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000000000000000' + +;CHAR_U START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;CHAR_V START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000110011000000' + dc b'0000001100000000' + dc b'0000000000000000' + +;CHAR_W START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011110011110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;CHAR_X START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000110011000000' + dc b'0000001100000000' + dc b'0000110011000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;CHAR_Y START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000110011000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000000000000000' +;CHAR_Z START + dc b'0011111111110000' + dc b'0000000000110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0011000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + +; _[_ + dc b'0011111111110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + +; \ + dc b'0000000000000000' + dc b'0011000000000000' + dc b'0000110000000000' + dc b'0000001100000000' + dc b'0000000011000000' + dc b'0000000000110000' + dc b'0000000000000000' + dc b'0000000000000000' + +; ] + dc b'0011111111110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0011111111110000' + dc b'0000000000000000' + +; ^ + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000110011000000' + dc b'0011000000110000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + +;CHAR__ START + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'1111111111111111' + +; ` + dc b'0000110000000000' + dc b'0000001100000000' + dc b'0000000011000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + + +; a + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111000000' + dc b'0000000000110000' + dc b'0000111111110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000000000' + +;b + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0000000000000000' + +;c + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0000111111110000' + dc b'0000000000000000' + +;d + + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000111111110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000000000' + +;e + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011111111110000' + dc b'0011000000000000' + dc b'0000111111110000' + dc b'0000000000000000' + +;f + + dc b'0000001111000000' + dc b'0000110000110000' + dc b'0000110000000000' + dc b'0011111111000000' + dc b'0000110000000000' + dc b'0000110000000000' + dc b'0000110000000000' + dc b'0000000000000000' + + +; g + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000110000' + dc b'0000111111000000' + +;h + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;i + dc b'0000001100000000' + dc b'0000000000000000' + dc b'0000111100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000111111000000' + dc b'0000000000000000' + +; j + + dc b'0000000011000000' + dc b'0000000000000000' + dc b'0000001111000000' + dc b'0000000011000000' + dc b'0000000011000000' + dc b'0000000011000000' + dc b'0000110011000000' + dc b'0000001100000000' + +; k + + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000011000000' + dc b'0011001100000000' + dc b'0011111100000000' + dc b'0011000011000000' + dc b'0011000000110000' + dc b'0000000000000000' + +;l + dc b'0000111100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000111111000000' + dc b'0000000000000000' + +;m + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011110011110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;n + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + + +;o + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;p + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0011000000000000' + dc b'0011000000000000' + +;q + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000110000' + dc b'0000000000110000' + +;r + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011001111110000' + dc b'0011110000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0000000000000000' + +;s + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111110000' + dc b'0011000000000000' + dc b'0000111111000000' + dc b'0000000000110000' + dc b'0011111111000000' + dc b'0000000000000000' + +;t + dc b'0000110000000000' + dc b'0000110000000000' + dc b'0011111111000000' + dc b'0000110000000000' + dc b'0000110000000000' + dc b'0000110000110000' + dc b'0000001111000000' + dc b'0000000000000000' + +;u + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000011110000' + dc b'0000111100110000' + dc b'0000000000000000' + +;v + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000110011000000' + dc b'0000001100000000' + dc b'0000000000000000' + +; w + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011110011110000' + dc b'0000000000000000' + +;x + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011000000110000' + dc b'0000110011000000' + dc b'0000001100000000' + dc b'0000110011000000' + dc b'0011000000110000' + dc b'0000000000000000' + +;y + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000110000' + dc b'0000111111000000' + +;z + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011111111110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0011111111110000' + dc b'0000000000000000' + +;{ + + dc b'0000001111110000' + dc b'0000111100000000' + dc b'0000111100000000' + dc b'0011110000000000' + dc b'0000111100000000' + dc b'0000111100000000' + dc b'0000001111110000' + dc b'0000000000000000' + + +;| + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + +;} + dc b'0011111100000000' + dc b'0000001111000000' + dc b'0000001111000000' + dc b'0000000011110000' + dc b'0000001111000000' + dc b'0000001111000000' + dc b'0011111100000000' + dc b'0000000000000000' + +;~ + + dc b'0000111100110000' + dc b'0011001111000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + + END + diff --git a/display.c b/display.c index 35964ef..fd3fd60 100644 --- a/display.c +++ b/display.c @@ -1,408 +1,56 @@ -#pragma noroot -#pragma lint -1 - -#include -#include -#include -#include -#include "Marinetti.h" - -#define ESC "\x1b" - -extern void ScrollRegion(word,word); -extern void ScrollDown(void); -extern void PrintChar(int the_char, unsigned int andMask); -extern void ClearScreen(void); -extern void ClearScreenFrom(int Y); -extern void ClearLine(int Y); -extern void ClearLineFrom(int Y, int X); - -void handle_ansi(word code, char *buffer, word cnt); - -extern void GrafOn(void) inline(0x0a04, 0xe10000); -extern void GrafOff(void) inline(0x0b04, 0xe10000); -extern pascal void SetColorTable(Word, ColorTable) inline(0x0E04,dispatcher); -extern pascal void SysBeep2(Word) inline(0x3803,dispatcher); -extern pascal void SetAllSCBs(Word) inline(0x1404,dispatcher); -extern pascal void SetMasterSCB(Word) inline(0x1604,dispatcher); -extern pascal void InitColorTable(ColorTable) inline(0x0D04,dispatcher); - - - -extern word Xpos; -extern word Ypos; -extern word __scroll[2]; -extern word and_mask; -extern word xor_mask; - -word esc; -char esc_buffer[256]; - -struct errlist -{ - Word Error; - Word MsgLen; - const char *Msg; -}; - -#define _ERR(n,msg) { n, sizeof(msg), msg } - -struct errlist errors[] = -{ - _ERR(1,"tcperrDeafDestPort"), - _ERR(2,"tcperrHostReset"), - _ERR(3,"tcperrConExists"), - _ERR(4,"tcperrConIllegal"), - _ERR(5,"tcperrNoResources"), - _ERR(6,"tcperrNoSocket"), - _ERR(7,"tcperrBadPrec"), - _ERR(8,"tcperrBadSec"), - _ERR(9,"tcperrBadConnection"), - _ERR(0x0a,"tcperrConClosing"), - _ERR(0x0b,"tcperrClosing"), - _ERR(0x0c,"tcperrConReset"), - _ERR(0x0d,"tcperrUserTimeout"), - _ERR(0x0e,"tcperrConRefused"), - - {0,0,NULL} -}; -void display_str(const char *buffer, word cnt); - -void display_err(Word err) -{ -struct errlist *l; - - for (l = &errors[0]; l->Error; l++) - if (l->Error == err) break; - if (l->Error != err) return; - - display_str("\r\n" "\x1b" "[1m", 6); // bold on - display_str(l->Msg, l->MsgLen); // show the string - display_str("\x1b" "[0m", 4); // bold off -} - -void display_cstr(const char *cstr) -{ - if (cstr && *cstr) - display_str(cstr, strlen(cstr)); -} - -void display_pstr(const char *pstr) -{ - if (pstr && *pstr) - display_str(pstr + 1, *pstr); -} - - -void display_char(char c) -{ - switch(c) - { - case 0x07: - SysBeep2(0); - break; - - //backspace - case 0x08: - if (Xpos) Xpos--; - break; - - //tab - case 0x09: - // 1, 9, 17, 25, ... - // not sure this is right - Xpos = Xpos & 0xf8; - Xpos += 8; - //TODO - wrapping - break; - - // line feed - case 0x0A: - if (++Ypos > 23) - { - ScrollRegion(__scroll[0], __scroll[1]); - Ypos = 23; - } - break; - - - case 0x0D: //carriage return - Xpos = 0; - break; - - default: - if (isprint(c)); - { - // check the wrapping flag ... - if (Xpos > 80) - { - Xpos = 0; - if (++Ypos > 23) - { - ScrollRegion(__scroll[0], - __scroll[1]); - - Ypos = 23; - } - } - PrintChar(c, and_mask); - Xpos++; - } - } -} - -/* - * this reads text & has it drawn on the shr screen - * - */ -// todo - and_mask + xor_mask -void display_str(const char *buffer, word cnt) -{ -word i; - - - asm - { - phk - plb - } - - for ( i = 0; i < cnt; i++) - { - if (esc) - { - esc_buffer[esc++] = buffer[i]; - if (isalpha(buffer[i]) - || buffer[i] == '~' - || buffer[i] == '=' - || buffer[i] == '>' - ) - { - handle_ansi(buffer[i], - esc_buffer, esc); - esc = 0; - } - } - else switch (buffer[i]) - { - // bell - case 0x07: - SysBeep2(0); - break; - - //backspace - case 0x08: - if (Xpos) Xpos--; - break; - - //tab - case 0x09: - // 1, 9, 17, 25, ... - // not sure this is right - Xpos = Xpos & 0xf8; - Xpos += 8; - //TODO - wrapping - break; - - // line feed - case 0x0A: - if (++Ypos > 23) - { - ScrollRegion(__scroll[0], - __scroll[1]); - - Ypos = 23; - } - break; - - - case 0x0D: //carriage return - Xpos = 0; - break; - - case 0x1b: //start of escape sequence - - esc = 1; - esc_buffer[0] = 0x1b; - break; - - default: - if (isprint(buffer[i])) - { - // check the wrapping flag ... - if (Xpos > 80) - { - Xpos = 0; - if (++Ypos > 23) - { - ScrollRegion(__scroll[0], - __scroll[1]); - - Ypos = 23; - } - } - PrintChar(buffer[i], and_mask); - Xpos++; - } - } - } -} - -// -// remap the iigs key to a vt100 code (if necessary) and send it out. - -void send_event(EventRecord *event, Word ipid) -{ -char *cp; -int len = 0; -word key; -word mods; - - key = event->message; - mods = event->modifiers; - - - if (mods & keyPad) - { - switch (key) - { - case 0x72: // insert - cp = ESC "[2~"; - len = 4; - break; - - case 0x75: // delete - cp = ESC "[3~"; - len = 4; - break; - - case 0x73: // home - cp = ESC "[1~"; - len = 4; - break; - - case 0x77: // end - cp = ESC "[4~"; - len = 4; - break; - - case 0x74: // page up - cp = ESC "[5~"; - len = 4; - break; - - case 0x79: // page down - cp = ESC "[6~"; - len = 4; - break; - - case 0x7a: // f1 - cp = mods & shiftKey ? ESC "[23~" : ESC "[11~"; - len = 5; - break; - - case 0x78: // f2 - cp = mods & shiftKey ? ESC "[24~" : ESC "[12~"; - len = 5; - break; - - case 0x63: // f3 - cp = mods & shiftKey ? ESC "[25~" : ESC "[13~"; - len = 5; - break; - - case 0x76: // f4 - cp = mods & shiftKey ? ESC "[26~" : ESC "[14~"; - len = 5; - break; - - - case 0x60: // f5 - cp = mods & shiftKey ? ESC "[28~" : ESC "[15~"; - len = 5; - break; - - case 0x61: // f6 - cp = mods & shiftKey ? ESC "[29~" : ESC "[17~"; - len = 5; - break; - - - case 0x62: // f7 - cp = mods & shiftKey ? ESC "[31~" : ESC "[18~"; - len = 5; - break; - - case 0x64: // f8 - cp = mods & shiftKey ? ESC "[32~" : ESC "[19~"; - len = 5; - break; - - case 0x65: // f9 - cp = mods & shiftKey ? ESC "[33~" : ESC "[20~"; - len = 5; - break; - - case 0x6d: // f10 - cp = mods & shiftKey ? ESC "[34~" : ESC "[21~"; - len = 5; - break; - - case 0x67: // f11 - cp = ESC "[23~"; - len = 5; - break; - - case 0x6f: // f12 - cp = ESC "[24~"; - len = 5; - break; - - default: len = 0; cp = NULL; - } - } - else if (mods & controlKey) - { - cp = (char *)&event->message; - len = 1; - } - else - { - switch(key) - { - case 0x0d: - cp = "\r\n"; - len = 2; - break; - case 0x08: // <--- arrow - cp = ESC "[D"; - len = 3; - break; - case 0x0A: // down arrow - cp = ESC "[B"; - len = 3; - break; - case 0x0B: // up arrow - cp = ESC "[A"; - len = 3; - break; - case 0x15: // ---> arrow - cp = ESC "[C"; - len = 3; - break; - - // backspace to delete char - case 0x7f: - cp = "\x08"; - len = 1; - break; - - default: - cp = (char *)&event->message; - len = 1; - } - } - - if (len) TCPIPWriteTCP(ipid, cp, len, false, false); - -} +#pragma noroot + +#include +#include "Marinetti.h" + + +struct errlist { + Word Error; + Word MsgLen; + const char *Msg; +}; + +#define ESC "\x1b" +#define _ERR(n,msg) { n, sizeof(msg) - 1, msg } + +extern void vt100_process(const unsigned char *buffer, unsigned buffer_size); + +static struct errlist errors[] = { + _ERR(1,"tcperrDeafDestPort"), + _ERR(2,"tcperrHostReset"), + _ERR(3,"tcperrConExists"), + _ERR(4,"tcperrConIllegal"), + _ERR(5,"tcperrNoResources"), + _ERR(6,"tcperrNoSocket"), + _ERR(7,"tcperrBadPrec"), + _ERR(8,"tcperrBadSec"), + _ERR(9,"tcperrBadConnection"), + _ERR(0x0a,"tcperrConClosing"), + _ERR(0x0b,"tcperrClosing"), + _ERR(0x0c,"tcperrConReset"), + _ERR(0x0d,"tcperrUserTimeout"), + _ERR(0x0e,"tcperrConRefused"), +}; + +void display_err(Word err) { + + if (err == 0 || err >= 0x0f) return; + --err; + vt100_process("\r\n" ESC "[1m", 6); // bold on + vt100_process(errors[err].Msg, errors[err].MsgLen); + vt100_process(ESC "[0m", 4); // bold off +} + +void display_cstr(const char *cstr) { + if (cstr && *cstr) + vt100_process(cstr, strlen(cstr)); +} + +void display_pstr(const char *pstr) { + if (pstr && *pstr) + vt100_process(pstr + 1, *pstr); +} + + + + diff --git a/fctelnet.c b/fctelnet.c index 25b3a97..c5584b2 100644 --- a/fctelnet.c +++ b/fctelnet.c @@ -1,515 +1,382 @@ -#include "Marinetti.h" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "telnet.h" - -extern void ScrollRegion(word,word); -extern void ScrollDown(void); -extern void PrintChar(int the_char, unsigned int andMask); -extern void ClearScreen(void); -extern void ClearScreenFrom(int Y); -extern void ClearLine(int Y); -extern void ClearLineFrom(int Y, int X); - -extern void GrafOn(void) inline(0x0a04, 0xe10000); -extern void GrafOff(void) inline(0x0b04, 0xe10000); -extern pascal void SetColorTable(Word, ColorTable) inline(0x0E04,dispatcher); -extern pascal void SysBeep2(Word) inline(0x3803,dispatcher); -extern pascal void SetAllSCBs(Word) inline(0x1404,dispatcher); -extern pascal void SetMasterSCB(Word) inline(0x1604,dispatcher); -extern pascal void InitColorTable(ColorTable) inline(0x0D04,dispatcher); - - -Word MyID; -Word __gno; - -Word modeTelnet = 1; -Word flagEcho = 1; // if *I* echo - - -void init_ansi(void); - -Word ResolveHost(const char *name, cvtRecPtr cvt); -Word GetChar(word ipid, unsigned char *c); -Word UngetChar(char c); - - -void display_str(const char *txt, word cnt); -void display_pstr(const char *); -void display_cstr(const char *); -void display_err(Word); - -void send_event(EventRecord *, Word); - - -#pragma databank 1 - -/* - * called to print connect/disconnect messages from - * Marinetti. msg is a pstring. - */ -void printCallBack(const char *msg) -{ -word i; - i = *msg; - if (i) - { - display_str("\x1b" "[1m", 4); // bold on - display_str(msg + 1, i); // show the string - display_str("\x1b" "[0m\n\r", 6); // bold off - } -} -#pragma databank 0 - -extern word esc; -extern word Xpos; -extern word Ypos; - -void init_screen(void) -{ -#define WHITE 0x0fff -#define YELLOW 0x0ff0 -#define BLACK 0x0000 -#define BLUE 0x000f -#define GREEN 0x00f0 -#define RED 0x0f00 - -static ColorTable ct = -{ - BLACK, // background - RED, // underline / blink - BLUE, // bold - GREEN, // foreground - - BLACK, - RED, - BLUE, - GREEN, - - BLACK, - RED, - BLUE, - GREEN, - - BLACK, - RED, - BLUE, - GREEN, -}; -int i; - - - // linearize memory, disable shadowing. - asm - { - lda #0x00C1 - sep #0x20 - ora >0xe0c029 - sta >0xe0c029 - rep #0x20 - - lda #0x0008 - sep #0x20 - ora >0xe0c035 - sta >0xe0c035 - rep #0x20 - - } - - SetMasterSCB(0xc080); - SetAllSCBs(0xc080); - //InitColorTable(ct); - for (i = 0; i < 15; i++) - SetColorTable(i, ct); - - ClearScreen(); - GrafOn(); -} - - -/* - * this is (more or less) a state machine. - * old state (and character) are passed in - * new state is returned. - * - * 0 = starting state. - */ -#define SB_IAC 0xfaff -Word do_iac(Word state, char c, Word ipid) -{ -static char buffer[64]; -static int cnt; - - if (state == 0) return c == IAC ? IAC : 0; - // FF must be escaped as FF FF within SB. - // SB_IAC means the first FF has been processed. - if (state == SB) - { - if (c == IAC) return SB_IAC; - buffer[cnt++] = c; - return SB; - } - - if (state == SB_IAC) - { - // it was an escaped FF - if (c == IAC) - { - buffer[cnt++] = IAC; - return SB; - } - else state = IAC; // process below... - } - if (state == IAC) - switch (c) - { - case DONT: - case DO: - case WONT: - case WILL: - return c; - case SB: - cnt = 0; - return c; - case SE: - // buffer is the data between - // IAC SB <...> IAC SE - if (buffer[0] == TELOPT_TTYPE - && buffer[1] == TELQUAL_SEND) - { - static char msg[] = - { - IAC, SB, TELOPT_TTYPE, TELQUAL_IS, - 'V', 'T', '1', '0', '0', - IAC, SE - }; - TCPIPWriteTCP(ipid, msg, - sizeof(msg), true, false); - } - else if (buffer[0] == TELOPT_NAWS - && buffer[1] == TELQUAL_SEND) - { - static char msg[] = - { - IAC, SB, TELOPT_NAWS, - 0, 80, 0, 24, - IAC, SE - }; - TCPIPWriteTCP(ipid, msg, - sizeof(msg), true, false); - } - else if (buffer[0] == TELOPT_TSPEED - && buffer[1] == TELQUAL_SEND) - { - static char msg[] = - { - IAC, SB, TELOPT_TSPEED, - '9', '6', '0', '0', ',', '9', '6', '0', '0', - IAC, SE - }; - TCPIPWriteTCP(ipid, msg, - sizeof(msg), true, false); - } - cnt = 0; - return 0; - default: - return 0; - } - if (state == DO) - { - buffer[0] = IAC; - buffer[1] = WONT; - buffer[2] = c; - if (c == TELOPT_TTYPE - || c == TELOPT_SGA - || c == TELOPT_NAWS - || c == TELOPT_TSPEED) - { - buffer[1] = WILL; - } - TCPIPWriteTCP(ipid, buffer, 3, true, false); - - } - if (state == DONT) - { - buffer[0] = IAC; - buffer[1] = WONT; - buffer[2] = c; - - TCPIPWriteTCP(ipid, buffer, 3, true, false); - } - if (state == WILL || state == WONT) - { - buffer[0] = IAC; - buffer[1] = DONT; - buffer[2] = c; - if (c == TELOPT_ECHO) - { - buffer[1] = DO; - } - cnt = 3; - - TCPIPWriteTCP(ipid, buffer, cnt, true, false); - } - - return 0; -} - - -int main(int argc, char **argv) -{ -static EventRecord event; -static srBuffer sr; -static rrBuff rr; -static char str[16]; -static cvtRec cvt; -static QuitRecGS qDCB = {2, 0, 0x4000}; - - - Word iLoaded; - Word iConnected; - Word iStarted; - Word Quit; - Word ipid; - Handle dp; - - - int i; - Word key; - Word err; - unsigned char c; - //int fd; - int iac_state; - - - Xpos = Ypos = 0; - esc = 0; - //iac = 0; - iLoaded = iStarted = iConnected = false; - __gno = false; - - - MyID = MMStartUp(); - - kernStatus(); - if (!_toolErr) __gno = true; - - TextStartUp(); - SetOutputDevice(1,3); - SetOutGlobals(0x7f, 0); - - - dp = NewHandle(0x0100, MyID, - attrBank | attrPage |attrNoCross | attrFixed | attrLocked, - 0x000000); - HLock(dp); - EMStartUp((Word)*dp, 0x14, 0, 0, 0, 0, MyID); - - - if (argc != 2) - { - ErrWriteCString("Usage: marlene host[:port]\r\n"); - goto _exit; - } - - init_screen(); - - init_ansi(); - - - TCPIPStatus(); - if (_toolErr) - { - display_str("\n\rLoading Marinetti...\n\r", 23); - LoadOneTool(0x36, 0x200); //load Marinetti - if (_toolErr) - { - ErrWriteCString("Unable to load Marinetti\r\n"); - goto _exit; - } - iLoaded = true; - } - - // Marinetti now loaded - if (!TCPIPStatus()) - { - display_str("\n\rStarting Marinetti...\n\r", 24); - TCPIPStartUp(); - iStarted = true; - } - - if (!TCPIPGetConnectStatus()) - { - display_str("\n\rConnecting Marinetti...\n\r", 26); - TCPIPConnect(printCallBack); - if (_toolErr) - { - ErrWriteCString("Unable to establish network connection\r\n"); - goto _exit; - } - iConnected = true; - } - // marinetti is now connected - - if (!ResolveHost(argv[1], &cvt)) - { - ErrWriteCString("Unable to resolve address\r\n"); - goto _exit; - } - - if (!cvt.cvtPort) cvt.cvtPort = 23; - - ipid = TCPIPLogin(MyID, cvt.cvtIPAddress, cvt.cvtPort, 0, 0x0040); - - display_str("\n\rConnecting to ", 16); - display_str(str, TCPIPConvertIPToCAscii(cvt.cvtIPAddress, str, 0)); - - TCPIPOpenTCP(ipid); - - // wait for the connection to occur. - while (1) - { - TCPIPPoll(); - err = TCPIPStatusTCP(ipid, &sr); - if (err) - { - display_err(err); - goto _exit1; - } - - if (sr.srState == tcpsESTABLISHED) break; - //if (sr.srState == tcpsCLOSED) goto _exit1; - GetNextEvent(keyDownMask | autoKeyMask ,&event); - if (event.what != keyDownEvt) continue; - if (!(event.modifiers & appleKey)) continue; - if ((Word)event.message == '.') goto _exit1; - if ((Word)event.message == 'q') goto _exit1; - if ((Word)event.message == 'Q') goto _exit1; - } - - display_str("\n\rConnected\n\r", 13); - - - //fd = open ("tcp.log", O_TRUNC | O_WRONLY | O_CREAT, 0777); - - Quit = false; - - - iac_state = 0; - while (!Quit) - { - - TCPIPPoll(); - - // check for incoming data... - // 0xffff = no data - // 0 = data - // otherwise = marinetti error. - err = GetChar(ipid, &c); - - if (err && (err != 0xffff)) - { - display_err(err); - Quit++; - continue; - } - - if (err == 0) - { - //if (fd > 0) write(fd, &c, 1); - if (iac_state) - iac_state = do_iac(iac_state, c, ipid); - else if (modeTelnet && c == IAC) - iac_state = do_iac(0, c, ipid); - else display_str(&c, 1); - } - - GetNextEvent(keyDownMask | autoKeyMask, &event); - if (event.what != keyDownEvt) continue; - c = key = event.message; - - if (event.modifiers & appleKey) - { - switch (key) - { - case 'Q': // quit - case 'q': - Quit++; - break; - case 'V': // paste - case 'v': - break; - case 'Z': // suspend (gnome) - case 'z': - if (__gno) - { - static struct sgttyb sb; - static int err; - gtty(1,&sb); - sb.sg_flags &= ~RAW; - stty(1,&sb); - GrafOff(); - Kkill(Kgetpid(), SIGSTOP, &err); - sb.sg_flags |= RAW; - stty(1,&sb); - GrafOn(); - } - break; - } - continue; - - } - else send_event(&event, ipid); - - } - -_exit1: - //if (fd > 0) close(fd); - TCPIPCloseTCP(ipid); - TCPIPPoll(); // wait until closed... - TCPIPLogout(ipid); - - // be nice and - while (GetNextEvent(keyDownMask | autoKeyMask, &event)); - display_str("\n\rPress any key to exit.\n\r", 26); - while (!GetNextEvent(keyDownMask | autoKeyMask, &event)); - - -_exit: - - if (iConnected) - TCPIPDisconnect(false, printCallBack); - - if (iStarted) - TCPIPShutDown(); - - if (iLoaded) - UnloadOneTool(0x36); - - - EMShutDown(); - GrafOff(); - TextShutDown(); - QuitGS(&qDCB); - -} - +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "telnet.h" + +extern void ClearScreen(void); + +extern pascal void GrafOn(void) inline(0x0a04, dispatcher); +extern pascal void GrafOff(void) inline(0x0b04, dispatcher); + +extern pascal void SetColorTable(Word, ColorTable) inline(0x0E04,dispatcher); +extern pascal void SysBeep2(Word) inline(0x3803,dispatcher); +extern pascal void SetAllSCBs(Word) inline(0x1404,dispatcher); +extern pascal void SetMasterSCB(Word) inline(0x1604,dispatcher); +extern pascal void InitColorTable(ColorTable) inline(0x0D04,dispatcher); + + +Word ResolveHost(const char *name, cvtRecPtr cvt); +int WaitForStatus(word ipid, word status); + + +void display_pstr(const char *); +void display_cstr(const char *); +void display_err(Word); + +extern void telnet_init(void); +extern void telnet_process(void); + +extern void vt100_init(void); +extern void vt100_process(const unsigned char *buffer, unsigned buffer_size); +extern void vt100_event(EventRecord *event); + + + + +Word MyID; +Word __gno; + + +#define ESC "\x1b" + + + +#pragma databank 1 + +/* + * called to print connect/disconnect messages from + * Marinetti. msg is a pstring. + */ +void printCallBack(const char *msg) { + if (msg && *msg) { + display_cstr(ESC "\n\r[1m"); // bold on + display_pstr(msg); // show the string + display_cstr(ESC "[0m\n\r"); // bold off + } +} +#pragma databank 0 + + +static void screen_init(void) { +#define WHITE 0x0fff +#define YELLOW 0x0ff0 +#define BLACK 0x0000 +#define BLUE 0x000f +#define GREEN 0x00f0 +#define RED 0x0f00 + + static ColorTable ct = + { + BLACK, // background + RED, // underline / blink + BLUE, // bold + GREEN, // foreground + + BLACK, + RED, + BLUE, + GREEN, + + BLACK, + RED, + BLUE, + GREEN, + + BLACK, + RED, + BLUE, + GREEN, + }; + + unsigned i; + + // linearize memory, disable shadowing. + asm + { + lda #0x00C1 + sep #0x20 + ora >0xe0c029 + sta >0xe0c029 + rep #0x20 + + lda #0x0008 + sep #0x20 + ora >0xe0c035 + sta >0xe0c035 + rep #0x20 + + } + + SetMasterSCB(0xc080); + SetAllSCBs(0xc080); + //InitColorTable(ct); + for (i = 0; i < 16; i++) + SetColorTable(i, ct); + + ClearScreen(); + GrafOn(); +} + +static char out_buffer[1024]; +static char out_buffer_size = 0; + +static word ipid = -1; + +static void flush(void) { + if (out_buffer_size) { + TCPIPWriteTCP(ipid, out_buffer, out_buffer_size, true, false); + out_buffer_size = 0; + } +} + + + +void send(char *data, unsigned size) { + + if (out_buffer_size + size > sizeof(out_buffer)) { + flush(); + } + if (size > sizeof(out_buffer) / 2) { + TCPIPWriteTCP(ipid, data, size, true, false); + return; + } + memcpy(out_buffer + out_buffer_size, data, size); + out_buffer_size += size; +} + + +unsigned buffer_size; +unsigned char buffer[2048]; // 1500 is normal MTU size? + + +int main(int argc, char **argv) { + + static EventRecord event; + static rrBuff rr; + static char str[16]; + static cvtRec cvt; + static QuitRecGS qDCB = {2, 0, 0x4000}; + + + Word iLoaded; + Word iConnected; + Word iStarted; + Handle dp; + + Word err; + int ok; + + + iLoaded = iStarted = iConnected = false; + __gno = false; + ipid = -1; + + MyID = MMStartUp(); + + kernStatus(); + if (!_toolErr) __gno = true; + + TextStartUp(); + SetOutputDevice(1,3); + SetOutGlobals(0x7f, 0); + + + dp = NewHandle(0x0100, MyID, + attrBank | attrPage |attrNoCross | attrFixed | attrLocked, + 0x000000); + EMStartUp((Word)*dp, 0x14, 0, 0, 0, 0, MyID); + + + // todo: -vt52 -> start in vt52 mode (DECANM = 0) + // todo:keypad flag of some sort? + + if (argc != 2) { + ErrWriteCString("Usage: marlene host[:port]\r\n"); + goto _exit; + } + + screen_init(); + + vt100_init(); + + + TCPIPStatus(); + if (_toolErr) { + display_cstr("Loading Marinetti...\n\r"); + LoadOneTool(0x36, 0x200); //load Marinetti + if (_toolErr) { + display_cstr("Unable to load Marinetti.\r\n"); + goto _exit; + } + iLoaded = true; + } + + // Marinetti now loaded + if (!TCPIPStatus()) { + display_cstr("Starting Marinetti...\n\r"); + TCPIPStartUp(); + iStarted = true; + } + + if (!TCPIPGetConnectStatus()) { + display_cstr("Connecting Marinetti...\n\r"); + TCPIPConnect(printCallBack); + if (_toolErr) { + display_cstr("Unable to establish network connection.\r\n"); + goto _exit; + } + iConnected = true; + } + // marinetti is now connected + + if (!ResolveHost(argv[1], &cvt)) { + display_cstr("Unable to resolve address.\r\n"); + goto _exit; + } + + if (!cvt.cvtPort) cvt.cvtPort = 23; + + ipid = TCPIPLogin(MyID, cvt.cvtIPAddress, cvt.cvtPort, 0, 0x0040); + + TCPIPConvertIPToCASCII(cvt.cvtIPAddress, str, 0); + display_cstr("Connecting to "); + display_cstr(str); + display_cstr("...\n\r"); + + TCPIPOpenTCP(ipid); + + // wait for the connection to occur. + ok = WaitForStatus(ipid, TCPSESTABLISHED); + if (ok > 0) display_err(ok); + if (ok != 0) goto _exit2; + + + display_cstr("Connected.\n\r"); + + telnet_init(); + + //fd = open ("tcp.log", O_TRUNC | O_WRONLY | O_CREAT, 0777); + + for(;;) { + static rrBuff rr; + + + TCPIPPoll(); + + rr.rrBuffCount = 0; + err = TCPIPReadTCP(ipid, 0, (Ref)buffer, sizeof(buffer), &rr); + // tcperrConClosing and tcperrClosing aren't fatal. + + buffer_size = rr.rrBuffCount; + if (buffer_size) err = 0; + if (err) { + if (err == tcperrConClosing || err == tcperrClosing) + display_cstr("\r\nTCP Connection Closed.\r\n"); + else + display_err(err); + goto _exit1; + } + + if (buffer_size) { + telnet_process(); + } + if (buffer_size) { + vt100_process(buffer, buffer_size); + } + + GetNextEvent(keyDownMask | autoKeyMask, &event); + if (event.what == keyDownEvt) { + + unsigned char key = event.message; + + if (event.modifiers & appleKey) { + switch (key) { + case 'Q': // quit + case 'q': + goto _exit1; + break; + case 'V': // paste... + case 'v': + break; + case 'Z': // suspend (gnome) + case 'z': + if (__gno) { + static struct sgttyb sb; + static int err; + gtty(1,&sb); + sb.sg_flags &= ~RAW; + stty(1,&sb); + GrafOff(); + Kkill(Kgetpid(), SIGSTOP, &err); + sb.sg_flags |= RAW; + stty(1,&sb); + GrafOn(); + } + break; + } + + } else { + vt100_event(&event); + } + } + flush(); + } + +_exit1: + flush(); + + display_cstr("\n\rClosing TCP Connection...\n\r"); + + TCPIPCloseTCP(ipid); + WaitForStatus(ipid, TCPSCLOSED); + +_exit2: + + +_exit: + + if (ipid != -1) TCPIPLogout(ipid); + + if (iConnected) + TCPIPDisconnect(false, printCallBack); + + if (iStarted) + TCPIPShutDown(); + + if (iLoaded) + UnloadOneTool(0x36); + + + // flush q + while (GetNextEvent(keyDownMask | autoKeyMask, &event)) ; + display_cstr("\n\rPress any key to exit.\n\r"); + while (!GetNextEvent(keyDownMask | autoKeyMask, &event)) ; + + + EMShutDown(); + DisposeHandle(dp); + GrafOff(); + TextShutDown(); + QuitGS(&qDCB); + return 0; +} + diff --git a/makefile b/makefile index b1789bc..00fcc67 100644 --- a/makefile +++ b/makefile @@ -1,23 +1,24 @@ -PROG = fctelnet -OBJS = fctelnet.o vt100.o ansi.o chars.o marinetti.o display.o - -OPTIMIZE *= 79 - -CFLAGS = -w -O$(OPTIMIZE) - -$(PROG): $(OBJS) - $(RM) ansi.root - $(RM) chars.root - $(CC) $(CFLAGS) $(OBJS) -o $@ - - -fctelnet.o: fctelnet.c marinetti.h -vt100.o: vt100.c -ansi.o: ansi.asm -chars.o: chars.asm -marinetti.o: marinetti.c - -clean: - $(RM) -f *.o *.root *.a *.r -clobber: clean - $(RM) -f $(PROG) +PROG = fctelnet +OBJS = fctelnet.o vt100.o telnet.o ansi.o chars.o marinetti.o display.o + +OPTIMIZE *= 79 + +CFLAGS = -w -O$(OPTIMIZE) + +$(PROG): $(OBJS) + $(RM) ansi.root + $(RM) chars.root + $(CC) $(CFLAGS) $(OBJS) -o $@ + + +fctelnet.o: fctelnet.c marinetti.h +vt100.o: vt100.c +ansi.o: ansi.asm +chars.o: chars.asm +marinetti.o: marinetti.c +telnet.o: telnet.c + +clean: + $(RM) -f *.o *.root *.a *.r +clobber: clean + $(RM) -f $(PROG) diff --git a/marinetti.c b/marinetti.c index 87f67f4..abd877a 100644 --- a/marinetti.c +++ b/marinetti.c @@ -1,137 +1,111 @@ -#pragma noroot -#pragma lint -1 - -#include -#include "Marinetti.h" - -#include -#include - -static char * __c2pstrMalloc(const char *cp) -{ -Word len; -char *ret; - - len = strlen(cp); - ret = (char *)malloc(len + 2); - - if (ret) - { - ret[0] = len; - memmove(&ret[1], cp, len+1); // copy over NULL too - } - - return ret; -} - -// -// returns true if resolved, false if not -// -// name is a c-string - -// todo - add /etc/host support - -Word ResolveHost(const char *name, cvtRecPtr cvt) -{ -dnrBuffer dnr; -char *pstr; -Word port; -EventRecord event; - - cvt->cvtIPAddress = 0; - cvt->cvtPort = 0; - - if (!name || !*name) return false; - - pstr = __c2pstrMalloc(name); - if (!pstr) return false; - - port = TCPIPMangleDomainName(0xf800, pstr); - - // check if name is a dotted decimal or a host... - - if (TCPIPValidateIPString(pstr)) - { - TCPIPConvertIPToHex(cvt, pstr); - cvt->cvtPort = port; - free (pstr); - return true; - } - else - { - TCPIPDNRNameToIP(pstr, &dnr); - if (_toolErr) - { - free(pstr); - return false; - } - while (dnr.DNRStatus == DNRPending) - { - TCPIPPoll(); - GetNextEvent(keyDownMask | autoKeyMask, &event); - if ((event.what == keyDownEvt) - && (event.modifiers & appleKey) - && ((Word)event.message == '.')) - { - TCPIPCancelDNR(&dnr); - break; - } - } - if (dnr.DNRStatus == DNROK) - { - cvt->cvtIPAddress = dnr.DNRIPAddress; - cvt->cvtPort = port; - free(pstr); - return true; - } - } - - free(pstr); - - return false; -} - - -/* - * pcnt is the next place to store data - * bptr is the current ptr. - */ -static unsigned char buffer[1024]; -static unsigned char pushback[1024]; -static int pcnt = 0; -static int bcnt = 0; -static int bptr = 0; -static rrBuff rr; - -Word GetChar(word ipid, unsigned char *c) -{ -word err; - - *c = 0; - - if (pcnt) - { - *c = pushback[--pcnt]; - return 0; - } - if (!bcnt) - { - err = TCPIPReadTCP(ipid, 0, (Ref)buffer, 1024, &rr); - bcnt = rr.rrBuffCount; - bptr = 0; - if (err) return err; - } - if (bcnt) - { - bcnt--; - *c = buffer[bptr++]; - return 0; - } - return 0xffff; -} - -void UngetChar(char c) -{ - pushback[pcnt++] = c; -} - +#pragma noroot +#pragma lint -1 + +#include +#include "Marinetti.h" + +#include +#include + +static char * __c2pstrMalloc(const char *cp) +{ +Word len; +char *ret; + + len = strlen(cp); + ret = (char *)malloc(len + 2); + + if (ret) + { + ret[0] = len; + memmove(&ret[1], cp, len+1); // copy over NULL too + } + + return ret; +} + +// +// returns true if resolved, false if not +// +// name is a c-string + +// todo - add /etc/host support + +Word ResolveHost(const char *name, cvtRecPtr cvt) +{ +dnrBuffer dnr; +char *pstr; +Word port; +EventRecord event; + + cvt->cvtIPAddress = 0; + cvt->cvtPort = 0; + + if (!name || !*name) return false; + + pstr = __c2pstrMalloc(name); + if (!pstr) return false; + + port = TCPIPMangleDomainName(0xf800, pstr); + + // check if name is a dotted decimal or a host... + + if (TCPIPValidateIPString(pstr)) + { + TCPIPConvertIPToHex(cvt, pstr); + cvt->cvtPort = port; + free (pstr); + return true; + } + else + { + TCPIPDNRNameToIP(pstr, &dnr); + if (_toolErr) { + free(pstr); + return false; + } + while (dnr.DNRStatus == DNRPending) { + TCPIPPoll(); + GetNextEvent(keyDownMask | autoKeyMask, &event); + if ((event.what == keyDownEvt) + && (event.modifiers & appleKey) + && ((Word)event.message == '.')) { + TCPIPCancelDNR(&dnr); + break; + } + } + if (dnr.DNRStatus == DNROK) { + cvt->cvtIPAddress = dnr.DNRIPAddress; + cvt->cvtPort = port; + free(pstr); + return true; + } + } + + free(pstr); + + return false; +} + +int WaitForStatus(word ipid, word status) { + static srBuffer sr; + EventRecord event; + Word err; + + for(;;) { + TCPIPPoll(); + err = TCPIPStatusTCP(ipid, &sr); + if (err) return err; + + if (sr.srState == status) return 0; + GetNextEvent(keyDownMask | autoKeyMask, &event); + if (event.what != keyDownEvt) continue; + if (!(event.modifiers & appleKey)) continue; + if ((Word)event.message == '.') return -1; + //if ((Word)event.message == 'q') return -1; + //if ((Word)event.message == 'Q') return -1; + } + return 0; +} + + diff --git a/marinetti.h b/marinetti.h index cff8387..dfb9ce5 100644 --- a/marinetti.h +++ b/marinetti.h @@ -1,139 +1,139 @@ -#ifndef __TCPIP_H__ -#define __TCPIP_H__ - -#include - -struct dnrBuffer -{ - Word DNRStatus; - LongWord DNRIPAddress; -}; -typedef struct dnrBuffer dnrBuffer, *dnrBufferPtr, **dnrBufferHndl; - -#define DNRPending 0x0000 -#define DNROK 0x0001 -#define DNRFailed 0x0002 -#define DNRNoDNSEntry 0x0003 -#define DNRCancelled 0x0004 - -struct srBuffer -{ - Word srState; - Word srNetworkError; - LongWord srSndQueued; - LongWord srRcvQueued; - LongWord srDestIP; - Word srDestPort; - Word srConnectType; - Word srAcceptCount; -}; -typedef struct srBuffer srBuffer, *srBufferPtr, **srBufferHndl; - -struct rrBuff -{ - LongWord rrBuffCount; - Handle rrBuffHandle; - Word rrMoreFlag; - Word rrPushFlag; - Word rrUrgentFlag; -}; -typedef struct rrBuff rrBuff, *rrBuffPtr, **rrBuffHndl; - -struct cvtRec -{ - LongWord cvtIPAddress; - Word cvtPort; -}; -typedef struct cvtRec cvtRec, *cvtRecPtr, **cvtRecHndl; - - -/* - * TCP states - */ -#define tcpsCLOSED 0x0000 -#define tcpsLISTEN 0x0001 -#define tcpsSYNSENT 0x0002 -#define tcpsSYNRCVD 0x0003 -#define tcpsESTABLISHED 0x0004 -#define tcpsFINWAIT1 0x0005 -#define tcpsFINWAIT2 0x0006 -#define tcpsCLOSEWAIT 0x0007 -#define tcpsLASTACK 0x0008 -#define tcpsCLOSING 0x0009 -#define tcpsTIMEWAIT 0x000A - - -pascal void TCPIPStartUp(void) - inline(0x0236 ,0xe10000); -pascal void TCPIPShutDown(void) - inline(0x0336 ,0xe10000); - -pascal Word TCPIPStatus(void) - inline(0x0636 ,0xe10000); - -pascal Word TCPIPGetConnectStatus(void) - inline(0x0936, 0xe10000); - - -pascal void TCPIPConvertIPToHex(cvtRecPtr, const char *) - inline(0x0d36 ,0xe10000); -pascal void TCPIPConvertIPCToHex(cvtRecPtr, const char *) - inline(0x3f36 ,0xe10000); - -pascal Word TCPIPConvertIPToAscii(LongWord, const char *, Word) - inline(0x0e36 ,0xe10000); -pascal Word TCPIPConvertIPToCAscii(LongWord, const char *, Word) - inline(0x5836 ,0xe10000); - -pascal Word TCPIPMangleDomainName(Word, char *) - inline(0x5936 ,0xe10000); - -pascal Word TCPIPValidateIPString(const char *) - inline(0x4836 ,0xe10000); -pascal Word TCPIPValidateIPCString(const char *) - inline(0x1536 ,0xe10000); - - - - - -pascal void TCPIPConnect(void *) - inline(0x1236 ,0xe10000); -pascal void TCPIPDisconnect(word, void *) - inline(0x1336 ,0xe10000); - -pascal void TCPIPCancelDNR(dnrBufferPtr) - inline(0x2036 ,0xe10000); -pascal void TCPIPDNRNameToIP(const char *, dnrBufferPtr) - inline(0x2136 ,0xe10000); - -pascal void TCPIPPoll(void) - inline(0x2236 ,0xe10000); - -pascal Word TCPIPLogin(Word, LongWord, Word, Word, Word) - inline(0x2336 ,0xe10000); -pascal void TCPIPLogout(Word) - inline(0x2436 ,0xe10000); - -pascal Word TCPIPOpenTCP(Word) - inline(0x2C36 ,0xe10000); -pascal Word TCPIPWriteTCP(Word, void *, LongWord, Word, Word) - inline(0x2D36 ,0xe10000); -pascal Word TCPIPReadTCP(Word, Word, Ref, LongWord, rrBuffPtr) - inline(0x2E36 ,0xe10000); - - -pascal Word TCPIPCloseTCP(Word) - inline(0x2F36 ,0xe10000); - - -pascal Word TCPIPStatusTCP(Word, srBufferPtr) - inline(0x3136, 0xe10000); - - - - - - -#endif - +#ifndef __TCPIP_H__ +#define __TCPIP_H__ + +#include + +struct dnrBuffer +{ + Word DNRStatus; + LongWord DNRIPAddress; +}; +typedef struct dnrBuffer dnrBuffer, *dnrBufferPtr, **dnrBufferHndl; + +#define DNRPending 0x0000 +#define DNROK 0x0001 +#define DNRFailed 0x0002 +#define DNRNoDNSEntry 0x0003 +#define DNRCancelled 0x0004 + +struct srBuffer +{ + Word srState; + Word srNetworkError; + LongWord srSndQueued; + LongWord srRcvQueued; + LongWord srDestIP; + Word srDestPort; + Word srConnectType; + Word srAcceptCount; +}; +typedef struct srBuffer srBuffer, *srBufferPtr, **srBufferHndl; + +struct rrBuff +{ + LongWord rrBuffCount; + Handle rrBuffHandle; + Word rrMoreFlag; + Word rrPushFlag; + Word rrUrgentFlag; +}; +typedef struct rrBuff rrBuff, *rrBuffPtr, **rrBuffHndl; + +struct cvtRec +{ + LongWord cvtIPAddress; + Word cvtPort; +}; +typedef struct cvtRec cvtRec, *cvtRecPtr, **cvtRecHndl; + + +/* + * TCP states + */ +#define tcpsCLOSED 0x0000 +#define tcpsLISTEN 0x0001 +#define tcpsSYNSENT 0x0002 +#define tcpsSYNRCVD 0x0003 +#define tcpsESTABLISHED 0x0004 +#define tcpsFINWAIT1 0x0005 +#define tcpsFINWAIT2 0x0006 +#define tcpsCLOSEWAIT 0x0007 +#define tcpsLASTACK 0x0008 +#define tcpsCLOSING 0x0009 +#define tcpsTIMEWAIT 0x000A + + +pascal void TCPIPStartUp(void) + inline(0x0236 ,0xe10000); +pascal void TCPIPShutDown(void) + inline(0x0336 ,0xe10000); + +pascal Word TCPIPStatus(void) + inline(0x0636 ,0xe10000); + +pascal Word TCPIPGetConnectStatus(void) + inline(0x0936, 0xe10000); + + +pascal void TCPIPConvertIPToHex(cvtRecPtr, const char *) + inline(0x0d36 ,0xe10000); +pascal void TCPIPConvertIPCToHex(cvtRecPtr, const char *) + inline(0x3f36 ,0xe10000); + +pascal Word TCPIPConvertIPToAscii(LongWord, const char *, Word) + inline(0x0e36 ,0xe10000); +pascal Word TCPIPConvertIPToCAscii(LongWord, const char *, Word) + inline(0x5836 ,0xe10000); + +pascal Word TCPIPMangleDomainName(Word, char *) + inline(0x5936 ,0xe10000); + +pascal Word TCPIPValidateIPString(const char *) + inline(0x4836 ,0xe10000); +pascal Word TCPIPValidateIPCString(const char *) + inline(0x1536 ,0xe10000); + + + + + +pascal void TCPIPConnect(void *) + inline(0x1236 ,0xe10000); +pascal void TCPIPDisconnect(word, void *) + inline(0x1336 ,0xe10000); + +pascal void TCPIPCancelDNR(dnrBufferPtr) + inline(0x2036 ,0xe10000); +pascal void TCPIPDNRNameToIP(const char *, dnrBufferPtr) + inline(0x2136 ,0xe10000); + +pascal void TCPIPPoll(void) + inline(0x2236 ,0xe10000); + +pascal Word TCPIPLogin(Word, LongWord, Word, Word, Word) + inline(0x2336 ,0xe10000); +pascal void TCPIPLogout(Word) + inline(0x2436 ,0xe10000); + +pascal Word TCPIPOpenTCP(Word) + inline(0x2C36 ,0xe10000); +pascal Word TCPIPWriteTCP(Word, void *, LongWord, Word, Word) + inline(0x2D36 ,0xe10000); +pascal Word TCPIPReadTCP(Word, Word, Ref, LongWord, rrBuffPtr) + inline(0x2E36 ,0xe10000); + + +pascal Word TCPIPCloseTCP(Word) + inline(0x2F36 ,0xe10000); + + +pascal Word TCPIPStatusTCP(Word, srBufferPtr) + inline(0x3136, 0xe10000); + + + + + + +#endif + diff --git a/telnet.h b/telnet.h index 2f65fde..6098d5d 100644 --- a/telnet.h +++ b/telnet.h @@ -1,83 +1,83 @@ -#ifndef __TELNET_H__ -#define __TELNET_H__ - -#define IAC 255 /* interpret as command: */ -#define DONT 254 /* you are not to use option */ -#define DO 253 /* please, you use option */ -#define WONT 252 /* I won't use option */ -#define WILL 251 /* I will use option */ -#define SB 250 /* interpret as subnegotiation */ -#define GA 249 /* you may reverse the line */ -#define EL 248 /* erase the current line */ -#define EC 247 /* erase the current character */ -#define AYT 246 /* are you there */ -#define AO 245 /* abort output--but let prog finish */ -#define IP 244 /* interrupt process--permanently */ -#define BREAK 243 /* break */ -#define DM 242 /* data mark--for connect. cleaning */ -#define NOP 241 /* nop */ -#define SE 240 /* end sub negotiation */ -#define EOR 239 /* end of record (transparent mode) */ -#define ABORT 238 /* Abort process */ -#define SUSP 237 /* Suspend process */ -#define xEOF 236 /* End of file: EOF is already used... */ - -#define SYNCH 242 /* for telfunc calls */ - -#define TELCMD_FIRST xEOF -#define TELCMD_LAST IAC -#define TELCMD_OK(x) ((x) <= TELCMD_LAST && (x) >= TELCMD_FIRST) -#define TELCMD(x) telcmds[(x)-TELCMD_FIRST] - -/* telnet options */ -#define TELOPT_BINARY 0 /* 8-bit data path */ -#define TELOPT_ECHO 1 /* echo */ -#define TELOPT_RCP 2 /* prepare to reconnect */ -#define TELOPT_SGA 3 /* suppress go ahead */ -#define TELOPT_NAMS 4 /* approximate message size */ -#define TELOPT_STATUS 5 /* give status */ -#define TELOPT_TM 6 /* timing mark */ -#define TELOPT_RCTE 7 /* remote controlled transmission and echo */ -#define TELOPT_NAOL 8 /* negotiate about output line width */ -#define TELOPT_NAOP 9 /* negotiate about output page size */ -#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ -#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ -#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ -#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ -#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ -#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ -#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ -#define TELOPT_XASCII 17 /* extended ascic character set */ -#define TELOPT_LOGOUT 18 /* force logout */ -#define TELOPT_BM 19 /* byte macro */ -#define TELOPT_DET 20 /* data entry terminal */ -#define TELOPT_SUPDUP 21 /* supdup protocol */ -#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ -#define TELOPT_SNDLOC 23 /* send location */ -#define TELOPT_TTYPE 24 /* terminal type */ -#define TELOPT_EOR 25 /* end or record */ -#define TELOPT_TUID 26 /* TACACS user identification */ -#define TELOPT_OUTMRK 27 /* output marking */ -#define TELOPT_TTYLOC 28 /* terminal location number */ -#define TELOPT_3270REGIME 29 /* 3270 regime */ -#define TELOPT_X3PAD 30 /* X.3 PAD */ -#define TELOPT_NAWS 31 /* window size */ -#define TELOPT_TSPEED 32 /* terminal speed */ -#define TELOPT_LFLOW 33 /* remote flow control */ -#define TELOPT_LINEMODE 34 /* Linemode option */ -#define TELOPT_XDISPLOC 35 -#define TELOPT_OLD_ENVIRON 36 -#define TELOPT_AUTHENTICATION 37 /* authenticate */ -#define TELOPT_ENCRYPT 38 /* encryption */ -#define TELOPT_NEW_ENVIRON 39 - -#define TELOPT_EXOPL 255 /* extended-options-list */ - -#define TELQUAL_IS 0 -#define TELQUAL_SEND 1 -#define TELQUAL_INFO 2 -#define TELQUAL_REPLY 2 -#define TELQUAL_NAME 3 - - -#endif +#ifndef __TELNET_H__ +#define __TELNET_H__ + +#define IAC 255 /* interpret as command: */ +#define DONT 254 /* you are not to use option */ +#define DO 253 /* please, you use option */ +#define WONT 252 /* I won't use option */ +#define WILL 251 /* I will use option */ +#define SB 250 /* interpret as subnegotiation */ +#define GA 249 /* you may reverse the line */ +#define EL 248 /* erase the current line */ +#define EC 247 /* erase the current character */ +#define AYT 246 /* are you there */ +#define AO 245 /* abort output--but let prog finish */ +#define IP 244 /* interrupt process--permanently */ +#define BREAK 243 /* break */ +#define DM 242 /* data mark--for connect. cleaning */ +#define NOP 241 /* nop */ +#define SE 240 /* end sub negotiation */ +#define EOR 239 /* end of record (transparent mode) */ +#define ABORT 238 /* Abort process */ +#define SUSP 237 /* Suspend process */ +#define xEOF 236 /* End of file: EOF is already used... */ + +#define SYNCH 242 /* for telfunc calls */ + +#define TELCMD_FIRST xEOF +#define TELCMD_LAST IAC +#define TELCMD_OK(x) ((x) <= TELCMD_LAST && (x) >= TELCMD_FIRST) +#define TELCMD(x) telcmds[(x)-TELCMD_FIRST] + +/* telnet options */ +#define TELOPT_BINARY 0 /* 8-bit data path */ +#define TELOPT_ECHO 1 /* echo */ +#define TELOPT_RCP 2 /* prepare to reconnect */ +#define TELOPT_SGA 3 /* suppress go ahead */ +#define TELOPT_NAMS 4 /* approximate message size */ +#define TELOPT_STATUS 5 /* give status */ +#define TELOPT_TM 6 /* timing mark */ +#define TELOPT_RCTE 7 /* remote controlled transmission and echo */ +#define TELOPT_NAOL 8 /* negotiate about output line width */ +#define TELOPT_NAOP 9 /* negotiate about output page size */ +#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ +#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ +#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ +#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ +#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ +#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ +#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ +#define TELOPT_XASCII 17 /* extended ascic character set */ +#define TELOPT_LOGOUT 18 /* force logout */ +#define TELOPT_BM 19 /* byte macro */ +#define TELOPT_DET 20 /* data entry terminal */ +#define TELOPT_SUPDUP 21 /* supdup protocol */ +#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ +#define TELOPT_SNDLOC 23 /* send location */ +#define TELOPT_TTYPE 24 /* terminal type */ +#define TELOPT_EOR 25 /* end or record */ +#define TELOPT_TUID 26 /* TACACS user identification */ +#define TELOPT_OUTMRK 27 /* output marking */ +#define TELOPT_TTYLOC 28 /* terminal location number */ +#define TELOPT_3270REGIME 29 /* 3270 regime */ +#define TELOPT_X3PAD 30 /* X.3 PAD */ +#define TELOPT_NAWS 31 /* window size */ +#define TELOPT_TSPEED 32 /* terminal speed */ +#define TELOPT_LFLOW 33 /* remote flow control */ +#define TELOPT_LINEMODE 34 /* Linemode option */ +#define TELOPT_XDISPLOC 35 +#define TELOPT_OLD_ENVIRON 36 +#define TELOPT_AUTHENTICATION 37 /* authenticate */ +#define TELOPT_ENCRYPT 38 /* encryption */ +#define TELOPT_NEW_ENVIRON 39 + +#define TELOPT_EXOPL 255 /* extended-options-list */ + +#define TELQUAL_IS 0 +#define TELQUAL_SEND 1 +#define TELQUAL_INFO 2 +#define TELQUAL_REPLY 2 +#define TELQUAL_NAME 3 + + +#endif diff --git a/vt100.c b/vt100.c index 66cf67b..41aa2e8 100644 --- a/vt100.c +++ b/vt100.c @@ -1,279 +1,802 @@ -#pragma noroot - -#include -#include -#include -// handle vt100 escape codes - -extern void ReverseScrollRegion(word, word); -extern void ScrollRegion(word, word); -extern void ScrollDown(void); -extern void PrintChar(int the_char, unsigned int andMask); -extern void ClearScreen(void); -extern void ClearScreenFrom(int Y); -extern void ClearLine(int Y); -extern void ClearLineFrom(int Y, int X); - - -word Xpos; -word Ypos; -static word __pos[2]; // saved cursor position -word __scroll[2]; -word and_mask; -word xor_mask; - - -void init_ansi(void) -{ - Xpos = 0; - Ypos = 0; - __pos[0] = 0; - __pos[1] = 0; - __scroll[0] = 0; - __scroll[1] = 23; - and_mask = 0xffff; - xor_mask = 0x0000; -} - -//not yet added: -//esc[6n - return sursor position report -//esc[m - set graphics mode -// - -void dump(const char * buffer, word cnt, int impl) -{ -int i; -char tmp[] = " xx x"; -char c; - - if ( impl) WriteCString("Unimplemented: "); - for (i = 0; i < cnt; i++) - { - c = buffer[i]; - tmp[1] = "0123456789abcdef"[c >> 4]; - tmp[2] = "0123456789abcdef"[c & 0x0f]; - tmp[4] = isprint(c) ? c : '.'; - WriteCString(tmp); - } - WriteCString("\r\n"); -} - - -void handle_ansi(word code, char *buffer, word cnt) -{ -word i; -word r0; -word r1; -//word r2; -//word r3; -word pop = 0; - - - if (buffer[1] == '[') - { - i = 2; - - switch (code) - { - case 'A': //cursor up - // esc[#A - r0 = 0; - while (isdigit(buffer[i])) - r0 = r0 * 10 + (buffer[i++] - '0'); - if (buffer[i] != 'A') pop = 1; - else - { - if (!r0) r0 = 1; - Ypos -= r0; - if (Ypos < __scroll[0]) Ypos = __scroll[0]; - //if (Ypos > r0) Ypos -= r0; - //else Ypos = 0; - } - break; - - case 'B': //cursor down - // esc[#B - r0 = 0; - while (isdigit(buffer[i])) - r0 = r0 * 10 + (buffer[i++] - '0'); - if (buffer[i] != 'B') pop = 1; - else - { - if (!r0) r0 = 1; - Ypos += r0; - if (Ypos > __scroll[1]) Ypos = __scroll[1]; - //if (Ypos + r0 > 24) Ypos = 24; - //else Ypos += r0; - } - break; - - case 'C': // cursor forward - // esc[#C - r0 = 0; - while (isdigit(buffer[i])) - r0 = r0 * 10 + (buffer[i++] - '0'); - if (buffer[i] != 'C') pop = 1; - else - { - if (!r0) r0 = 1; - Xpos += r0; - if (Xpos > 79) Xpos = 79; - } - break; - - case 'D': // cursor backward - // esc[#D - r0 = 0; - while (isdigit(buffer[i])) - r0 = r0 * 10 + (buffer[i++] - '0'); - if (buffer[i] != 'D') pop = 1; - else - { - if (!r0) r0 = 1; - Xpos -= r0; - if (Xpos < 0) Xpos = 0; - } - break; - - case 'H': //cursor position - case 'f': - //esc[#;#H or esc[;H or esc[H - //esc[#;#f or esc[;f or esc[f - if (cnt > 3) - { - r0 = r1 = 0; - while (isdigit(buffer[i])) - r0 = r0 * 10 + (buffer[i++] - '0'); - if (buffer[i++] != ';') pop = 1; - else while (isdigit(buffer[i])) - r1 = r1 * 10 + (buffer[i++] - '0'); - if (buffer[i] != 'H' && buffer[i] != 'f') pop = 1; - if (r0 == 0) r0++; - if (r1 == 0) r1++; - } - else r0 = r1 = 1; - - if (!pop) - { - Xpos = r1 - 1; - Ypos = r0 - 1; - } - break; - - case 'J': - if (cnt == 3) //clear c - { - ClearLineFrom(Ypos, Xpos); - if (Ypos < 23) - ClearScreenFrom(Ypos+1); - - } - else if (cnt == 4 && buffer[2] == '2') - { - ClearScreen(); - //Ypos = 0; // cursor position unchanged - //Xpos = 0; - } - break; - - case 'K': //erase from cursor to end-of-line (including cursor) - if (cnt == 3) // no parms - ClearLineFrom(Ypos, Xpos); - else dump(buffer, cnt,1); - break; - - case 'L': // erase current line and - // scroll preceding lines down 1 - // esc[#L - ReverseScrollRegion(Ypos, __scroll[1]); - break; - - case 'M': // erase current line and - //scroll following lines up 1 - // esc[#M - ScrollRegion(Ypos, __scroll[1]); - break; - - case 's': // save cursor position - __pos[0] = Xpos; - __pos[1] = Ypos; - break; - - case 'u': // restore cursor position - Xpos = __pos[0]; - Ypos = __pos[1]; - break; - - // not yet added! - case 'n': - break; - case 'm': - while (1) - { - r0 = 0; - while (isdigit(buffer[i])) - r0 = r0 * 10 + (buffer[i++] - '0'); - - switch(r0) - { - case 0: // all attributes off - and_mask = 0xffff; - xor_mask = 0x0000; - break; - case 1: //bold - and_mask = 0xaaaa; - break; - case 4: //underscore - case 5: // blink - and_mask = 0x5555; - break; - case 7://reverse video - xor_mask = 0xffff; - break; - case 8://cancel - and_mask = 0x0000; - break; - } - if (buffer[i] == ';') i++; - else if (buffer[i] == 'm') break; - } - break; - - case 'r': // #;#r == set scrolling region - // esc[#;#r - r0 = r1 = 0; - - while (isdigit(buffer[i])) - r0 = r0 * 10 + (buffer[i++] - '0'); - if (buffer[i++] != ';') pop = 1; - else while (isdigit(buffer[i])) - r1 = r1 * 10 + (buffer[i++] - '0'); - if (buffer[i] != 'r') pop = 1; - if (r0 && r1 && !pop) - { - __scroll[0] = r0 - 1; - __scroll[1] = r1 - 1; - } - break; - - default: - dump(buffer, cnt,1); - } - } - else - { - switch(buffer[1]) - { - case 'M': // scroll screen down 1 line - ReverseScrollRegion(__scroll[0], __scroll[1]); - break; - case '=': // alt key pad - case '>': // normal key pad - break; - default: - dump(buffer, cnt,1); - - } - } -} - +/* + * This handles vt100 commands. + * + */ +#pragma noroot + +#include +#include + +#define ESC "\x1b" +#define send_str(x) send((const unsigned char *)x, sizeof(x)-1) + +extern void send(const unsigned char *, unsigned); + +extern unsigned char buffer[]; +extern unsigned buffer_size; + + + +extern void ReverseScrollRegion(unsigned, unsigned); +extern void ScrollRegion(unsigned, unsigned); +extern void PrintChar(unsigned x, unsigned y, unsigned the_char, unsigned andMask, unsigned eorMask); + +extern void ClearScreen(void); +extern void ClearScreen2(unsigned start, unsigned end); +extern void ClearLine(unsigned line); +extern void ClearLine2(unsigned line, unsigned start, unsigned end); + +extern void SetCursor(unsigned x, unsigned y); + +extern pascal void SysBeep2(Word) inline(0x3803,dispatcher); + + +int __x; +int __y; + + +static unsigned saved_cursor[2]; // saved cursor position +static unsigned window[2]; +static unsigned and_mask; +static unsigned xor_mask; + + +static unsigned DECANM = 1; +static unsigned DECAWM = 1; +static unsigned DECCKM = 0; +static unsigned DECKPAM = 0; +static unsigned DECCOLM = 80; +static unsigned DECOM = 0; +static unsigned DECSCNM = 0; +static unsigned LNM = 0; + +unsigned tabs[9] = { 0 }; + +static unsigned parms[10]; +static unsigned parm_count; +static unsigned private; +static unsigned state; + +void vt100_init(void) +{ + __x = 0; + __y = 0; + saved_cursor[0] = 0; + saved_cursor[1] = 0; + window[0] = 0; + window[1] = 23; + and_mask = 0xffff; + xor_mask = 0x0000; + + DECANM = 1; + DECAWM = 1; + DECCKM = 0; + DECKPAM = 0; + DECCOLM = 80; + DECOM = 0; + DECSCNM = 0; + LNM = 0; + + tabs[0] = 0x8080; + tabs[1] = 0x8080; + tabs[2] = 0x8080; + tabs[3] = 0x8080; + tabs[4] = 0x0080; + + parms[0] = 0; + parm_count = 0; + private = 0; + state = 0; +} + +#if 0 +void dump(const char * buffer, word cnt, int impl) +{ +int i; +char tmp[] = " xx x"; +char c; + + if ( impl) WriteCString("Unimplemented: "); + for (i = 0; i < cnt; i++) + { + c = buffer[i]; + tmp[1] = "0123456789abcdef"[c >> 4]; + tmp[2] = "0123456789abcdef"[c & 0x0f]; + tmp[4] = isprint(c) ? c : '.'; + WriteCString(tmp); + } + WriteCString("\r\n"); +} +#endif + +static void cursor_left(void){ + unsigned n = parms[0]; + if (n == 0) n = 1; + + __x -= n; + if (__x < 0) __x = 0; +} + +static void cursor_right(void){ + unsigned n = parms[0]; + if (n == 0) n = 1; + // edge case + if (__x == 80) return; + __x += n; + if (__x >= 80) n = 79; +} + +static void cursor_up(void) { + unsigned n = parms[0]; + if (n == 0) n = 1; + + /* can't escape scrolling region */ + if (__y >= window[0]) { + __y -= n; + if (__y < window[0]) __y = window[0]; + } else { + __y -= n; + if (__y < 0) __y = 0; + } + +} + +static void cursor_down(void) { + unsigned n = parms[0]; + if (n == 0) n = 1; + + /* can't escape scrolling region */ + if (__y <= window[1]) { + __y += n; + if (__y > window[1]) __y = window[1]; + } else { + __y += n; + if (__y >= 24) __y = 23; + } +} + +static void cursor_position(void) { + unsigned y = parms[0]; + unsigned x = parms[1]; + + if (y) --y; + if (x) --x; + + __x = x; + if (x >= 80) x = 79; + if (DECOM) { + __y = window[0] + y; + if (__y > window[1]) __y = window[1]; + } else { + __y = y; + if (__y >= 24) __y = 23; + } +} + +static void cursor_position_vt52(void) { + unsigned y = parms[0]; + unsigned x = parms[1]; + + if (y) --y; + if (x) --x; + + // if x or y are out of range, do not move them. + + if (x < 80) __x = x; + + if (DECOM) { + y = window[0] + y; + if (y <= window[1]) __y = y; + } else { + if (y < 24) __y = y; + } +} + + +static void scrolling_region(void) { + unsigned top = parms[0]; + unsigned bottom = parms[1]; + + if (top) --top; + if (!bottom) bottom = 24; + --bottom; + + + if (top < bottom && bottom < 24) { + window[0] = top; + window[1] = bottom; + __y = DECOM ? top : 0; + __x = 0; + } +} + + +static void set_attributes(void) { + unsigned i; + for (i = 0; i < parm_count; ++i) { + switch(parms[i]) { + case 0: // all attributes off + and_mask = 0xffff; + xor_mask = 0x0000; + break; + case 1: //bold + and_mask = 0xaaaa; + break; + case 4: //underscore + case 5: // blink + and_mask = 0x5555; + break; + case 7://reverse video + xor_mask = 0xffff; + break; + } + } +} + +static void set_mode(void) { + + unsigned i; + for (i = 0; i < parm_count; ++i) { + switch(parms[i]) { + case 1: if (private) DECCKM = 1; break; + case 2: if (private) DECANM = 1; break; + case 3: if (private) DECCOLM = 132; break; + case 6: if (private) { DECOM = 1; __x = 0; __y = window[0]; } break; + case 7: if (private) DECAWM = 1; break; + case 20: if (!private) LNM = 1; break; + } + } +} + +static void reset_mode(void) { + + unsigned i; + for (i = 0; i < parm_count; ++i) { + switch(parms[i]) { + case 1: if (private) DECCKM = 0; break; + case 2: if (private) DECANM = 0; break; + case 3: if (private) DECCOLM = 80; break; + case 6: if (private) { DECOM = 0; __x = 0; __y = 0; } break; + case 7: if (private) DECAWM = 0; break; + case 20: if (!private) LNM = 0; break; + } + } +} + +static void save_cursor(void) { + saved_cursor[0] = __y; + saved_cursor[1] = __x; +} + +static void restore_cursor(void) { + __y = saved_cursor[0]; + __x = saved_cursor[1]; + // vt220+ also saves/restores DECAWM and DECOM... +} + +static void tab(void) { + unsigned chunk; + unsigned mask; + + if (__x >= 80) return; + + __x = __x + 1; + chunk = __x >> 0x4; + mask = 1 << (__x & 0x0f); + + while (chunk < 5) { + unsigned bits = tabs[chunk]; + if (!bits) { + __x += 16; + } else { + do { + if (bits & mask) return; + ++__x; + mask <<= 1; + } while (mask); + } + mask = 1; + ++chunk; + } + // nothing... go to right margin. + __x = 79; +} + + +static void set_tab(void) { + unsigned chunk; + unsigned mask; + + if (__x >= 80) return; + + chunk = __x >> 0x04; + mask = 1 << (__x & 0x0f); + + tabs[chunk] |= mask; +} + +static void clear_tabs(void) { + unsigned i; + + unsigned chunk; + unsigned mask; + + for (i = 0; i < parm_count; ++i) { + switch(parms[i]) { + case 0: + if (__x < 80) { + chunk = __x >> 0x04; + mask = 1 << (__x & 0x0f); + tabs[chunk] &= ~mask; + } + break; + case 5: + tabs[0] = 0; + tabs[1] = 0; + tabs[2] = 0; + tabs[3] = 0; + tabs[4] = 0; + break; + } + } + +} + +static void linefeed(void) { + if (__y == window[1]) { + ScrollRegion(window[0], window[1]+1); + } else ++__y; +} + +static void reverse_linefeed(void) { + if (__y == window[0]) { + ReverseScrollRegion(window[0], window[1]+1); + } else --__y; +} + +static void erase_line(void) { + unsigned i; + for (i = 0; i < parm_count; ++i) { + switch(parms[i]) { + case 0: + ClearLine2(__y, __x, 80); + break; + case 1: + ClearLine2(__y, 0, __x + 1); + break; + case 2: + ClearLine(__y); + break; + } + } +} + +static void erase_screen(void) { + unsigned i; + for (i = 0; i < parm_count; ++i) { + switch(parms[i]) { + case 0: + ClearLine2(__y, __x, 80); + ClearScreen2(__y + 1, 24); + break; + case 1: + ClearLine2(__y, 0, __x + 1); + ClearScreen2(0, __y); + break; + case 2: + ClearScreen(); + break; + } + } +} + +/* Device Status Report */ +static void dsr(void) { + unsigned i; + for (i = 0; i < parm_count; ++i) { + switch(parms[i]) { + case 0: send_str(ESC "[0n"); break; + case 5: { /* cursor position */ + static char buffer[16]; + unsigned i = 15; + unsigned x = __x + 1; + unsigned y = __y + 1; + if (DECOM) y += window[0]; + buffer[i--] = ']'; + while(x) { + buffer[i--] = '0' + (x % 10); + x = x / 10; + } + buffer[i--] = ';'; + while(y) { + buffer[i--] = '0' + (y % 10); + y = y / 10; + } + buffer[i--] = '['; + buffer[i] = 0x1b; + send(buffer + i, 16 - i); + break; + } + } + } +} + +enum { + st_text, + st_escape, + st_escape_v52, + st_dca1, + st_dca2, + st_pound, + st_rparen, + st_lparen, + st_lbracket, + st_lbracket2, + st_parm, +}; + +static void do_control(char c) { + switch(c) { + case 005: /* ENQ */ break; + case 007: /* BEL */ SysBeep2(0); break; + case 010: /* BS */ if (__x) --__x; break; + case 011: /* HT */ tab(); break; + case 012: /* LF */ + case 013: /* VT */ + case 014: /* FF */ + linefeed(); + if (LNM) __x = 0; + break; + case 015: /* CR */ __x = 0; break; + case 016: /* SO */ break; + case 017: /* SI */ break; + case 021: /* XON */ break; + case 023: /* XOFF */ break; + + case 030: /* CAN */ + case 032: /* SUB */ + state = st_text; break; + case 033: /* ESC */ + switch (state) { + case st_text: state = DECANM ? st_escape : st_escape_v52; break; + case st_escape_v52: + case st_escape: + break; + default: + state = st_text; + } + break; + } +} + +void vt100_process(const unsigned char *buffer, unsigned buffer_size) { + + unsigned i; + for (i = 0; i < buffer_size; ++i) { + unsigned char c = buffer[i] & 0x7f; + if (c == 0 || c == 0x7f) continue; + if (c < 0x20) { + do_control(c); + continue; + } + switch (state) { + case st_text: + if (__x == 80) { + if (DECAWM) { + __x = 0; + if (__y == window[1]) { + ScrollRegion(window[0], window[1]+1); + } else ++__y; + } else { + __x = 79; + } + } + PrintChar(__x, __y, c, and_mask, xor_mask); + ++__x; + + break; + + case st_escape: + switch (c) { + case '#': state = st_pound; break; + case '(': state = st_lparen; break; + case ')': state = st_rparen; break; + case '[': state = st_lbracket; break; + case 'E': /* next line */ __x = 0; /* drop through */ + case 'D': /* index */ linefeed(); break; + case 'H': set_tab(); break; + case 'M': /* reverse index */ reverse_linefeed(); break; + case 'Z': send_str(ESC "[?1;0c"); break; + case '7': save_cursor(); break; + case '8': restore_cursor(); break; + case '=': DECKPAM = 1; break; + case '>': DECKPAM = 0; break; + case 'c': vt100_init(); ClearScreen(); break; + case '1': case '2': /* vt105 graphic stuff */ break; + default: + break; + } + if (state == st_escape) state = st_text; + break; + + case st_pound: + /* #8 -> fill with Es */ + state = st_text; break; + case st_lparen: + case st_rparen: + state = st_text; break; + break; + + case st_lbracket: + private = 0; + parm_count = 0; + parms[0] = 0; + parms[1] = 0; + if (c == '?') { private = 1; state = st_parm; continue; } + if (isdigit(c)) { + parms[0] = c - '0'; + state = st_parm; + break; + } + /* fall through */ + case st_lbracket2: + lbracket2: + switch (c) { + case 'A': cursor_up(); break; + case 'B': cursor_down(); break; + case 'C': cursor_right(); break; + case 'D': cursor_left(); break; + case 'H': case 'f': cursor_position(); break; + case 'K': erase_line(); break; + case 'J': erase_screen(); break; + case 'c': if (parms[0] == 0) send_str(ESC "[?1;0c"); break; + case 'g': clear_tabs(); break; + case 'h': set_mode(); break; + case 'l': reset_mode(); break; + case 'm': set_attributes(); break; + case 'n': dsr(); break; + case 'r': scrolling_region(); break; + } + state = st_text; + break; + + case st_parm: + if (isdigit(c)) { + parms[parm_count] *= 10; + parms[parm_count] += c - '0'; + continue; + } + if (c == ';') { + if (parm_count < 10) ++parm_count; + parms[parm_count] = 0; + continue; + } + state = st_lbracket2; + goto lbracket2; + + case st_escape_v52: + parm_count = 0; + parms[0] = 0; + if (c == 'Y') { state = st_dca1; break; } + switch (c) { + case 'A': cursor_up(); break; + case 'B': cursor_down(); break; + case 'C': cursor_right(); break; + case 'D': cursor_left(); break; + case 'F': case 'G': break; /* graphics mode */ + case 'H': cursor_position(); break; + case 'I': reverse_linefeed(); break; + case 'J': erase_screen(); break; + case 'K': erase_line(); break; + case 'Z': send_str(ESC "/Z"); break; + case '=': DECKPAM = 1; break; + case '>': DECKPAM = 0; break; + case '<': DECANM = 1; break; + + } + state = st_text; + break; + case st_dca1: + parms[0] = c - 0x20; + state = st_dca2; + break; + case st_dca2: + parms[1] = c - 0x20; + cursor_position_vt52(); + state = st_text; + break; + + } + } +} + + +// +// remap the iigs key to a vt100 code (if necessary) and send it out. + +/* + * see Apple IIgs Toolbox Ref Volume 1, 3-22. (ADB codes) + */ +void vt100_event(EventRecord *event) { + unsigned char *cp; + int len = 0; + unsigned char key; + word mods; + + key = event->message; + mods = event->modifiers; + + + /* iigs -> vt100 + * clear -> PF1 + * = -> PF2 + * / -> PF3 + * * -> PF4 + * + -> - + * - -> , + * . -> . + * + * + * win32 layout: + * numlock -> PF1 + * / -> PF2 + * * -> PF3 + * - -> PF4 + * shift+ -> - + * + -> , + * + * ------ + * option - , 1 2 3 4 to use normal keys as keypad. + */ + + if (mods & keyPad) { + switch (key) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + case '-': + case ',': + { + static unsigned char buffer[3] = { 0x1b, 'x', 'x' }; + if (DECKPAM) { + cp = buffer; len = 3; + buffer[2] = key | 0x40; + buffer[1] = DECANM ? 'O' : '?'; + } else { + len = 1; + cp = &key; + } + } + break; + + case 0x0d: // enter + if (DECKPAM) { + cp = DECANM ? ESC "OM" : ESC "?M"; + len = 3; + } else goto enter; + break; + + + case 0x7a: // f1 + if (DECANM) { cp = ESC "OP"; len = 3; } + else { cp = ESC "P"; len = 2; } + break; + + case 0x78: // f2 + if (DECANM) { cp = ESC "OQ"; len = 3; } + else { cp = ESC "Q"; len = 2; } + break; + + case 0x63: // f3 + if (DECANM) { cp = ESC "OR"; len = 3; } + else { cp = ESC "R"; len = 2; } + break; + + case 0x76: // f4 + if (DECANM) { cp = ESC "OS"; len = 3; } + else { cp = ESC "S"; len = 2; } + break; + + /* Real IIgs keyboard - clear = 0x18, =, /, * for PF1-4? */ + case 0x18: // clear - PF1 on IIgs keyboard + if (0) { + if (DECANM) { cp = ESC "OP"; len = 3; } + else { cp = ESC "P"; len = 2; } + } + break; + + case '=': // PF2 on IIgs keyboard + if (0) { + if (DECANM) { cp = ESC "OQ"; len = 3; } + else { cp = ESC "Q"; len = 2; } + } + break; + + case '/': // PF3 on IIgs keyboard + if (0) { + if (DECANM) { cp = ESC "OR"; len = 3; } + else { cp = ESC "R"; len = 2; } + } else { + len = 1; + cp = &key; + } + break; + + case '*': // PF4 on IIgs keyboard + if (0) { + if (DECANM) { cp = ESC "OS"; len = 3; } + else { cp = ESC "S"; len = 2; } + } else { + len = 1; + cp = &key; + } + break; + + case '+': + // send as normal key. + len = 1; + cp = &key; + break; + + default: return; + } + } else if (mods & controlKey) { + cp = &key; + len = 1; + } else { + switch(key) { + case 0x0d: + enter: + if (LNM) { cp = "\r\n"; len = 2; } + else { cp = "\r"; len = 1; } + break; + case 0x08: // <--- arrow + // todo -- cursor keys + if (DECANM) { + cp = DECCKM ? ESC "OD" : ESC "[D"; + len = 3; + } else { cp = ESC "D"; len = 2; } + break; + case 0x0A: // down arrow + if (DECANM) { + cp = DECCKM ? ESC "OB" : ESC "[B"; + len = 3; + } else { cp = ESC "B"; len = 2; } + break; + case 0x0B: // up arrow + if (DECANM) { + cp = DECCKM ? ESC "OA" : ESC "[A"; + len = 3; + } else { cp = ESC "A"; len = 2; } + + break; + case 0x15: // ---> arrow + if (DECANM) { + cp = DECCKM ? ESC "OC" : ESC "[C"; + len = 3; + } else { cp = ESC "C"; len = 2; } + break; + + // backspace to delete char + case 0x7f: // delete + cp = "\x08"; + len = 1; + break; + + default: + if (key < 0x7f) { + cp = &key; len = 1; + } + } + } + + if (len) send(cp, len); +}