mirror of
https://github.com/aap/pdp6.git
synced 2026-03-23 01:16:30 +00:00
lua interface for new pdp6 emulator
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
INC=
|
||||
LIBS=-lpthread -lm -lSDL2
|
||||
INC=`pkg-config lua --cflags`
|
||||
LIBS=-lpthread -lm -lSDL2 `pkg-config lua --libs`
|
||||
#CFLAGS=-Wall -Wextra -g -O3
|
||||
#CFLAGS=-g -O3 -mcpu=cortex-a53 -mtune=cortex-a53
|
||||
CFLAGS=-g -Wall -Wno-parentheses
|
||||
|
||||
pdp6: main.c panel6.c pdp6.c netmem.c tty.c pt.c dis340.c dc.c ut.c ge.c audio.c common.c
|
||||
pdp6: main.c panel6.c pdp6.c netmem.c tty.c pt.c dis340.c dc.c ut.c ge.c audio.c ttytelnet.c common.c lua.c
|
||||
cc $(CFLAGS) -o $@ $^ $(INC) $(LIBS)
|
||||
|
||||
run: pdp6
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
#include <poll.h>
|
||||
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -58,6 +60,35 @@ readn(int fd, void *data, int n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
socketlisten(int port)
|
||||
{
|
||||
int x;
|
||||
struct sockaddr_in server;
|
||||
int fd;
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(fd < 0) {
|
||||
perror("error: socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
x = 1;
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&x, sizeof x);
|
||||
|
||||
memset(&server, 0, sizeof(server));
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = INADDR_ANY;
|
||||
server.sin_port = htons(port);
|
||||
if(bind(fd, (struct sockaddr*)&server, sizeof(server)) < 0) {
|
||||
close(fd);
|
||||
perror("error: bind");
|
||||
return -1;
|
||||
}
|
||||
listen(fd, 1);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int
|
||||
dial(const char *host, int port)
|
||||
{
|
||||
@@ -97,27 +128,12 @@ serve1(int port)
|
||||
{
|
||||
int sockfd, confd;
|
||||
socklen_t len;
|
||||
struct sockaddr_in server, client;
|
||||
int x;
|
||||
struct sockaddr_in client;
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sockfd < 0){
|
||||
perror("error: socket");
|
||||
sockfd = socketlisten(port);
|
||||
if(sockfd < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
x = 1;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&x, sizeof x);
|
||||
|
||||
memset(&server, 0, sizeof(server));
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = INADDR_ANY;
|
||||
server.sin_port = htons(port);
|
||||
if(bind(sockfd, (struct sockaddr*)&server, sizeof(server)) < 0){
|
||||
perror("error: bind");
|
||||
return -1;
|
||||
}
|
||||
listen(sockfd, 5);
|
||||
len = sizeof(client);
|
||||
confd = accept(sockfd, (struct sockaddr*)&client, &len);
|
||||
close(sockfd);
|
||||
@@ -126,6 +142,50 @@ serve1(int port)
|
||||
perror("error: accept");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// listen on multiple ports
|
||||
void
|
||||
serveN(struct PortHandler *ports, int nports, void *arg)
|
||||
{
|
||||
int i;
|
||||
int confd;
|
||||
struct pollfd pfds[100];
|
||||
struct sockaddr_in client;
|
||||
socklen_t len;
|
||||
|
||||
// create and listen on sockets for the given ports
|
||||
for(i = 0; i < nports; i++) {
|
||||
pfds[i].revents = 0;
|
||||
pfds[i].events = 0;
|
||||
pfds[i].fd = socketlisten(ports[i].port);
|
||||
if(pfds[i].fd >= 0)
|
||||
pfds[i].events = POLLIN;
|
||||
}
|
||||
|
||||
// now poll to accept connections and hand off to handle function
|
||||
for(;;) {
|
||||
int ret = poll(pfds, nports, -1);
|
||||
if(ret < 0)
|
||||
break;
|
||||
if(ret == 0)
|
||||
continue;
|
||||
|
||||
for(i = 0; i < nports; i++) {
|
||||
if(pfds[i].revents & POLLIN) {
|
||||
len = sizeof(client);
|
||||
confd = accept(pfds[i].fd, (struct sockaddr*)&client, &len);
|
||||
if(confd >= 0)
|
||||
ports[i].handle(confd, arg);
|
||||
} else if(pfds[i].revents) {
|
||||
printf("weird stuff on port %d\n", ports[i].port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < nports; i++)
|
||||
close(pfds[i].fd);
|
||||
}
|
||||
|
||||
void
|
||||
nodelay(int fd)
|
||||
{
|
||||
@@ -255,8 +315,6 @@ split(char *line, int *pargc)
|
||||
}
|
||||
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
struct FDmsg
|
||||
{
|
||||
int msg;
|
||||
|
||||
@@ -22,6 +22,12 @@ int hasinput(int fd);
|
||||
int readn(int fd, void *data, int n);
|
||||
int dial(const char *host, int port);
|
||||
int serve1(int port);
|
||||
struct PortHandler {
|
||||
int port;
|
||||
void (*handle)(int fd, void *arg);
|
||||
};
|
||||
void serveN(struct PortHandler *ports, int nports, void *arg);
|
||||
|
||||
void nodelay(int fd);
|
||||
|
||||
void *createseg(const char *name, size_t sz);
|
||||
|
||||
@@ -63,6 +63,7 @@ struct Dis340
|
||||
int pnt;
|
||||
u32 cmdbuf[128];
|
||||
u32 ncmds;
|
||||
u32 agetime;
|
||||
};
|
||||
|
||||
#define LDB(p, s, w) ((w)>>(p) & (1<<(s))-1)
|
||||
@@ -71,54 +72,67 @@ static void calc_dis_req(PDP6 *pdp, Dis340 *dis);
|
||||
|
||||
|
||||
static void
|
||||
addcmd(Dis340 *dis, u32 cmd)
|
||||
flushdis(Dis340 *d)
|
||||
{
|
||||
dis->cmdbuf[dis->ncmds++] = cmd;
|
||||
if(dis->ncmds == nelem(dis->cmdbuf)) {
|
||||
int n = write(dis->fd.fd, dis->cmdbuf, sizeof(dis->cmdbuf));
|
||||
dis->ncmds = 0;
|
||||
if(n < (int)sizeof(dis->cmdbuf)) {
|
||||
// TODO: close fd
|
||||
dis->fd.fd = -1;
|
||||
}
|
||||
}
|
||||
int sz = d->ncmds*sizeof(d->cmdbuf[0]);
|
||||
int n = write(d->fd.fd, d->cmdbuf, sz);
|
||||
d->ncmds = 0;
|
||||
if(n < sz)
|
||||
closefd(&d->fd);
|
||||
}
|
||||
|
||||
static void
|
||||
agedisplay(Dis340 *dis)
|
||||
discmd(Dis340 *d, u32 cmd)
|
||||
{
|
||||
if(dis->fd.fd < 0)
|
||||
d->cmdbuf[d->ncmds++] = cmd;
|
||||
if(d->ncmds == nelem(d->cmdbuf))
|
||||
flushdis(d);
|
||||
}
|
||||
|
||||
static void
|
||||
agedisplay(Dis340 *d)
|
||||
{
|
||||
if(d->fd.fd < 0)
|
||||
return;
|
||||
u32 cmd = 510<<23;
|
||||
assert(dis->lasttime <= dis->simtime);
|
||||
u64 dt = (dis->simtime - dis->lasttime)/1000;
|
||||
while(dt >= 510) {
|
||||
dis->lasttime += 510*1000;
|
||||
addcmd(dis, cmd);
|
||||
dt = (dis->simtime - dis->lasttime)/1000;
|
||||
int ival = d->agetime;
|
||||
assert(d->lasttime <= d->simtime);
|
||||
u64 dt = (d->simtime - d->lasttime)/1000;
|
||||
if(dt >= ival) {
|
||||
discmd(d, 511<<23);
|
||||
discmd(d, dt);
|
||||
d->lasttime = d->simtime;
|
||||
flushdis(d);
|
||||
if(d->agetime < 1000*1000)
|
||||
d->agetime += d->agetime/10;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
intensify(Dis340 *dis)
|
||||
{
|
||||
// need to make sure dt field doesn't overflow cmd
|
||||
dis->agetime = 510;
|
||||
agedisplay(dis);
|
||||
// reset age interval for every point shown
|
||||
dis->agetime = 50*1000;
|
||||
if(dis->fd.fd < 0)
|
||||
return;
|
||||
|
||||
if(dis->pen && dis->lp_enable) {
|
||||
int dx = dis->penx - dis->x;
|
||||
int dy = dis->peny - dis->y;
|
||||
if(dx*dx + dy*dy <= 4)
|
||||
dis->lp_find = 1;
|
||||
}
|
||||
if(dis->fd.fd >= 0){
|
||||
agedisplay(dis);
|
||||
u32 cmd;
|
||||
cmd = dis->x;
|
||||
cmd |= dis->y<<10;
|
||||
cmd |= dis->i<<20;
|
||||
int dt = (dis->simtime - dis->lasttime)/1000;
|
||||
cmd |= dt<<23;
|
||||
dis->lasttime = dis->simtime;
|
||||
addcmd(dis, cmd);
|
||||
}
|
||||
|
||||
int dt = (dis->simtime - dis->lasttime)/1000;
|
||||
u32 cmd;
|
||||
cmd = dis->x;
|
||||
cmd |= dis->y<<10;
|
||||
cmd |= dis->i<<20;
|
||||
cmd |= dt<<23;
|
||||
dis->lasttime = dis->simtime;
|
||||
discmd(dis, cmd);
|
||||
}
|
||||
|
||||
enum {
|
||||
@@ -646,6 +660,12 @@ dis_connect(Dis340 *dis, int fd)
|
||||
{
|
||||
if(dis->fd.fd >= 0)
|
||||
closefd(&dis->fd);
|
||||
dis->fd.fd = fd;
|
||||
waitfd(&dis->fd);
|
||||
else {
|
||||
nodelay(fd);
|
||||
dis->fd.fd = fd;
|
||||
dis->fd.id = -1;
|
||||
waitfd(&dis->fd);
|
||||
dis->lasttime = dis->simtime;
|
||||
dis->agetime = 50*1000;
|
||||
}
|
||||
}
|
||||
|
||||
44
newemu/init.lua
Normal file
44
newemu/init.lua
Normal file
@@ -0,0 +1,44 @@
|
||||
function o(n)
|
||||
return tonumber(tostring(n), 8)
|
||||
end
|
||||
function fw(w)
|
||||
local l = (w >> 18) & o(777777)
|
||||
local r = w & o(777777)
|
||||
return oct(l,6) .. ",," .. oct(r,6)
|
||||
end
|
||||
|
||||
--uxmount(1, "t/system.dtr");
|
||||
uxmount(1, "t/systemdis.dtr");
|
||||
uxmount(2, "t/its138.dtr");
|
||||
uxmount(3, "t/music.dtr");
|
||||
|
||||
|
||||
-- MACDMP RIM loader
|
||||
d(o(00), o(255000000000), 0)
|
||||
d(o(01), o(205000255000), 0)
|
||||
d(o(02), o(700200635550), 0)
|
||||
d(o(03), o(700600011577), 0)
|
||||
d(o(04), o(721200223110), 0)
|
||||
d(o(05), o(720200004010), 0)
|
||||
d(o(06), o(720340001000), 0)
|
||||
d(o(07), o(254000000006), 0)
|
||||
d(o(10), o(720040000013), 0)
|
||||
d(o(11), o(345540000006), 0)
|
||||
d(o(12), o(602540777777), 0)
|
||||
d(o(13), o(000000000013), 0)
|
||||
d(o(14), o(254000000006), 0)
|
||||
|
||||
-- PTR RIM loader
|
||||
d(o(20), o(710600000060))
|
||||
d(o(21), o(710740000010))
|
||||
d(o(22), o(254000000021))
|
||||
d(o(23), o(710440000026))
|
||||
d(o(24), o(710740000010))
|
||||
d(o(25), o(254000000024))
|
||||
d(o(27), o(254000000021))
|
||||
|
||||
--setpc(readmemory("t/ddt.16k.oct"))
|
||||
|
||||
ptrmount("t/hello.rim")
|
||||
ptpmount("out.ptp")
|
||||
ttycon()
|
||||
268
newemu/lua.c
Normal file
268
newemu/lua.c
Normal file
@@ -0,0 +1,268 @@
|
||||
#include "common.h"
|
||||
#include "pdp6.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
lua_State *L;
|
||||
|
||||
// initdevs(pdp);
|
||||
// attach_ptp(pdp);
|
||||
// attach_ptr(pdp);
|
||||
// attach_tty(pdp);
|
||||
// dis = attach_dis(pdp);
|
||||
// Dc136 *dc = attach_dc(pdp);
|
||||
// Ut551 *ut = attach_ut(pdp, dc);
|
||||
// ux1 = attach_ux(ut, 1);
|
||||
// ux2 = attach_ux(ut, 2);
|
||||
// ux3 = attach_ux(ut, 3);
|
||||
// ux4 = attach_ux(ut, 4);
|
||||
// // stub for ITS
|
||||
// attach_ge(pdp);
|
||||
|
||||
|
||||
// this is not ideal...
|
||||
extern Word memory[01000000];
|
||||
extern Word fmem[020];
|
||||
extern Dis340 *dis;
|
||||
extern Ux555 *ux1;
|
||||
extern Ux555 *ux2;
|
||||
extern Ux555 *ux3;
|
||||
extern Ux555 *ux4;
|
||||
|
||||
static PDP6 *pdp;
|
||||
|
||||
// things we would like to be able to do:
|
||||
|
||||
// pdp->netmem_fd.fd = dial("maya", 20006);
|
||||
// if(pdp->netmem_fd.fd >= 0)
|
||||
// printf("netmem connected\n");
|
||||
// waitfd(&pdp->netmem_fd);
|
||||
|
||||
|
||||
// fix the language a bit
|
||||
static int
|
||||
L_oct(lua_State *L)
|
||||
{
|
||||
lua_Integer n = luaL_checkinteger(L, 1);
|
||||
int pad = luaL_optinteger(L, 2, -1);
|
||||
char buf[100];
|
||||
if(pad < 0)
|
||||
snprintf(buf, sizeof(buf), "%0llo", (unsigned long long)n);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%0*llo", pad, (unsigned long long)n);
|
||||
lua_pushstring(L, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
L_examine(lua_State *L)
|
||||
{
|
||||
lua_Integer addr = luaL_checkinteger(L, 1);
|
||||
int fast = luaL_optinteger(L, 2, 1);
|
||||
if(addr >= 0) {
|
||||
if(addr < 020 && fast)
|
||||
lua_pushinteger(L, fmem[addr]);
|
||||
else if(addr < 01000000)
|
||||
lua_pushinteger(L, memory[addr]);
|
||||
else
|
||||
lua_pushinteger(L, 0);
|
||||
} else
|
||||
lua_pushinteger(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
L_deposit(lua_State *L)
|
||||
{
|
||||
lua_Integer addr = luaL_checkinteger(L, 1);
|
||||
lua_Integer word = luaL_checkinteger(L, 2);
|
||||
int fast = luaL_optinteger(L, 3, 1);
|
||||
if(addr >= 0) {
|
||||
if(addr < 020 && fast)
|
||||
fmem[addr] = word;
|
||||
else if(addr < 01000000)
|
||||
memory[addr] = word;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Hword readmemory(const char *path);
|
||||
|
||||
static int
|
||||
L_readmemory(lua_State *L)
|
||||
{
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
int start = readmemory(path);
|
||||
lua_pushinteger(L, start);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
L_setpc(lua_State *L)
|
||||
{
|
||||
int pc = luaL_checkinteger(L, 1);
|
||||
pdp->pc = pc & 0777777;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
L_ttycon(lua_State *L)
|
||||
{
|
||||
const char *path = luaL_optstring(L, 1, "/tmp/tty");
|
||||
if(pdp->tty_fd.fd >= 0)
|
||||
closefd(&pdp->tty_fd);
|
||||
if((pdp->tty_fd.fd = open(path, O_RDWR)) < 0)
|
||||
printf("couldn't open %s\n", path);
|
||||
waitfd(&pdp->tty_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
L_ptrmount(lua_State *L)
|
||||
{
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
int fd = open(path, O_RDONLY);
|
||||
if(fd < 0)
|
||||
printf("couldn't open %s\n", path);
|
||||
else
|
||||
ptrmount(pdp, fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
L_ptrunmount(lua_State *L)
|
||||
{
|
||||
ptrunmount(pdp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
L_ptpmount(lua_State *L)
|
||||
{
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
int fd = open(path, O_CREAT|O_WRONLY|O_TRUNC, 0644);
|
||||
if(fd < 0)
|
||||
printf("couldn't open %s\n", path);
|
||||
else
|
||||
ptpmount(pdp, fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
L_ptpunmount(lua_State *L)
|
||||
{
|
||||
ptpunmount(pdp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
L_uxmount(lua_State *L)
|
||||
{
|
||||
int unit = luaL_checkinteger(L, 1);
|
||||
const char *path = luaL_checkstring(L, 2);
|
||||
|
||||
Ux555 *ux[] = { ux1, ux2, ux3, ux4 };
|
||||
if(0 < unit && unit <= 4)
|
||||
uxmount(ux[unit-1], path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
L_uxunmount(lua_State *L)
|
||||
{
|
||||
int unit = luaL_checkinteger(L, 1);
|
||||
|
||||
Ux555 *ux[] = { ux1, ux2, ux3, ux4 };
|
||||
if(0 < unit && unit <= 4)
|
||||
uxunmount(ux[unit-1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
L_discon(lua_State *L)
|
||||
{
|
||||
const char *host = luaL_optstring(L, 1, "localhost");
|
||||
int port = luaL_optinteger(L, 2, 3400);
|
||||
int dis_fd = dial(host, port);
|
||||
if(dis_fd < 0)
|
||||
printf("can't open display\n");
|
||||
dis_connect(dis, dis_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
doline(char *line)
|
||||
{
|
||||
char *retline = nil;
|
||||
asprintf(&retline, "return %s", line);
|
||||
|
||||
int status = luaL_loadstring(L, retline);
|
||||
free(retline);
|
||||
|
||||
if(status != LUA_OK) {
|
||||
lua_pop(L, 1);
|
||||
status = luaL_loadstring(L, line);
|
||||
}
|
||||
if(status != LUA_OK) {
|
||||
fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
|
||||
return;
|
||||
}
|
||||
status = lua_pcall(L, 0, LUA_MULTRET, 0);
|
||||
|
||||
const char *s;
|
||||
int n = lua_gettop(L);
|
||||
for(int i = 1; i <= n; i++) {
|
||||
if(lua_type(L, i) == LUA_TNUMBER) {
|
||||
lua_getglobal(L, "pnum");
|
||||
lua_pushvalue(L, i);
|
||||
lua_pcall(L, 1, 1, 0);
|
||||
s = lua_tostring(L, -1);
|
||||
printf("%s%s", i > 1 ? "\t" : "", s);
|
||||
lua_pop(L, 1);
|
||||
} else {
|
||||
s = luaL_tolstring(L, i, nil);
|
||||
printf("%s%s", i > 1 ? "\t" : "", s);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
if (n > 0) {
|
||||
lua_pushvalue(L, n);
|
||||
lua_setglobal(L, "_");
|
||||
printf("\n");
|
||||
}
|
||||
lua_settop(L, 0);
|
||||
}
|
||||
|
||||
void
|
||||
initlua(PDP6 *apdp)
|
||||
{
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
|
||||
pdp = apdp;
|
||||
lua_register(L, "oct", L_oct);
|
||||
lua_register(L, "pnum", L_oct);
|
||||
lua_register(L, "e", L_examine);
|
||||
lua_register(L, "d", L_deposit);
|
||||
lua_register(L, "readmemory", L_readmemory);
|
||||
lua_register(L, "setpc", L_setpc);
|
||||
lua_register(L, "ttycon", L_ttycon);
|
||||
lua_register(L, "ptrmount", L_ptrmount);
|
||||
lua_register(L, "ptrunmount", L_ptrunmount);
|
||||
lua_register(L, "ptpmount", L_ptpmount);
|
||||
lua_register(L, "ptpunmount", L_ptpunmount);
|
||||
lua_register(L, "uxmount", L_uxmount);
|
||||
lua_register(L, "uxunmount", L_uxunmount);
|
||||
lua_register(L, "discon", L_discon);
|
||||
|
||||
if(luaL_dofile(L, "init.lua") != LUA_OK) {
|
||||
fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
191
newemu/main.c
191
newemu/main.c
@@ -5,6 +5,9 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
@@ -46,7 +49,7 @@ readmemory(const char *path)
|
||||
FILE *f;
|
||||
|
||||
f = fopen(path, "r");
|
||||
if(f == NULL) {
|
||||
if(f == nil) {
|
||||
printf("couldn't open file %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
@@ -68,7 +71,54 @@ readmemory(const char *path)
|
||||
return pc;
|
||||
}
|
||||
|
||||
const bool throttle = 1;
|
||||
void
|
||||
readmem(const char *file, Word *mem, Hword size)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[100], *s;
|
||||
Hword a;
|
||||
Word w;
|
||||
if(f = fopen(file, "r"), f == nil)
|
||||
return;
|
||||
a = 0;
|
||||
while(s = fgets(buf, 100, f)){
|
||||
while(*s){
|
||||
if(*s == ';')
|
||||
break;
|
||||
else if('0' <= *s && *s <= '7'){
|
||||
w = strtoull(s, &s, 8);
|
||||
if(*s == ':' || *s == '/'){
|
||||
a = w;
|
||||
s++;
|
||||
}else if(a < size)
|
||||
mem[a++] = w;
|
||||
else
|
||||
fprintf(stderr, "Address out of range: %o\n", a++);
|
||||
}else
|
||||
s++;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void
|
||||
dumpmem(const char *file, Word *mem, Hword size)
|
||||
{
|
||||
FILE *f;
|
||||
Hword a;
|
||||
|
||||
if(f = fopen("coremem", "w"), f == nil)
|
||||
return;
|
||||
|
||||
for(a = 0; a < size; a++)
|
||||
if(mem[a] != 0){
|
||||
fprintf(f, "%06o/ ", a);
|
||||
fprintf(f, "%012llo\n", mem[a]);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
const bool dothrottle = 1;
|
||||
|
||||
// TODO: this sucks
|
||||
Dis340 *dis;
|
||||
@@ -80,8 +130,8 @@ Ux555 *ux4;
|
||||
void
|
||||
configmachine(PDP6 *pdp)
|
||||
{
|
||||
uxmount(ux1, "t/systemdis.dtr");
|
||||
// uxmount(ux1, "t/system.dtr");
|
||||
// uxmount(ux1, "t/systemdis.dtr");
|
||||
uxmount(ux1, "t/system.dtr");
|
||||
// uxmount(ux2, "t/syseng.dtr");
|
||||
uxmount(ux2, "t/its138.dtr");
|
||||
// uxmount(ux3, "t/foo.dtr");
|
||||
@@ -117,8 +167,8 @@ configmachine(PDP6 *pdp)
|
||||
// assumes reader motor will be off
|
||||
// memory[0101] |= I(0, 1, 0, 0, 0); // disable device tests in part3
|
||||
// part4: start with 1 in switches, flip back to 0 at some point
|
||||
// pdp->pc = readmemory("t/ddt.16k.oct");
|
||||
pdp->pc = readmemory("t/ddt.d16k.oct"); // needs moby
|
||||
pdp->pc = readmemory("t/ddt.16k.oct");
|
||||
// pdp->pc = readmemory("t/ddt.d16k.oct"); // needs moby
|
||||
// pdp->pc = readmemory("t/nts.lisp.u16k.oct");
|
||||
// pdp->pc = readmemory("t/nts.teco6.u256k.oct");
|
||||
// pdp->pc = readmemory("t/spcwar.oct");
|
||||
@@ -151,13 +201,44 @@ initemu(PDP6 *pdp)
|
||||
attach_ge(pdp);
|
||||
|
||||
|
||||
srand(time(NULL));
|
||||
srand(time(nil));
|
||||
pwrclr(pdp);
|
||||
cycle_io(pdp, 0);
|
||||
|
||||
if(domusic) initmusic();
|
||||
}
|
||||
|
||||
|
||||
void prompt(void) { printf("> "); fflush(stdout); }
|
||||
void
|
||||
cli(PDP6 *pdp, FD *fd)
|
||||
{
|
||||
char line[1024];
|
||||
int n;
|
||||
|
||||
n = read(fd->fd, line, sizeof(line));
|
||||
if(n <= 0) {
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
if(n > 0 && n < sizeof(line)) {
|
||||
line[n] = '\0';
|
||||
void doline(char *line);
|
||||
doline(line);
|
||||
prompt();
|
||||
waitfd(fd);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
throttle(void)
|
||||
{
|
||||
while(realtime < simtime) {
|
||||
usleep(1000);
|
||||
realtime = gettime();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
emu(PDP6 *pdp, Panel *panel)
|
||||
{
|
||||
@@ -167,6 +248,12 @@ emu(PDP6 *pdp, Panel *panel)
|
||||
|
||||
updateswitches(pdp, panel);
|
||||
|
||||
FD clifd;
|
||||
clifd.id = -1;
|
||||
clifd.fd = 0;
|
||||
prompt();
|
||||
waitfd(&clifd);
|
||||
|
||||
inittime();
|
||||
simtime = 0; //gettime();
|
||||
pdp->clk_timer = 0;
|
||||
@@ -203,7 +290,8 @@ stopmusic();
|
||||
cycle_io(pdp, 1);
|
||||
handlenetmem(pdp);
|
||||
|
||||
if(throttle) while(realtime < simtime) realtime = gettime();
|
||||
if(dothrottle) throttle();
|
||||
while(realtime < simtime) realtime = gettime();
|
||||
} else {
|
||||
stopmusic();
|
||||
if(power)
|
||||
@@ -211,17 +299,57 @@ stopmusic();
|
||||
|
||||
lightsoff(panel);
|
||||
|
||||
if(throttle)
|
||||
if(dothrottle)
|
||||
simtime = gettime();
|
||||
else
|
||||
simtime += 1500;
|
||||
cycle_io(pdp, 0);
|
||||
}
|
||||
|
||||
// cli(pdp);
|
||||
if(clifd.ready)
|
||||
cli(pdp, &clifd);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handledis(int fd, void *arg)
|
||||
{
|
||||
// PDP6 *pdp = (PDP6*)arg;
|
||||
nodelay(fd);
|
||||
dis_connect(dis, fd);
|
||||
}
|
||||
|
||||
void
|
||||
handleptr(int fd, void *arg)
|
||||
{
|
||||
PDP6 *pdp = (PDP6*)arg;
|
||||
nodelay(fd);
|
||||
ptrmount(pdp, fd);
|
||||
}
|
||||
|
||||
void
|
||||
handleptp(int fd, void *arg)
|
||||
{
|
||||
PDP6 *pdp = (PDP6*)arg;
|
||||
nodelay(fd);
|
||||
ptpmount(pdp, fd);
|
||||
}
|
||||
|
||||
void*
|
||||
netthread(void *arg)
|
||||
{
|
||||
struct PortHandler ports[] = {
|
||||
// { 1640, handlenetcmd },
|
||||
// // 1041 is teletype
|
||||
{ 1642, handleptr },
|
||||
{ 1643, handleptp },
|
||||
{ 3400, handledis },
|
||||
};
|
||||
serveN(ports, nelem(ports), arg);
|
||||
return nil;
|
||||
}
|
||||
|
||||
/*
|
||||
char *argv0;
|
||||
void
|
||||
usage(void)
|
||||
@@ -229,6 +357,15 @@ usage(void)
|
||||
fprintf(stderr, "usage: %s [-h host] [-p port]\n", argv0);
|
||||
exit(1);
|
||||
}
|
||||
*/
|
||||
|
||||
static void
|
||||
cleanup(void *arg)
|
||||
{
|
||||
Panel *panel = (Panel*)arg;
|
||||
lightsoff(panel);
|
||||
dumpmem("coremem", memory, 01000000);
|
||||
}
|
||||
|
||||
void
|
||||
inthandler(int sig)
|
||||
@@ -239,9 +376,11 @@ inthandler(int sig)
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t th;
|
||||
Panel *panel;
|
||||
PDP6 pdp6, *pdp = &pdp6;
|
||||
|
||||
/*
|
||||
const char *host;
|
||||
int port;
|
||||
|
||||
@@ -257,6 +396,7 @@ main(int argc, char *argv[])
|
||||
default:
|
||||
usage();
|
||||
} ARGEND;
|
||||
*/
|
||||
|
||||
panel = getpanel();
|
||||
if(panel == nil) {
|
||||
@@ -268,36 +408,61 @@ main(int argc, char *argv[])
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGINT, inthandler);
|
||||
|
||||
addcleanup((void (*)(void*))lightsoff, panel);
|
||||
addcleanup(cleanup, panel);
|
||||
|
||||
initemu(pdp);
|
||||
configmachine(pdp);
|
||||
readmem("coremem", memory, 01000000);
|
||||
|
||||
startpolling();
|
||||
|
||||
// now in lua
|
||||
// configmachine(pdp);
|
||||
|
||||
/*
|
||||
int dis_fd = dial(host, port);
|
||||
if(dis_fd < 0)
|
||||
printf("can't open display\n");
|
||||
nodelay(dis_fd);
|
||||
dis_connect(dis, dis_fd);
|
||||
*/
|
||||
|
||||
/*
|
||||
const char *tape = "t/hello.rim";
|
||||
// const char *tape = "t/ptp_test.rim";
|
||||
// const char *tape = "t/bla.txt";
|
||||
pdp->ptr_fd.fd = open(tape, O_RDONLY);
|
||||
waitfd(&pdp->ptr_fd);
|
||||
pdp->ptp_fd = open("out.ptp", O_CREAT|O_WRONLY|O_TRUNC, 0644);
|
||||
|
||||
pdp->ptp_fd = open("out.ptp", O_CREAT|O_WRONLY|O_TRUNC, 0644);
|
||||
*/
|
||||
|
||||
/*
|
||||
pdp->tty_fd.fd = open("/tmp/tty", O_RDWR);
|
||||
if(pdp->tty_fd.fd < 0)
|
||||
printf("can't open /tmp/tty\n");
|
||||
waitfd(&pdp->tty_fd);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// pdp->netmem_fd.fd = dial("maya", 10006);
|
||||
/*
|
||||
pdp->netmem_fd.fd = dial("maya", 20006);
|
||||
if(pdp->netmem_fd.fd >= 0)
|
||||
printf("netmem connected\n");
|
||||
waitfd(&pdp->netmem_fd);
|
||||
*/
|
||||
|
||||
void initlua(PDP6 *pdp);
|
||||
initlua(pdp);
|
||||
|
||||
pthread_create(&th, nil, netthread, pdp);
|
||||
int fd[2];
|
||||
socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
|
||||
pdp->tty_fd.fd = fd[0];
|
||||
waitfd(&pdp->tty_fd);
|
||||
void ttytelnet(int port, int fd);
|
||||
ttytelnet(1641, fd[1]);
|
||||
|
||||
emu(pdp, panel);
|
||||
return 0; // can't happen
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
@@ -279,8 +279,12 @@ void cycle_io(PDP6 *pdp, int pwr);
|
||||
void setreq(PDP6 *pdp, IOdev *dev, u8 req);
|
||||
|
||||
void attach_ptp(PDP6 *pdp);
|
||||
void ptpunmount(PDP6 *pdp);
|
||||
void ptpmount(PDP6 *pdp, int fd);
|
||||
void ptr_set_motor(PDP6 *pdp, int state);
|
||||
void attach_ptr(PDP6 *pdp);
|
||||
void ptrunmount(PDP6 *pdp);
|
||||
void ptrmount(PDP6 *pdp, int fd);
|
||||
void attach_tty(PDP6 *pdp);
|
||||
|
||||
|
||||
|
||||
38
newemu/pt.c
38
newemu/pt.c
@@ -129,9 +129,25 @@ calc_ptp_req(PDP6 *pdp)
|
||||
void
|
||||
attach_ptp(PDP6 *pdp)
|
||||
{
|
||||
pdp->ptp_fd = -1;
|
||||
installdev(pdp, &ptp_dev);
|
||||
}
|
||||
|
||||
void
|
||||
ptpunmount(PDP6 *pdp)
|
||||
{
|
||||
if(pdp->ptp_fd >= 0)
|
||||
close(pdp->ptp_fd);
|
||||
pdp->ptp_fd = -1;
|
||||
}
|
||||
|
||||
void
|
||||
ptpmount(PDP6 *pdp, int fd)
|
||||
{
|
||||
ptpunmount(pdp);
|
||||
pdp->ptp_fd = fd;
|
||||
}
|
||||
|
||||
/* PTR */
|
||||
|
||||
static void calc_ptr_req(PDP6 *pdp);
|
||||
@@ -223,8 +239,13 @@ cycle_ptr(PDP6 *pdp, IOdev *dev, int pwr)
|
||||
|
||||
if(!pdp->ptr_fd.ready)
|
||||
return;
|
||||
if(read(pdp->ptr_fd.fd, &c, 1) <= 0)
|
||||
if(read(pdp->ptr_fd.fd, &c, 1) <= 0) {
|
||||
closefd(&pdp->ptr_fd);
|
||||
return;
|
||||
}
|
||||
// write back in case this is over a socket
|
||||
// and we need to synchronize
|
||||
write(pdp->ptr_fd.fd, &c, 1);
|
||||
waitfd(&pdp->ptr_fd);
|
||||
if(pdp->ptr_busy && (c & 0200 || !pdp->ptr_b)) {
|
||||
// PTR STROBE
|
||||
@@ -265,3 +286,18 @@ attach_ptr(PDP6 *pdp)
|
||||
|
||||
installdev(pdp, &ptr_dev);
|
||||
}
|
||||
|
||||
void
|
||||
ptrunmount(PDP6 *pdp)
|
||||
{
|
||||
if(pdp->ptr_fd.fd >= 0)
|
||||
closefd(&pdp->ptr_fd);
|
||||
}
|
||||
|
||||
void
|
||||
ptrmount(PDP6 *pdp, int fd)
|
||||
{
|
||||
ptrunmount(pdp);
|
||||
pdp->ptr_fd.fd = fd;
|
||||
waitfd(&pdp->ptr_fd);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,8 @@ attach_tty(PDP6 *pdp)
|
||||
pdp->tty_fd.fd = -1;
|
||||
pdp->tty_fd.id = -1;
|
||||
|
||||
pdp->tty_baud = 110;
|
||||
// pdp->tty_baud = 110;
|
||||
pdp->tty_baud = 300;
|
||||
pdp->tty_dly = 1000000000 / pdp->tty_baud;
|
||||
installdev(pdp, &tty_dev);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user