initial version (200x)

This commit is contained in:
Kelvin Sherlock 2013-08-20 22:10:47 -04:00
commit eb3ab28a81
9 changed files with 3342 additions and 0 deletions

774
ansi.asm Normal file
View File

@ -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 <line1
cmp #0
bcc exit
lda <line2
cmp #24
bcs exit
lda <line1
cmp <line2
bcs exit
; a = (line2 - line1) * 8 * 160 - 1
lda <line2
sec
sbc <line1
; a = a * 256 * 5
xba ; a = a * 256
; 5x = 4x + x
pha ; save
asl a ; x2
asl a ; x4
clc
adc 1,s
sta 1,s
pla
dec a ; a = a - 1
pha ; save
;
; 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
lda <line2
inc a
xba ; x256
pha ; save
asl a ; x 2
asl a ; x 4
clc
adc #$2000+4*160
adc 1,s
dec a ; - 1
sta 1,s ;store it...
sec
sbc #1280
tax ; src address
ply ; dest address
pla ; length
mvp $e10000,$e10000
;
; now empty first line
;
pei (line1)
jsl ClearLine
exit anop
lda <_rtlb
sta <line1
lda <_rtlb+2
sta <line2
pld
pla
pla
plb
rtl
END
;
; ScrollRegion(line1, line2);
;
ScrollRegion START
line2 equ 9
line1 equ 7
_rtlb equ 3
_d equ 1
; brk $ea
phb
phd
tsc
tcd
lda <line1
cmp #0
bcc exit
lda <line2
cmp #24
bcs exit
lda <line1
cmp <line2
bcs exit
; a = (line2 - line1) * 8 * 160 - 1
lda <line2
sec
sbc <line1
; a = a * 256 * 5
xba ; a = a * 256
; 5x = 4x + x
pha ; save
asl a ; x2
asl a ; x4
clc
adc 1,s
sta 1,s
pla
dec a ; a = a - 1
pha ; save
; src address = $2000 + line1
; ldx #$e12000+1920 ; src address
; ldy #$e12000+640 ; dest address
; dest = $2000 + 640 + line1 * 8 * 160
; src = dest + 1280
lda <line1
xba ; x256
pha ; save
asl a ; x 2
asl a ; x 4
clc
adc #$2000+4*160
adc 1,s
sta 1,s ;store it...
adc #1280
tax ; src address
ply ; dest address
pla ; length
mvn $e10000,$e10000
;
; now empty last line
;
pei (line2)
jsl ClearLine
exit anop
lda <_rtlb
sta <line1
lda <_rtlb+2
sta <line2
pld
pla
pla
plb
rtl
END
;
; scroll 1 line
;
;
ScrollDown START
phb
;
; mvn:
; while (--a != -1)
; dest[y++] = dest[x++];
;
; mvp:
; while(--a != -1)
; dest[y--] = dest[x--];
lda #29440-1 ; length -1 ->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 <line
and #$00ff
xba ; x256
sta <tmp
asl a ; x 512
asl a ; x 1024
clc
adc <tmp
sta <tmp
clc
adc #4*160
sta <tmp
clc
adc #$2000 ; graphics begin @ $e12000
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
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 <Y
and #$00ff
xba ; x256
sta <tmp
asl a ; x 512
asl a ; x 1024
clc
adc <tmp
sta <tmp
clc
adc #4*160
sta <tmp
clc
adc #$2000 ; graphics begin @ $e12000
tax
lda #0
sta >$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 <X
cmp #80
bcs exit
lda <Y
and #$00ff
xba ; x 256
sta <tmp
asl a ; x 512
asl a ; x 1024
clc
adc <tmp ; Y * 8 * 160
clc
adc #160*4
sta <tmp
; each char takes up 2 bytes
lda <X
asl a ; x 2
clc
adc <tmp
sta <tmp
tax
lda #80
sec
sbc <X
loop anop
dec a
bmi exit
stz $2000,x
stz $2000+160,x
stz $2000+320,x
stz $2000+480,x
stz $2000+640,x
stz $2000+800,x
stz $2000+960,x
stz $2000+1120,x
inx
inx
bra loop
exit anop
pld
pla
pla
sta 3,s
pla
sta 3,s
plb
rtl
END
;
; void DrawCursor(int Xpos, int Ypos, int state);
;
;
DrawCursor START
state equ 13
Ypos equ 11
Xpos equ 9
_rtlb equ 5
tmp equ 3
_d equ 1
phb
pha ;tmp
phd
tsc
tcd
lda <Ypos
and #$00ff
xba ; x 256
sta <tmp
asl a ; x 512
asl a ; x 1024
clc
adc <tmp ; a = Y * 1280
adc #11*160 ; last row of it
sta <tmp
adc <Xpos ; + X * 2
adc <Xpos
tax
lda #$ffff ; assume to draw it
ldy <state
bne draw
lda #0 ; nope!
draw anop
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 #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 <pos ; store temporarily
asl a ; x 512
asl a ; x 1024
clc
adc <pos
sta <pos
;
; lower 1/2 row additional
;
clc
adc #160*4
sta <pos
;
; for x offset, 160 bytes per row / 80 chars = 2 bytes/letter
;
lda >Xpos
asl a ; x 2
clc
adc <pos
sta <pos
tay
;
; $e12000 + pos = location to start drawing the character
;
lda <char
cmp #$20 ; smallest printing char
bcc exit ; not printable....
cmp #127 ; 126 is biggest
bcs exit ; not printable
;
; each char takes up 16 bytes :. the offset is (char - $20) * 16
;
sec
sbc #$20
asl a ; x2
asl a ; x4
asl a ; x8
asl a ; x16
tax
lda >CHAR_SPACE,x
eor >xor_mask
and <andMask
sta |$2000,y ; blast it to the screen
lda >CHAR_SPACE+2,x
eor >xor_mask
and <andMask
sta |$2000+160,y
lda >CHAR_SPACE+4,x
eor >xor_mask
and <andMask
sta |$2000+320,y
lda >CHAR_SPACE+6,x
eor >xor_mask
and <andMask
sta |$2000+480,y
lda >CHAR_SPACE+8,x
eor >xor_mask
and <andMask
sta |$2000+640,y
lda >CHAR_SPACE+10,x
eor >xor_mask
and <andMask
sta |$2000+800,y
lda >CHAR_SPACE+12,x
eor >xor_mask
and <andMask
sta |$2000+960,y
lda >CHAR_SPACE+14,x
eor >xor_mask
and <andMask
sta |$2000+1120,y
exit anop
lda <_rtlb+2
sta <andMask
lda <_rtlb
sta <char
pld
pla
pla
pla
plb
rtl
end
Cursor START
StartCursor ENTRY
pha
; ~ReadBParam #$2f
pla
sta blinkRate
stz savedX
stz savedY
; ~SetHeartBeat #CursorHB
rtl
StopCursor ENTRY
; ~DelHeartBeat #CursorHB
rtl
notSafe ENTRY
ds 2
blinkRate ds 2
savedX ds 2
savedY ds 2
CursorHB anop
dc i4'0'
count dc i2'30'
dc h'5AA5'
longa off
phb
phk
plb
php
; long ai
lda notSafe
bne exit
lda Xpos
cmp savedX
bne moved
lda Ypos
cmp savedY
bne moved
bra exit
moved jsr drawCursor
exit anop
plp
plb
clc
rtl
drawCursor anop
rts
END

