Skip to content

Instantly share code, notes, and snippets.

@OhMeadhbh
Last active August 16, 2020 20:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OhMeadhbh/7dea34420cf3f3fa1ff3291d9f48b4a5 to your computer and use it in GitHub Desktop.
Save OhMeadhbh/7dea34420cf3f3fa1ff3291d9f48b4a5 to your computer and use it in GitHub Desktop.
Update xace emulator to look for rom file at $XACEROM
112c112
< main(argc,argv)
---
> main(argc,argv,envp)
114a115
> char **envp;
128,129c129,130
<      
<   loadrom(mem);
---
>
>   loadrom(mem,envp);
172c173
< loadrom(x)
---
> loadrom(x,env)
173a175
> unsigned char ** env;
175c177
<   int i;
---
>   int i,len;
176a179,204
>   char *xacerom = NULL;
>
>   i = 0;
>
>   while( NULL != env[i] )
>     {
>       if( ! strncmp( "XACEROM", env[i], 7 ) ) {
>           len = strlen(  & env[i][8] );  
>           if( len > 0 )
>             {
>               xacerom = (char *) malloc( len + 1 );
>             }
>
>           if( NULL != xacerom )
>             {
>               strncpy( xacerom, & env[i][8], len + 1 );
>             }
>
>           break;
>       }
>       i++;
>   }
>
>   if(NULL==xacerom) {
>       xacerom="ace.rom";
>   }
178c206
<   if((in=fopen("ace.rom", "rb"))!=NULL)
---
>   if((in=fopen(xacerom, "rb"))!=NULL)
/* xace, an X-based Jupiter ACE emulator (based on xz81)
*
* Copyright (C) 1994 Ian Collier.
* xz81 changes (C) 1995-6 Russell Marks.
* xace changes (C) 1997 Edward Patel.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/Intrinsic.h>
#ifdef MITSHM
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
#endif
#ifdef HAS_UNAME
#include <sys/utsname.h>
#endif
#include "z80.h"
#define MAX_DISP_LEN 256
/* #define SPOOLING_HOOK */
#include "xace.icon"
#if SCALE>1
static unsigned long scaleup[256]; /* to hold table of scaled up bytes,
e.g. 00110100B -> 0000111100110000B */
#endif
unsigned char keyports[8]={0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff};
#define BORDER_WIDTH (20*SCALE)
int rrshm=2,rrnoshm=4,mitshm=1;
unsigned char mem[65536];
unsigned char *memptr[8]={mem,
mem+0x2000,
mem+0x4000,
mem+0x6000,
mem+0x8000,
mem+0xa000,
mem+0xc000,
mem+0xe000};
unsigned long tstates=0,tsmax=(1<<30);
int topspeed=0,lowref=0;
int memattr[8]={0,1,1,1,1,1,1,1}; /* 8K RAM Banks */
int screen_dirty;
int hsize=256*SCALE,vsize=192*SCALE;
volatile int interrupted=0;
int scrn_freq=2;
unsigned char chrmap_old[24*32],chrmap[24*32];
unsigned char himap_old[192*32],himap[192*32];
int refresh_screen=1;
void sighandler(a)
int a;
{
if(interrupted<2) interrupted=1;
}
void dontpanic()
{
closedown();
exit(1);
}
main(argc,argv,envp)
int argc;
char **argv;
char **envp;
{
struct sigaction sa;
struct itimerval itv;
int tmp=1000/50; /* 50 ints/sec */
printf("xace: Jupiter ACE emulator v0.4 (by Edward Patel)\n");
printf("Keys:\n");
printf("\tESC - Quit xace\n");
printf("\tF1 - Delete Line\n");
printf("\tF4 - Inverse Video\n");
printf("\tF9 - Graphics\n");
printf("\tCtl - Break\n");
printf("\tF12 - Reset\n");
loadrom(mem,envp);
patches();
memset(mem+8192,0xff,57344);
memset(chrmap_old,0xff,768);
startup(&argc,argv);
if(argc==2) scrn_freq=atoi(argv[1]);
if(scrn_freq<1) scrn_freq=1;
if(scrn_freq>50) scrn_freq=50;
memset(&sa,0,sizeof(sa));
sa.sa_handler=sighandler;
sa.sa_flags=SA_RESTART;
sigaction(SIGALRM,&sa,NULL);
sa.sa_handler=dontpanic;
sa.sa_flags=0;
sigaction(SIGINT, &sa,NULL);
sigaction(SIGHUP, &sa,NULL);
sigaction(SIGILL, &sa,NULL);
sigaction(SIGTERM,&sa,NULL);
sigaction(SIGQUIT,&sa,NULL);
sigaction(SIGSEGV,&sa,NULL);
itv.it_interval.tv_sec=tmp/1000;
itv.it_interval.tv_usec=(tmp%1000)*1000;
itv.it_value.tv_sec=itv.it_interval.tv_sec;
itv.it_value.tv_usec=itv.it_interval.tv_usec;
setitimer(ITIMER_REAL,&itv,NULL);
#ifndef SPOOLING_HOOK
tsmax=62500;
#endif
mainloop();
}
loadrom(x,env)
unsigned char *x;
unsigned char ** env;
{
int i,len;
FILE *in;
char *xacerom = NULL;
i = 0;
while( NULL != env[i] )
{
if( ! strncmp( "XACEROM", env[i], 7 ) ) {
len = strlen( & env[i][8] );
if( len > 0 )
{
xacerom = (char *) malloc( len + 1 );
}
if( NULL != xacerom )
{
strncpy( xacerom, & env[i][8], len + 1 );
}
break;
}
i++;
}
if(NULL==xacerom) {
xacerom="ace.rom";
}
if((in=fopen(xacerom, "rb"))!=NULL)
{
fread(x,1,8192,in);
fclose(in);
}
else
{
printf("Couldn't load ROM.\n");
exit(1);
}
}
patches()
{
/* patch the ROM here */
mem[0x18a7]=0xed; /* for load_p */
mem[0x18a8]=0xfc;
mem[0x18a9]=0xc9;
mem[0x1820]=0xed; /* for save_p */
mem[0x1821]=0xfd;
mem[0x1822]=0xc9;
}
unsigned int in(h,l)
int h,l;
{
if(l==0xfe) /* keyboard */
switch(h)
{
case 0xfe: return(keyports[0]);
case 0xfd: return(keyports[1]);
case 0xfb: return(keyports[2]);
case 0xf7: return(keyports[3]);
case 0xef: return(keyports[4]);
case 0xdf: return(keyports[5]);
case 0xbf: return(keyports[6]);
case 0x7f: return(keyports[7]);
default: return(255);
}
return(255);
}
unsigned int out(h,l,a)
int h,l,a;
{
return(0);
}
save_p(c,_de,_hl,cf)
int c;
int _de;
int _hl;
int cf;
{
char filename[32];
int i;
static int firstTime=1;
static FILE *fp;
/* printf("Save! c=%d de=%d hl=0x%04x cf=%d\n",c,_de,_hl,cf); */
/* printf("[%d]\n",mem[8961]); */
if (firstTime) {
i=0;
while (!isspace(mem[_hl+1+i])&&i<10) {
filename[i]=mem[_hl+1+i]; i++;
}
filename[i++]='.';
if (mem[8961]) { /* dict or bytes save */
filename[i++]='b';
filename[i++]='y';
filename[i++]='t';
} else {
filename[i++]='d';
filename[i++]='i';
filename[i++]='c';
}
filename[i++]='\0';
printf("Saving to file '%s'\n",filename);
fp = fopen(filename,"wb");
if (!fp) {
printf("Couldn't open file\n");
} else {
_de++;
fputc(_de&0xff,fp);
fputc((_de>>8)&0xff,fp);
fwrite(&mem[_hl],1,_de,fp);
firstTime = 0;
}
} else {
_de++;
fputc(_de&0xff,fp);
fputc((_de>>8)&0xff,fp);
fwrite(&mem[_hl],1,_de,fp);
fclose(fp);
fp=NULL;
firstTime = 1;
}
}
unsigned char empty_bytes[799] = { /* a small screen */
0x1a,0x00,0x20,0x6f, /* will be loaded if */
0x74,0x68,0x65,0x72, /* wanted file can't be */
0x20,0x20,0x20,0x20, /* opened */
0x20,0x00,0x03,0x00,
0x24,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,
0x01,0x03,0x43,0x6f,
0x75,0x6c,0x64,0x6e,
0x27,0x74,0x20,0x6c,
0x6f,0x61,0x64,0x20,
0x79,0x6f,0x75,0x72,
0x20,0x66,0x69,0x6c,
0x65,0x21,0x20,
};
unsigned char empty_dict[] = { /* a small forth program */
0x1a,0x00,0x00,0x6f, /* will be loaded if */
0x74,0x68,0x65,0x72, /* wanted file can't be */
0x20,0x20,0x20,0x20, /* opened */
0x20,0x2a,0x00,0x51,
0x3c,0x58,0x3c,0x4c,
0x3c,0x4c,0x3c,0x4f,
0x3c,0x7b,0x3c,0x20,
0x2b,0x00,0x52,0x55,
0xce,0x27,0x00,0x49,
0x3c,0x03,0xc3,0x0e,
0x1d,0x0a,0x96,0x13,
0x18,0x00,0x43,0x6f,
0x75,0x6c,0x64,0x6e,
0x27,0x74,0x20,0x6c,
0x6f,0x61,0x64,0x20,
0x79,0x6f,0x75,0x72,
0x20,0x66,0x69,0x6c,
0x65,0x21,0xb6,0x04,
0xff,0x00
};
load_p(c,_de,_hl,cf)
int c;
int _de;
int _hl;
int cf;
{
char filename[32];
int i;
static unsigned char *empty_tape;
static int efp;
static int firstTime=1;
static FILE *fp;
/* printf("Load! c=%d de=%d hl=0x%04x cf=%d\n",c,_de,_hl,cf); */
/* printf("[%d]\n",mem[9985]); */
if (firstTime) {
i=0;
while (!isspace(mem[9985+1+i])&&i<10) {
filename[i]=mem[9985+1+i]; i++;
}
filename[i++]='.';
if (mem[9985]) { /* dict or bytes load */
filename[i++]='b';
filename[i++]='y';
filename[i++]='t';
empty_tape = empty_bytes;
} else {
filename[i++]='d';
filename[i++]='i';
filename[i++]='c';
empty_tape = empty_dict;
}
filename[i++]='\0';
fp = fopen(filename,"rb");
if (!fp) {
printf("Couldn't open file '%s'\n",filename);
efp=0;
_de=empty_tape[efp++];
_de+=256*empty_tape[efp++];
memcpy(&mem[_hl],&empty_tape[efp],_de-1); /* -1 -> skip last byte */
for (i=0;i<_de;i++) /* get memory OK */
store(_hl+i,fetch(_hl+i));
efp+=_de;
for (i=0;i<10;i++) /* let this file be it! */
mem[_hl+1+i]=mem[9985+1+i];
firstTime = 0;
} else {
printf("Reading from file '%s'\n",filename);
_de=fgetc(fp);
_de+=256*fgetc(fp);
fread(&mem[_hl],1,_de-1,fp); /* -1 -> skip last byte */
fgetc(fp); /* skip last byte */
for (i=0;i<_de;i++) /* get memory OK */
store(_hl+i,fetch(_hl+i));
for (i=0;i<10;i++) /* let this file be it! */
mem[_hl+1+i]=mem[9985+1+i];
firstTime = 0;
}
} else {
if (fp) {
_de=fgetc(fp);
_de+=256*fgetc(fp);
fread(&mem[_hl],1,_de-1,fp); /* -1 -> skip last byte */
fgetc(fp); /* skip last byte */
for (i=0;i<_de;i++) /* get memory OK */
store(_hl+i,fetch(_hl+i));
fclose(fp);
fp=NULL;
} else {
_de=empty_tape[efp++];
_de+=256*empty_tape[efp++];
memcpy(&mem[_hl],&empty_tape[efp],_de-1); /* -1 -> skip last byte */
for (i=0;i<_de;i++) /* get memory OK */
store(_hl+i,fetch(_hl+i));
}
firstTime = 1;
}
}
fix_tstates()
{
tstates=0;
pause();
}
do_interrupt()
{
static int count=0;
/* only do refresh() every 1/Nth */
count++;
if(count>=scrn_freq)
count=0,refresh();
check_events();
/* be careful not to screw up any pending reset... */
if(interrupted==1)
interrupted=0;
}
/* the remainder of xmain.c is based on xz80's xspectrum.c. */
#ifdef SunKludge
char *shmat();
char *getenv();
#endif
static Display *display;
static Screen *scrptr;
static int screen;
static Window root;
static Colormap cmap;
static GC maingc;
static GC fggc, bggc;
static Window borderwin, mainwin;
static XImage *ximage;
static unsigned char *image;
static int linelen;
static int black,white;
static int bytecycles;
static int framebytes;
#ifdef MITSHM
static XShmSegmentInfo xshminfo;
#endif
static int invert=0;
static int borderchange=1;
static int is_local_server(name)
char *name;
{
#ifdef HAS_UNAME
struct utsname un;
#else
char sysname[MAX_DISP_LEN];
#endif
if(name[0]==':')return 1;
if(!strncmp(name,"unix",4))return 1;
if(!strncmp(name,"localhost",9))return 1;
#ifdef HAS_UNAME
uname(&un);
if(!strncmp(name,un.sysname,strlen(un.sysname)))return 1;
if(!strncmp(name,un.nodename,strlen(un.nodename)))return 1;
#else
gethostname(sysname,MAX_DISP_LEN);
if(!strncmp(name,sysname,strlen(sysname)))return 1;
#endif
return 0;
}
static Display *open_display(argc,argv)
int *argc;
char **argv;
{
int i;
char *ptr;
char *myname="xace",*myclass="XAce";
char dispname[MAX_DISP_LEN];
Display *display;
if((ptr=getenv("DISPLAY")))
strcpy(dispname,ptr);
else
strcpy(dispname,":0.0");
if(!(display=XOpenDisplay(dispname))){
fprintf(stderr,"Unable to open display %s\n",dispname);
exit(1);
}
#ifdef MITSHM
mitshm=1;
#else
mitshm=0;
#endif
/* XXX deal with args here */
if(mitshm && !is_local_server(dispname)){
fputs("Disabling MIT-SHM on remote X server\n",stderr);
mitshm=0;
}
return display;
}
static int image_init()
{
#ifdef MITSHM
if(mitshm){
ximage=XShmCreateImage(display,DefaultVisual(display,screen),
DefaultDepth(display,screen),ZPixmap,NULL,&xshminfo,
hsize,vsize);
if(!ximage){
fputs("Couldn't create X image\n",stderr);
return 1;
}
xshminfo.shmid=shmget(IPC_PRIVATE,
ximage->bytes_per_line*(ximage->height+1),
IPC_CREAT|0777);
if(xshminfo.shmid == -1){
perror("Couldn't perform shmget");
return 1;
}
xshminfo.shmaddr=ximage->data=shmat(xshminfo.shmid,0,0);
if(!xshminfo.shmaddr){
perror("Couldn't perform shmat");
return 1;
}
xshminfo.readOnly=0;
if(!XShmAttach(display,&xshminfo)){
perror("Couldn't perform XShmAttach");
return 1;
}
scrn_freq=rrshm;
} else
#endif
{
ximage=XCreateImage(display,DefaultVisual(display,screen),
DefaultDepth(display,screen),
ZPixmap,0,NULL,hsize,vsize,
8,0);
if(!ximage){
perror("XCreateImage failed");
return 1;
}
ximage->data=malloc(ximage->bytes_per_line*(ximage->height+1));
if(!ximage->data){
perror("Couldn't get memory for XImage data");
return 1;
}
scrn_freq=rrnoshm;
}
linelen=ximage->bytes_per_line/SCALE;
if(linelen!=32 && linelen!=256 && linelen!=512 && linelen!=1024)
fprintf(stderr,"Line length=%d; expect strange results!\n",linelen);
#if 0
if(linelen==32 &&
(BitmapBitOrder(display)!=MSBFirst || ImageByteOrder(display)!=MSBFirst))
fprintf(stderr,"BitmapBitOrder=%s and ImageByteOrder=%s.\n",
BitmapBitOrder(display)==MSBFirst?"MSBFirst":"LSBFirst",
ImageByteOrder(display)==MSBFirst?"MSBFirst":"LSBFirst"),
fputs("If the display is mixed up, please mail me these values\n",stderr),
fputs("and describe the display as accurately as possible.\n",stderr);
#endif
ximage->data+=linelen;
image=ximage->data;
return 0;
}
static void notify(argc,argv)
int *argc;
char **argv;
{
Pixmap icon;
XWMHints xwmh;
XSizeHints xsh;
XClassHint xch;
XTextProperty appname, iconname;
char *apptext;
char *icontext="XAce";
#ifdef WHITE_ON_BLACK
icon=XCreatePixmapFromBitmapData(display,root,icon_bits,
icon_width,icon_height,white,black,DefaultDepth(display,screen));
#else
icon=XCreatePixmapFromBitmapData(display,root,icon_bits,
icon_width,icon_height,black,white,DefaultDepth(display,screen));
#endif
apptext="xace";
xsh.flags=PSize|PMinSize|PMaxSize;
xsh.min_width=hsize;
xsh.min_height=vsize;
xsh.max_width=hsize+BORDER_WIDTH*2;
xsh.max_height=vsize+BORDER_WIDTH*2;
if(!XStringListToTextProperty(&apptext,1,&appname)){
fputs("Can't create a TextProperty!",stderr);
return;
}
if(!XStringListToTextProperty(&icontext,1,&iconname)){
fputs("Can't create a TextProperty!",stderr);
return;
}
xwmh.initial_state=NormalState;
xwmh.input=1;
xwmh.icon_pixmap=icon;
xwmh.flags=StateHint|IconPixmapHint|InputHint;
xch.res_name="xace";
xch.res_class="XAce";
XSetWMProperties(display,borderwin,&appname,&iconname,argv,
*argc,&xsh,&xwmh,&xch);
}
#if SCALE>1
static void scaleup_init(){
int j, k, l, m;
unsigned long bigval; /* SCALING must be <= 4! */
for(l=0;l<256;scaleup[l++]=bigval)
for(m=l,bigval=j=0;j<8;j++) {
for(k=0;k<SCALE;k++)
bigval=(bigval>>1)|((m&1)<<31);
m>>=1;
}
}
#endif
startup(argc,argv)
int *argc;
char **argv;
{
display=open_display(argc,argv);
if(!display){
fputs("Failed to open X display\n",stderr);
exit(1);
}
invert=0;
screen=DefaultScreen(display);
scrptr=DefaultScreenOfDisplay(display);
root=DefaultRootWindow(display);
#ifdef WHITE_ON_BLACK
black=WhitePixel(display,screen);
white=BlackPixel(display,screen);
#else
white=WhitePixel(display,screen);
black=BlackPixel(display,screen);
#endif /* WHITE_ON_BLACK */
maingc=XCreateGC(display,root,0,NULL);
XCopyGC(display,DefaultGC(display,screen),~0,maingc);
XSetGraphicsExposures(display,maingc,0);
fggc=XCreateGC(display,root,0,NULL);
XCopyGC(display,DefaultGC(display,screen),~0,fggc);
XSetGraphicsExposures(display,fggc,0);
bggc=XCreateGC(display,root,0,NULL);
XCopyGC(display,DefaultGC(display,screen),~0,bggc);
XSetGraphicsExposures(display,bggc,0);
cmap=DefaultColormap(display,screen);
if(image_init()){
if(mitshm){
fputs("Failed to create X image - trying again with mitshm off\n",stderr);
mitshm=0;
if(image_init())exit(1);
}
else exit(1);
}
#if SCALE>1
if(linelen==32) scaleup_init();
#endif
borderwin=XCreateSimpleWindow(display,root,0,0,
hsize+BORDER_WIDTH*2,vsize+BORDER_WIDTH*2,0,0,0);
mainwin=XCreateSimpleWindow(display,borderwin,BORDER_WIDTH,
BORDER_WIDTH,hsize,vsize,0,0,0);
notify(argc,argv);
XSelectInput(display,borderwin,KeyPressMask|KeyReleaseMask|
ExposureMask|EnterWindowMask|LeaveWindowMask|
StructureNotifyMask);
XMapRaised(display,borderwin);
XMapRaised(display,mainwin);
XFlush(display);
refresh_screen=1;
}
clear_keyboard()
{
keyports[0]=0xff;
keyports[1]=0xff;
keyports[2]=0xff;
keyports[3]=0xff;
keyports[4]=0xff;
keyports[5]=0xff;
keyports[6]=0xff;
keyports[7]=0xff;
}
#ifdef SPOOLING_HOOK
static FILE *spoolFile=NULL;
static int flipFlop;
#endif
int process_keypress(kev)
XKeyEvent *kev;
{
char buf[3];
KeySym ks;
#ifdef SPOOLING_HOOK
if (spoolFile && (ks=fgetc(spoolFile))) {
if (ks==EOF) {
fclose(spoolFile);
spoolFile=NULL;
return 0;
}
} else
#endif
XLookupString(kev,buf,2,&ks,NULL);
switch(ks){
case XK_Escape:
dontpanic();
/* doesn't return */
break;
#ifdef SPOOLING_HOOK
case XK_F11:
{
char str[80];
printf("Enter spool file:");
scanf("%s",str);
spoolFile=fopen(str,"rt");
flipFlop=0;
}
break;
#endif
case XK_F12:
interrupted=2; /* will cause a reset */
memset(mem+8192,0xff,57344);
refresh_screen=1;
clear_keyboard();
break;
case '\n':
case XK_Return:
keyports[6]&=0xfe;
break;
case XK_Shift_R:
case XK_Shift_L:
case XK_Alt_L:
case XK_Alt_R:
case XK_Meta_L:
case XK_Meta_R:
break;
case XK_F4:
keyports[3]&=0xf7;
keyports[0]&=0xfe;
break;
case XK_F9:
keyports[4]&=0xfd;
keyports[0]&=0xfe;
break;
case XK_Control_L:
case XK_Control_R:
keyports[7]&=0xfe;
keyports[0]&=0xfe;
break;
case XK_F1:
keyports[3]&=0xfe;
keyports[0]&=0xfe;
break;
case XK_BackSpace:
case XK_Delete:
keyports[0]&=0xfe;
keyports[4]&=0xfe;
break;
case XK_Up:
keyports[4]&=0xef;
keyports[0]&=0xfe;
break;
case XK_Down:
keyports[4]&=0xf7;
keyports[0]&=0xfe;
break;
case XK_Left:
keyports[3]&=0xef;
keyports[0]&=0xfe;
break;
case XK_Right:
keyports[4]&=0xfb;
keyports[0]&=0xfe;
break;
break;
case XK_space:
keyports[7]&=0xfe;
break;
case XK_exclam:
keyports[3]&=0xfe;
keyports[0]&=0xfd;
break;
case XK_quotedbl:
keyports[5]&=0xfe;
keyports[0]&=0xfd;
break;
case XK_numbersign:
keyports[3]&=0xfb;
keyports[0]&=0xfd;
break;
case XK_dollar:
keyports[3]&=0xf7;
keyports[0]&=0xfd;
break;
case XK_percent:
keyports[3]&=0xef;
keyports[0]&=0xfd;
break;
case XK_ampersand:
keyports[4]&=0xef;
keyports[0]&=0xfd;
break;
case XK_apostrophe:
keyports[4]&=0xf7;
keyports[0]&=0xfd;
break;
case XK_parenleft:
keyports[4]&=0xfb;
keyports[0]&=0xfd;
break;
case XK_parenright:
keyports[4]&=0xfd;
keyports[0]&=0xfd;
break;
case XK_asterisk:
keyports[7]&=0xf7;
keyports[0]&=0xfd;
break;
case XK_plus:
keyports[6]&=0xfb;
keyports[0]&=0xfd;
break;
case XK_comma:
keyports[7]&=0xfb;
keyports[0]&=0xfd;
break;
case XK_minus:
keyports[6]&=0xf7;
keyports[0]&=0xfd;
break;
case XK_period:
keyports[7]&=0xfd;
keyports[0]&=0xfd;
break;
case XK_slash:
keyports[7]&=0xef;
keyports[0]&=0xfd;
break;
case XK_0:
keyports[4]&=0xfe;
break;
case XK_1:
keyports[3]&=0xfe;
break;
case XK_2:
keyports[3]&=0xfd;
break;
case XK_3:
keyports[3]&=0xfb;
break;
case XK_4:
keyports[3]&=0xf7;
break;
case XK_5:
keyports[3]&=0xef;
break;
case XK_6:
keyports[4]&=0xef;
break;
case XK_7:
keyports[4]&=0xf7;
break;
case XK_8:
keyports[4]&=0xfb;
break;
case XK_9:
keyports[4]&=0xfd;
break;
case XK_colon:
keyports[0]&=0xfb;
keyports[0]&=0xfd;
break;
case XK_semicolon:
keyports[5]&=0xfd;
keyports[0]&=0xfd;
break;
case XK_less:
keyports[2]&=0xf7;
keyports[0]&=0xfd;
break;
case XK_equal:
keyports[6]&=0xfd;
keyports[0]&=0xfd;
break;
case XK_greater:
keyports[2]&=0xef;
keyports[0]&=0xfd;
break;
case XK_question:
keyports[0]&=0xef;
keyports[0]&=0xfd;
break;
case XK_at:
keyports[3]&=0xfd;
keyports[0]&=0xfd;
break;
case XK_A:
keyports[0]&=0xfe;
case XK_a:
keyports[1]&=0xfe;
break;
case XK_B:
keyports[0]&=0xfe;
case XK_b:
keyports[7]&=0xf7;
break;
case XK_C:
keyports[0]&=0xfe;
case XK_c:
keyports[0]&=0xef;
break;
case XK_D:
keyports[0]&=0xfe;
case XK_d:
keyports[1]&=0xfb;
break;
case XK_E:
keyports[0]&=0xfe;
case XK_e:
keyports[2]&=0xfb;
break;
case XK_F:
keyports[0]&=0xfe;
case XK_f:
keyports[1]&=0xf7;
break;
case XK_G:
keyports[0]&=0xfe;
case XK_g:
keyports[1]&=0xef;
break;
case XK_H:
keyports[0]&=0xfe;
case XK_h:
keyports[6]&=0xef;
break;
case XK_I:
keyports[0]&=0xfe;
case XK_i:
keyports[5]&=0xfb;
break;
case XK_J:
keyports[0]&=0xfe;
case XK_j:
keyports[6]&=0xf7;
break;
case XK_K:
keyports[0]&=0xfe;
case XK_k:
keyports[6]&=0xfb;
break;
case XK_L:
keyports[0]&=0xfe;
case XK_l:
keyports[6]&=0xfd;
break;
case XK_M:
keyports[0]&=0xfe;
case XK_m:
keyports[7]&=0xfd;
break;
case XK_N:
keyports[0]&=0xfe;
case XK_n:
keyports[7]&=0xfb;
break;
case XK_O:
keyports[0]&=0xfe;
case XK_o:
keyports[5]&=0xfd;
break;
case XK_P:
keyports[0]&=0xfe;
case XK_p:
keyports[5]&=0xfe;
break;
case XK_Q:
keyports[0]&=0xfe;
case XK_q:
keyports[2]&=0xfe;
break;
case XK_R:
keyports[0]&=0xfe;
case XK_r:
keyports[2]&=0xf7;
break;
case XK_S:
keyports[0]&=0xfe;
case XK_s:
keyports[1]&=0xfd;
break;
case XK_T:
keyports[0]&=0xfe;
case XK_t:
keyports[2]&=0xef;
break;
case XK_U:
keyports[0]&=0xfe;
case XK_u:
keyports[5]&=0xf7;
break;
case XK_V:
keyports[0]&=0xfe;
case XK_v:
keyports[7]&=0xef;
break;
case XK_W:
keyports[0]&=0xfe;
case XK_w:
keyports[2]&=0xfd;
break;
case XK_X:
keyports[0]&=0xfe;
case XK_x:
keyports[0]&=0xf7;
break;
case XK_Y:
keyports[0]&=0xfe;
case XK_y:
keyports[5]&=0xef;
break;
case XK_Z:
keyports[0]&=0xfe;
case XK_z:
keyports[0]&=0xfb;
break;
case XK_bracketleft:
keyports[5]&=0xef;
keyports[0]&=0xfd;
break;
case XK_backslash:
keyports[1]&=0xfb;
keyports[0]&=0xfd;
break;
case XK_bracketright:
keyports[5]&=0xf7;
keyports[0]&=0xfd;
break;
case XK_asciicircum:
keyports[6]&=0xef;
keyports[0]&=0xfd;
break;
case XK_underscore:
keyports[4]&=0xfe;
keyports[0]&=0xfd;
break;
case XK_grave:
keyports[5]&=0xfb;
keyports[0]&=0xfd;
break;
case XK_braceleft:
keyports[1]&=0xf7;
keyports[0]&=0xfd;
break;
case XK_bar:
keyports[1]&=0xfd;
keyports[0]&=0xfd;
break;
case XK_braceright:
keyports[1]&=0xef;
keyports[0]&=0xfd;
break;
case XK_asciitilde:
keyports[1]&=0xfe;
keyports[0]&=0xfd;
break;
default:
break;
}
return 0;
}
void process_keyrelease(kev)
XKeyEvent *kev;
{
char buf[3];
KeySym ks;
XLookupString(kev,buf,2,&ks,NULL);
switch(ks){
case XK_Return:
keyports[6]|=1;
break;
case XK_Shift_L:
case XK_Shift_R:
case XK_Alt_L:
case XK_Alt_R:
case XK_Meta_L:
case XK_Meta_R:
case XK_Escape:
case XK_Tab:
clear_keyboard();
break;
case XK_F4:
keyports[3]|=~0xf7;
keyports[0]|=~0xfe;
break;
case XK_F9:
keyports[4]|=~0xfd;
keyports[0]|=~0xfe;
break;
case XK_Control_L:
case XK_Control_R:
keyports[7]|=~0xfe;
keyports[0]|=~0xfe;
break;
case XK_F1:
keyports[3]|=~0xfe;
keyports[0]|=~0xfe;
break;
case XK_BackSpace:
case XK_Delete:
keyports[0]|=1;
keyports[4]|=1;
break;
case XK_Up:
keyports[4]|=~0xef;
keyports[0]|=~0xfe;
break;
case XK_Down:
keyports[4]|=~0xf7;
keyports[0]|=~0xfe;
break;
case XK_Left:
keyports[3]|=~0xef;
keyports[0]|=~0xfe;
break;
case XK_Right:
keyports[4]|=~0xfb;
keyports[0]|=~0xfe;
break;
break;
case XK_space:
keyports[7]|=~0xfe;
break;
case XK_exclam:
keyports[3]|=~0xfe;
keyports[0]|=~0xfd;
break;
case XK_quotedbl:
keyports[5]|=~0xfe;
keyports[0]|=~0xfd;
break;
case XK_numbersign:
keyports[3]|=~0xfb;
keyports[0]|=~0xfd;
break;
case XK_dollar:
keyports[3]|=~0xf7;
keyports[0]|=~0xfd;
break;
case XK_percent:
keyports[3]|=~0xef;
keyports[0]|=~0xfd;
break;
case XK_ampersand:
keyports[4]|=~0xef;
keyports[0]|=~0xfd;
break;
case XK_apostrophe:
keyports[4]|=~0xf7;
keyports[0]|=~0xfd;
break;
case XK_parenleft:
keyports[4]|=~0xfb;
keyports[0]|=~0xfd;
break;
case XK_parenright:
keyports[4]|=~0xfd;
keyports[0]|=~0xfd;
break;
case XK_asterisk:
keyports[7]|=~0xf7;
keyports[0]|=~0xfd;
break;
case XK_plus:
keyports[6]|=~0xfb;
keyports[0]|=~0xfd;
break;
case XK_comma:
keyports[7]|=~0xfb;
keyports[0]|=~0xfd;
break;
case XK_minus:
keyports[6]|=~0xf7;
keyports[0]|=~0xfd;
break;
case XK_period:
keyports[7]|=~0xfd;
keyports[0]|=~0xfd;
break;
case XK_slash:
keyports[7]|=~0xef;
keyports[0]|=~0xfd;
break;
case XK_0:
keyports[4]|=~0xfe;
break;
case XK_1:
keyports[3]|=~0xfe;
break;
case XK_2:
keyports[3]|=~0xfd;
break;
case XK_3:
keyports[3]|=~0xfb;
break;
case XK_4:
keyports[3]|=~0xf7;
break;
case XK_5:
keyports[3]|=~0xef;
break;
case XK_6:
keyports[4]|=~0xef;
break;
case XK_7:
keyports[4]|=~0xf7;
break;
case XK_8:
keyports[4]|=~0xfb;
break;
case XK_9:
keyports[4]|=~0xfd;
break;
case XK_colon:
keyports[0]|=~0xfb;
keyports[0]|=~0xfd;
break;
case XK_semicolon:
keyports[5]|=~0xfd;
keyports[0]|=~0xfd;
break;
case XK_less:
keyports[2]|=~0xf7;
keyports[0]|=~0xfd;
break;
case XK_equal:
keyports[6]|=~0xfd;
keyports[0]|=~0xfd;
break;
case XK_greater:
keyports[2]|=~0xef;
keyports[0]|=~0xfd;
break;
case XK_question:
keyports[0]|=~0xef;
keyports[0]|=~0xfd;
break;
case XK_at:
keyports[3]|=~0xfd;
keyports[0]|=~0xfd;
break;
case XK_A:
keyports[0]|=~0xfe;
case XK_a:
keyports[1]|=~0xfe;
break;
case XK_B:
keyports[0]|=~0xfe;
case XK_b:
keyports[7]|=~0xf7;
break;
case XK_C:
keyports[0]|=~0xfe;
case XK_c:
keyports[0]|=~0xef;
break;
case XK_D:
keyports[0]|=~0xfe;
case XK_d:
keyports[1]|=~0xfb;
break;
case XK_E:
keyports[0]|=~0xfe;
case XK_e:
keyports[2]|=~0xfb;
break;
case XK_F:
keyports[0]|=~0xfe;
case XK_f:
keyports[1]|=~0xf7;
break;
case XK_G:
keyports[0]|=~0xfe;
case XK_g:
keyports[1]|=~0xef;
break;
case XK_H:
keyports[0]|=~0xfe;
case XK_h:
keyports[6]|=~0xef;
break;
case XK_I:
keyports[0]|=~0xfe;
case XK_i:
keyports[5]|=~0xfb;
break;
case XK_J:
keyports[0]|=~0xfe;
case XK_j:
keyports[6]|=~0xf7;
break;
case XK_K:
keyports[0]|=~0xfe;
case XK_k:
keyports[6]|=~0xfb;
break;
case XK_L:
keyports[0]|=~0xfe;
case XK_l:
keyports[6]|=~0xfd;
break;
case XK_M:
keyports[0]|=~0xfe;
case XK_m:
keyports[7]|=~0xfd;
break;
case XK_N:
keyports[0]|=~0xfe;
case XK_n:
keyports[7]|=~0xfb;
break;
case XK_O:
keyports[0]|=~0xfe;
case XK_o:
keyports[5]|=~0xfd;
break;
case XK_P:
keyports[0]|=~0xfe;
case XK_p:
keyports[5]|=~0xfe;
break;
case XK_Q:
keyports[0]|=~0xfe;
case XK_q:
keyports[2]|=~0xfe;
break;
case XK_R:
keyports[0]|=~0xfe;
case XK_r:
keyports[2]|=~0xf7;
break;
case XK_S:
keyports[0]|=~0xfe;
case XK_s:
keyports[1]|=~0xfd;
break;
case XK_T:
keyports[0]|=~0xfe;
case XK_t:
keyports[2]|=~0xef;
break;
case XK_U:
keyports[0]|=~0xfe;
case XK_u:
keyports[5]|=~0xf7;
break;
case XK_V:
keyports[0]|=~0xfe;
case XK_v:
keyports[7]|=~0xef;
break;
case XK_W:
keyports[0]|=~0xfe;
case XK_w:
keyports[2]|=~0xfd;
break;
case XK_X:
keyports[0]|=~0xfe;
case XK_x:
keyports[0]|=~0xf7;
break;
case XK_Y:
keyports[0]|=~0xfe;
case XK_y:
keyports[5]|=~0xef;
break;
case XK_Z:
keyports[0]|=~0xfe;
case XK_z:
keyports[0]|=~0xfb;
break;
case XK_bracketleft:
keyports[5]|=~0xef;
keyports[0]|=~0xfd;
break;
case XK_backslash:
keyports[1]|=~0xfb;
keyports[0]|=~0xfd;
break;
case XK_bracketright:
keyports[5]|=~0xf7;
keyports[0]|=~0xfd;
break;
case XK_asciicircum:
keyports[6]|=~0xef;
keyports[0]|=~0xfd;
break;
case XK_underscore:
keyports[4]|=~0xfe;
keyports[0]|=~0xfd;
break;
case XK_grave:
keyports[5]|=~0xfb;
keyports[0]|=~0xfd;
break;
case XK_braceleft:
keyports[1]|=~0xf7;
keyports[0]|=~0xfd;
break;
case XK_bar:
keyports[1]|=~0xfd;
keyports[0]|=~0xfd;
break;
case XK_braceright:
keyports[1]|=~0xef;
keyports[0]|=~0xfd;
break;
case XK_asciitilde:
keyports[1]|=~0xfe;
keyports[0]|=~0xfd;
break;
default:
clear_keyboard();
break;
}
return;
}
check_events()
{
int i;
static XEvent xev;
XConfigureEvent *conf_ev;
XCrossingEvent *cev;
while (XEventsQueued(display,QueuedAfterReading)){
XNextEvent(display,&xev);
switch(xev.type){
case Expose: refresh_screen=1;
break;
case ConfigureNotify:
conf_ev=(XConfigureEvent *)&xev;
XMoveWindow(display,mainwin,(conf_ev->width-hsize)/2,
(conf_ev->height-vsize)/2);
break;
case MapNotify: case UnmapNotify: case ReparentNotify:
break;
case EnterNotify:
cev=(XCrossingEvent *)&xev;
if(cev->detail!=NotifyInferior)
XAutoRepeatOff(display),XFlush(display);
break;
case LeaveNotify:
cev=(XCrossingEvent *)&xev;
if(cev->detail!=NotifyInferior)
XAutoRepeatOn(display),XFlush(display);
break;
case KeyPress: process_keypress((XKeyEvent *)&xev);
break;
case KeyRelease: process_keyrelease((XKeyEvent *)&xev);
break;
default:
fprintf(stderr,"unhandled X event, type %d\n",xev.type);
}
}
}
/* XXX tryout */
/* to redraw the (low-res, at least) screen, we translate it into
* a more normal char. map, then find the smallest rectangle which
* covers all the changes, and update that.
*/
refresh(){
int h,i,j,k,l,m,n;
int attr;
unsigned char *ptr,*cptr,*dst,*tmp;
unsigned char val;
int x,y,a,b,c,d,inv,x2,mask;
int pasteol;
int xmin,ymin,xmax,ymax;
int ofs;
#ifdef SPOOLING_HOOK
if (spoolFile) {
if (flipFlop==1) {
process_keypress(NULL);
}
if (flipFlop==3) {
flipFlop=0;
clear_keyboard();
}
flipFlop++;
}
#endif
if(borderchange>0)
{
/* XXX what about expose events? need to set borderchange... */
XSetWindowBackground(display,borderwin,white);
XClearWindow(display,borderwin);
XFlush(display);
borderchange=0;
}
/* draw normal lo-res screen */
/* translate to char map, comparing against previous */
ptr=mem+0x2400; /* D_FILE */
/* since we can't just do "don't bother if it's junk" as we always
* need to draw a screen, just draw *valid* junk that won't result
* in a segfault or anything. :-)
*/
if(ptr-mem<0 || ptr-mem>0xf000) ptr=mem+0xf000;
/* ptr++; /* skip first HALT */
cptr=mem+0x2c00; /* char. set */
xmin=31; ymin=23; xmax=0; ymax=0;
ofs=0;
for(y=0;y<24;y++)
{
pasteol=0;
for(x=0;x<32;x++,ptr++,ofs++)
{
c=*ptr;
if((chrmap[ofs]=c)!=chrmap_old[ofs] || refresh_screen)
{
/* update size of area to be drawn */
if(x<xmin) xmin=x;
if(y<ymin) ymin=y;
if(x>xmax) xmax=x;
if(y>ymax) ymax=y;
/* draw character into image */
inv=(c&128); c&=127;
for(b=0;b<8;b++)
{
d=cptr[c*8+b]; if(inv) d^=255;
if(linelen==32)
{
/* 1-bit mono */
/* XXX doesn't support SCALE>1 */
image[(y*8+b)*linelen+x]=~d;
}
else if (linelen == 1024)
{
unsigned * t;
tmp=image+((y*8+b)*hsize+x*8)*SCALE*4;
t = (unsigned *) tmp;
mask=256;
while((mask>>=1))
{
m=((d&mask)?black:white);
for(j=0;j<SCALE;j++)
for(k=0;k<SCALE;k++)
t[j*hsize+k]=m;
t+=SCALE;
}
}
else
{
/* assume 8-bit */
unsigned short *t;
tmp=image+((y*8+b)*hsize+x*8)*SCALE*(linelen==512?2:1);
t = (unsigned short*)tmp;
mask=256;
while((mask>>=1))
#if SCALE<2
{
/* i.e. actual size */
if (linelen==512)
*t++=(d&mask)?black:white;
else
*tmp++=(d&mask)?black:white;
}
#else
{
m=((d&mask)?black:white);
for(j=0;j<SCALE;j++)
for(k=0;k<SCALE;k++)
if (linelen==512)
t[j*hsize+k]=m;
else
tmp[j*hsize+k]=m;
tmp+=SCALE;
t+=SCALE;
}
#endif
}
}
}
}
}
/* now, copy new to old for next time */
memcpy(chrmap_old,chrmap,768);
/* next bit happens for both hi and lo-res */
if(refresh_screen) xmin=0,ymin=0,xmax=31,ymax=23;
if(xmax>=xmin && ymax>=ymin)
{
#ifdef MITSHM
if(mitshm)
XShmPutImage(display,mainwin,maingc,ximage,
xmin*8*SCALE,ymin*8*SCALE,xmin*8*SCALE,ymin*8*SCALE,
(xmax-xmin+1)*8*SCALE,(ymax-ymin+1)*8*SCALE,0);
else
#endif
XPutImage(display,mainwin,maingc,ximage,
xmin*8*SCALE,ymin*8*SCALE,xmin*8*SCALE,ymin*8*SCALE,
(xmax-xmin+1)*8*SCALE,(ymax-ymin+1)*8*SCALE);
}
XFlush(display);
refresh_screen=0;
}
closedown(){
#ifdef MITSHM
if(mitshm){
XShmDetach(display,&xshminfo);
XDestroyImage(ximage);
shmdt(xshminfo.shmaddr);
shmctl(xshminfo.shmid,IPC_RMID,0);
}
#endif
XAutoRepeatOn(display);
XCloseDisplay(display);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment