From 447672be5c1e3e0b972c793d243383c429240b71 Mon Sep 17 00:00:00 2001 From: aiju Date: Tue, 28 Mar 2017 19:43:09 +0000 Subject: add games/blit --- sys/src/games/blit/blit.c | 219 +++ sys/src/games/blit/cpu.c | 1184 +++++++++++++ sys/src/games/blit/dat.h | 31 + sys/src/games/blit/diagbits | Bin 0 -> 7338 bytes sys/src/games/blit/fns.h | 8 + sys/src/games/blit/mem.c | 180 ++ sys/src/games/blit/mkfile | 12 + sys/src/games/blit/mmap | 88 + sys/src/games/blit/rom0 | 4096 +++++++++++++++++++++++++++++++++++++++++++ sys/src/games/blit/rom1 | 4096 +++++++++++++++++++++++++++++++++++++++++++ sys/src/games/blit/rom2 | 4096 +++++++++++++++++++++++++++++++++++++++++++ sys/src/games/blit/rom3 | 4096 +++++++++++++++++++++++++++++++++++++++++++ sys/src/games/blit/rom4 | 2239 +++++++++++++++++++++++ sys/src/games/blit/rom5 | 2239 +++++++++++++++++++++++ sys/src/games/blit/telnet.c | 149 ++ sys/src/games/mkfile | 1 + 16 files changed, 22734 insertions(+) create mode 100644 sys/src/games/blit/blit.c create mode 100644 sys/src/games/blit/cpu.c create mode 100644 sys/src/games/blit/dat.h create mode 100644 sys/src/games/blit/diagbits create mode 100644 sys/src/games/blit/fns.h create mode 100644 sys/src/games/blit/mem.c create mode 100644 sys/src/games/blit/mkfile create mode 100644 sys/src/games/blit/mmap create mode 100644 sys/src/games/blit/rom0 create mode 100644 sys/src/games/blit/rom1 create mode 100644 sys/src/games/blit/rom2 create mode 100644 sys/src/games/blit/rom3 create mode 100644 sys/src/games/blit/rom4 create mode 100644 sys/src/games/blit/rom5 create mode 100644 sys/src/games/blit/telnet.c diff --git a/sys/src/games/blit/blit.c b/sys/src/games/blit/blit.c new file mode 100644 index 000000000..4fa81ae27 --- /dev/null +++ b/sys/src/games/blit/blit.c @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include +#include +#include +#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; + } +} diff --git a/sys/src/games/blit/cpu.c b/sys/src/games/blit/cpu.c new file mode 100644 index 000000000..8a7e8db86 --- /dev/null +++ b/sys/src/games/blit/cpu.c @@ -0,0 +1,1184 @@ +#include +#include +#include +#include "dat.h" +#include "fns.h" + +enum { + FLAGS = 1<<13, + FLAGX = 16, + FLAGN = 8, + FLAGZ = 4, + FLAGV = 2, + FLAGC = 1, +}; + +u32int r[16], pc, curpc; +u32int asp, irq, stop; +extern u32int irql[8]; +u32int irqla[8]; +u16int rS; +static u32int op; +int trace, tim; +#define ra (r+8) + +static void +undef(void) +{ + sysfatal("undefined opcode %#o at pc=%#.6x", op, curpc); +} + +static u16int +fetch16(void) +{ + u16int v; + + v = memread(pc); + pc += 2; + return v; +} + +static u32int +fetch32(void) +{ + u32int v; + + v = fetch16() << 16; + return v | fetch16(); +} + +static void +push16(u16int u) +{ + ra[7] -= 2; + memwrite(ra[7], u, -1); +} + +static u16int +pop16(void) +{ + u16int v; + + v = memread(ra[7]); + ra[7] += 2; + return v; +} + +static void +push32(u32int u) +{ + ra[7] -= 4; + memwrite(ra[7], u >> 16, -1); + memwrite(ra[7] + 2, u, -1); +} + +static u32int +pop32(void) +{ + u32int v; + v = memread(ra[7]) << 16; + v |= memread(ra[7] + 2); + ra[7] += 4; + return v; +} + +static vlong +amode(int m, int n, int s) +{ + u16int w; + u32int v; + + m &= 7; + n &= 7; + s &= 3; + if(n == 7 && s == 0) + s++; + switch(m){ + case 0: + return ~n; + case 1: + return ~(n+8); + case 2: + tim += s == 2 ? 8 : 4; + return ra[n]; + case 3: + v = ra[n]; + ra[n] += 1<> 12]; + if((w & 1<<11) == 0) + v = (s16int)v; + return (u32int)(ra[n] + v + (s8int)w); + case 7: + switch(n){ + case 0: + tim += s == 2 ? 12 : 8; + return (u32int)(s16int)fetch16(); + case 1: + tim += s == 2 ? 16 : 12; + return fetch32(); + case 2: + tim += s == 2 ? 12 : 8; + v = fetch16(); + return (u32int)(pc + (s16int)v - 2); + case 3: + tim += s == 2 ? 14 : 4; + w = fetch16(); + v = r[w >> 12]; + if((w & 1<<11) == 0) + v = (s16int)v; + return (u32int)(pc + v + (s8int)w - 2); + case 4: + tim += s == 2 ? 8 : 4; + v = pc; + pc += 1<= 0){ + switch(s & 3){ + case 0: + v = memread(a); + if((a & 1) == 0) + v >>= 8; + return (s8int) v; + default: + return (s16int) memread(a); + case 2: + v = memread(a) << 16; + return v | memread(a + 2); + } + } + v = r[~a]; + switch(s & 3){ + case 0: return (s8int) v; + case 1: return (s16int) v; + default: return v; + } +} + +static void +wmode(vlong a, int s, u32int v) +{ + int n; + + if(a >= 0){ + switch(s & 3){ + case 0: + memwrite(a, (u8int)v | (u8int)v << 8, (a & 1) != 0 ? 0xff : 0xff00); + return; + default: + memwrite(a, v, -1); + return; + case 2: + memwrite(a, v >> 16, -1); + memwrite(a + 2, v, -1); + return; + } + } + n = ~a; + if(n < 8){ + switch(s){ + case 0: r[n] = r[n] & 0xffffff00 | v & 0xff; break; + case 1: r[n] = r[n] & 0xffff0000 | v & 0xffff; break; + default: r[n] = v; + } + }else{ + if(s == 1) + v = (s16int) v; + r[n] = v; + } +} + +static void +nz(u32int v, int s) +{ + switch(s){ + case 0: v = (s8int) v; break; + case 1: v = (s16int) v; break; + } + rS &= ~(FLAGC|FLAGN|FLAGV|FLAGZ); + if(v == 0) + rS |= FLAGZ; + if((s32int)v < 0) + rS |= FLAGN; +} + +static u32int +add(u32int u, u32int w, int c, int s) +{ + u64int v; + + rS &= ~(FLAGN|FLAGV|FLAGC); + switch(s){ + case 0: + v = (u8int)w + (u8int)u + c; + if(v >= 0x100) + rS |= FLAGC; + if((v & 0x80) != 0) + rS |= FLAGN; + if((~(w ^ u) & (v ^ u) & 0x80) != 0) + rS |= FLAGV; + if((u8int)v != 0) + rS &= ~FLAGZ; + break; + case 1: + v = (u16int)w + (u16int)u + c; + if(v >= 0x10000) + rS |= FLAGC; + if((v & 0x8000) != 0) + rS |= FLAGN; + if((~(w ^ u) & (v ^ u) & 0x8000) != 0) + rS |= FLAGV; + if((u16int)v != 0) + rS &= ~FLAGZ; + break; + default: + v = (u64int)w + u + c; + if((v >> 32) != 0) + rS |= FLAGC; + if((v & 0x80000000) != 0) + rS |= FLAGN; + if((~(w ^ u) & (v ^ u) & 0x80000000) != 0) + rS |= FLAGV; + if((u32int)v != 0) + rS &= ~FLAGZ; + break; + } + return v; +} + +static u32int +sub(u32int u, u32int w, int c, int s) +{ + u64int v; + + rS &= ~(FLAGN|FLAGV|FLAGC); + switch(s){ + case 0: + v = (u8int)u - (u8int)w - c; + if(v >= 0x100) + rS |= FLAGC; + if((v & 0x80) != 0) + rS |= FLAGN; + if(((w ^ u) & (v ^ u) & 0x80) != 0) + rS |= FLAGV; + if((u8int)v != 0) + rS &= ~FLAGZ; + break; + case 1: + v = (u16int)u - (u16int)w - c; + if(v >= 0x10000) + rS |= FLAGC; + if((v & 0x8000) != 0) + rS |= FLAGN; + if(((w ^ u) & (v ^ u) & 0x8000) != 0) + rS |= FLAGV; + if((u16int)v != 0) + rS &= ~FLAGZ; + break; + default: + v = (u64int)u - w - c; + if((v >> 32) != 0) + rS |= FLAGC; + if((v & 0x80000000) != 0) + rS |= FLAGN; + if(((w ^ u) & (v ^ u) & (1<<31)) != 0) + rS |= FLAGV; + if((u32int)v != 0) + rS &= ~FLAGZ; + break; + } + return v; +} + +static int +cond(int n) +{ + switch(n){ + case 0: return 1; break; + default: return 0; break; + case 2: return (rS & (FLAGC|FLAGZ)) == 0; break; + case 3: return (rS & (FLAGC|FLAGZ)) != 0; break; + case 4: return (rS & FLAGC) == 0; break; + case 5: return (rS & FLAGC) != 0; break; + case 6: return (rS & FLAGZ) == 0; break; + case 7: return (rS & FLAGZ) != 0; break; + case 8: return (rS & FLAGV) == 0; break; + case 9: return (rS & FLAGV) != 0; break; + case 10: return (rS & FLAGN) == 0; break; + case 11: return (rS & FLAGN) != 0; break; + case 12: return ((rS ^ (rS << 2)) & FLAGN) == 0; break; + case 13: return ((rS ^ (rS << 2)) & FLAGN) != 0; break; + case 14: return ((rS ^ (rS << 2)) & FLAGN) == 0 && (rS & FLAGZ) == 0; break; + case 15: return ((rS ^ (rS << 2)) & FLAGN) != 0 || (rS & FLAGZ) != 0; break; + } +} + +static u32int +rot(u32int v, int m, int n, int s) +{ + int l, ll, x, vf; + u32int msb; + + msb = 1 << ((8 << s) - 1); + v &= (msb << 1) - 1; + if(m == 0) + x = (v & msb) != 0; + else + x = 0; + if((m & 6) == 4) + ll = l = (rS & FLAGX) != 0; + else + ll = l = 0; + vf = 0; + while(n--){ + if((m & 1) == 0){ + l = v & 1; + v >>= 1; + }else{ + l = (v & msb) != 0; + v <<= 1; + } + rS = rS & ~FLAGX | l << 4; + if(m >= 6) + x = l; + else if(m >= 4){ + x = ll; + ll = l; + } + if((m & 1) == 0){ + if(x != 0) + v |= msb; + }else + v |= x; + vf |= x ^ (v & msb) != 0; + tim += 2; + } + nz(v, s); + rS |= l; + if(m <= 1 && vf) + rS |= FLAGV; + tim += s == 2 ? 8 : 6; + return v; +} + +static u8int +addbcd(u8int a, u8int b) +{ + int r; + + r = (a & 0xf) + (b & 0xf) + ((rS & FLAGX) != 0); + if(r > 0x09) r += 0x06; + if(r > 0x1f) r -= 0x10; + r += (a & 0xf0) + (b & 0xf0); + if(r > 0x9f) r += 0x60; + if((u8int)r != 0) + rS &= ~FLAGZ; + if(r > 0xff) + rS |= FLAGC|FLAGX; + else + rS &= ~(FLAGC|FLAGX); + return r; +} + +static u8int +subbcd(u8int a, u8int b) +{ + int x; + + x = (a & 0xf) + (~b & 0xf) + ((rS & FLAGX) == 0); + if(x < 0x10) x -= 0x06; + if(x < 0) x += 0x10; + x += (a & 0xf0) + (~b & 0xf0); + if(x > 0xff) + rS &= ~(FLAGC|FLAGX); + else{ + rS |= FLAGC|FLAGX; + x -= 0x60; + } + if((u8int)x != 0) + rS &= ~FLAGZ; + return x; +} + +static void +dtime(u16int op, u8int s) +{ + if((op & 0x100) != 0){ + if(s == 2) + if((op & 0x30) == 0 || (op & 0x3f) == 0x3c) + tim += 8; + else + tim += 6; + else + tim += 4; + }else + tim += s == 2 ? 12 : 8; +} + +static void +stime(int a, u8int s) +{ + if(a) + tim += s == 2 ? 6 : 4; + else + tim += s == 2 ? 12 : 8; +} + +static void +trap(int n, u32int pcv) +{ + int l, v; + u32int sr, t; + + sr = rS; + if(n < 0){ + for(l = 7; l > ((rS >> 8) & 7); l--) + if((irql[l] & irq) != 0) + break; + v = intack(l); + rS = rS & ~0x700 | l << 8; + tim += 44; + }else{ + switch(n){ + case 2: case 3: tim += 50; break; + case 5: tim += 38; break; + case 6: tim += 40; break; + default: tim += 34; break; + } + v = n; + } + if((rS & FLAGS) == 0){ + t = asp; + asp = ra[7]; + ra[7] = t; + } + rS |= FLAGS; + push32(pcv); + push16(sr); + pc = memread(v * 4) << 16; + pc |= memread(v * 4 + 2); + stop = 0; +} + +void +cpureset(void) +{ + u32int v; + int i; + + ra[7] = memread(0) << 16 | memread(2); + pc = memread(4) << 16 | memread(6); + rS = 0x2700; + for(i = 7, v = 0; i >= 0; i--){ + irqla[i] = v; + v |= irql[i]; + } +} + +int +step(void) +{ + u32int v, w; + vlong a; + int s; + int n, m, d; + static int cnt; + + if(0 && pc == 0x4118c){ + trace++; + print("%x\n", curpc); + } + tim = 0; + curpc = pc; + if(irq && (irqla[(rS >> 8) & 7] & irq) != 0){ + trap(-1, curpc); + return tim; + } + if(stop) + return 1; + op = fetch16(); + if(trace) + print("%.6ux %.6uo %.4ux %.8ux | %.8ux %.8ux %.8ux %.8ux | %.8ux %.8ux %.8ux\n", curpc, op, rS, memread(ra[7])<<16|memread(ra[7]+2), r[0], r[1], r[2], r[3], ra[0], ra[6], ra[7]); + s = op >> 6 & 3; + n = op >> 9 & 7; + switch(op >> 12){ + case 0: + if((op & 0x3f) == 0x3c){ /* (ORI|ANDI|EORI) to (CCR|SR) */ + if(s == 1 && (rS & FLAGS) == 0){ + trap(8, curpc); + break; + } + v = rS; + w = fetch16(); + switch(n){ + case 0: v |= w; break; + case 1: v &= w; break; + case 5: v ^= w; break; + default: undef(); + } + if(s != 1) + v = v & 0xff | rS & 0xff00; + rS = v; + if(s == 1 && (rS & FLAGS) == 0){ + v = ra[7]; + ra[7] = asp; + asp = v; + } + tim += 20; + break; + } + if((op & 0x138) == 0x108){ /* MOVEP */ + a = ra[op & 7] + (s16int)fetch16(); + switch(s){ + case 0: + v = (u8int)rmode(a, 0) << 8; + v |= (u8int)rmode(a + 2, 0); + r[n] = r[n] & 0xff00 | v; + tim += 16; + break; + case 1: + v = (u8int)rmode(a, 0) << 24; + v |= (u8int)rmode(a + 2, 0) << 16; + v |= (u8int)rmode(a + 4, 0) << 8; + v |= (u8int)rmode(a + 6, 0); + tim += 24; + r[n] = v; + break; + case 2: + wmode(a, 0, r[n] >> 8); + wmode(a + 2, 0, r[n]); + tim += 16; + break; + case 3: + wmode(a, 0, r[n] >> 24); + wmode(a + 2, 0, r[n] >> 16); + wmode(a + 4, 0, r[n] >> 8); + wmode(a + 6, 0, r[n]); + tim += 24; + break; + } + break; + } + if((op & 0x100) != 0 || n == 4){ /* BTST, BCHG, BCLR, BSET */ + if((op & 0x100) != 0) + w = r[n]; + else + w = fetch16(); + if((op & 0x38) != 0){ + n = 0; + w = 1<<(w & 7); + }else{ + n = 2; + w = 1<<(w & 31); + } + a = amode(op >> 3, op, n); + v = rmode(a, n); + rS &= ~FLAGZ; + if((v & w) == 0) + rS |= FLAGZ; + switch(s){ + case 1: v ^= w; break; + case 2: v &= ~w; if(n == 2) tim += 2; break; + case 3: v |= w; break; + } + if(s != 0){ + wmode(a, n, v); + tim += (op & 0x100) != 0 ? 8 : 12; + }else{ + tim += (op & 0x100) != 0 ? 4 : 8; + if(n == 2) + tim += 2; + } + break; + } + switch(s){ + case 0: w = (s8int)fetch16(); break; + default: w = fetch16(); break; + case 2: w = fetch32(); break; + } + a = amode(op >> 3, op, s); + v = rmode(a, s); + switch(n){ + case 0: nz(v |= w, s); break; + case 1: nz(v &= w, s); break; + case 2: rS |= FLAGZ; v = sub(v, w, 0, s); break; + case 3: rS |= FLAGZ; v = add(v, w, 0, s); break; + case 5: nz(v ^= w, s); break; + case 6: rS |= FLAGZ; sub(v, w, 0, s); break; + default: undef(); + } + if(a < 0) + tim += s == 2 ? (n == 1 || n == 6 ? 14 : 16) : 8; + else + tim += s == 2 ? 20 : 12; + if(n != 6) + wmode(a, s, v); + break; + case 1: /* MOVE */ + s = 0; + goto move; + case 2: + s = 2; + goto move; + case 3: + s = 1; + move: + v = rmode(amode(op >> 3, op, s), s); + wmode(amode(op >> 6, op >> 9, s), s, v); + if((op & 0x1c0) != 0x40) + nz(v, s); + tim += 4; + break; + case 4: + if((op & 0x1c0) == 0x1c0){ /* LEA */ + ra[n] = amode(op >> 3, op, 2); + break; + } + if((op & 0x1c0) == 0x180){ /* CHK */ + a = amode(op >> 3, op, s); + v = rmode(a, s); + if((s32int)r[n] < 0 || (s32int)r[n] > (s32int)v) + trap(6, curpc); + else + tim += 10; + } + if((op & 0xb80) == 0x880 && (op & 0x38) >= 0x10){ /* MOVEM */ + s = (op >> 6 & 1) + 1; + w = fetch16(); + if((op & 0x38) == 0x18){ + n = op & 7; + a = ra[n]; + for(m = 0; m < 16; m++){ + if((w & 1) != 0){ + r[m] = rmode(a, s); + a += 1<>= 1; + } + ra[n] = a; + tim += 12; + break; + } + if((op & 0x38) == 0x20){ + n = op & 7; + a = ra[n]; + for(m = 0; m < 16; m++){ + if((w & 1) != 0){ + a -= 1<>= 1; + } + ra[n] = a; + tim += 8; + break; + } + a = amode(op >> 3, op, s); + for(m = 0; m < 16; m++){ + if((w & 1) != 0){ + if((op & 0x400) != 0) + r[m] = rmode(a, s); + else + wmode(a, s, r[m]); + a += 1<>= 1; + } + tim += (op & 0x400) != 0 ? 8 : 12; + break; + } + switch(op >> 8 & 0xf){ + case 0: + if(s == 3){ /* MOVE from SR */ + if((rS & FLAGS) != 0){ + a = amode(op >> 3, op, 1); + wmode(a, 1, rS); + tim += a < 0 ? 6 : 8; + }else + trap(8, curpc); + break; + } /* NEGX */ + a = amode(op >> 3, op, s); + m = (rS & FLAGX) != 0; + d = 1<<(8<> 3, op, s); + wmode(a, s, 0); + nz(0, 0); + stime(a < 0, s); + break; + case 4: + if(s == 3){ /* MOVE to CCR */ + rS = rS & 0xff00 | rmode(amode(op >> 3, op, 1), 1); + tim += 12; + break; + } /* NEG */ + a = amode(op >> 3, op, s); + v = -rmode(a, s); + nz(v, s); + rS = rS & ~FLAGX | ~rS << 2 & FLAGX | ~rS >> 2 & FLAGC; + wmode(a, s, v); + stime(a < 0, s); + break; + case 6: + if(s == 3){ /* MOVE to SR */ + if((rS & FLAGS) != 0){ + rS = rmode(amode(op >> 3, op, 1), 1); + if((rS & FLAGS) == 0){ + v = asp; + asp = ra[7]; + ra[7] = v; + } + tim += 12; + }else + trap(8, curpc); + break; + } /* NOT */ + a = amode(op >> 3, op, s); + v = ~rmode(a, s); + nz(v, s); + wmode(a, s, v); + stime(a < 0, s); + break; + case 8: + n = op & 7; + switch(s){ + case 0: /* NBCD */ + a = amode(op >> 3, op, 0); + v = rmode(a, 0); + wmode(a, 0, subbcd(0, v)); + if(a < 0) + tim += 8; + else + tim += 6; + break; + case 1: + if((op >> 3 & 7) != 0){ + push32(amode(op >> 3, op, 0)); /* PEA */ + tim += 8; + }else{ + nz(r[n] = r[n] >> 16 | r[n] << 16, 2); /* SWAP */ + tim += 4; + } + break; + case 2: /* EXT */ + nz(r[n] = r[n] & 0xffff0000 | (u16int)(s8int)r[n], 1); + tim += 4; + break; + case 3: /* EXT */ + nz(r[n] = (s16int)r[n], 2); + tim += 4; + break; + } + break; + case 10: + if(s == 3){ /* TAS */ + a = amode(op >> 3, op, 0); + v = rmode(a, 0); + nz(v, 0); + wmode(a, s, v | 0x80); + tim += a < 0 ? 4 : 14; + break; + } /* TST */ + a = amode(op >> 3, op, s); + nz(rmode(a, s), s); + tim += 4; + break; + case 14: + v = op >> 4 & 0xf; + n = op & 7; + if(v == 4){ /* TRAP */ + trap(0x20 | op & 0xf, pc); + break; + }else if(v == 5){ + if((op & 8) == 0){ /* LINK */ + push32(ra[n]); + ra[n] = ra[7]; + ra[7] += (s16int)fetch16(); + tim += 16; + }else{ /* UNLK */ + ra[7] = ra[n]; + ra[n] = pop32(); + tim += 12; + } + break; + }else if(v == 6){ /* MOVE USP */ + if((rS & FLAGS) != 0){ + if((op & 8) != 0) + ra[n] = asp; + else + asp = ra[n]; + tim += 4; + }else + trap(8, curpc); + break; + } + if((op & 0xc0) == 0xc0){ /* JMP */ + pc = amode(op >> 3, op, 2); + tim += 4; + break; + } + if((op & 0xc0) == 0x80){ /* JSR */ + a = amode(op >> 3, op, 2); + push32(pc); + pc = a; + tim += 12; + break; + } + switch(op){ + case 0x4e70: tim += 132; break; /* RESET */ + case 0x4e71: tim += 4; break; /* NOP */ + case 0x4e72: /* STOP */ + if((rS & FLAGS) != 0){ + rS = fetch16(); + stop = 1; + }else + trap(8, curpc); + tim += 4; + break; + case 0x4e73: /* RTE */ + if((rS & FLAGS) != 0){ + v = rS; + rS = pop16(); + pc = pop32(); + if(((v ^ rS) & FLAGS) != 0){ + v = asp; + asp = ra[7]; + ra[7] = v; + } + tim += 20; + }else + trap(8, curpc); + break; + case 0x4e75: pc = pop32(); tim += 16; break; /* RTS */ + case 0x4e76: if((rS & FLAGV) != 0) trap(7, curpc); tim += 4; break; /* TRAPV */ + case 0x4e77: /* RTR */ + rS = rS & 0xff00 | pop16() & 0xff; + pc = pop32(); + tim += 20; + break; + default: undef(); + } + break; + default: + undef(); + } + break; + case 5: + if((op & 0xf8) == 0xc8){ /* DBcc */ + n = op & 7; + v = (s16int)fetch16(); + if(!cond((op >> 8) & 0xf)){ + if((u16int)r[n] != 0){ + r[n]--; + pc = pc + v - 2; + tim += 10; + }else{ + r[n] |= 0xffff; + tim += 14; + } + }else + tim += 12; + break; + } + if(s == 3){ /* Scc */ + a = amode(op >> 3, op, 0); + v = cond(op >> 8 & 0xf); + wmode(a, 0, -v); + if(a < 0) + tim += 4 + 2 * v; + else + tim += 8; + break; + } /* ADDQ, SUBQ */ + rS |= FLAGZ; + if((op & 0x38) == 0x08) + s = 2; + a = amode(op >> 3, op, s); + v = rmode(a, s); + if(n == 0) + n = 8; + if((op & 0x100) == 0) + v = add(v, n, 0, s); + else + v = sub(v, n, 0, s); + rS = rS & ~FLAGX | rS << 4 & FLAGX; + if(a < 0) + tim += s == 2 || (op & 0x130) == 0x110 ? 8 : 4; + else + tim += s == 2 ? 12 : 8; + wmode(a, s, v); + break; + case 6: /* BRA */ + v = (s8int)op; + if(v == 0) + v = (s16int)fetch16(); + else if(v == (u32int)-1) + v = fetch32(); + if((op & 0xf00) == 0x100){ /* BSR */ + push32(pc); + pc = curpc + 2 + v; + tim += 18; + break; + } + if(cond((op >> 8) & 0xf)){ + pc = curpc + 2 + v; + tim += 10; + }else + tim += (u8int)(op + 1) <= 1 ? 12 : 8; + break; + case 7: /* MOVEQ */ + r[n] = (s8int)op; + nz(r[n], 0); + tim += 4; + break; + case 8: + if(s == 3){ /* DIVU, DIVS */ + a = amode(op >> 3, op, 1); + v = rmode(a, 1); + if(v == 0){ + trap(5, curpc); + break; + } + if((op & 0x100) != 0){ + w = (s32int)r[n] % (s16int)v; + v = (s32int)r[n] / (s16int)v; + if(((s16int)w ^ (s16int)v) < 0) + w = -w; + if(v != (u32int)(s16int)v){ + rS = rS & ~FLAGC | FLAGV; + break; + } + tim += 158; + }else{ + w = r[n] % (u16int)v; + v = r[n] / (u16int)v; + if(v >= 0x10000){ + rS = rS & ~FLAGC | FLAGV; + break; + } + tim += 140; + } + r[n] = (u16int)v | w << 16; + nz(v, 1); + break; + } + if((op & 0x1f0) == 0x100){ /* SBCD */ + n = (op >> 9) & 7; + m = op & 7; + if((op & 8) != 0){ + a = amode(4, n, 0); + v = rmode(a, 0); + w = rmode(amode(4, m, 0), 0); + v = subbcd(v, w); + wmode(a, 0, v); + tim += 18; + }else{ + r[n] = r[n] & 0xffffff00 | subbcd((u8int)r[n], (u8int)r[m]); + tim += 6; + } + break; + } + logic: /* OR, EOR, AND */ + a = amode(op >> 3, op, s); + n = (op >> 9) & 7; + v = rmode(a, s); + switch(op >> 12){ + case 8: v |= r[n]; break; + case 11: v ^= r[n]; break; + case 12: v &= r[n]; break; + } + if((op & 0x100) == 0) + a = ~n; + wmode(a, s, v); + nz(v, s); + dtime(op, s); + break; + case 11: + if(s == 3){ /* CMPA */ + s = (op >> 8 & 1) + 1; + a = amode(op >> 3, op, s); + rS |= FLAGZ; + sub(ra[n], rmode(a, s), 0, 2); + tim += 6; + break; + } + if((op & 0x138) == 0x108){ /* CMPM */ + m = op & 7; + rS |= FLAGZ; + sub(rmode(amode(3, n, s), s), rmode(amode(3, m, s), s), 0, s); + tim += s == 2 ? 20 : 12; + break; + } + if((op & 0x100) == 0){ /* CMP */ + a = amode(op >> 3, op, s); + rS |= FLAGZ; + sub(r[n], rmode(a, s), 0, s); + tim += s == 2 ? 6 : 4; + break; + } + goto logic; + case 12: + if(s == 3){ /* MULU, MULS */ + a = amode(op >> 3, op, 1); + v = rmode(a, 1); + if((op & 0x100) != 0) + v *= (s16int)r[n]; + else + v = (u16int)v * (u16int)r[n]; + r[n] = v; + nz(v, 1); + tim += 70; + break; + } + if((op & 0x1f0) == 0x100){ /* ABCD */ + n = (op >> 9) & 7; + m = op & 7; + if((op & 8) != 0){ + a = amode(4, n, 0); + v = rmode(a, 0); + w = rmode(amode(4, m, 0), 0); + v = addbcd(v, w); + wmode(a, 0, v); + tim += 18; + }else{ + r[n] = r[n] & 0xffffff00 | addbcd((u8int)r[n], (u8int)r[m]); + tim += 6; + } + break; + + } + if((op & 0x130) == 0x100){ /* EXG */ + m = op & 0xf; + if((op & 0xc8) == 0x48) + n |= 8; + v = r[n]; + r[n] = r[m]; + r[m] = v; + tim += 6; + break; + } + goto logic; + case 9: + case 13: + if(s == 3){ /* ADDA, SUBA */ + if((op & 0x100) != 0){ + s = 2; + tim += 6; + }else{ + s = 1; + tim += 8; + } + a = amode(op >> 3, op, s); + if((op >> 12) == 13) + ra[n] += rmode(a, s); + else + ra[n] -= rmode(a, s); + break; + } + if((op & 0x130) == 0x100){ /* ADDX, SUBX */ + m = op & 7; + if((op & 8) != 0){ + a = ra[n] -= 1<> 12) == 13) + v = add(v, w, (rS & FLAGX) != 0, s); + else + v = sub(v, w, (rS & FLAGX) != 0, s); + wmode(a, s, v); + rS = rS & ~FLAGX | rS << 4 & FLAGX; + break; + } /* ADD, SUB */ + a = amode(op >> 3, op, s); + rS |= FLAGZ; + d = (op & 0x100) == 0; + v = rmode(a, s); + if((op >> 12) == 13) + v = add(v, r[n], 0, s); + else + v = sub(d ? r[n] : v, d ? v : r[n], 0, s); + rS = rS & ~FLAGX | rS << 4 & FLAGX; + if(d) + a = ~n; + wmode(a, s, v); + dtime(op, s); + break; + case 14: /* shifts */ + if(s == 3){ + m = op >> 8 & 7; + n = 1; + s = 1; + a = amode(op >> 3, op, s); + }else{ + a = ~(uvlong)(op & 7); + m = op >> 2 & 6 | op >> 8 & 1; + n = (op >> 9) & 7; + if((op & 0x20) != 0) + n = r[n] & 63; + else if(n == 0) + n = 8; + } + wmode(a, s, rot(rmode(a, s), m, n, s)); + break; + case 10: + trap(10, curpc); + break; + case 15: + trap(11, curpc); + break; + default: + undef(); + } + return tim; +} diff --git a/sys/src/games/blit/dat.h b/sys/src/games/blit/dat.h new file mode 100644 index 000000000..f96cee674 --- /dev/null +++ b/sys/src/games/blit/dat.h @@ -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, +}; diff --git a/sys/src/games/blit/diagbits b/sys/src/games/blit/diagbits new file mode 100644 index 000000000..9f1302e52 Binary files /dev/null and b/sys/src/games/blit/diagbits differ diff --git a/sys/src/games/blit/fns.h b/sys/src/games/blit/fns.h new file mode 100644 index 000000000..516527215 --- /dev/null +++ b/sys/src/games/blit/fns.h @@ -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 *); diff --git a/sys/src/games/blit/mem.c b/sys/src/games/blit/mem.c new file mode 100644 index 000000000..08a3a4d41 --- /dev/null +++ b/sys/src/games/blit/mem.c @@ -0,0 +1,180 @@ +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/sys/src/games/blit/mkfile b/sys/src/games/blit/mkfile new file mode 100644 index 000000000..77aab9aa3 --- /dev/null +++ b/sys/src/games/blit/mkfile @@ -0,0 +1,12 @@ + +#include +#include +#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); +} diff --git a/sys/src/games/mkfile b/sys/src/games/mkfile index 039d5cd36..636ea3726 100644 --- a/sys/src/games/mkfile +++ b/sys/src/games/mkfile @@ -3,6 +3,7 @@ TARG=4s\ 5s\ ana\ + blit\ catclock\ festoon\ geigerstats\ -- cgit v1.2.3