1000
chars.asm Normal file

File diff suppressed because it is too large Load Diff

499
darlene.c Normal file
View File

@ -0,0 +1,499 @@
#include "Marinetti.h"
#include <Locator.h>
#include <Memory.h>
#include <texttool.h>
#include <gsos.h>
#include <Event.h>
#include <fcntl.h>
#include <sgtty.h>
#include <errno.h>
#include <gno/gno.h>
#include <gno/kerntool.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/ioctl.compat.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#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);
}

408
display.c Normal file
View File

@ -0,0 +1,408 @@
#pragma noroot
#pragma lint -1
#include <types.h>
#include <string.h>
#include <ctype.h>
#include <Event.h>
#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);
}

23
makefile Normal file
View File

@ -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)

137
marinetti.c Normal file
View File

@ -0,0 +1,137 @@
#pragma noroot
#pragma lint -1
#include <Event.h>
#include "Marinetti.h"
#include <stdlib.h>
#include <string.h>
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;
}

139
marinetti.h Normal file
View File

@ -0,0 +1,139 @@
#ifndef __TCPIP_H__
#define __TCPIP_H__
#include <types.h>
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

83
telnet.h Normal file
View File

@ -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

279
vt100.c Normal file
View File

@ -0,0 +1,279 @@
#pragma noroot
#include <Types.h>
#include <texttool.h>
#include <ctype.h>
// 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);
}
}
}