commit eb3ab28a813d41a50ea5f967d5b15c28bead22b2 Author: Kelvin Sherlock Date: Tue Aug 20 22:10:47 2013 -0400 initial version (200x) diff --git a/ansi.asm b/ansi.asm new file mode 100644 index 0000000..a7115f7 --- /dev/null +++ b/ansi.asm @@ -0,0 +1,774 @@ + 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 + 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/darlene.c b/darlene.c new file mode 100644 index 0000000..d428b65 --- /dev/null +++ b/darlene.c @@ -0,0 +1,499 @@ +#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 +static ColorTable ct = +{ + 0x0000, //black + 0x00f0, //green 0x5555 + 0x0f00, //blue 0xaaaa + WHITE, //white 0xffff + 0x0000, //black + 0x00f0, //green + 0x0f00, //blue + WHITE, //white + 0x0000, //black + 0x00f0, //green + 0x0f00, //blue + WHITE, //white + 0x0000, //black + 0x00f0, //green + 0x0f00, //blue + WHITE //white +}; +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 escped 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) -1, 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) - 1, 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) + { + 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); + +} + diff --git a/display.c b/display.c new file mode 100644 index 0000000..35964ef --- /dev/null +++ b/display.c @@ -0,0 +1,408 @@ +#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); + +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..8a12d0b --- /dev/null +++ b/makefile @@ -0,0 +1,23 @@ +PROG = darlene +OBJS = darlene.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 $@ + + +darlene.o: darlene.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) diff --git a/marinetti.c b/marinetti.c new file mode 100644 index 0000000..87f67f4 --- /dev/null +++ b/marinetti.c @@ -0,0 +1,137 @@ +#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; +} + diff --git a/marinetti.h b/marinetti.h new file mode 100644 index 0000000..cff8387 --- /dev/null +++ b/marinetti.h @@ -0,0 +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 + diff --git a/telnet.h b/telnet.h new file mode 100644 index 0000000..2f65fde --- /dev/null +++ b/telnet.h @@ -0,0 +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 diff --git a/vt100.c b/vt100.c new file mode 100644 index 0000000..66cf67b --- /dev/null +++ b/vt100.c @@ -0,0 +1,279 @@ +#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); + + } + } +} +