add games/blit
This commit is contained in:
parent
f14e277c58
commit
447672be5c
16 changed files with 22734 additions and 0 deletions
219
sys/src/games/blit/blit.c
Normal file
219
sys/src/games/blit/blit.c
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
1184
sys/src/games/blit/cpu.c
Normal file
1184
sys/src/games/blit/cpu.c
Normal file
File diff suppressed because it is too large
Load diff
31
sys/src/games/blit/dat.h
Normal file
31
sys/src/games/blit/dat.h
Normal file
|
@ -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,
|
||||
};
|
BIN
sys/src/games/blit/diagbits
Normal file
BIN
sys/src/games/blit/diagbits
Normal file
Binary file not shown.
8
sys/src/games/blit/fns.h
Normal file
8
sys/src/games/blit/fns.h
Normal file
|
@ -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 *);
|
180
sys/src/games/blit/mem.c
Normal file
180
sys/src/games/blit/mem.c
Normal file
|
@ -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;
|
||||
}
|
12
sys/src/games/blit/mkfile
Normal file
12
sys/src/games/blit/mkfile
Normal file
|
@ -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
|
88
sys/src/games/blit/mmap
Normal file
88
sys/src/games/blit/mmap
Normal file
|
@ -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
|
4096
sys/src/games/blit/rom0
Normal file
4096
sys/src/games/blit/rom0
Normal file
File diff suppressed because it is too large
Load diff
4096
sys/src/games/blit/rom1
Normal file
4096
sys/src/games/blit/rom1
Normal file
File diff suppressed because it is too large
Load diff
4096
sys/src/games/blit/rom2
Normal file
4096
sys/src/games/blit/rom2
Normal file
File diff suppressed because it is too large
Load diff
4096
sys/src/games/blit/rom3
Normal file
4096
sys/src/games/blit/rom3
Normal file
File diff suppressed because it is too large
Load diff
2239
sys/src/games/blit/rom4
Normal file
2239
sys/src/games/blit/rom4
Normal file
File diff suppressed because it is too large
Load diff
2239
sys/src/games/blit/rom5
Normal file
2239
sys/src/games/blit/rom5
Normal file
File diff suppressed because it is too large
Load diff
149
sys/src/games/blit/telnet.c
Normal file
149
sys/src/games/blit/telnet.c
Normal file
|
@ -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 a new issue