Get it compiling and running with 32bit TrueColor

This commit is contained in:
Aaron Culliney 2013-06-24 23:14:39 -07:00
parent a57b7c129a
commit faa279f075

View File

@ -16,6 +16,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
@ -34,8 +35,6 @@
#include "misc.h" #include "misc.h"
#include "keys.h" #include "keys.h"
/* copied from svideo.c (didn't bother to rename!) */
static unsigned char *svga_GM;
static unsigned char vga_mem_page_0[SCANWIDTH*SCANHEIGHT]; /* page0 framebuffer */ static unsigned char vga_mem_page_0[SCANWIDTH*SCANHEIGHT]; /* page0 framebuffer */
static unsigned char vga_mem_page_1[SCANWIDTH*SCANHEIGHT]; /* page1 framebuffer */ static unsigned char vga_mem_page_1[SCANWIDTH*SCANHEIGHT]; /* page1 framebuffer */
@ -45,13 +44,17 @@ static GC gc;
static unsigned int width, height; /* window size */ static unsigned int width, height; /* window size */
static int screen_num; static int screen_num;
static Visual* visual;
static XVisualInfo visualinfo; static XVisualInfo visualinfo;
static XColor colors[256]; static XColor colors[256];
XImage *image; XImage *image;
static Colormap cmap; static Colormap cmap;
XEvent xevent; XEvent xevent;
static uint32_t red_shift;
static uint32_t green_shift;
static uint32_t blue_shift;
static uint32_t alpha_shift;
int doShm = 1;/* assume true */ int doShm = 1;/* assume true */
XShmSegmentInfo xshminfo; XShmSegmentInfo xshminfo;
int xshmeventtype; int xshmeventtype;
@ -62,24 +65,7 @@ int xshmeventtype;
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void video_setpage(int p) void video_setpage(int p)
{ {
if (p == video__current_page) return; video__current_page = p;
if (p)
{
memcpy(vga_mem_page_0,svga_GM,SCANWIDTH*SCANHEIGHT);
memcpy(svga_GM,vga_mem_page_1,SCANWIDTH*SCANHEIGHT);
video__current_page = 1;
video__fb1 = vga_mem_page_0;
video__fb2 = svga_GM;
}
else
{
memcpy(vga_mem_page_1,svga_GM,SCANWIDTH*SCANHEIGHT);
memcpy(svga_GM,vga_mem_page_0,SCANWIDTH*SCANHEIGHT);
video__current_page = 0;
video__fb1 = svga_GM;
video__fb2 = vga_mem_page_1;
}
} }
/* /*
@ -100,39 +86,35 @@ static void getshm(int size) {
do do
{ {
id = shmget((key_t) key, 0, 0777); id = shmget((key_t) key, 0, 0777);
if (id != -1) if (id == -1) {
{ /* no stale ID's */
/* we got someone else's ID. check if it's stale. */ id = shmget((key_t)key, size, IPC_CREAT|0777);
printf("Found shared memory key=`%c%c%c%c', id=%d\n", if (id == -1) {
(key & 0xff000000)>>24, perror("shmget");
(key & 0xff0000)>>16, printf("Could not get shared memory\n");
(key & 0xff00)>>8, ++key;
(key & 0xff),
id
);
rc=shmctl(id, IPC_STAT, &shminfo); /* get stats */
if (!rc) {
/* someone's using the emulator */
if (shminfo.shm_nattch) {
printf( "User uid=%d, key=`%c%c%c%c' appears to be running "
"the emulator.\n",
shminfo.shm_perm.cuid,
(key & 0xff000000)>>24,
(key & 0xff0000)>>16,
(key & 0xff00)>>8,
(key & 0xff)
);
++key; /* increase the key count */
} }
break;
/* found a stale ID. */ } else {
else { /* we got someone else's ID. check if it's stale. */
/* it's my stale ID */ printf("Found shared memory key=`%c%c%c%c', id=%d\n", (key & 0xff000000)>>24, (key & 0xff0000)>>16, (key & 0xff00)>>8, (key & 0xff), id);
rc=shmctl(id, IPC_STAT, &shminfo); /* get stats */
if (rc) {
/* error. what to do now? */
perror("shmctl");
printf("Could not get stats on key=`%c%c%c%c', id=%d\n", (key & 0xff000000)>>24, (key & 0xff0000)>>16, (key & 0xff00)>>8, (key & 0xff), id);
++key;
} else {
if (shminfo.shm_nattch) {
printf( "User uid=%d, key=`%c%c%c%c' appears to be running the emulator.\n", shminfo.shm_perm.cuid, (key & 0xff000000)>>24, (key & 0xff0000)>>16, (key & 0xff00)>>8, (key & 0xff));
++key; /* increase the key count */
} else {
if (getuid() == shminfo.shm_perm.cuid) { if (getuid() == shminfo.shm_perm.cuid) {
/* it's my stale ID */
rc = shmctl(id, IPC_RMID, 0); rc = shmctl(id, IPC_RMID, 0);
if (!rc) if (!rc) {
printf("Was able to kill my old shared memory\n"); printf("Was able to kill my old shared memory\n");
else { } else {
perror("shmctl"); perror("shmctl");
printf("Was NOT able to kill my old shared memory\n"); printf("Was NOT able to kill my old shared memory\n");
} }
@ -149,60 +131,26 @@ static void getshm(int size) {
} }
break; break;
} }
/* not my ID, but maybe we can use it */
if (size == shminfo.shm_segsz) { if (size == shminfo.shm_segsz) {
printf( "Will use stale shared memory of uid=%d\n", /* not my ID, but maybe we can use it */
shminfo.shm_perm.cuid); printf("Will use stale shared memory of uid=%d\n", shminfo.shm_perm.cuid);
break; break;
} }
/* not my ID, and we can't use it */ /* not my ID, and we can't use it */
else { else {
printf( "Can't use stale shared memory belonging to uid=%d, " printf("Can't use stale shared memory belonging to uid=%d, key=`%c%c%c%c', id=%d\n", shminfo.shm_perm.cuid, (key & 0xff000000)>>24, (key & 0xff0000)>>16, (key & 0xff00)>>8, (key & 0xff), id);
"key=`%c%c%c%c', id=%d\n",
shminfo.shm_perm.cuid,
(key & 0xff000000)>>24,
(key & 0xff0000)>>16,
(key & 0xff00)>>8,
(key & 0xff),
id
);
++key; ++key;
} }
} }
} }
else
{
/* oops. what to do now? */
perror("shmctl");
printf( "Could not get stats on key=`%c%c%c%c', id=%d\n",
(key & 0xff000000)>>24,
(key & 0xff0000)>>16,
(key & 0xff00)>>8,
(key & 0xff),
id
);
++key;
}
}
else
{
/* no stale ID's */
id = shmget((key_t)key, size, IPC_CREAT|0777);
if (id == -1) {
perror("shmget");
printf("Could not get shared memory\n");
++key;
}
break;
} }
} while (--counter); } while (--counter);
if (!counter) if (!counter) {
{ printf( "System has too many stale/used shared memory segments!\n");
printf( "System has too many stale/used "
"shared memory segments!\n");
} }
xshminfo.shmid = id; xshminfo.shmid = id;
@ -216,13 +164,7 @@ static void getshm(int size) {
exit(1); exit(1);
} }
printf( "Using shared memory key=`%c%c%c%c', id=%d, addr=0x%x\n", printf("Using shared memory key=`%c%c%c%c', id=%d, addr=%p\n", (key & 0xff000000)>>24, (key & 0xff0000)>>16, (key & 0xff00)>>8, (key & 0xff), id, image->data);
(key & 0xff000000)>>24,
(key & 0xff0000)>>16,
(key & 0xff00)>>8,
(key & 0xff),
id,
(int) (image->data));
} }
@ -231,8 +173,6 @@ static void c_initialize_colors() {
static int firstcall = 1; static int firstcall = 1;
int c,i,j; int c,i,j;
if (visualinfo.class == PseudoColor && visualinfo.depth == 8)
{
/* initialize the colormap */ /* initialize the colormap */
if (firstcall) { if (firstcall) {
firstcall = 0; firstcall = 0;
@ -246,11 +186,11 @@ static void c_initialize_colors() {
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
for (j = 0; j < 3; j++) { for (j = 0; j < 3; j++) {
c = (i & 1) ? col2[ j ] : 0; c = (i & 1) ? col2[ j ] : 0;
colors[ j+i*3+32].red = (c<<8) + c; colors[ j+i*3+32].red = c;
c = (i & 2) ? col2[ j ] : 0; c = (i & 2) ? col2[ j ] : 0;
colors[ j+i*3+32].green = (c<<8) + c; colors[ j+i*3+32].green = c;
c = (i & 4) ? col2[ j ] : 0; c = (i & 4) ? col2[ j ] : 0;
colors[ j+i*3+32].blue = (c<<8) + c; colors[ j+i*3+32].blue = c;
} }
} }
colors[ COLOR_FLASHING_BLACK].red = 0; colors[ COLOR_FLASHING_BLACK].red = 0;
@ -341,9 +281,9 @@ static void c_initialize_colors() {
colors[i<<4].green = (colors[i<<4].green<<8) | colors[i<<4].green; colors[i<<4].green = (colors[i<<4].green<<8) | colors[i<<4].green;
colors[i<<4].blue = (colors[i<<4].blue<<8) | colors[i<<4].blue; colors[i<<4].blue = (colors[i<<4].blue<<8) | colors[i<<4].blue;
} }
// store the colors to the current colormap // store the colors to the current colormap
XStoreColors(display, cmap, colors, 256); //XStoreColors(display, cmap, colors, 256);
}
} }
@ -459,6 +399,22 @@ static int keysym_to_scancode(void) {
} }
static void post_image() { static void post_image() {
// copy Apple //e video memory into XImage uint32_t buffer
uint8_t *fb = !video__current_page ? video__fb1 : video__fb2;
uint8_t index;
unsigned int count = SCANWIDTH * SCANHEIGHT;
for (unsigned int i=0, j=0; i<count; i++, j+=4) {
index = *(fb + i);
*( (uint32_t*)(image->data + j) ) = (uint32_t)(
((uint32_t)(colors[index].red) << red_shift) |
((uint32_t)(colors[index].green) << green_shift) |
((uint32_t)(colors[index].blue) << blue_shift) |
((uint32_t)0xff /* alpha */ << alpha_shift)
);
}
// post image...
if (doShm) { if (doShm) {
if (!XShmPutImage( if (!XShmPutImage(
display, display,
@ -506,7 +462,7 @@ static void c_flash_cursor(int on) {
} }
// store the colors to the current colormap // store the colors to the current colormap
XStoreColors(display, cmap, colors, 256); //XStoreColors(display, cmap, colors, 256);
} }
} }
@ -556,25 +512,27 @@ POLL_FINISHED:
} }
} }
#if 0
static Cursor hidecursor() { static Cursor hidecursor() {
Pixmap cursormask; Pixmap cursormask;
XGCValues xgc; XGCValues xgc;
XColor dummycolour; XColor dummycolour;
Cursor cursor; Cursor cursor;
GC cursor_gc;
cursormask = XCreatePixmap(display, win, 1, 1, 1/*depth*/); cursormask = XCreatePixmap(display, win, 1, 1, 1/*depth*/);
xgc.function = GXclear; xgc.function = GXclear;
gc = XCreateGC(display, cursormask, GCFunction, &xgc); cursor_gc = XCreateGC(display, cursormask, GCFunction, &xgc);
XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
dummycolour.pixel = 0; dummycolour.pixel = 0;
dummycolour.red = 0; dummycolour.red = 0;
dummycolour.flags = 04; dummycolour.flags = 04;
cursor = XCreatePixmapCursor(display, cursormask, cursormask, cursor = XCreatePixmapCursor(display, cursormask, cursormask, &dummycolour,&dummycolour, 0,0);
&dummycolour,&dummycolour, 0,0);
XFreePixmap(display,cursormask); XFreePixmap(display,cursormask);
XFreeGC(display,gc); XFreeGC(display,cursor_gc);
return cursor; return cursor;
} }
#endif
static void parseArgs() { static void parseArgs() {
int i; int i;
@ -605,8 +563,8 @@ void video_init() {
progname = argv[0]; progname = argv[0];
/* give up root privileges. equivalent of vga_init() */ /* give up root privileges. equivalent of vga_init() */
setegid(getgid()); //setegid(getgid());
seteuid(getuid()); //seteuid(getuid());
parseArgs(); parseArgs();
@ -631,20 +589,56 @@ void video_init() {
exit(1); exit(1);
} }
/* get screen size from display structure macro */
screen_num = DefaultScreen(display); screen_num = DefaultScreen(display);
if (!XMatchVisualInfo(display, screen_num, 8, PseudoColor, &visualinfo)) { // Note that in a real Xlib application, we would support more than the default visual :-P
fprintf(stderr, //visual = DefaultVisual(display, screen_num);
"Sorry bud, xapple2 only supports " //XVisualInfo *visuals_list=NULL;
"8bit PseudoColor displays.\n" //visualinfo.screen=screen_num;
"Maybe you can fix this!\n"); /*
int numvisuals=0;
if (!(visuals_list = XGetVisualInfo(display, VisualScreenMask, &visualinfo, &numvisuals))) {
fprintf(stderr, "XGetVisualInfo() failed...");
exit(1);
}
visualinfo = visuals_list[0];
if ( (visualinfo.class == PseudoColor) || (visualinfo.depth == 8) ) {
fprintf(stderr, "PseudoColor or 8bit color is unimplemented, FIXME!");
exit(1);
}
XFree(visuals_list);
*/
if (!XMatchVisualInfo(display, XDefaultScreen(display), 32, TrueColor, &visualinfo))
{
fprintf(stderr, "no such visual\n");
exit(1); exit(1);
} }
visual = visualinfo.visual;
//display_width = DisplayWidth(display, screen_num);
//display_height = DisplayHeight(display, screen_num);
/* Note that in a real application, x and y would default to 0 // determine mask bits ...
// red_mask: 00ff0000
// green_mask: 0000ff00
// blue_mask: 000000ff
// bits_per_rgb: 8
unsigned int shift = 0;
for (unsigned int i=0; i<4; i++) {
if ((((uint32_t)visualinfo.red_mask >>shift) & 0xff) == (uint32_t)0xff) {
red_shift = shift;
} else if ((((uint32_t)visualinfo.green_mask>>shift) & 0xff) == (uint32_t)0xff) {
green_shift = shift;
} else if ((((uint32_t)visualinfo.blue_mask >>shift) & 0xff) == (uint32_t)0xff) {
blue_shift = shift;
} else {
alpha_shift = shift;
}
shift += 8;
}
if ((!red_shift) && (!green_shift) && (!blue_shift)) {
fprintf(stderr, "Could not calculate red/green/blue color masks...\n");
exit(1);
}
fprintf(stderr, "red mask:%08x green mask:%08x blue mask:%08x\n", (uint32_t)visualinfo.red_mask, (uint32_t)visualinfo.blue_mask, (uint32_t)visualinfo.green_mask);
fprintf(stderr, "redshift:%08d greenshift:%08d blueshift:%08d alphashift:%08d\n", red_shift, blue_shift, green_shift, alpha_shift);
/* Note that in a real Xlib application, x and y would default to 0
* but would be settable from the command line or resource database. * but would be settable from the command line or resource database.
*/ */
x = y = 0; x = y = 0;
@ -654,63 +648,44 @@ void video_init() {
if (doShm) { if (doShm) {
/* make sure we have it */ /* make sure we have it */
doShm = XShmQueryExtension(display); doShm = XShmQueryExtension(display);
}
/* and it's a local connection */
if (!displayname)
displayname = getenv("DISPLAY"); displayname = getenv("DISPLAY");
if (displayname) if (displayname) {
{
if ((*displayname != ':') || !doShm) {
printf("Cannot run MITSHM version of emulator "
"with display \"%s\"\n"
"Try something like \":0.0\". "
"Reverting to regular X with no sound.\n",
displayname);
doShm = 0;
soundAllowed=0;
c_initialize_sound();
}
}
} else {
/* and it's a local connection */
if (!displayname)
displayname = getenv("DISPLAY");
if (displayname)
{
if (*displayname != ':') { if (*displayname != ':') {
printf("Sound not allowed for remote display \"%s\".\n", printf("NOTE: Sound not allowed for remote display \"%s\".\n", displayname);
if (doShm) {
printf("NOTE: Cannot run MITSHM version of emulator with display \"%s\"\n"
"Try setting DISPLAY to something like \":0.0\"...Reverting to regular X.\n",
displayname); displayname);
soundAllowed=0;
c_initialize_sound();
} }
doShm=0;
soundAllowed=0;
} }
} }
/* initialize colors */ /* initialize colors */
cmap = XCreateColormap(display, RootWindow(display, screen_num),
visual, AllocAll);
c_initialize_colors(); c_initialize_colors();
cmap = XCreateColormap(display, XDefaultRootWindow(display), visualinfo.visual, AllocNone);
//XStoreColors(display, cmap, colors, 256);
attribs.colormap = cmap; attribs.colormap = cmap;
attribs.border_pixel = 0; attribs.border_pixel = 0;
/* select event types wanted */ /* select event types wanted */
attribmask = CWEventMask | CWColormap | CWBorderPixel;/* HACK CWBorderPixel? */ attribmask = CWEventMask | CWColormap | CWBorderPixel;/* HACK CWBorderPixel? */
attribs.event_mask = attribs.event_mask = KeyPressMask | KeyReleaseMask | ExposureMask;
KeyPressMask
| KeyReleaseMask
| ExposureMask;
/* create opaque window */ /* create opaque window */
win = XCreateWindow(display, RootWindow(display,screen_num), win = XCreateWindow(display, RootWindow(display, screen_num),
x, y, width, height, x, y, width, height,
0,/* border_width */ 0,/* border_width */
8,/* depth */ visualinfo.depth,/* depth */
InputOutput, InputOutput,
visual, visualinfo.visual,
attribmask, attribmask,
&attribs); &attribs);
/* set size hints for window manager. We don't want the user to /* set size hints for window manager. We don't want the user to
* dynamically allocate window size since we won't do the right * dynamically allocate window size since we won't do the right
* scaling in response. Whaddya want, performance or a snazzy gui? * scaling in response. Whaddya want, performance or a snazzy gui?
@ -732,6 +707,7 @@ void video_init() {
exit(1); exit(1);
} }
// set up window manager hints...
wm_hints->initial_state = NormalState; wm_hints->initial_state = NormalState;
wm_hints->input = True; wm_hints->input = True;
wm_hints->flags = StateHint | IconPixmapHint/* | InputHint*/; wm_hints->flags = StateHint | IconPixmapHint/* | InputHint*/;
@ -743,16 +719,13 @@ void video_init() {
argv, argc, size_hints, wm_hints, argv, argc, size_hints, wm_hints,
class_hints); class_hints);
XDefineCursor(display, win, hidecursor(display, win)); // FIXME!!!!! hidecursor segfaults
//XDefineCursor(display, win, hidecursor(display, win));
/* create the GC */ /* create the GC */
valuemask = GCGraphicsExposures; valuemask = GCGraphicsExposures;
xgcvalues.graphics_exposures = False; xgcvalues.graphics_exposures = False;
/*gc = */XCreateGC( gc = XCreateGC(display, win, valuemask, &xgcvalues);
display,
win,
valuemask,
&xgcvalues);
/* display window */ /* display window */
XMapWindow(display, win); XMapWindow(display, win);
@ -768,29 +741,25 @@ void video_init() {
} }
} }
// pad pixels to uint32_t boundaries
int bitmap_pad = sizeof(uint32_t);
int pixel_buffer_size = SCANWIDTH*SCANHEIGHT*bitmap_pad;
xshmeventtype = XShmGetEventBase(display) + ShmCompletion; xshmeventtype = XShmGetEventBase(display) + ShmCompletion;
/* create the image */ /* create the image */
if (doShm) { if (doShm) {
image = XShmCreateImage( image = XShmCreateImage(display, visualinfo.visual, visualinfo.depth, ZPixmap, NULL, &xshminfo, SCANWIDTH, SCANHEIGHT);
display,
visual,
8,
ZPixmap,
0,
&xshminfo,
SCANWIDTH,
SCANHEIGHT);
if (!image) { if (!image) {
fprintf(stderr, "XShmCreateImage failed\n"); fprintf(stderr, "XShmCreateImage failed\n");
exit(1); exit(1);
} }
printf("Allocating shared memory %dx%d region\n", printf("Allocating shared memory: bytes_per_line:%ds height:x%d (depth:%d) bitmap_pad:%d\n",
image->bytes_per_line, image->height); image->bytes_per_line, image->height, visualinfo.depth, bitmap_pad);
getshm(image->bytes_per_line * image->height); getshm(pixel_buffer_size);
/* get the X server to attach to it */ /* get the X server to attach to it */
if (!XShmAttach(display, &xshminfo)) { if (!XShmAttach(display, &xshminfo)) {
@ -798,37 +767,26 @@ void video_init() {
exit(1); exit(1);
} }
} else { } else {
char *data = malloc(SCANWIDTH*SCANHEIGHT*sizeof(unsigned char)); void *data = malloc(pixel_buffer_size); // pad to uint32_t
if (!data) { if (!data) {
fprintf(stderr, "no memory for image data!\n"); fprintf(stderr, "no memory for image data!\n");
exit(1); exit(1);
} }
printf("Creating regular XImage\n"); printf("Creating regular XImage\n");
image = XCreateImage( image = XCreateImage(display, visualinfo.visual, visualinfo.depth, ZPixmap, 0/*offset*/, data, SCANWIDTH, SCANHEIGHT, 8, SCANWIDTH*bitmap_pad/*bytes_per_line*/);
display,
visual,
8,
ZPixmap,
0,
data,
SCANWIDTH,
SCANHEIGHT,
8/*bitmap_pad*/,
SCANWIDTH/*bytes_per_line*/);
if (!image) { if (!image) {
fprintf(stderr, "XCreateImage failed\n"); fprintf(stderr, "XCreateImage failed\n");
exit(1); exit(1);
} }
} }
svga_GM = video__fb1 = (unsigned char*)image->data; video__fb1 = vga_mem_page_0;
video__fb2 = vga_mem_page_1; video__fb2 = vga_mem_page_1;
// reset Apple2 softframebuffers
memset(video__fb1,0,SCANWIDTH*SCANHEIGHT); memset(video__fb1,0,SCANWIDTH*SCANHEIGHT);
memset(video__fb2,0,SCANWIDTH*SCANHEIGHT); memset(video__fb2,0,SCANWIDTH*SCANHEIGHT);
} }
void video_shutdown(void) void video_shutdown(void)