add games/blit
parent
f14e277c58
commit
447672be5c
|
@ -0,0 +1,219 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <draw.h>
|
||||
#include <keyboard.h>
|
||||
#include <mouse.h>
|
||||
#include <cursor.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
int baud = 40000;
|
||||
int scale = 1;
|
||||
Rectangle picr;
|
||||
Image *tmp, *bg;
|
||||
Channel *keych, *uartrxch, *uarttxch;
|
||||
Mousectl *mc;
|
||||
int daddr;
|
||||
u16int dstat;
|
||||
u8int invert;
|
||||
int vblctr, uartrxctr;
|
||||
Rectangle updated;
|
||||
u32int colbgv, colfgv;
|
||||
Image *colbg, *colfg;
|
||||
int realcolors;
|
||||
|
||||
static void
|
||||
screeninit(void)
|
||||
{
|
||||
Point p;
|
||||
|
||||
p = divpt(addpt(screen->r.min, screen->r.max), 2);
|
||||
picr = (Rectangle){subpt(p, Pt(scale * SX/2, scale * SY/2)), addpt(p, Pt(scale * SX/2, scale * SY/2))};
|
||||
if(tmp != nil) freeimage(tmp);
|
||||
tmp = allocimage(display, Rect(0, 0, scale * SX, scale > 1 ? 1 : scale * SY), CHAN1(CMap, 1), scale > 1, 0);
|
||||
if(bg != nil) freeimage(bg);
|
||||
bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
|
||||
colbg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, colbgv);
|
||||
colfg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, colfgv);
|
||||
draw(screen, screen->r, bg, nil, ZP);
|
||||
updated = Rect(0, 0, SX, SY);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw(void)
|
||||
{
|
||||
static uchar pic[SX*SY/8];
|
||||
ushort *p;
|
||||
uchar *q;
|
||||
int o, n;
|
||||
Mouse m;
|
||||
Rectangle r;
|
||||
|
||||
if(nbrecvul(mc->resizec) > 0){
|
||||
if(getwindow(display, Refnone) < 0)
|
||||
sysfatal("resize failed: %r");
|
||||
screeninit();
|
||||
}
|
||||
while(nbrecv(mc->c, &m) > 0){
|
||||
if(ptinrect(m.xy, picr)){
|
||||
mousex = picr.max.x - m.xy.x - 1;
|
||||
mousey = picr.max.y - m.xy.y - 1;
|
||||
}
|
||||
n = m.buttons >> 2 & 1 | m.buttons & 2 | m.buttons << 2 & 4;
|
||||
if(n != mousebut){
|
||||
mousebut = n;
|
||||
irq |= INTMOUSE;
|
||||
}
|
||||
}
|
||||
|
||||
if(Dy(updated) <= 0 || Dx(updated) <= 0)
|
||||
return;
|
||||
|
||||
assert(daddr + sizeof(pic) <= sizeof(ram));
|
||||
|
||||
r = tmp->r;
|
||||
if(updated.min.y > r.min.y)
|
||||
r.min.y = updated.min.y;
|
||||
if(updated.max.y < r.max.y)
|
||||
r.max.y = updated.max.y;
|
||||
|
||||
o = r.min.y*(SX/8);
|
||||
p = ram + (daddr + o) / 2;
|
||||
q = pic + o;
|
||||
for(n = Dy(r)*(SX/16); --n >= 0; ){
|
||||
*q++ = invert ^ *p >> 8;
|
||||
*q++ = invert ^ *p++;
|
||||
}
|
||||
|
||||
loadimage(tmp, r, pic+o, Dy(r)*(SX/8));
|
||||
if(realcolors){
|
||||
draw(screen, rectaddpt(r, picr.min), colfg, nil, r.min);
|
||||
draw(screen, rectaddpt(r, picr.min), colbg, tmp, r.min);
|
||||
}else
|
||||
draw(screen, rectaddpt(r, picr.min), tmp, nil, r.min);
|
||||
updated = Rect(SX, SY, 0, 0);
|
||||
flushimage(display, 1);
|
||||
}
|
||||
|
||||
static uchar
|
||||
keymap[] = {
|
||||
[Kup-KF] 0xf1,
|
||||
[Kdown-KF] 0xf2,
|
||||
[Kleft-KF] 0xf3,
|
||||
[Kright-KF] 0xf4,
|
||||
[1] 0xf6, /* PF1 */
|
||||
[2] 0xf7, /* PF2 */
|
||||
[3] 0xf8, /* PF3 */
|
||||
[4] 0xf9, /* PF4 */
|
||||
[12] 0xfe, /* SET-UP */
|
||||
[Kpgdown-KF] 0xb0, /* SCROLL */
|
||||
[Kins-KF] 0xe0, /* BREAK */
|
||||
};
|
||||
|
||||
static void
|
||||
keyproc(void *)
|
||||
{
|
||||
int fd, cfd, ch, rc;
|
||||
static char buf[256];
|
||||
char *p;
|
||||
Rune r;
|
||||
|
||||
fd = open("/dev/cons", OREAD);
|
||||
if(fd < 0)
|
||||
sysfatal("open: %r");
|
||||
cfd = open("/dev/consctl", OWRITE);
|
||||
if(cfd < 0)
|
||||
sysfatal("open: %r");
|
||||
fprint(cfd, "rawon");
|
||||
for(;;){
|
||||
rc = read(fd, buf, sizeof(buf) - 1);
|
||||
if(rc <= 0)
|
||||
sysfatal("read /dev/cons: %r");
|
||||
for(p = buf; p < buf + rc && (p += chartorune(&r, p)); ){
|
||||
if(r == Kend){
|
||||
close(fd);
|
||||
threadexitsall(nil);
|
||||
}
|
||||
ch = r;
|
||||
if(ch == '\n') ch = '\r';
|
||||
else if(ch >= KF){
|
||||
if(ch >= KF + nelem(keymap)) continue;
|
||||
ch = keymap[ch - KF];
|
||||
if(ch == 0) continue;
|
||||
}else if(ch >= 0x80) continue;
|
||||
send(keych, &ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: %s [-b baud] [-C bg,fg] [-d] [-t [net!]host[!service]]\n", argv0);
|
||||
threadexitsall("usage");
|
||||
}
|
||||
|
||||
void
|
||||
threadmain(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
static Cursor blank;
|
||||
char *telnet;
|
||||
char *p;
|
||||
extern int diag;
|
||||
|
||||
telnet = nil;
|
||||
ARGBEGIN{
|
||||
case 'b':
|
||||
baud = strtol(EARGF(usage()), &p, 0);
|
||||
if(*p != 0) usage();
|
||||
break;
|
||||
case 't':
|
||||
telnet = EARGF(usage());
|
||||
break;
|
||||
case 'C':
|
||||
if(realcolors) usage();
|
||||
realcolors++;
|
||||
p = EARGF(usage());
|
||||
colbgv = strtol(p, &p, 16) << 8 | 0xff;
|
||||
if(*p++ != ',') usage();
|
||||
colfgv = strtol(p, &p, 16) << 8 | 0xff;
|
||||
if(*p != 0) usage();
|
||||
break;
|
||||
case 'd':
|
||||
diag++;
|
||||
break;
|
||||
default: usage();
|
||||
}ARGEND;
|
||||
if(argc != 0) usage();
|
||||
|
||||
keych = chancreate(sizeof(int), 64);
|
||||
uartrxch = chancreate(sizeof(int), 128);
|
||||
uarttxch = chancreate(sizeof(int), 128);
|
||||
if(telnet != nil) telnetinit(telnet);
|
||||
meminit();
|
||||
if(initdraw(nil, nil, nil) < 0)
|
||||
sysfatal("initdraw: %r");
|
||||
|
||||
screeninit();
|
||||
proccreate(keyproc, nil, mainstacksize);
|
||||
mc = initmouse(nil, screen);
|
||||
if(mc == nil)
|
||||
sysfatal("initmouse: %r");
|
||||
setcursor(mc, &blank);
|
||||
|
||||
cpureset();
|
||||
for(;;){
|
||||
keycheck();
|
||||
n = step();
|
||||
vblctr += n;
|
||||
if(vblctr >= VBLDIV){
|
||||
irq |= INTVBL;
|
||||
redraw();
|
||||
vblctr -= VBLDIV;
|
||||
}
|
||||
if(uartrxctr > 0)
|
||||
uartrxctr -= n;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,31 @@
|
|||
typedef signed char s8int;
|
||||
typedef signed short s16int;
|
||||
typedef signed long s32int;
|
||||
|
||||
extern u32int curpc, irq;
|
||||
extern int trace, debug;
|
||||
|
||||
extern ushort ram[128*1024];
|
||||
|
||||
extern int daddr;
|
||||
extern ushort dstat;
|
||||
extern uchar invert;
|
||||
|
||||
extern int mousex, mousey, mousebut;
|
||||
|
||||
extern int vblctr, uartrxctr;
|
||||
extern int baud;
|
||||
|
||||
enum {
|
||||
INTKEY = 1,
|
||||
INTMOUSE = 2,
|
||||
INTUART = 4,
|
||||
INTVBL = 8,
|
||||
};
|
||||
|
||||
enum {
|
||||
SX = 800,
|
||||
SY = 1024,
|
||||
FREQ = 8000*1000,
|
||||
VBLDIV = FREQ / 60,
|
||||
};
|
Binary file not shown.
|
@ -0,0 +1,8 @@
|
|||
u16int memread(u32int);
|
||||
void memwrite(u32int, u16int, u16int);
|
||||
int intack(int);
|
||||
int step(void);
|
||||
void meminit(void);
|
||||
void cpureset(void);
|
||||
void keycheck(void);
|
||||
void telnetinit(char *);
|
|
@ -0,0 +1,180 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <draw.h>
|
||||
#include <bio.h>
|
||||
#include <mouse.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
u32int irq;
|
||||
u32int irql[8] = {
|
||||
[1] INTVBL,
|
||||
[2] INTKEY,
|
||||
[4] INTMOUSE,
|
||||
[5] INTUART,
|
||||
};
|
||||
int diag;
|
||||
|
||||
ushort ram[128*1024];
|
||||
ushort rom[3*4096];
|
||||
Channel *keych;
|
||||
Channel *uartrxch, *uarttxch;
|
||||
int mousex, mousey, mousebut;
|
||||
|
||||
int yes;
|
||||
u8int kbdctrl, uartctrl;
|
||||
enum {
|
||||
ACIATXMASK = 0x60,
|
||||
ACIATXIRQ = 0x20,
|
||||
ACIARXIRQ = 0x80,
|
||||
};
|
||||
|
||||
int keybuf = -1;
|
||||
int uartrxbuf = -1;
|
||||
int uarttxbuf = -1;
|
||||
|
||||
void
|
||||
meminit(void)
|
||||
{
|
||||
int i, x;
|
||||
Biobuf *bp;
|
||||
char *s;
|
||||
ushort *p, *q;
|
||||
|
||||
p = rom;
|
||||
if(diag){
|
||||
bp = Bopen("diagbits", OREAD);
|
||||
if(bp == nil) sysfatal("Bopen: %r");
|
||||
Bread(bp, rom, sizeof(rom));
|
||||
Bterm(bp);
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < 6; i++){
|
||||
bp = Bopen(smprint("rom%d", i), OREAD);
|
||||
if(bp == nil) sysfatal("Bopen: %r");
|
||||
q = p;
|
||||
for(;;){
|
||||
s = Brdline(bp, '\n');
|
||||
if(s == nil || Blinelen(bp) == 0) break;
|
||||
s[Blinelen(bp) - 1] = 0;
|
||||
x = strtol(s, nil, 8);
|
||||
if((i & 1) != 0)
|
||||
*p |= x << 8;
|
||||
else
|
||||
*p |= x;
|
||||
p++;
|
||||
}
|
||||
if((i & 1) == 0) p = q;
|
||||
Bterm(bp);
|
||||
}
|
||||
write(3, rom, sizeof(rom));
|
||||
}
|
||||
|
||||
void
|
||||
keycheck(void)
|
||||
{
|
||||
yield();
|
||||
|
||||
if(keybuf < 0)
|
||||
nbrecv(keych, &keybuf);
|
||||
if(keybuf >= 0 && (kbdctrl & ACIARXIRQ) != 0)
|
||||
irq |= INTKEY;
|
||||
else
|
||||
irq &= ~INTKEY;
|
||||
|
||||
if(uartrxbuf < 0 && uartrxctr <= 0){
|
||||
nbrecv(uartrxch, &uartrxbuf);
|
||||
uartrxctr = FREQ * 11 / baud;
|
||||
}
|
||||
if(uarttxbuf >= 0 && nbsend(uarttxch, &uarttxbuf) > 0)
|
||||
uarttxbuf = -1;
|
||||
if(uartrxbuf >= 0 && (uartctrl & ACIARXIRQ) != 0 || uarttxbuf < 0 && (uartctrl & ACIATXMASK) == ACIATXIRQ)
|
||||
irq |= INTUART;
|
||||
else
|
||||
irq &= ~INTUART;
|
||||
}
|
||||
|
||||
u16int
|
||||
memread(u32int a)
|
||||
{
|
||||
int rc;
|
||||
|
||||
a &= 0x3fffff;
|
||||
if(a < 8) a += 0x40000;
|
||||
if(a < 0x40000) return ram[a/2];
|
||||
if(a >= 0x40000 && a < 0x40000 + sizeof(rom))
|
||||
return rom[(a - 0x40000)/2];
|
||||
switch(a & ~1){
|
||||
case 01400000: return mousey;
|
||||
case 01400002: return mousex;
|
||||
case 01400010: /* uart status */
|
||||
rc = 0;
|
||||
if(uartrxbuf >= 0) rc |= 1;
|
||||
if(uarttxbuf < 0) rc |= 2;
|
||||
return rc | rc << 8;
|
||||
case 01400012: /* uart data */
|
||||
rc = uartrxbuf;
|
||||
uartrxbuf = -1;
|
||||
yes=1;
|
||||
return rc | rc << 8;
|
||||
case 01400020:
|
||||
case 01400024:
|
||||
irq &= ~INTMOUSE;
|
||||
return mousebut | mousebut << 8;
|
||||
case 01400026: return 0; /* mouse: unknown purpose */
|
||||
case 01400030: return daddr >> 2; /* display address */
|
||||
case 01400040: return dstat; /* display status */
|
||||
case 01400060: /* keyboard status */
|
||||
rc = 2;
|
||||
if(keybuf >= 0) rc |= 1;
|
||||
return rc | rc << 8;
|
||||
case 01400062: /* keyboard data */
|
||||
rc = keybuf;
|
||||
keybuf = -1;
|
||||
return rc | rc << 8;
|
||||
}
|
||||
print("read %.8o (curpc = %.6x)\n", a, curpc & 0x3fffff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
memwrite(u32int a, u16int v, u16int m)
|
||||
{
|
||||
extern Rectangle updated;
|
||||
int x, y;
|
||||
|
||||
a &= 0x3fffff;
|
||||
if(a < 0x40000){
|
||||
if(a >= daddr){
|
||||
y = (a - daddr) / 100;
|
||||
x = (((a & ~1) - daddr) % 100) * 8;
|
||||
if(updated.min.x > x) updated.min.x = x;
|
||||
if(updated.max.x < x+16) updated.max.x = x+16;
|
||||
if(updated.min.y > y) updated.min.y = y;
|
||||
if(updated.max.y <= y) updated.max.y = y+1;
|
||||
}
|
||||
ram[a/2] = ram[a/2] & ~m | v & m;
|
||||
return;
|
||||
}
|
||||
switch(a & ~1){
|
||||
case 01400010: uartctrl = v; return;
|
||||
case 01400012: uarttxbuf = (uchar) v; return;
|
||||
case 01400024: return; /* mouse: purpose unknown */
|
||||
case 01400026: return; /* mouse: purpose unknown */
|
||||
case 01400030: daddr = ((daddr >> 2) & ~m | v & m) << 2; return;
|
||||
case 01400040: dstat = dstat & ~m | v & m; invert = -(dstat & 1); updated = Rect(0, 0, SX, SY); return;
|
||||
case 01400056: /* sound; exact function unknown */ return;
|
||||
case 01400060: kbdctrl = v; return;
|
||||
case 01400062: /* reset keyboard */ return;
|
||||
case 01400070: irq &= ~INTVBL; return;
|
||||
case 01400156: /* sound; exact function unknown */ return;
|
||||
}
|
||||
print("write %.8o = %.4x (mask = %.4x, curpc = %.6x)\n", a, v, m, curpc & 0x3fffff);
|
||||
}
|
||||
|
||||
int
|
||||
intack(int l)
|
||||
{
|
||||
return 24+l;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
BIN=/$objtype/bin
|
||||
TARG=blit
|
||||
HFILES=dat.h fns.h
|
||||
OFILES=\
|
||||
blit.$O\
|
||||
cpu.$O\
|
||||
mem.$O\
|
||||
telnet.$O\
|
||||
|
||||
</sys/src/cmd/mkone
|
|
@ -0,0 +1,88 @@
|
|||
- main CPU is a MC68000 running at 8 MHz.
|
||||
the exact clock speed is most likely one of: 7.9872, 7.68 or 7.3728 MHz (to divide to 19200 baud)
|
||||
- display is 800x1024, refreshed at 30 Hz (60 Hz interlaced).
|
||||
it simply displays the 100K framebuffer from the address given in register 030.
|
||||
- the host is connected through a UART running at 19200 baud.
|
||||
- the keyboard is connected through a UART running at an unknown baudrate.
|
||||
- the mouse is connected through some unknown circuitry.
|
||||
|
||||
memory map
|
||||
|
||||
start end purpose
|
||||
0x00000 0x00008 see register 050 below
|
||||
0x00008 0x40000 RAM (256K)
|
||||
0x40000 ??? ROM (24K ?) (not known if mirrored)
|
||||
0x60000 ??? memory mapped I/O
|
||||
|
||||
mmio addresses (in *octal*):
|
||||
|
||||
0000 16-bit mouse y
|
||||
0002 16-bit mouse x
|
||||
|
||||
0011 8-bit terminal UART status/control (MC 6850 ACIA)
|
||||
0013 8-bit terminal UART data
|
||||
the software uses 2 stop bits, no parity, 8 bits; clock divided by 16
|
||||
|
||||
0021 8-bit mouse buttons
|
||||
bit 0: rmb
|
||||
bit 1: mmb
|
||||
bit 2: lmb
|
||||
reading clears the mouse interrupt
|
||||
|
||||
0025 8-bit second copy of 0021 (?)
|
||||
0027 8-bit ???
|
||||
only the ROM binaries contain references to 0025, 0027 in buttons.c.
|
||||
the corresponding source code appears to have been deleted.
|
||||
possibly some older variant of the button hardware?
|
||||
|
||||
0030 16-bit start address of framebuffer divided by 4 (800*1024/8 = 100K bytes)
|
||||
0040 16-bit status/control register of display
|
||||
bit 0: invert display
|
||||
with this bit set 0 bits are white and 1 bits are black (most software does this).
|
||||
|
||||
0050 16-bit writing different values makes 0-8 either mapped to 0x40000 or error out (details unclear)
|
||||
resets so that they map to the reset vector at 0x40000.
|
||||
|
||||
0056 8-bit some kind of sound-making device (standard programmable timer + piezoelectric speaker?)
|
||||
0156 referenced by demo pacman.
|
||||
0256
|
||||
|
||||
0060 8-bit keyboard status/control register (MC 6850 ACIA)
|
||||
the software uses 2 stop bits, no parity, 8 bits; clock divided by 16
|
||||
0062 8-bit keyboard data register
|
||||
|
||||
0070 16-bit? acknowledge vblank interrupt; software writes 0
|
||||
|
||||
tx to the keyboard sets the 7 lights and can also ring the bell.
|
||||
could deduce the order of lights from diag.c.
|
||||
writing 2 is used to sound the bell.
|
||||
|
||||
irq lines; using the 68k autovectoring
|
||||
|
||||
vector 1 (0x64) is vblank
|
||||
vector 2 (0x68) is keyboard
|
||||
vector 4 (0x70) is mouse buttons
|
||||
vector 5 (0x74) is uart
|
||||
|
||||
MC 6850 bits:
|
||||
+0 (r) status register
|
||||
bit 0: receive buffer full
|
||||
bit 1: transmit buffer empty
|
||||
bit 2: data carrier detected (inverted)
|
||||
bit 3: clear-to-send (inverted)
|
||||
bit 4: framing error
|
||||
bit 5: receiver overrun
|
||||
bit 6: parity error
|
||||
bit 7: irq active
|
||||
+0 (w) control register
|
||||
bit 1-0: clock divider
|
||||
00: /1
|
||||
01: /16
|
||||
10: /64
|
||||
11: master reset
|
||||
bit 4-2: parity and stop bits (see datasheet)
|
||||
bit 6-5:
|
||||
RTS/ is high only if these bits are 10
|
||||
TX interrupts are enabled only if these bits are 01
|
||||
break is transmitted continuously if these bits are 11
|
||||
bit 7: RX interrupt enabled
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,149 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
Channel *telnetrxch, *telnettxch;
|
||||
extern Channel *uartrxch, *uarttxch;
|
||||
int teldebug;
|
||||
|
||||
enum {
|
||||
SE = 240,
|
||||
NOP = 241,
|
||||
BRK = 243,
|
||||
IP = 244,
|
||||
AO = 245,
|
||||
AYT = 246,
|
||||
EC = 247,
|
||||
EL = 248,
|
||||
GA = 249,
|
||||
SB = 250,
|
||||
WILL = 251,
|
||||
WONT = 252,
|
||||
DO = 253,
|
||||
DONT = 254,
|
||||
IAC = 255,
|
||||
|
||||
XMITBIN = 0,
|
||||
ECHO = 1,
|
||||
SUPRGA = 3,
|
||||
LINEEDIT = 34,
|
||||
|
||||
};
|
||||
|
||||
int telfd;
|
||||
|
||||
static void
|
||||
netrproc(void *)
|
||||
{
|
||||
static uchar buf[512];
|
||||
int n, c;
|
||||
uchar *p;
|
||||
|
||||
for(;;){
|
||||
n = read(telfd, buf, sizeof(buf));
|
||||
if(n < 0) sysfatal("read: %r");
|
||||
for(p = buf; p < buf + n; p++){
|
||||
c = *p;
|
||||
send(telnetrxch, &c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
netwproc(void *)
|
||||
{
|
||||
static uchar buf[512];
|
||||
int c;
|
||||
uchar *p;
|
||||
|
||||
for(;;){
|
||||
recv(telnettxch, &c);
|
||||
p = buf;
|
||||
do
|
||||
*p++ = c;
|
||||
while(nbrecv(telnettxch, &c) > 0);
|
||||
if(write(telfd, buf, p - buf) < p - buf)
|
||||
sysfatal("write: %r");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
telnetrthread(void *)
|
||||
{
|
||||
int c;
|
||||
|
||||
for(;;){
|
||||
recv(telnetrxch, &c);
|
||||
if(c != IAC){
|
||||
send(uartrxch, &c);
|
||||
continue;
|
||||
}
|
||||
recv(telnetrxch, &c);
|
||||
switch(c){
|
||||
case NOP: break;
|
||||
case WILL:
|
||||
recv(telnetrxch, &c);
|
||||
if(teldebug) fprint(2, "WILL %d\n", c);
|
||||
break;
|
||||
case WONT:
|
||||
recv(telnetrxch, &c);
|
||||
if(teldebug) fprint(2, "WONT %d\n", c);
|
||||
break;
|
||||
case DO:
|
||||
recv(telnetrxch, &c);
|
||||
if(teldebug) fprint(2, "DO %d\n", c);
|
||||
break;
|
||||
case DONT:
|
||||
recv(telnetrxch, &c);
|
||||
if(teldebug) fprint(2, "DONT %d\n", c);
|
||||
break;
|
||||
case IAC:
|
||||
send(uartrxch, &c);
|
||||
break;
|
||||
default:
|
||||
fprint(2, "unknown telnet command %d\n", c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd(int a, int b)
|
||||
{
|
||||
send(telnettxch, &a);
|
||||
if(b >= 0) send(telnettxch, &b);
|
||||
}
|
||||
|
||||
static void
|
||||
telnetwthread(void *)
|
||||
{
|
||||
int c;
|
||||
|
||||
for(;;){
|
||||
recv(uarttxch, &c);
|
||||
send(telnettxch, &c);
|
||||
if(c == 0xff)
|
||||
send(telnettxch, &c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
telnetinit(char *dialstr)
|
||||
{
|
||||
telfd = dial(netmkaddr(dialstr, nil, "telnet"), nil, nil, nil);
|
||||
if(telfd < 0) sysfatal("dial: %r");
|
||||
telnetrxch = chancreate(sizeof(int), 128);
|
||||
telnettxch = chancreate(sizeof(int), 128);
|
||||
cmd(WILL, XMITBIN);
|
||||
cmd(DO, XMITBIN);
|
||||
cmd(DONT, ECHO);
|
||||
cmd(DO, SUPRGA);
|
||||
cmd(WILL, SUPRGA);
|
||||
cmd(WONT, LINEEDIT);
|
||||
cmd(DONT, LINEEDIT);
|
||||
proccreate(netrproc, nil, mainstacksize);
|
||||
proccreate(netwproc, nil, mainstacksize);
|
||||
threadcreate(telnetrthread, nil, mainstacksize);
|
||||
threadcreate(telnetwthread, nil, mainstacksize);
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
TARG=4s\
|
||||
5s\
|
||||
ana\
|
||||
blit\
|
||||
catclock\
|
||||
festoon\
|
||||
geigerstats\
|
||||
|
|
Loading…
Reference in New Issue