terug.gif
#include <stdio.h>
#include <malloc.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "system.h"
#include "cpu.h"
#include "screen.h"
#include "keyboard.h"
#include "atom.h"
#define WIDTH   256
#define HEIGHT  192
static Display  *display;
static Screen   *screen;
static Window   window;
static Visual   *visual;
static XComposeStatus   keyboard_status;
static XImage   *image;
static GC       gc;
bool need_to_refresh = FALSE;
static int colortable[4] =
{
    0x000000,
    0xff0000,
    0x00ff00,
    0xffffff
};
static int  colours[4];
static bool mode;
static int xlen,  /* number of pixels in x direction */
           xpix,  /* size of a pixel in x direction */
           ylen,  /* number of pizels in y direction */
           ypix,  /* size of a pixel in y direction */
           xlen8, /* number of bytes for one line */
           len8,  /* number of bytes in the whole screen */
           color; /* 8: black/white, 4: color graphics */
void init_screen()
{   int i;
        XSetWindowAttributes    xswda;
        XGCValues       xgcvl;
        int     depth;
        char    *data;
        int     offset = 0;
        int     bitmap_pad = 8;
        int     bytes_per_line = 0;
        display = XOpenDisplay (NULL);
        if (!display)
        {
                printf ("Failed to open display\n");
                exit (1);
        }
        screen = XDefaultScreenOfDisplay (display);
        if (!screen)
        {
                printf ("Unable to get screen\n");
                exit (1);
        }
        depth = XDefaultDepthOfScreen (screen);
    xswda.event_mask = KeyPress | KeyRelease |
                       ExposureMask | EnterWindowMask | LeaveWindowMask;
        window = XCreateWindow (display,
                        XRootWindowOfScreen(screen),
                        50, 50,
                        WIDTH, HEIGHT, 3, depth,
                        InputOutput, visual,
                        CWEventMask | CWBackPixel,
                        &xswda);
        XStoreName (display, window, TITLE);
    for (i=0;i<4;i++)
        {
                XColor  colour;
                int     rgb = colortable[i];
                int     status;
                colour.red = (rgb & 0x00ff0000) >> 8;
                colour.green = (rgb & 0x0000ff00);
                colour.blue = (rgb & 0x000000ff) << 8;
                status = XAllocColor (display,
                                XDefaultColormapOfScreen(screen),
                                &colour);
        colours[i] = colour.pixel;
        }
    xgcvl.background = colours[0];
    xgcvl.foreground = colours[3];
    gc = XCreateGC (display, window,
                GCForeground | GCBackground,
                &xgcvl);
        XMapWindow (display, window);
        XSync (display, False);
        data = malloc (WIDTH * HEIGHT);
        if (!data)
        {
                printf ("Failed to allocate space for image\n");
                exit (1);
        }
        image = XCreateImage (display,
                        visual,
                        depth,
                        ZPixmap,
                        offset,
                        data,
                        WIDTH,
                        HEIGHT,
                        bitmap_pad,
                        bytes_per_line);
        if (!image)
        {
                printf ("Failed to allocate image\n");
                exit (1);
        }
    mode = 1;
    set_mode(0, 1);
    SetMemory(0x8000, 0x81FF, VIDEO);
}
void exit_screen()
{
        XSync (display, True);
        XDestroyImage (image);
        XUnmapWindow (display, window);
        XDestroyWindow (display, window);
        XCloseDisplay (display);
}
void refresh_screen()
{   
    XPutImage (display, window, gc, image, 0, 0, 0, 0, WIDTH, HEIGHT);
}
void update_screen()
{
    if (need_to_refresh)
    {   XPutImage (display, window, gc, image, 0, 0, 0, 0, WIDTH, HEIGHT);
        need_to_refresh = FALSE;
    }
}
void atom_hardware (void)
{
    while (XEventsQueued (display, QueuedAfterFlush) > 0)
    {
        XEvent  xevent;
        XNextEvent (display, &xevent);
        switch ( xevent.type )
                {
                        case Expose :
                refresh_screen();
                                break;
                        case KeyPress :
                handle_key (( XKeyEvent* ) &xevent, TRUE );
                                break;
                        case KeyRelease :
                handle_key (( XKeyEvent* ) &xevent, FALSE );
                                break;
                        case EnterNotify :
                XAutoRepeatOff ( display );
                XFlush ( display );
                                break;
                        case LeaveNotify :
                XAutoRepeatOn ( display );
                XFlush ( display );
                                break;
                        default :
                                /*
                                 * All other events are masked out, so this should
                                 * barf big-time.
                                 */
                                break;
                }
        }
}
void set_mode(UBYTE graphic, SBYTE graphic_mode)
{   /* CLEAR 0 is mapped to text mode, with cursor off, uses
       the graphical characters */
    if (graphic)
    {   int x,y,i,b;
        if (mode == graphic_mode)
            return;
        mode = graphic_mode;
        switch(mode)
        {   case 0: xlen =  64; ylen =  64; color = 4; break; /* CLEAR 1a */
            case 1: xlen = 128; ylen =  64; color = 8; break; /* CLEAR 1 */
            case 2: xlen = 128; ylen =  64; color = 4; break; /* CLEAR 2a */
            case 3: xlen = 128; ylen =  96; color = 8; break; /* CLEAR 2 */
            case 4: xlen = 128; ylen =  96; color = 4; break; /* CLEAR 3a */
            case 5: xlen = 128; ylen = 192; color = 8; break; /* CLEAR 3 */
            case 6: xlen = 128; ylen = 192; color = 4; break; /* CLEAR 4a */
            case 7: xlen = 256; ylen = 192; color = 8; break; /* CLEAR 4 */
        }
        xpix = 256 / xlen;
        ypix = 192 / ylen;
        xlen8 = xlen / color;
        len8 = xlen8 * ylen;
        printf("mode %d, xlen %d, ylen %d, xpix %d, ypix %d, xlen8 %d\n",
                mode,    xlen,    ylen,    xpix,    ypix,    xlen8);
        SetMemory(0x8000, 0x7fff + len8, VIDEO);
        SetMemory(0x8000 + len8, 0x9800, RAM);
        b = 0x8000;
        for (y = 0; y < 192; y += ypix)
        {   x = 0;
            for (i = 0; i < xlen8; i++, b++)
            {   int v = memory[b];
                int k;
                if (color == 4)
                    for (k = 6; k >= 0; k -= 2)
                    {   int x2, y2,
                            c = colours[(v >> k) & 3];
                        for (x2 = 0; x2 < xpix; x2++, x++)
                            for (y2 = 0; y2 < ypix; y2++)
                                XPutPixel (image, x, y + y2, c);
                    }
                else
                    for (k = 7; k >= 0; k--)
                    {   int x2, y2,
                            c = colours[((v >> k) & 1) ? 3 : 0];
                        for (x2 = 0; x2 < xpix; x2++, x++)
                            for (y2 = 0; y2 < ypix; y2++)
                                XPutPixel (image, x, y + y2, c);
                    }
            }
        }
    }
    else
    {   int x, y, b;
        if (mode == -1)
            return;
        mode = -1;
        SetMemory(0x8000, 0x81ff, VIDEO);
        SetMemory(0x8200, 0x9800, RAM);
        b = 0x8000;
        for (y = 0; y < 192; y += 12)
            for (x = 0; x < 256; x += 8, b++)
                draw_character(x, y, memory[b]);
    }
    need_to_refresh = TRUE; 
    /* XPutImage (display, window, gc, image, 0, 0, 0, 0, WIDTH, HEIGHT); */
}
UBYTE char_rep[64][7] =
{ { 14,17, 1,13,21,21,14 },
  {  4,10,17,17,31,17,17 },
  { 30, 9, 9,14, 9, 9,30 },
  { 14,17,16,16,16,17,14 },
  { 30, 9, 9, 9, 9, 9,30 },
  { 31,16,16,28,16,16,31 },
  { 31,16,16,30,16,16,16 },
  { 15,16,16,19,17,17,15 },
  { 17,17,17,31,17,17,17 },
  { 14, 4, 4, 4, 4, 4,14 },
  {  1, 1, 1,17,17,10, 4 },
  { 17,18,20,24,24,20,18 },
  { 16,16,16,16,16,16,31 },
  { 17,27,21,17,17,17,17 },
  { 17,25,21,19,17,17,17 },
  { 14,17,17,17,17,17,14 },
  { 30,17,17,30,16,16,16 },
  { 14,17,17,17,21,18,13 },
  { 30,17,17,30,20,18,17 },
  { 14,17, 8, 4, 2,17,14 },
  { 31, 4, 4, 4, 4, 4, 4 },
  { 17,17,17,17,17,17,14 },
  { 17,17,17,17,10,10, 4 },
  { 17,17,17,17,21,27,17 },
  { 17,17,10, 4,10,17,17 },
  { 17,17,10, 4, 4, 4, 4 },
  { 31, 1, 2, 4, 8,16,31 },
  { 14, 8, 8, 8, 8, 8,14 },
  { 16,16, 8, 4, 2, 1, 1 },
  { 14, 2, 2, 2, 2, 2,14 },
  {  4,14,31, 4, 4, 4, 4 },
  {  0, 4, 8,31, 8, 4, 0 },
  {  0, 0, 0, 0, 0, 0, 0 },
  {  4, 4, 4, 4, 4, 0, 4 },
  { 10,10, 0, 0, 0, 0, 0 },
  { 10,10,27, 0,27,10,10 },
  {  4,15,16,14, 1,30, 4 },
  { 25,25, 2, 4, 8,19,19 },
  {  8,20,20, 9,22,22, 9 },
  {  4, 4, 0, 0, 0, 0, 0 },
  {  2, 4, 8, 8, 8, 4, 2 },
  {  8, 4, 2, 2, 2, 4, 8 },
  {  0, 4,14,31,14, 4, 0 },
  {  0, 4, 4,31, 4, 4, 0 },
  {  0, 0, 0, 6, 6, 2, 4 },
  {  0, 0, 0,31, 0, 0, 0 },
  {  0, 0, 0, 0, 0, 4, 4 },
  {  1, 1, 2, 4, 8,16,16 },
  {  4,10,10,10,10,10, 4 },
  {  4,12, 4, 4, 4, 4,14 },
  { 14,17, 1,14,16,16,31 },
  { 14,17, 1, 6, 1,17,14 },
  {  2, 6,10,31, 2, 2, 2 },
  { 31,16,30, 1, 1,17,14 },
  { 14,16,16,30,17,17,14 },
  { 31, 1, 2, 4, 8,16,16 },
  { 14,17,17,14,17,17,14 },
  { 14,17,17,15, 1, 1,14 },
  {  0, 0, 4, 0, 4, 0, 0 },
  {  6, 6, 0, 6, 6, 2, 4 },
  {  2, 4, 8,16, 8, 4, 2 },
  {  0, 0,31, 0,31, 0, 0 },
  { 16, 8, 4, 2, 4, 8,16 },
  {  4,10, 2, 4, 4, 0, 4 },
};
static void draw_char(int x0, int y, UBYTE ch, UBYTE bl, UBYTE wh)
{   int i, x, j,
        x2 = x0 + 2,
        x8 = x0 + 8;
    UBYTE *ch_rep = char_rep[ch];
    for (i = 0; i < 3; i++, y++)
        for (x = x0; x < x8; x++)
            XPutPixel (image, x, y, bl);
    for (i = 0; i < 7; i++, y++, ch_rep++)
    {   for (x = x0; x < x2; x++)
            XPutPixel (image, x, y, bl);
        for (j = 4; j >= 0; j--, x++)
            XPutPixel (image, x, y, ((*ch_rep >> j) & 1) ? wh : bl);
        XPutPixel (image, x, y, bl);
    }
    for (i = 0; i < 2; i++, y++)
        for (x = x0; x < x8; x++)
            XPutPixel (image, x, y, bl);
}
static void draw_gr(int x, int y, UBYTE bl, UBYTE wh)
{   int i;
    for (i = 0; i < 2; i++)
    {   XPutPixel (image, x,     y, bl);
        XPutPixel (image, x + 1, y, wh);
        XPutPixel (image, x + 2, y, bl);
        XPutPixel (image, x + 3, y, wh);
        y++;
        XPutPixel (image, x,     y, wh);
        XPutPixel (image, x + 1, y, wh);
        XPutPixel (image, x + 2, y, wh);
        XPutPixel (image, x + 3, y, wh);
        y++;
    }
}
static void draw_graph(int x, int y, UBYTE ch, UBYTE bl, UBYTE wh)
{
    int v;
    v = ch & 32;
    draw_gr(x,     y, v ? bl : colours[0], v ? wh : colours[0]);
    v = ch & 16;
    draw_gr(x + 4, y, v ? bl : colours[0], v ? wh : colours[0]);
    y += 4;
    v = ch & 8;
    draw_gr(x,     y, v ? bl : colours[0], v ? wh : colours[0]);
    v = ch & 4;
    draw_gr(x + 4, y, v ? bl : colours[0], v ? wh : colours[0]);
    y += 4;
    v = ch & 2;
    draw_gr(x,     y, v ? bl : colours[0], v ? wh : colours[0]);
    v = ch & 1;
    draw_gr(x + 4, y, v ? bl : colours[0], v ? wh : colours[0]);
}
void draw_character(int x, int y, UBYTE ch)
{
    if (ch < 64)
        draw_char(x, y, ch, colours[0], colours[3]);
    else if (ch < 128)
        draw_graph(x, y, ch, colours[3], colours[3]);
    else if (ch < 192)
        draw_char(x, y, ch - 128, colours[3], colours[0]);
    else
        draw_graph(x, y, ch, colours[3], colours[0]);
}
void update_video(UWORD addr, UBYTE v)
{   UWORD pos = addr - 0x8000;
    if (memory[addr] == v)
        return;
    memory[addr] = v;
    if (mode == -1)
    {   int x = (pos % 32) * 8,
            y = (pos / 32) * 12;
        draw_character(x, y, v);
        /* copy [x, x + 7] [y, y + 11] */
        XPutImage (display, window, gc, image, x, y, x, y, 8, 12);
    }
    else
    {   int xb = pos % xlen8,       /* x pos in bytes */
            xo = xb * color * xpix,     /* x pos on screen */
            x = xo,
            yb = pos / xlen8,       /* y pos in bytes */
            yo  = yb * ypix,        /* y pos on screen */ 
            y = yo,
            k;
        if (color == 4)
            for (k = 6; k >= 0; k -= 2)
            {   int x2, y2,
                    c = colours[(v >> k) & 3];
                for (x2 = 0; x2 < xpix; x2++, x++)
                    for (y2 = 0; y2 < ypix; y2++)
                        XPutPixel (image, x, y + y2, c);
            }
        else
            for (k = 7; k >= 0; k--)
            {   int x2, y2,
                    c = colours[((v >> k) & 1) ? 3 : 0];
                for (x2 = 0; x2 < xpix; x2++, x++)
                    for (y2 = 0; y2 < ypix; y2++)
                        XPutPixel (image, x, y + y2, c);
            }
        /* copy [xo, xo + color * xpix - 1] [y, y + ypix - 1] */
        XPutImage (display, window, gc, image, xo, yo, xo, yo, 
                   color * xpix, ypix);
    }
    /* need_to_refresh = TRUE; */
    /* XPutImage (display, window, gc, image, 0, 0, 0, 0, WIDTH, HEIGHT); */
}
 terug.gif