Logo Search packages:      
Sourcecode: vgagamespack version File versions

vga16.c

/*
 * VGA 16 colour mode support routines
 *
 * Copyright (C) Evan Harris, 1993, 1994, 1995.
 *
 * Permission is granted to freely redistribute and modify this code,
 * providing the author(s) get credit for having written it.
 */

#include <stdlib.h>
#include <stdio.h>
#include <vga.h>
#include "vga16.h"

#define FONT_WIDTH 8
#define FONT_LINES 16


#ifndef USEGETPIXEL
static unsigned char *vga16mem = NULL;
static int vga16width, vga16height;
#endif
static unsigned char *vga16workmem =  NULL;
static char *font_bits;


/*
 * To be called after vga_setmode()
 */

int
vga16_init()
{
    vga_modeinfo *mode;
    FILE *f;
    int nelem;

    mode = vga_getmodeinfo(vga_getcurrentmode());
    if (mode->colors != 16) {
      return -1;
    }
#ifndef USEGETPIXEL
    if (vga16mem != NULL) {
      free(vga16mem);
    }
    vga16mem = calloc(mode->width * mode->height / 2, sizeof(unsigned char));
#endif
    vga16workmem = malloc(mode->width * sizeof(unsigned char));
    nelem = ((FONT_WIDTH + 7) / 8) * FONT_LINES * 256;
    font_bits = malloc(nelem * sizeof(char));
#ifndef USEGETPIXEL
    if (vga16mem == NULL || vga16workmem == NULL || font_bits == NULL) {
      return -1;
    }

    vga16width = mode->width;
    vga16height = mode->height;
#else
    if (vga16workmem == NULL || font_bits == NULL) {
      return -1;
    }
#endif      
    
    f = fopen(VGA16FONT, "r");
    if (f == NULL) {
      fprintf(stderr, "Cannot find '%s'\n", VGA16FONT);
      exit(1);
    }
    if (fread(font_bits, sizeof(char), nelem, f) != nelem) {
      fprintf(stderr, "Font reading failed - read error.\n");
    }
    fclose(f);

    return 0;
}


#ifndef USEGETPIXEL
void
vga16_drawscansegment(unsigned char *colors, int x, int y, int length)
{
    unsigned char *p, *c;
    int l, changed;
    
    p = &vga16mem[(y * vga16width + x) >> 1];
    c = colors;
    l = length;
    changed = 0;
    while (l > 0) {
      if (*p != (*c << 4 | *(c + 1))) {
          *p = *c << 4 | *(c + 1);
          changed = 1;
      }
      p++;
      c += 2;
      l -= 2;
    }

    if (changed) {
      vga_drawscansegment(colors, x, y, length);
    }
}


void
vga16_drawscanline(int y, unsigned char *colors)
{
    vga16_drawscansegment(colors, 0, y, vga16width);
}
#endif


static void
vga16_putchar(int x, int y, char c, int fg, int bg)
{
    int i, j, mask, colour;
#ifndef USEGETPIXEL
    int vp;
#endif

    y -= FONT_LINES - 1;
    for (i = FONT_LINES * c; i < FONT_LINES * (c + 1); i++) {
      mask = 0x80;
      for (j = x; j < x + 8; j++) {
          if (font_bits[i] & mask) {
            colour = fg;
          } else {
            colour = bg;
          }
          
#ifndef USEGETPIXEL
          vp = (y * vga16width + j) / 2;

          if (j & 1) {
            if ((vga16mem[vp] & 0x0f) != colour) {
                vga16mem[vp] = (vga16mem[vp] & 0xf0) | colour;
                vga_setcolor(colour);
                vga_drawpixel(j, y);
            }
          } else {
            if ((vga16mem[vp] >> 4) != colour) {
                vga16mem[vp] = (colour << 4) | (vga16mem[vp] & 0x0f);
                vga_setcolor(colour);
                vga_drawpixel(j, y);
            }
          }
#else
          vga_setcolor(colour);
          vga_drawpixel(j, y);
#endif          

          mask = mask >> 1;
      }
      y++;
    }
}


void
vga16_text(int x, int y, char *s, int fg, int bg)
{
    int startx = x;

    while (*s != '\0') {
      switch (*s) {
        case '\n':
          y += FONT_LINES;
          x = startx;
          break;
        case '\b':
          x -= FONT_WIDTH;
          break;
        default:
          vga16_putchar(x, y, *s, fg, bg);
          x += FONT_WIDTH;
          break;
      }
      s++;
    }
}


void
vga16_setpixel(int color, int x, int y)
{
#ifndef USEGETPIXEL
    unsigned char *vp = &vga16mem[(y * vga16width + x) >> 1];

    if (x & 1) {
      if ((*vp & 0x0f) == color) {
          return;
      }
      *vp = (*vp & 0xf0) | color;
    } else {
      if ((*vp >> 4) == color) {
          return;
      }
      *vp = (color << 4) | (*vp & 0x0f);
    }
#endif
    
    vga_setcolor(color);
    vga_drawpixel(x, y);
}


#ifndef USEGETPIXEL
int
vga16_getpixel(int x, int y)
{
    unsigned char *vp = &vga16mem[(y * vga16width + x) >> 1];

    if (x & 1) {
      return *vp & 0x0f;
    } else {
      return *vp >> 4;
    }
}
#endif


/*
 * This assumes that (x0 % 8 == 0) and (x1 % 8 == 7) due to
 * vga_drawscansegment()
 */

void
vga16_filledblock(int x0, int y0, int x1, int y1, int color)
{
    int x, y;
#ifndef USEGETPIXEL
    unsigned char *vp;
    int c;
#endif

    for (x = 0; x <= x1 - x0; x++) {
      vga16workmem[x] = color;
    }

    for (y = y0; y <= y1; y++) {
#ifndef USEGETPIXEL
      x = x0;
      c = (color << 4) | color;
      vp = &vga16mem[(y * vga16width + x) >> 1];
      if (x & 1) {
          *vp++ = (*vp & 0xf0) | color;
          x++;
      }
      while (x <= x1 - 1) {
          *vp++ = c;
          x += 2;
      }
      if (x < x1) {
          *vp++ = (*vp & 0x0f) | (color << 4);
      }
#endif      
      vga_drawscansegment(vga16workmem, x0, y, x1 - x0 + 1);
    }
}


void
vga16_redrawscreen()
{
#ifndef USEGETPIXEL
    unsigned char *vp, *vw;
    int x, y;
    
    for (y = 0; y < vga16height; y++) {
      vp = &vga16mem[(y * vga16width) >> 1];
      vw = vga16workmem;

      for (x = 0; x < vga16width / 2; x++) {
          *vw++ = (*vp & 0xf0) >> 4;
          *vw++ = *vp++ & 0x0f;
      }

      vga_drawscansegment(vga16workmem, 0, y, vga16width);
    }
#endif
}

Generated by  Doxygen 1.6.0   Back to index