gint_strcat/src/gray.c

256 lines
4.1 KiB
C

//---
//
// gint core/drawing module: gray
//
// Runs the gray engine and handles drawing for the dual-buffer system.
//
//---
#include <display.h>
#include <gray.h>
#include <screen.h>
#include <timer.h>
static int internal_vrams[3][256];
const void *vrams[4];
static int current = 0;
static int delays[2];
static int runs = 0;
#define GRAY_PRESCALER TIMER_Po_64
//---
// Engine control.
//---
/*
gray_runs()
Returns 1 if the gray engine is running, 0 otherwise.
*/
inline int gray_runs(void)
{
return runs;
}
/*
gray_start()
Starts the gray engine. The control of the screen is transferred to the
gray engine.
*/
void gray_start(void)
{
timer_start(TIMER_GRAY, delays[0], GRAY_PRESCALER, gray_interrupt, 0);
runs = 1;
}
/*
gray_stop()
Stops the gray engine. The monochrome display system takes control of
the video ram.
*/
void gray_stop(void)
{
timer_stop(TIMER_GRAY);
runs = 0;
display_useVRAM(display_getLocalVRAM());
}
/*
gray_lightVRAM()
Returns the module's gray vram address.
*/
inline void *gray_lightVRAM(void)
{
return (void *)vrams[current & 2];
}
/*
gray_lightVRAM()
Returns the module's dark vram address.
*/
inline void *gray_darkVRAM(void)
{
return (void *)vrams[(current & 2) | 1];
}
/*
gray_getDelays()
Returns the gray engine delays. Pointers are not set if NULL.
*/
void gray_getDelays(int *light, int *dark)
{
if(light) *light = delays[0];
if(dark) *dark = delays[1];
}
/*
gray_setDelays()
Changes the gray engine delays.
*/
void gray_setDelays(int light, int dark)
{
delays[0] = light;
delays[1] = dark;
}
//---
// Internal API.
//---
/*
gray_interrupt()
Answers a timer interrupt. Swaps the buffers.
*/
void gray_interrupt(void)
{
timer_reload(TIMER_GRAY, delays[current & 1]);
screen_display(vrams[current]);
current ^= 1;
}
/*
gray_init()
Initializes the gray engine.
*/
void gray_init(void)
{
vrams[0] = (const void *)display_getLocalVRAM();
vrams[1] = (const void *)internal_vrams[0];
vrams[2] = (const void *)internal_vrams[1];
vrams[3] = (const void *)internal_vrams[2];
delays[0] = 900;
delays[1] = 1000;
}
//---
// Global drawing functions
//---
/*
gupdate()
Swaps the vram buffer sets.
*/
inline void gupdate(void)
{
current ^= 2;
}
/*
gclear()
Clears the video ram.
*/
void gclear(void)
{
int *v1 = gray_lightVRAM();
int *v2 = gray_darkVRAM();
int i;
for(i = 0; i < 256; i++) v1[i] = v2[i] = 0;
}
/*
gclear_area()
Clears an area of the video ram. End points (x1, y1) and (x2, y2) are
included.
*/
void gclear_area(int x1, int y1, int x2, int y2)
{
display_useVRAM(gray_lightVRAM());
dclear_area(x1, y1, x2, y2);
display_useVRAM(gray_darkVRAM());
dclear_area(x1, y1, x2, y2);
}
/*
greverse_area()
Reverses an area of the vram. End points (x1, y1) and (x2, y2) are
included.
*/
void greverse_area(int x1, int y1, int x2, int y2)
{
display_useVRAM(gray_lightVRAM());
dreverse_area(x1, y1, x2, y2);
display_useVRAM(gray_darkVRAM());
dreverse_area(x1, y1, x2, y2);
}
//---
// Local drawing functions.
//---
/*
gpixel()
Puts a pixel in the vram.
*/
void gpixel(int x, int y, enum Color color)
{
if((unsigned int)x > 127 || (unsigned int)y > 63) return;
int offset = (y << 2) + (x >> 5);
int mask = 0x80000000 >> (x & 31);
int *v1 = gray_lightVRAM();
int *v2 = gray_lightVRAM();
switch(color)
{
case Color_White:
v1[offset] &= ~mask;
v2[offset] &= ~mask;
break;
case Color_Light:
v1[offset] |= mask;
v2[offset] &= ~mask;
break;
case Color_Dark:
v1[offset] &= ~mask;
v2[offset] |= mask;
break;
case Color_Black:
v1[offset] |= mask;
v2[offset] |= mask;
break;
case Color_Invert:
v1[offset] ^= mask;
v2[offset] ^= mask;
break;
default:
break;
}
}
/*
gline()
Draws a line in the vram. Automatically optimizes special cases.
*/
void gline(int x1, int y1, int x2, int y2, enum Color color)
{
enum Color c1, c2;
if(color == Color_None) return;
else if(color == Color_Invert) c1 = c2 = Color_Invert;
else c1 = color & 1, c2 = color >> 1;
display_useVRAM(gray_lightVRAM());
dline(x1, y1, x2, y2, c1);
display_useVRAM(gray_darkVRAM());
dline(x1, y1, x2, y2, c2);
}