152 lines
3.6 KiB
C
152 lines
3.6 KiB
C
#include "gfx.h"
|
|
#include "blit.h"
|
|
#include "util.h"
|
|
#include "internal.h"
|
|
#include "error.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <dpmi.h>
|
|
#include <pc.h>
|
|
|
|
static boolean _initialized = FALSE;
|
|
|
|
SURFACE *screen = NULL;
|
|
|
|
static SURFACE* surface_create_internal(int width, int height, byte *pixels) {
|
|
SURFACE *surface = malloc(sizeof(SURFACE));
|
|
|
|
surface->width = width;
|
|
surface->height = height;
|
|
surface->clip_region = rect(0, 0, width, height);
|
|
|
|
if (pixels != NULL) {
|
|
surface->aliased = TRUE;
|
|
surface->pixels = pixels;
|
|
} else {
|
|
surface->aliased = FALSE;
|
|
surface->pixels = malloc(width * height);
|
|
memset(surface->pixels, 0, width * height);
|
|
}
|
|
|
|
return surface;
|
|
}
|
|
|
|
boolean video_init(void) {
|
|
__dpmi_regs regs;
|
|
void *framebuffer;
|
|
|
|
if (_initialized) {
|
|
dgl_set_error(DGL_VIDEO_ALREADY_INITIALIZED);
|
|
return FALSE;
|
|
}
|
|
|
|
memset(®s, 0, sizeof(__dpmi_regs));
|
|
regs.h.ah = 0x00;
|
|
regs.h.al = 0x13;
|
|
if (__dpmi_int(0x10, ®s)) {
|
|
dgl_set_error(DGL_VIDEO_MODE_13H_INIT_FAILURE);
|
|
return FALSE;
|
|
}
|
|
|
|
framebuffer = map_dos_memory(0xa0000);
|
|
screen = surface_create_internal(320, 200, framebuffer);
|
|
surface_clear(screen, 0);
|
|
|
|
_initialized = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
boolean video_shutdown(void) {
|
|
__dpmi_regs regs;
|
|
|
|
if (!_initialized)
|
|
return TRUE; // don't care
|
|
|
|
memset(®s, 0, sizeof(__dpmi_regs));
|
|
regs.h.ah = 0x00;
|
|
regs.h.al = 0x03;
|
|
if (__dpmi_int(0x10, ®s)) {
|
|
dgl_set_error(DGL_VIDEO_TEXT_MODE_INIT_FAILURE);
|
|
return FALSE;
|
|
}
|
|
|
|
surface_free(screen);
|
|
screen = NULL;
|
|
|
|
_initialized = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
boolean video_is_initialized(void) {
|
|
return _initialized;
|
|
}
|
|
|
|
void video_wait_vsync(void) {
|
|
do {} while (inportb(0x3da) & 0x8);
|
|
do {} while (!(inportb(0x3da) & 0x8));
|
|
}
|
|
|
|
void video_set_color(ubyte color, ubyte r, ubyte g, ubyte b) {
|
|
outportb(0x3c6, 0xff);
|
|
outportb(0x3c8, color);
|
|
outportb(0x3c9, r);
|
|
outportb(0x3c9, g);
|
|
outportb(0x3c9, b);
|
|
}
|
|
|
|
void video_get_color(ubyte color, ubyte *r, ubyte *g, ubyte *b) {
|
|
outportb(0x3c6, 0xff);
|
|
outportb(0x3c7, color);
|
|
*r = inportb(0x3c9);
|
|
*g = inportb(0x3c9);
|
|
*b = inportb(0x3c9);
|
|
}
|
|
|
|
void video_set_palette(const byte *palette) {
|
|
int i = 0;
|
|
for (i = 0; i < 256; ++i) {
|
|
video_set_color(i, palette[0], palette[1], palette[2]);
|
|
palette += 3;
|
|
}
|
|
}
|
|
|
|
void video_get_palette(byte *palette) {
|
|
int i = 0;
|
|
for (i = 0; i < 256; ++i) {
|
|
video_get_color(i, palette, palette + 1, palette + 2);
|
|
palette += 3;
|
|
}
|
|
}
|
|
|
|
SURFACE* surface_create(int width, int height) {
|
|
return surface_create_internal(width, height, NULL);
|
|
}
|
|
|
|
void surface_free(SURFACE *surface) {
|
|
if (!surface)
|
|
return;
|
|
|
|
if (!surface->aliased)
|
|
free(surface->pixels);
|
|
free(surface);
|
|
}
|
|
|
|
void surface_clear(SURFACE *surface, int color) {
|
|
int length = surface->width * surface->height;
|
|
if (length % 4 == 0) {
|
|
color *= 0x01010101;
|
|
REP_STOSL(color, surface->pixels, length / 4);
|
|
} else {
|
|
memset(surface->pixels, color, surface->width * surface->height);
|
|
}
|
|
}
|
|
|
|
void surface_copy(const SURFACE *src, SURFACE *dest) {
|
|
if (src->width == dest->width && src->height == dest->height) {
|
|
memcpy(dest->pixels, src->pixels, src->width * src->height);
|
|
} else {
|
|
surface_blit(src, dest, 0, 0);
|
|
}
|
|
}
|
|
|