From 123d3b82562ae9650e81a44d910d14537be1ef89 Mon Sep 17 00:00:00 2001 From: gered Date: Sat, 28 Apr 2018 11:30:53 -0400 Subject: [PATCH] many updates. moved project over to watcom --- DGL.C | 68 +-- DGL.H | 33 +- BLIT.C => DGLBLIT.C | 136 ++--- BLIT.H => DGLBLIT.H | 34 +- DGLBLITA.ASM | 535 +++++++++++++++++ CLIPPING.C => DGLCLIP.C | 22 +- CLIPPING.H => DGLCLIP.H | 8 +- COMMON.H => DGLCMN.H | 6 +- DRAW.C => DGLDRAW.C | 195 ++++--- DRAW.H => DGLDRAW.H | 42 +- DGLDRAWA.ASM | 159 +++++ ERROR.H => DGLERROR.H | 6 +- DGLFIXP.C | 20 + DGLFIXP.H | 89 +++ DGLGFX.C | 103 ++++ DGLGFX.H | 44 ++ KEYBOARD.C => DGLKBRD.C | 71 +-- KEYBOARD.H => DGLKBRD.H | 10 +- KEYS.H => DGLKEYS.H | 4 +- MATHEXT.C => DGLMATH.C | 2 +- MATHEXT.H => DGLMATH.H | 33 +- DGLMOUSE.C | 159 +++++ MOUSE.H => DGLMOUSE.H | 20 +- MATRIX33.H => DGLMTX33.H | 102 ++-- DGLPAL.C | 109 ++++ DGLPAL.H | 27 + PCX.C => DGLPCX.C | 61 +- PCX.H => DGLPCX.H | 8 +- RECT.H => DGLRECT.H | 16 +- DGLUTIL.C | 22 + DGLUTIL.H | 100 ++++ DGLVEC2.H | 436 ++++++++++++++ GFX.C | 151 ----- GFX.H | 47 -- INTERNAL.C | 36 -- INTERNAL.H | 60 -- LIBDGL.GDT | Bin 8545 -> 0 bytes LIBDGL.GPR | Bin 14310 -> 0 bytes MAKEFILE | 80 +++ MOUSE.C | 188 ------ TEST.C | 1200 +++++++++++++++++++++++++++++++++++++- UTIL.C | 37 -- UTIL.H | 26 - VECTOR2.H | 284 --------- 44 files changed, 3497 insertions(+), 1292 deletions(-) rename BLIT.C => DGLBLIT.C (55%) rename BLIT.H => DGLBLIT.H (53%) create mode 100644 DGLBLITA.ASM rename CLIPPING.C => DGLCLIP.C (82%) rename CLIPPING.H => DGLCLIP.H (90%) rename COMMON.H => DGLCMN.H (83%) rename DRAW.C => DGLDRAW.C (62%) rename DRAW.H => DGLDRAW.H (54%) create mode 100644 DGLDRAWA.ASM rename ERROR.H => DGLERROR.H (86%) create mode 100644 DGLFIXP.C create mode 100644 DGLFIXP.H create mode 100644 DGLGFX.C create mode 100644 DGLGFX.H rename KEYBOARD.C => DGLKBRD.C (66%) rename KEYBOARD.H => DGLKBRD.H (78%) rename KEYS.H => DGLKEYS.H (94%) rename MATHEXT.C => DGLMATH.C (93%) rename MATHEXT.H => DGLMATH.H (68%) create mode 100644 DGLMOUSE.C rename MOUSE.H => DGLMOUSE.H (78%) rename MATRIX33.H => DGLMTX33.H (69%) create mode 100644 DGLPAL.C create mode 100644 DGLPAL.H rename PCX.C => DGLPCX.C (79%) rename PCX.H => DGLPCX.H (57%) rename RECT.H => DGLRECT.H (53%) create mode 100644 DGLUTIL.C create mode 100644 DGLUTIL.H create mode 100644 DGLVEC2.H delete mode 100644 GFX.C delete mode 100644 GFX.H delete mode 100644 INTERNAL.C delete mode 100644 INTERNAL.H delete mode 100644 LIBDGL.GDT delete mode 100644 LIBDGL.GPR create mode 100644 MAKEFILE delete mode 100644 MOUSE.C delete mode 100644 UTIL.C delete mode 100644 UTIL.H delete mode 100644 VECTOR2.H diff --git a/DGL.C b/DGL.C index ee45d94..4abd7aa 100644 --- a/DGL.C +++ b/DGL.C @@ -1,68 +1,22 @@ #include "dgl.h" -#include "keyboard.h" -#include "mouse.h" -#include "gfx.h" -#include "util.h" +#include "dglkbrd.h" +#include "dglmouse.h" +#include "dglgfx.h" +#include "dglutil.h" #include -#include -#include -static boolean _initialized = FALSE; static DGL_ERROR _last_error = DGL_NONE; -boolean dgl_init(void) { - if (_initialized) { - dgl_set_error(DGL_ALREADY_INIT); - return FALSE; - } - if (__djgpp_nearptr_enable() == 0) { - dgl_set_error(DGL_NEARPTR_ENABLE_FAILURE); - return FALSE; - } - - srandom((int)sys_clock()); - - // first call will return zero, so call here just to "init" - sys_clock(); - sys_ticks(); - - if (!video_init()) - return FALSE; - if (!keyboard_init()) - return FALSE; - if (!mouse_init()) - return FALSE; - - _initialized = TRUE; - return TRUE; -} - -boolean dgl_shutdown(void) { - if (!_initialized) - return TRUE; // don't care - - // remove installed services - if (!mouse_shutdown()) - return FALSE; - if (!keyboard_shutdown()) - return FALSE; - if (!video_shutdown()) - return FALSE; - - __djgpp_nearptr_disable(); - - _initialized = FALSE; - return TRUE; -} - DGL_ERROR dgl_last_error(void) { - return _last_error; + DGL_ERROR err = _last_error; + _last_error = DGL_NONE; + return err; } const char* dgl_last_error_message(void) { switch (_last_error) { case DGL_NONE: - return "No error."; + return ""; case DGL_ALREADY_INIT: return "DGL is already initialized."; case DGL_NEARPTR_ENABLE_FAILURE: @@ -104,3 +58,9 @@ void dgl_set_error(DGL_ERROR error) { _last_error = error; } +void dgl_init(void) { + atexit(mouse_shutdown); + atexit(keyboard_shutdown); + atexit(video_shutdown); +} + diff --git a/DGL.H b/DGL.H index 712a2b3..262d82c 100644 --- a/DGL.H +++ b/DGL.H @@ -1,24 +1,25 @@ #ifndef DGL_DGL_H_INCLUDED #define DGL_DGL_H_INCLUDED -#include "common.h" -#include "error.h" +#include "dglcmn.h" +#include "dglerror.h" -#include "keyboard.h" -#include "mouse.h" -#include "gfx.h" -#include "clipping.h" -#include "draw.h" -#include "blit.h" -#include "mathext.h" -#include "rect.h" -#include "vector2.h" -#include "matrix33.h" -#include "util.h" -#include "pcx.h" +#include "dglkbrd.h" +#include "dglmouse.h" +#include "dglgfx.h" +#include "dglpal.h" +#include "dglclip.h" +#include "dgldraw.h" +#include "dglblit.h" +#include "dglmath.h" +#include "dglfixp.h" +#include "dglrect.h" +#include "dglvec2.h" +#include "dglmtx33.h" +#include "dglutil.h" +#include "dglpcx.h" -boolean dgl_init(void); -boolean dgl_shutdown(void); +void dgl_init(void); #endif diff --git a/BLIT.C b/DGLBLIT.C similarity index 55% rename from BLIT.C rename to DGLBLIT.C index 34599a1..88286e2 100644 --- a/BLIT.C +++ b/DGLBLIT.C @@ -1,11 +1,10 @@ -#include "blit.h" -#include "clipping.h" -#include "internal.h" +#include "dglblit.h" +#include "dglclip.h" -static inline boolean clip_blit(const RECT *dest_clip_region, - RECT *src_blit_region, - int *dest_x, - int *dest_y) { +static boolean clip_blit(const RECT *dest_clip_region, + RECT *src_blit_region, + int *dest_x, + int *dest_y) { int dest_clip_right = rect_right(dest_clip_region); int dest_clip_bottom = rect_bottom(dest_clip_region); int offset; @@ -13,7 +12,7 @@ static inline boolean clip_blit(const RECT *dest_clip_region, // off the left edge? if (*dest_x < dest_clip_region->x) { // completely off the left edge? - if ((*dest_x + src_blit_region->width) < dest_clip_region->x) + if ((*dest_x + src_blit_region->width - 1) < dest_clip_region->x) return FALSE; offset = src_blit_region->x - *dest_x; @@ -35,7 +34,7 @@ static inline boolean clip_blit(const RECT *dest_clip_region, // off the top edge? if (*dest_y < dest_clip_region->y) { // completely off the top edge? - if ((*dest_y + src_blit_region->height) < dest_clip_region->y) + if ((*dest_y + src_blit_region->height - 1) < dest_clip_region->y) return FALSE; offset = dest_clip_region->y - *dest_y; @@ -85,34 +84,31 @@ void surface_blit_region_f(const SURFACE *src, int src_height, int dest_x, int dest_y) { - byte *psrc, *pdest; - int src_y_inc, dest_y_inc; - int width; - int lines_left; - int num_dwords; + const byte *psrc; + byte *pdest; + int lines; + int src_y_inc = src->width - src_width; + int dest_y_inc = dest->width - src_width; + int width_4, width_remainder; - psrc = surface_pointer(src, src_x, src_y); - src_y_inc = src->width; - pdest = surface_pointer(dest, dest_x, dest_y); - dest_y_inc = dest->width; - width = src_width; - lines_left = src_height; + psrc = (const byte*)surface_pointer(src, src_x, src_y); + pdest = (byte*)surface_pointer(dest, dest_x, dest_y); + lines = src_height; + + width_4 = src_width / 4; + width_remainder = src_width & 3; + + if (width_4 && !width_remainder) { + // width is a multiple of 4 (no remainder) + direct_blit_4(width_4, lines, pdest, psrc, dest_y_inc, src_y_inc); + + } else if (width_4 && width_remainder) { + // width is >= 4 and there is a remainder ( <= 3 ) + direct_blit_4r(width_4, lines, width_remainder, pdest, psrc, dest_y_inc, src_y_inc); - if (width % 4 == 0) { - num_dwords = width / 4; - while (lines_left) { - REP_MOVSL(psrc, pdest, num_dwords); - psrc += src_y_inc; - pdest += dest_y_inc; - --lines_left; - } } else { - while (lines_left) { - REP_MOVSB(psrc, pdest, width); - psrc += src_y_inc; - pdest += dest_y_inc; - --lines_left; - } + // width is <= 3 + direct_blit_r(width_remainder, lines, pdest, psrc, dest_y_inc, src_y_inc); } } @@ -144,61 +140,49 @@ void surface_blit_sprite_region_f(const SURFACE *src, int src_height, int dest_x, int dest_y) { - byte *psrc, *pdest; + const byte *psrc; + byte *pdest; byte pixel; int src_y_inc, dest_y_inc; - int width; + int width, width_4, width_8, width_remainder; int lines_left; int x; - psrc = surface_pointer(src, src_x, src_y); + psrc = (const byte*)surface_pointer(src, src_x, src_y); src_y_inc = src->width; - pdest = surface_pointer(dest, dest_x, dest_y); + pdest = (byte*)surface_pointer(dest, dest_x, dest_y); dest_y_inc = dest->width; width = src_width; lines_left = src_height; - // based on benchmarking on a DX2-66, there is VERY significant - // diminishing returns for loop unrolling beyond these sizes - // (in fact, even the one for 8 is a very small gain over 4) - if (width % 8 == 0) { - while (lines_left) { - for (x = 0; x < width; x += 8) { - if ((pixel = psrc[x + 0])) pdest[x + 0] = pixel; - if ((pixel = psrc[x + 1])) pdest[x + 1] = pixel; - if ((pixel = psrc[x + 2])) pdest[x + 2] = pixel; - if ((pixel = psrc[x + 3])) pdest[x + 3] = pixel; - if ((pixel = psrc[x + 4])) pdest[x + 4] = pixel; - if ((pixel = psrc[x + 5])) pdest[x + 5] = pixel; - if ((pixel = psrc[x + 6])) pdest[x + 6] = pixel; - if ((pixel = psrc[x + 7])) pdest[x + 7] = pixel; - } - psrc += src_y_inc; - pdest += dest_y_inc; - --lines_left; + src_y_inc -= width; + dest_y_inc -= width; + + width_4 = width / 4; + width_remainder = width & 3; + + if (width_4 && !width_remainder) { + if ((width_4 & 1) == 0) { + // width is actually an even multiple of 8! + direct_blit_sprite_8(width_4 / 2, lines_left, pdest, psrc, dest_y_inc, src_y_inc); + } else { + // width is a multiple of 4 (no remainder) + direct_blit_sprite_4(width_4, lines_left, pdest, psrc, dest_y_inc, src_y_inc); } - } else if (width % 4 == 0) { - while (lines_left) { - for (x = 0; x < width; x += 4) { - if ((pixel = psrc[x + 0])) pdest[x + 0] = pixel; - if ((pixel = psrc[x + 1])) pdest[x + 1] = pixel; - if ((pixel = psrc[x + 2])) pdest[x + 2] = pixel; - if ((pixel = psrc[x + 3])) pdest[x + 3] = pixel; - } - psrc += src_y_inc; - pdest += dest_y_inc; - --lines_left; + + } else if (width_4 && width_remainder) { + if ((width_4 & 1) == 0) { + // width is _mostly_ made up of an even multiple of 8, + // plus a small remainder + direct_blit_sprite_8r(width_4 / 2, lines_left, pdest, psrc, width_remainder, dest_y_inc, src_y_inc); + } else { + // width is >= 4 and there is a remainder + direct_blit_sprite_4r(width_4, lines_left, pdest, psrc, width_remainder, dest_y_inc, src_y_inc); } + } else { - while (lines_left) { - for (x = 0; x < width; ++x) { - if ((pixel = psrc[x])) - pdest[x] = pixel; - } - psrc += src_y_inc; - pdest += dest_y_inc; - --lines_left; - } + // width is <= 3 + direct_blit_sprite_r(width_remainder, lines_left, pdest, psrc, dest_y_inc, src_y_inc); } } diff --git a/BLIT.H b/DGLBLIT.H similarity index 53% rename from BLIT.H rename to DGLBLIT.H index 51cab6e..1109df1 100644 --- a/BLIT.H +++ b/DGLBLIT.H @@ -1,7 +1,8 @@ -#ifndef DGL_BLIT_H_INCLUDED -#define DGL_BLIT_H_INCLUDED +#ifndef DGL_DGLBLIT_H_INCLUDED +#define DGL_DGLBLIT_H_INCLUDED -#include "gfx.h" +#include "dglgfx.h" +#include "dglutil.h" void surface_blit_region(const SURFACE *src, SURFACE *dest, @@ -21,8 +22,9 @@ void surface_blit_region_f(const SURFACE *src, int dest_x, int dest_y); -static inline void surface_blit(const SURFACE *src, SURFACE *dest, int x, int y); -static inline void surface_blit_f(const SURFACE *src, SURFACE *dest, int x, int y); +static void surface_blit(const SURFACE *src, SURFACE *dest, int x, int y); + +static void surface_blit_f(const SURFACE *src, SURFACE *dest, int x, int y); void surface_blit_sprite_region(const SURFACE *src, SURFACE *dest, @@ -42,24 +44,34 @@ void surface_blit_sprite_region_f(const SURFACE *src, int dest_x, int dest_y); -static inline void surface_blit_sprite(const SURFACE *src, SURFACE *dest, int x, int y); -static inline void surface_blit_sprite_f(const SURFACE *src, SURFACE *dest, int x, int y); +void direct_blit_4(int width4, int lines, byte *dest, const byte *src, int dest_y_inc, int src_y_inc); +void direct_blit_4r(int width4, int lines, int remainder, byte *dest, const byte *src, int dest_y_inc, int src_y_inc); +void direct_blit_r(int width, int lines, byte *dest, const byte *src, int dest_y_inc, int src_y_inc); +void direct_blit_sprite_4(int width4, int lines, byte *dest, const byte *src, int dest_y_inc, int src_y_inc); +void direct_blit_sprite_4r(int width4, int lines, byte *dest, const byte *src, int remainder, int dest_y_inc, int src_y_inc); +void direct_blit_sprite_r(int width, int lines, byte *dest, const byte *src, int dest_y_inc, int src_y_inc); +void direct_blit_sprite_8(int width8, int lines, byte *dest, const byte *src, int dest_y_inc, int src_y_inc); +void direct_blit_sprite_8r(int width8, int lines, byte *dest, const byte *src, int remainder, int dest_y_inc, int src_y_inc); + +static void surface_blit_sprite(const SURFACE *src, SURFACE *dest, int x, int y); +static void surface_blit_sprite_f(const SURFACE *src, SURFACE *dest, int x, int y); // -------------------------------------------------------------------------- -static inline void surface_blit(const SURFACE *src, SURFACE *dest, int x, int y) { +static void surface_blit(const SURFACE *src, SURFACE *dest, int x, int y) { surface_blit_region(src, dest, 0, 0, src->width, src->height, x, y); } -static inline void surface_blit_f(const SURFACE *src, SURFACE *dest, int x, int y) { + +static void surface_blit_f(const SURFACE *src, SURFACE *dest, int x, int y) { surface_blit_region_f(src, dest, 0, 0, src->width, src->height, x, y); } -static inline void surface_blit_sprite(const SURFACE *src, SURFACE *dest, int x, int y) { +static void surface_blit_sprite(const SURFACE *src, SURFACE *dest, int x, int y) { surface_blit_sprite_region(src, dest, 0, 0, src->width, src->height, x, y); } -static inline void surface_blit_sprite_f(const SURFACE *src, SURFACE *dest, int x, int y) { +static void surface_blit_sprite_f(const SURFACE *src, SURFACE *dest, int x, int y) { surface_blit_sprite_region_f(src, dest, 0, 0, src->width, src->height, x, y); } diff --git a/DGLBLITA.ASM b/DGLBLITA.ASM new file mode 100644 index 0000000..7af4491 --- /dev/null +++ b/DGLBLITA.ASM @@ -0,0 +1,535 @@ +ideal + +p386 +p387 +model flat +codeseg + +locals + +public direct_blit_4_ +public direct_blit_4r_ +public direct_blit_r_ +public direct_blit_sprite_4_ +public direct_blit_sprite_4r_ +public direct_blit_sprite_r_ +public direct_blit_sprite_8_ +public direct_blit_sprite_8r_ + +; direct_blit_4_ +; eax = width4 +; edx = lines +; ebx = dest +; ecx = src +; ebp+8 = dest_y_inc +; ebp+12 = src_y_inc +proc direct_blit_4_ near +arg @@dest_y_inc:dword, @@src_y_inc:dword + + push ebp + mov ebp, esp + push edi + push esi + + mov edi, ebx ; dest pixels + mov esi, ecx ; source pixels + + mov ebx, [@@src_y_inc] + mov ebp, [@@dest_y_inc] ; WARNING: no stack/args access after this! + + ; eax = number of 4-pixel runs (dwords) + ; edx = line loop counter + ; ebx = src_y_inc + ; ebp = dest_y_inc + + test edx, edx ; make sure there is >0 lines to draw + jz @@done + +@@draw_line: + mov ecx, eax ; draw all 4-pixel runs (dwords) + rep movsd + + add esi, ebx ; move to next line + add edi, ebp + dec edx ; decrease line loop counter + jnz @@draw_line ; keep going if there's more lines to draw + +@@done: + pop esi + pop edi + pop ebp + ret 8 + + endp + +; direct_blit_4r_ +; eax = width4 +; edx = lines +; ebx = remainder +; ecx = dest +; ebp+8 = src +; ebp+12 = dest_y_inc +; ebp+16 = src_y_inc +proc direct_blit_4r_ near +arg @@src:dword, @@dest_y_inc:dword, @@src_y_inc:dword + + push ebp + mov ebp, esp + push edi + push esi + + mov edi, ecx ; dest pixels + mov esi, [@@src] ; source pixels + + ; eax = number of 4-pixel runs (dwords) + ; ebx = remaining number of pixels + ; edx = line loop counter + + test edx, edx ; make sure there is >0 lines to draw + jz @@done + +@@draw_line: + mov ecx, eax ; draw all 4-pixel runs (dwords) + rep movsd + mov ecx, ebx ; draw remaining pixels ( <= 3 bytes ) + rep movsb + + add esi, [@@src_y_inc] ; move to next line + add edi, [@@dest_y_inc] + dec edx ; decrease line loop counter + jnz @@draw_line ; keep going if there's more lines to draw + +@@done: + pop esi + pop edi + pop ebp + ret 12 + + endp + +; direct_blit_r_ +; eax = width +; edx = lines +; ebx = dest +; ecx = src +; ebp+8 = dest_y_inc +; ebp+12 = src_y_inc +proc direct_blit_r_ near +arg @@dest_y_inc:dword, @@src_y_inc:dword + + push ebp + mov ebp, esp + push edi + push esi + + mov edi, ebx ; dest pixels + mov esi, ecx ; source pixels + + ; eax = number of pixels to draw (bytes) + ; edx = line loop counter + + test edx, edx ; make sure there is >0 lines to draw + jz @@done + +@@draw_line: + mov ecx, eax ; draw pixels (bytes) + rep movsb + + add esi, [@@src_y_inc] ; move to next line + add edi, [@@dest_y_inc] + dec edx ; decrease line loop counter + jnz @@draw_line ; keep going if there's more lines to draw + +@@done: + pop esi + pop edi + pop ebp + ret 8 + + endp + +; direct_blit_sprite_4_ +; eax = width4 +; edx = lines +; ebx = dest +; ecx = src +; ebp+8 = dest_y_inc +; ebp+12 = src_y_inc +proc direct_blit_sprite_4_ near +arg @@dest_y_inc:dword, @@src_y_inc:dword + + push ebp + mov ebp, esp + push edi + push esi + + mov edi, ebx ; dest pixels + mov esi, ecx ; source pixels + + ; eax = number of 4-pixel runs (dwords) + ; edx = line loop counter + + test edx, edx ; make sure there is >0 lines to be drawn + jz @@done + +@@draw_line: + +@@start_4_run: + mov ecx, eax ; ecx = counter of 4-pixel runs left to draw +@@draw_px_0: + mov bx, [esi+0] ; load src pixel + test bl, bl + jz @@draw_px_1 ; if it is color 0, skip it + mov [edi+0], bl ; otherwise, draw it onto dest +@@draw_px_1: + test bh, bh + jz @@draw_px_2 + mov [edi+1], bh +@@draw_px_2: + mov bx, [esi+2] + test bl, bl + jz @@draw_px_3 + mov [edi+2], bl +@@draw_px_3: + test bh, bh + jz @@end_4_run + mov [edi+3], bh +@@end_4_run: + add esi, 4 ; move src and dest up 4 pixels + add edi, 4 + dec ecx ; decrease 4-pixel run loop counter + jnz @@draw_px_0 ; if there are still more runs, draw them + +@@end_line: + add esi, [@@src_y_inc] ; move src and dest to start of next line + add edi, [@@dest_y_inc] + dec edx ; decrease line loop counter + jnz @@draw_line ; keep going if there's more lines to draw + +@@done: + pop esi + pop edi + pop ebp + ret 8 + + endp + +; direct_blit_sprite_4r_ +; eax = width4 +; edx = lines +; ebx = dest +; ecx = src +; ebp+8 = remainder +; ebp+12 = dest_y_inc +; ebp+16 = src_y_inc +proc direct_blit_sprite_4r_ near +arg @@remainder:dword, @@dest_y_inc:dword, @@src_y_inc:dword + + push ebp + mov ebp, esp + push edi + push esi + + mov edi, ebx ; dest pixels + mov esi, ecx ; source pixels + + ; eax = number of 4-pixel runs (dwords) + ; edx = line loop counter + + test edx, edx ; make sure there is >0 lines to be drawn + jz @@done + +@@draw_line: + +@@start_4_run: ; draw 4-pixel runs first + mov ecx, eax ; ecx = counter of 4-pixel runs left to draw +@@draw_px_0: + mov bx, [esi+0] ; load src pixel + test bl, bl + jz @@draw_px_1 ; if it is color 0, skip it + mov [edi+0], bl ; otherwise, draw it onto dest +@@draw_px_1: + test bh, bh + jz @@draw_px_2 + mov [edi+1], bh +@@draw_px_2: + mov bx, [esi+2] + test bl, bl + jz @@draw_px_3 + mov [edi+2], bl +@@draw_px_3: + test bh, bh + jz @@end_4_run + mov [edi+3], bh +@@end_4_run: + add esi, 4 ; move src and dest up 4 pixels + add edi, 4 + dec ecx ; decrease 4-pixel run loop counter + jnz @@draw_px_0 ; if there are still more runs, draw them + +@@start_remainder_run: ; now draw remaining pixels ( <= 3 pixels ) + mov ecx, [@@remainder] ; ecx = counter of remaining pixels + +@@draw_pixel: + mov bl, [esi] ; load pixel + inc esi + test bl, bl ; if zero, skip to next pixel + jz @@end_pixel + mov [edi], bl ; else, draw pixel +@@end_pixel: + inc edi + dec ecx + jnz @@draw_pixel ; keep drawing pixels while there's still more + +@@end_line: + add esi, [@@src_y_inc] ; move src and dest to start of next line + add edi, [@@dest_y_inc] + dec edx ; decrease line loop counter + jnz @@draw_line ; keep going if there's more lines to draw + +@@done: + pop esi + pop edi + pop ebp + ret 12 + + endp + +; direct_blit_sprite_r_ +; eax = width +; edx = lines +; ebx = dest +; ecx = src +; ebp+8 = dest_y_inc +; ebp+12 = src_y_inc +proc direct_blit_sprite_r_ near +arg @@dest_y_inc:dword, @@src_y_inc:dword + + push ebp + mov ebp, esp + push edi + push esi + + mov edi, ebx ; dest pixels + mov esi, ecx ; source pixels + + ; eax = number of 4-pixel runs (dwords) + ; edx = line loop counter + + test edx, edx ; make sure there is >0 lines to be drawn + jz @@done + +@@draw_line: + mov ecx, eax ; ecx = counter of remaining pixels + +@@draw_pixel: + mov bl, [esi] ; load pixel + inc esi + test bl, bl ; if zero, skip to next pixel + jz @@end_pixel + mov [edi], bl ; else, draw pixel +@@end_pixel: + inc edi + dec ecx + jnz @@draw_pixel ; loop while there's still pixels left + +@@end_line: + add esi, [@@src_y_inc] ; move src and dest to start of next line + add edi, [@@dest_y_inc] + dec edx ; decrease line loop counter + jnz @@draw_line ; keep going if there's more lines to draw + +@@done: + pop esi + pop edi + pop ebp + ret 8 + + endp + +; direct_blit_sprite_8_ +; eax = width8 +; edx = lines +; ebx = dest +; ecx = src +; ebp+8 = dest_y_inc +; ebp+12 = src_y_inc +proc direct_blit_sprite_8_ near +arg @@dest_y_inc:dword, @@src_y_inc:dword + + push ebp + mov ebp, esp + push edi + push esi + + mov edi, ebx ; dest pixels + mov esi, ecx ; source pixels + mov ebp, eax ; WARNING: no named local access after this! + + ; ebp = number of 8-pixel runs + ; edx = line loop counter + ; ebx = pixel data + ; eax = pixel data + + test edx, edx ; make sure there is >0 lines to be drawn + jz @@done + +@@draw_line: + mov ecx, ebp ; ecx = counter of 8-pixel runs left to draw +@@draw_px_0: + mov bx, [esi+0] ; load src pixel + mov ax, [esi+2] + test bl, bl + jz @@draw_px_1 ; if it is color 0, skip it + mov [edi+0], bl ; otherwise, draw it onto dest +@@draw_px_1: + test al, al + jz @@draw_px_2 + mov [edi+2], al +@@draw_px_2: + test bh, bh + jz @@draw_px_3 + mov [edi+1], bh +@@draw_px_3: + test ah, ah + jz @@draw_px_4 + mov [edi+3], ah +@@draw_px_4: + mov bx, [esi+4] + mov ax, [esi+6] + test bl, bl + jz @@draw_px_5 + mov [edi+4], bl +@@draw_px_5: + test al, al + jz @@draw_px_6 + mov [edi+6], al +@@draw_px_6: + test bh, bh + jz @@draw_px_7 + mov [edi+5], bh +@@draw_px_7: + test ah, ah + jz @@end_8_run + mov [edi+7], ah +@@end_8_run: + add esi, 8 ; move src and dest up 8 pixels + add edi, 8 + dec ecx ; decrease 8-pixel run loop counter + jnz @@draw_px_0 ; if there are still more runs, draw them + +@@end_line: + add esi, [esp+20] ; move src and dest to start of next line + add edi, [esp+16] + dec edx ; decrease line loop counter + jnz @@draw_line ; keep going if there's more lines to draw + +@@done: + pop esi + pop edi + pop ebp + ret 8 + + endp + +; direct_blit_sprite_8r_ +; eax = width8 +; edx = lines +; ebx = dest +; ecx = src +; ebp+8 = remainder +; ebp+12 = dest_y_inc +; ebp+16 = src_y_inc +proc direct_blit_sprite_8r_ near +arg @@remainder:dword, @@dest_y_inc:dword, @@src_y_inc:dword + + push ebp + mov ebp, esp + push edi + push esi + + mov edi, ebx ; dest pixels + mov esi, ecx ; source pixels + + ; eax = number of 8-pixel runs + ; edx = line loop counter + + test edx, edx ; make sure there is >0 lines to be drawn + jz @@done + +@@draw_line: + +@@start_8_run: ; draw 8-pixel runs first + mov ecx, eax ; ecx = counter of 8-pixel runs left to draw +@@draw_px_0: + mov bx, [esi+0] ; load src pixel + test bl, bl + jz @@draw_px_1 ; if it is color 0, skip it + mov [edi+0], bl ; otherwise, draw it onto dest +@@draw_px_1: + test bh, bh + jz @@draw_px_2 + mov [edi+1], bh +@@draw_px_2: + mov bx, [esi+2] + test bl, bl + jz @@draw_px_3 + mov [edi+2], bl +@@draw_px_3: + test bh, bh + jz @@draw_px_4 + mov [edi+3], bh +@@draw_px_4: + mov bx, [esi+4] + test bl, bl + jz @@draw_px_5 + mov [edi+4], bl +@@draw_px_5: + test bh, bh + jz @@draw_px_6 + mov [edi+5], bh +@@draw_px_6: + mov bx, [esi+6] + test bl, bl + jz @@draw_px_7 + mov [edi+6], bl +@@draw_px_7: + test bh, bh + jz @@end_8_run + mov [edi+7], bh +@@end_8_run: + add esi, 8 ; move src and dest up 8 pixels + add edi, 8 + dec ecx ; decrease 8-pixel run loop counter + jnz @@draw_px_0 ; if there are still more runs, draw them + +@@start_remainder_run: ; now draw remaining pixels ( <= 7 pixels ) + mov ecx, [@@remainder] ; ecx = counter of remaining pixels + +@@draw_pixel: + mov bl, [esi] ; load pixel + inc esi + test bl, bl ; if zero, skip to next pixel + jz @@end_pixel + mov [edi], bl ; else, draw pixel +@@end_pixel: + inc edi + dec ecx + jnz @@draw_pixel ; loop while there's still pixels left + +@@end_line: + add esi, [@@src_y_inc] ; move src and dest to start of next line + add edi, [@@dest_y_inc] + dec edx ; decrease line loop counter + jnz @@draw_line ; keep going if there's more lines to draw + +@@done: + pop esi + pop edi + pop ebp + ret 12 + + endp + +end + diff --git a/CLIPPING.C b/DGLCLIP.C similarity index 82% rename from CLIPPING.C rename to DGLCLIP.C index fae546b..0731a34 100644 --- a/CLIPPING.C +++ b/DGLCLIP.C @@ -1,15 +1,15 @@ -#include "clipping.h" -#include "common.h" -#include "mathext.h" +#include "dglclip.h" +#include "dglcmn.h" +#include "dglmath.h" -static inline boolean is_in_bounds(int clip_x, - int clip_y, - int clip_right, - int clip_bottom, - int x1, - int y1, - int x2, - int y2) { +static boolean is_in_bounds(int clip_x, + int clip_y, + int clip_right, + int clip_bottom, + int x1, + int y1, + int x2, + int y2) { if (y1 < clip_y && y2 < clip_y) return FALSE; if (y1 > clip_bottom && y2 > clip_bottom) diff --git a/CLIPPING.H b/DGLCLIP.H similarity index 90% rename from CLIPPING.H rename to DGLCLIP.H index 1602a59..4e124d0 100644 --- a/CLIPPING.H +++ b/DGLCLIP.H @@ -1,8 +1,8 @@ -#ifndef DGL_CLIPPING_H_INCLUDED -#define DGL_CLIPPING_H_INCLUDED +#ifndef DGL_DGLCLIP_H_INCLUDED +#define DGL_DGLCLIP_H_INCLUDED -#include "common.h" -#include "rect.h" +#include "dglcmn.h" +#include "dglrect.h" /* * Determines if the given point lies within the clipping region. diff --git a/COMMON.H b/DGLCMN.H similarity index 83% rename from COMMON.H rename to DGLCMN.H index 4ac384a..bfaf68e 100644 --- a/COMMON.H +++ b/DGLCMN.H @@ -1,5 +1,5 @@ -#ifndef DGL_COMMON_H_INCLUDED -#define DGL_COMMON_H_INCLUDED +#ifndef DGL_DGLCMN_H_INCLUDED +#define DGL_DGLCMN_H_INCLUDED typedef int boolean; @@ -27,7 +27,7 @@ typedef unsigned int uint; #define BIT_6 0x40 #define BIT_7 0x80 -#define BIT_ISSET(bit, x) ((x) & (bit) != 0) +#define BIT_ISSET(bit, x) ((x) & (bit)) #define BIT_SET(bit, x) ((x) |= (bit)) #define BIT_CLEAR(bit, x) ((x) &= ~(bit)) #define BIT_TOGGLE(bit, x) ((x) ^= (bit)) diff --git a/DRAW.C b/DGLDRAW.C similarity index 62% rename from DRAW.C rename to DGLDRAW.C index 5b4f017..aa35905 100644 --- a/DRAW.C +++ b/DGLDRAW.C @@ -1,27 +1,36 @@ -#include "draw.h" -#include "gfx.h" -#include "mathext.h" -#include "util.h" -#include "internal.h" +#include "dgldraw.h" +#include "dglgfx.h" +#include "dglmath.h" +#include "dglutil.h" #include #include #include +#include static char printf_buffer[1024]; void surface_hline_f(SURFACE *surface, int x1, int x2, int y, int color) { byte *p = surface_pointer(surface, x1, y); - memset(p, color, x2 - x1 + 1); + mem_fill(p, color, (x2 - x1 + 1)); } void surface_vline_f(SURFACE *surface, int x, int y1, int y2, int color) { byte *p = surface_pointer(surface, x, y1); int line_inc = surface->width; - int y; + int lines_left = y2 - y1 + 1; - for (y = y1; y <= y2; ++y, p += line_inc) { - *p = (byte)color; - } + extern void draw_line(byte *dest, int color, int line_inc, int lines_left); + #pragma aux draw_line = \ + " test ecx, ecx" \ + " jz done" \ + "draw:" \ + " mov [edx], al" \ + " add edx, ebx" \ + " dec ecx" \ + " jnz draw" \ + "done:" \ + parm [edx] [eax] [ebx] [ecx]; + draw_line(p, color, line_inc, lines_left); } void surface_line(SURFACE *surface, int x1, int y1, int x2, int y2, int color) { @@ -152,77 +161,95 @@ void surface_line_f(SURFACE *surface, int x1, int y1, int x2, int y2, int color) } } +extern void draw_both_vert_lines(byte *left, byte *right, int color, int y_inc, int height); +#pragma aux draw_both_vert_lines = \ + " inc ecx" \ + "draw:" \ + " mov [edi], al" \ + " mov [esi], al" \ + " add edi, edx" \ + " add esi, edx" \ + " dec ecx" \ + " jnz draw" \ + "done:" \ + parm [edi] [esi] [eax] [edx] [ecx]; + +extern void draw_vert_line(byte *dest, int color, int y_inc, int height); +#pragma aux draw_vert_line = \ + " inc ecx" \ + "draw:" \ + " mov [edi], al" \ + " add edi, edx" \ + " dec ecx" \ + " jnz draw" \ + "done:" \ + parm [edi] [eax] [edx] [ecx]; + void surface_rect(SURFACE *surface, int x1, int y1, int x2, int y2, int color) { - byte *p1, *p2; - int width; - int y; - int y_inc = surface->width; - int clipped_x1 = x1; - int clipped_y1 = y1; - int clipped_x2 = x2; - int clipped_y2 = y2; - int clip_right = rect_right(&surface->clip_region); - int clip_bottom = rect_bottom(&surface->clip_region); + RECT clipped; + int clipped_x2, clipped_y2; - if (x1 < surface->clip_region.x) - clipped_x1 = surface->clip_region.x; - if (x2 > clip_right) - clipped_x2 = clip_right; + if (x2 < x1) + SWAP(int, x1, x2); + if (y2 < y1) + SWAP(int, y1, y2); - width = clipped_x2 - clipped_x1 + 1; + clipped.x = x1; + clipped.y = y1; + clipped.width = x2 - x1 + 1; + clipped.height = y2 - y1 + 1; + + if (!clip_to_region(&surface->clip_region, &clipped)) + return; + + clipped_x2 = clipped.x + clipped.width - 1; + clipped_y2 = clipped.y + clipped.height - 1; + color = fill32(color); // top line, only if y1 was within bounds - if (y1 < surface->clip_region.y) - clipped_y1 = surface->clip_region.y; - else - memset(surface_pointer(surface, clipped_x1, clipped_y1), color, width); + if (y1 == clipped.y) { + byte *p = surface_pointer(surface, clipped.x, clipped.y); + mem_fill32(p, color, clipped.width); + } // bottom line, only if y2 was within bounds - if (y2 > clip_bottom) - clipped_y2 = clip_bottom; - else - memset(surface_pointer(surface, clipped_x1, clipped_y2), color, width); + if (y2 == clipped_y2) { + byte *p = surface_pointer(surface, clipped.x, clipped_y2); + mem_fill32(p, color, clipped.width); + } // draw both left and right lines if neither x1 nor x2 were clipped - if (x1 == clipped_x1 && x2 == clipped_x2) { - p1 = surface_pointer(surface, x1, y1); - p2 = surface_pointer(surface, x2, y1); - for (y = y1; y <= y2; ++y, p1 += y_inc, p2 += y_inc) { - *p1 = (byte)color; - *p2 = (byte)color; - } + if (x1 == clipped.x && x2 == clipped_x2) { + byte *p1 = surface_pointer(surface, clipped.x, clipped.y); + byte *p2 = surface_pointer(surface, clipped_x2, clipped.y); + draw_both_vert_lines(p1, p2, color, surface->width, clipped.height - 1); // draw left line if x1 was not clipped - } else if (x1 == clipped_x1) { - p1 = surface_pointer(surface, x1, y1); - for (y = y1; y <= y2; ++y, p1 += y_inc) - *p1 = (byte)color; + } else if (x1 == clipped.x) { + byte *p = surface_pointer(surface, clipped.x, clipped.y); + draw_vert_line(p, color, surface->width, clipped.height - 1); // draw right line if x2 was not clipped } else if (x2 == clipped_x2) { - p1 = surface_pointer(surface, x2, y1); - for (y = y1; y <= y2; ++y, p1 += y_inc) - *p1 = (byte)color; + byte *p = surface_pointer(surface, clipped_x2, clipped.y); + draw_vert_line(p, color, surface->width, clipped.height - 1); } } void surface_rect_f(SURFACE *surface, int x1, int y1, int x2, int y2, int color) { - byte *p1, *p2; + byte *p; + byte *p1; + byte *p2; int width = x2 - x1 + 1; - int y; + int lines_left = y2 - y1; int y_inc = surface->width; - p1 = surface_pointer(surface, x1, y1); - p2 = surface_pointer(surface, x1, y2); - memset(p1, color, width); - memset(p2, color, width); + p = surface_pointer(surface, x1, y1); - p1 = surface_pointer(surface, x1, y1); - p2 = surface_pointer(surface, x2, y1); - for (y = y1; y <= y2; ++y, p1 += y_inc, p2 += y_inc) { - *p1 = (byte)color; - *p2 = (byte)color; - } + p1 = p; + p2 = p + width - 1; + + direct_rect_f(color, width, y_inc, lines_left, p1, p2); } void surface_filled_rect(SURFACE *surface, @@ -234,6 +261,11 @@ void surface_filled_rect(SURFACE *surface, if (!clamp_to_region(&surface->clip_region, &x1, &y1, &x2, &y2)) return; + if (x2 < x1) + SWAP(int, x1, x2); + if (y2 < y1) + SWAP(int, y1, y2); + surface_filled_rect_f(surface, x1, y1, x2, y2, color); } @@ -245,14 +277,12 @@ void surface_filled_rect_f(SURFACE *surface, int color) { byte *p; int width = x2 - x1 + 1; - int y; int y_inc = surface->width; + int lines_left = y2 - y1 + 1; p = surface_pointer(surface, x1, y1); - for (y = y1; y <= y2; ++y) { - memset(p, (byte)color, width); - p += y_inc; - } + + direct_filled_rect_f(color, y_inc, width, lines_left, p); } #define CHAR_WIDTH 8 @@ -262,12 +292,12 @@ void surface_filled_rect_f(SURFACE *surface, // dest_x, dest_y - original unclipped render x,y coords // dest_clipped - clipped destination render region -static inline void print_char(SURFACE *surface, - int dest_x, - int dest_y, - const RECT *dest_clipped, - int color, - char c) { +static void print_char(SURFACE *surface, + int dest_x, + int dest_y, + const RECT *dest_clipped, + int color, + char c) { byte *p; byte *rom_char; char char_line_bits; @@ -277,7 +307,7 @@ static inline void print_char(SURFACE *surface, int y_inc = surface->width; p = surface_pointer(surface, dest_clipped->x, dest_clipped->y); - rom_char = map_dos_memory(0xffa6e) + (c * CHAR_HEIGHT); + rom_char = ((byte*)0xffa6e) + (c * CHAR_HEIGHT); // get offset x,y to start rendering char from (will be in range 0-7) offset_x = dest_clipped->x - dest_x; @@ -298,12 +328,12 @@ static inline void print_char(SURFACE *surface, } } -static inline void print_text(SURFACE *surface, - int x, - int y, - int color, - boolean clip, - const char *text) { +static void print_text(SURFACE *surface, + int x, + int y, + int color, + boolean clip, + const char *text) { const char *c; RECT r; RECT draw_r; @@ -311,12 +341,17 @@ static inline void print_text(SURFACE *surface, r = rect(x, y, CHAR_WIDTH, CHAR_HEIGHT); for (c = text; *c; ++c) { - if (*c == '\n') { + switch (*c) { + case '\n': r.x = x; r.y += r.height; - } else if (*c == ' ') { + break; + case ' ': r.x += r.width; - } else { + break; + case '\r': + break; + default: if (clip) { draw_r = r; if (clip_to_region(&surface->clip_region, &draw_r)) diff --git a/DRAW.H b/DGLDRAW.H similarity index 54% rename from DRAW.H rename to DGLDRAW.H index f1460ce..e48a886 100644 --- a/DRAW.H +++ b/DGLDRAW.H @@ -1,18 +1,18 @@ -#ifndef DGL_DRAW_H_INCLUDED -#define DGL_DRAW_H_INCLUDED +#ifndef DGL_DGLDRAW_H_INCLUDED +#define DGL_DGLDRAW_H_INCLUDED -#include "gfx.h" -#include "clipping.h" -#include "util.h" +#include "dglgfx.h" +#include "dglclip.h" +#include "dglutil.h" -static inline void surface_pset(SURFACE *surface, int x, int y, int color); -static inline void surface_pset_f(SURFACE *surface, int x, int y, int color); -static inline int surface_point(const SURFACE *surface, int x, int y); -static inline int surface_point_f(const SURFACE *surface, int x, int y); +static void surface_pset(SURFACE *surface, int x, int y, int color); +static void surface_pset_f(SURFACE *surface, int x, int y, int color); +static int surface_point(const SURFACE *surface, int x, int y); +static int surface_point_f(const SURFACE *surface, int x, int y); -static inline void surface_hline(SURFACE *surface, int x1, int x2, int y, int color); +static void surface_hline(SURFACE *surface, int x1, int x2, int y, int color); void surface_hline_f(SURFACE *surface, int x1, int x2, int y, int color); -static inline void surface_vline(SURFACE *surface, int x, int y1, int y2, int color); +static void surface_vline(SURFACE *surface, int x, int y1, int y2, int color); void surface_vline_f(SURFACE *surface, int x, int y1, int y2, int color); void surface_line(SURFACE *surface, int x1, int y1, int x2, int y2, int color); void surface_line_f(SURFACE *surface, int x1, int y1, int x2, int y2, int color); @@ -27,37 +27,41 @@ void surface_text_f(SURFACE *surface, int x, int y, int color, const char *text) void surface_printf(SURFACE *surface, int x, int y, int color, const char *format, ...); void surface_printf_f(SURFACE *surface, int x, int y, int color, const char *format, ...); +void direct_rect_f(int color, int width, int y_inc, int lines, byte *p1, byte *p2); +void direct_filled_rect_f(int color, int y_inc, int width, int lines, byte *dest); // -------------------------------------------------------------------------- -static inline void surface_pset(SURFACE *surface, int x, int y, int color) { +static void surface_pset(SURFACE *surface, int x, int y, int color) { if (is_point_in_bounds(&surface->clip_region, x, y)) surface_pset_f(surface, x, y, color); } -static inline void surface_pset_f(SURFACE *surface, int x, int y, int color) { - *(surface_pointer(surface, x, y)) = (byte)color; +static void surface_pset_f(SURFACE *surface, int x, int y, int color) { + int offset = surface_offset(surface, x, y); + surface->pixels[offset] = color; } -static inline int surface_point(const SURFACE *surface, int x, int y) { +static int surface_point(const SURFACE *surface, int x, int y) { if (is_point_in_bounds(&surface->clip_region, x, y)) return surface_point_f(surface, x, y); else return 0; } -static inline int surface_point_f(const SURFACE *surface, int x, int y) { - return (int)*(surface_pointer(surface, x, y)); +static int surface_point_f(const SURFACE *surface, int x, int y) { + int offset = surface_offset(surface, x, y); + return surface->pixels[offset]; } -static inline void surface_hline(SURFACE *surface, int x1, int x2, int y, int color) { +static void surface_hline(SURFACE *surface, int x1, int x2, int y, int color) { if (x2 < x1) SWAP(int, x1, x2); if (clamp_to_region(&surface->clip_region, &x1, &y, &x2, &y)) surface_hline_f(surface, x1, x2, y, color); } -static inline void surface_vline(SURFACE *surface, int x, int y1, int y2, int color) { +static void surface_vline(SURFACE *surface, int x, int y1, int y2, int color) { if (y2 < y1) SWAP(int, y1, y2); if (clamp_to_region(&surface->clip_region, &x, &y1, &x, &y2)) diff --git a/DGLDRAWA.ASM b/DGLDRAWA.ASM new file mode 100644 index 0000000..604d18c --- /dev/null +++ b/DGLDRAWA.ASM @@ -0,0 +1,159 @@ +ideal + +p386 +p387 +model flat +codeseg + +locals + +public direct_rect_f_ +public direct_filled_rect_f_ + + +; direct_rect_f_ +; eax = color +; edx = width +; ebx = y_inc +; ecx = lines +; ebp+8 = p1 +; ebp+12 = p2 +proc direct_rect_f_ near +arg @@p1:dword, @@p2:dword + + push ebp + mov ebp, esp + push edi + push esi + + mov ah, al ; spread color byte out over all 32-bits + shl eax, 8 ; so 4 pixels can be written horizontally + mov al, ah ; later on + shl eax, 8 + mov al, ah + + mov edi, [@@p1] ; left edge + mov esi, [@@p2] ; right edge + + ; al = color to draw + ; ebx = amount to inc both pointers by to move down 1 line + ; ecx = number of lines vertically to draw + + test ecx, ecx + jz @@draw_horiz1 + +@@draw_vert: + mov [edi], al + mov [esi], al + add edi, ebx + add esi, ebx + dec ecx + jnz @@draw_vert + +@@draw_horiz1: + ; edi is currently at (x1,y2) after previous drawing. this is the + ; correct location to draw the bottom horizontal line, so we will + ; draw it now + mov ecx, edx ; edx = number of pixels to draw + mov ebx, ecx ; ecx = number of dwords to draw + shr ecx, 2 ; ebx = remaining number of pixels ( <= 3 ) + and ebx, 3 + + rep stosd ; draw the line + mov ecx, ebx + rep stosb + +@@draw_horiz2: + ; now draw top horizontal line + mov edi, [@@p1] ; reset edi to top horizontal line start position + mov ecx, edx ; edx = number of pixels to draw + mov ebx, ecx ; ecx = number of dwords to draw + shr ecx, 2 ; ebx = remaining number of pixels ( <= 3 ) + and ebx, 3 + + rep stosd ; draw the line + mov ecx, ebx + rep stosb + + pop esi + pop edi + pop ebp + ret 8 + + endp + +; direct_filled_rect_f_ +; eax = color +; edx = y_inc +; ebx = width +; ecx = lines +; ebp+8 = dest +proc direct_filled_rect_f_ near +arg @@dest:dword + + push ebp + mov ebp, esp + push edi + push esi + + mov esi, ecx ; get number of lines to be drawn + test esi, esi ; if there are no lines to draw, then return + jz @@done + + mov ah, al ; spread color byte out over all 32-bits + shl eax, 8 ; so 4 pixels can be written horizontally + mov al, ah ; later on + shl eax, 8 + mov al, ah + + mov edi, [@@dest] + sub edx, ebx ; edx = y_inc - width + ; (this is because rep stos will inc edi, so we + ; just need to y-inc by the remaining amount) + + ; *** WARNING: no stack/locals access after this! :) *** + push ebp + mov ebp, ebx ; get width as number of dwords and remaining bytes + and ebp, 3 + shr ebx, 2 + + ; esi = loop counter of number of lines to draw + ; edi = destination to draw at + ; eax = color to draw (filled out over all 32-bits) + ; edx = y_inc - width + ; ebx = number of dwords to draw + ; ebp = remaining number of pixels to draw after the dwords + + test ebp, ebp ; if there are no remaining bytes after dwords + jz @@draw_4 ; then we can do a slightly more optimized draw + +@@draw_4_with_remainder: ; scenario #1: draw dwords + remainder + mov ecx, ebx + rep stosd + mov ecx, ebp + rep stosb + + add edi, edx ; move to start of next line + dec esi ; decrease loop counter (lines left to draw) + jnz @@draw_4_with_remainder + jmp @@done ; done drawing, skip to return + +@@draw_4: ; scenario #2: draw dwords only + mov ecx, ebx + rep stosd + + add edi, edx ; move to start of next line + dec esi ; decrease loop counter (lines left to draw) + jnz @@draw_4 + +@@done: + pop ebp + pop esi + pop edi + pop ebp + ret 4 + + endp + +end + diff --git a/ERROR.H b/DGLERROR.H similarity index 86% rename from ERROR.H rename to DGLERROR.H index bd03c07..c6bd353 100644 --- a/ERROR.H +++ b/DGLERROR.H @@ -1,7 +1,7 @@ -#ifndef DGL_ERROR_H_INCLUDED -#define DGL_ERROR_H_INCLUDED +#ifndef DGL_DGLERROR_H_INCLUDED +#define DGL_DGLERROR_H_INCLUDED -#include "common.h" +#include "dglcmn.h" typedef enum { DGL_NONE = 0, diff --git a/DGLFIXP.C b/DGLFIXP.C new file mode 100644 index 0000000..b644651 --- /dev/null +++ b/DGLFIXP.C @@ -0,0 +1,20 @@ +#include "dglfixp.h" + +fixed fix_sqrt(fixed x) { + int t, q, b, r; + r = x; + b = 0x40000000; + q = 0; + while (b > 0x40) { + t = q + b; + if (r >= t) { + r -= t; + q = t + b; + } + r <<= 1; + b >>= 1; + } + q >>= 8; + return q; +} + diff --git a/DGLFIXP.H b/DGLFIXP.H new file mode 100644 index 0000000..a8c4c07 --- /dev/null +++ b/DGLFIXP.H @@ -0,0 +1,89 @@ +#ifndef DGL_DGLFIXP_H_INCLUDED +#define DGL_DGLFIXP_H_INCLUDED + +#include "dglcmn.h" +#include + +typedef int fixed; + +#define FP_INT_SHIFT 16 +#define FP_FLOAT_SHIFT 65536.0f + +static fixed fix_sin(fixed x); +static fixed fix_cos(fixed x); +static fixed fix_tan(fixed x); + +fixed fix_sqrt(fixed x); + +fixed fix_mul(fixed a, fixed b); +#pragma aux fix_mul = \ + "imul ebx" \ + "shrd eax, edx, 16" \ + parm [eax] [ebx] \ + modify [eax ebx edx]; + +fixed fix_div(fixed a, fixed b); +#pragma aux fix_div = \ + "cdq" \ + "shld edx, eax, 16" \ + "sal eax, 16" \ + "idiv ebx" \ + parm [eax] [ebx] \ + modify [eax ebx edx]; + +#define FTOFIX(f) ((fixed)((f) * FP_FLOAT_SHIFT)) +#define ITOFIX(i) ((fixed)((i) << FP_INT_SHIFT)) +#define FIXTOF(x) ((float)((x) / FP_FLOAT_SHIFT)) +#define FIXTOI(x) ((int)(((x) + 0x8000) >> FP_INT_SHIFT)) + +#define FP_1 ITOFIX(1) +#define FP_2 ITOFIX(2) +#define FP_3 ITOFIX(3) +#define FP_4 ITOFIX(4) +#define FP_5 ITOFIX(5) +#define FP_6 ITOFIX(6) +#define FP_7 ITOFIX(7) +#define FP_8 ITOFIX(8) +#define FP_9 ITOFIX(9) +#define FP_10 ITOFIX(10) + +#define FP_16 ITOFIX(16) +#define FP_32 ITOFIX(32) +#define FP_64 ITOFIX(64) +#define FP_128 ITOFIX(128) +#define FP_256 ITOFIX(256) + +#define FP_0_1 FTOFIX(0.1f) +#define FP_0_2 FTOFIX(0.2f) +#define FP_0_3 FTOFIX(0.3f) +#define FP_0_4 FTOFIX(0.4f) +#define FP_0_5 FTOFIX(0.5f) +#define FP_0_6 FTOFIX(0.6f) +#define FP_0_7 FTOFIX(0.7f) +#define FP_0_8 FTOFIX(0.8f) +#define FP_0_9 FTOFIX(0.9f) + +#define FP_0_25 FTOFIX(0.25f) +#define FP_0_75 FTOFIX(0.75f) + +#define FP_1_OVER_3 FTOFIX(1.0f / 3.0f) +#define FP_2_OVER_3 FTOFIX(2.0f / 3.0f) + +#define FP_PI FTOFIX(3.1415927f) + +// --------------------------------------------------------------------------- + +static fixed fix_sin(fixed x) { + return FTOFIX(sin(FIXTOF(x))); +} + +static fixed fix_cos(fixed x) { + return FTOFIX(cos(FIXTOF(x))); +} + +static fixed fix_tan(fixed x) { + return FTOFIX(tan(FIXTOF(x))); +} + +#endif + diff --git a/DGLGFX.C b/DGLGFX.C new file mode 100644 index 0000000..53e45fb --- /dev/null +++ b/DGLGFX.C @@ -0,0 +1,103 @@ +#include "dglgfx.h" +#include "dglblit.h" +#include "dglutil.h" +#include "dglerror.h" +#include +#include + +extern void _video_mode(int mode); +#pragma aux _video_mode = \ + "int 0x10" \ + parm [eax]; + +static boolean _initialized = FALSE; + +SURFACE *screen = NULL; + +static SURFACE* surface_create_internal(int width, int height, byte *pixels) { + SURFACE *surface = (SURFACE*)malloc(sizeof(SURFACE)); + + surface->width = width; + surface->height = height; + surface->clip_region = rect(0, 0, width, height); + surface->flags = 0; + + if (pixels != NULL) { + surface->flags |= SURFACE_FLAGS_ALIASED; + surface->pixels = pixels; + } else { + int size = width * height; + surface->pixels = (byte*)malloc(size); + mem_fill(surface->pixels, 0, size); + } + + return surface; +} + +boolean video_init(void) { + byte *framebuffer; + + if (_initialized) { + dgl_set_error(DGL_VIDEO_ALREADY_INITIALIZED); + return FALSE; + } + + _video_mode(0x13); + + framebuffer = (byte*)0xa0000; + screen = surface_create_internal(320, 200, framebuffer); + surface_clear(screen, 0); + + _initialized = TRUE; + return TRUE; +} + +boolean video_shutdown(void) { + if (!_initialized) + return TRUE; // don't care + + _video_mode(0x03); + + surface_free(screen); + screen = NULL; + + _initialized = FALSE; + return TRUE; +} + +boolean video_is_initialized(void) { + return _initialized; +} + +void video_wait_vsync(void) { + do {} while (inp(0x3da) & 0x8); + do {} while (!(inp(0x3da) & 0x8)); +} + +SURFACE* surface_create(int width, int height) { + return surface_create_internal(width, height, NULL); +} + +void surface_free(SURFACE *surface) { + if (!surface) + return; + + if (!BIT_ISSET(SURFACE_FLAGS_ALIASED, surface->flags)) + free(surface->pixels); + free(surface); +} + +void surface_clear(SURFACE *surface, int color) { + int length = surface->width * surface->height; + mem_fill(surface->pixels, (byte)color, length); +} + +void surface_copy(const SURFACE *src, SURFACE *dest) { + if (src->width == dest->width && src->height == dest->height) { + int length = src->width * src->height; + mem_copy(dest->pixels, src->pixels, length); + } else { + surface_blit(src, dest, 0, 0); + } +} + diff --git a/DGLGFX.H b/DGLGFX.H new file mode 100644 index 0000000..c4241f3 --- /dev/null +++ b/DGLGFX.H @@ -0,0 +1,44 @@ +#ifndef DGL_DGLGFX_H_INCLUDED +#define DGL_DGLGFX_H_INCLUDED + +#include "dglcmn.h" +#include "dglrect.h" + +typedef struct { + int width; + int height; + byte *pixels; + RECT clip_region; + unsigned int flags; +} SURFACE; + +#define SURFACE_FLAGS_ALIASED BIT_0 + +extern SURFACE *screen; + +boolean video_init(void); +boolean video_shutdown(void); +boolean video_is_initialized(void); + +void video_wait_vsync(void); + +SURFACE* surface_create(int width, int height); +void surface_free(SURFACE *surface); +void surface_clear(SURFACE *surface, int color); +void surface_copy(const SURFACE *src, SURFACE *dest); + +static int surface_offset(const SURFACE *surface, int x, int y); +static byte* surface_pointer(const SURFACE *surface, int x, int y); + +// -------------------------------------------------------------------------- + +static int surface_offset(const SURFACE *surface, int x, int y) { + return (surface->width * y) + x; +} + +static byte* surface_pointer(const SURFACE *surface, int x, int y) { + return surface->pixels + surface_offset(surface, x, y); +} + +#endif + diff --git a/KEYBOARD.C b/DGLKBRD.C similarity index 66% rename from KEYBOARD.C rename to DGLKBRD.C index f3ba4d1..82db172 100644 --- a/KEYBOARD.C +++ b/DGLKBRD.C @@ -1,11 +1,8 @@ -#include "keyboard.h" -#include "internal.h" -#include "util.h" -#include "error.h" +#include "dglkbrd.h" +#include "dglutil.h" +#include "dglerror.h" #include -#include -#include -#include +#include #define PIC_CTRL_PORT 0x20 #define KEYBRD_DATA_PORT 0x60 @@ -33,44 +30,43 @@ volatile KEY _key_scan; uword _old_flags; -_go32_dpmi_seginfo _old_handler; -_go32_dpmi_seginfo _new_handler; +void (interrupt far *_old_handler)(); -static inline void reset_key_states() { +static void reset_key_states() { memset((void*)keys, 0, 128); } // waits until the keyboard status port indicates the data port // can be read from once again -static inline void wait_kb_data_read() { - while ((inportb(KEYBRD_STATUS_PORT) & BIT_0) == 0) { +static void wait_kb_data_read() { + while ((inp(KEYBRD_STATUS_PORT) & BIT_0) == 0) { } } // waits until the keyboard status port indicates the data port // can be written to once again -static inline void wait_kb_data_write() { - while ((inportb(KEYBRD_STATUS_PORT) & BIT_1) != 0) { +static void wait_kb_data_write() { + while ((inp(KEYBRD_STATUS_PORT) & BIT_1) != 0) { } } // sends data to the keyboard data port. checks for success // and returns TRUE if the data write succeeded -static inline boolean send_kb_data(ubyte data) { +static boolean send_kb_data(ubyte data) { ubyte result; wait_kb_data_write(); - outportb(KEYBRD_DATA_PORT, data); + outp(KEYBRD_DATA_PORT, data); wait_kb_data_read(); - result = inportb(KEYBRD_DATA_PORT); + result = inp(KEYBRD_DATA_PORT); return (result == 0xFA); } // keyboard interrupt handler -void kb_int_handler(void) { +void interrupt far kb_int_handler(void) { // read scan code of key that was just pressed - _key_scan = inportb(KEYBRD_DATA_PORT); + _key_scan = inp(KEYBRD_DATA_PORT); if (_key_scan & 0x80) { // high bit set indicates key was released, clear high bit to get // the actual key scan code @@ -83,19 +79,18 @@ void kb_int_handler(void) { _key_last_scan = _key_scan; // indicate key event was processed to keyboard controller - _key_scan = inportb(KEYBRD_CTRL_PORT) | 0x82; - outportb(KEYBRD_CTRL_PORT, _key_scan); - outportb(KEYBRD_CTRL_PORT, _key_scan & 0x7f); - outportb(PIC_CTRL_PORT, 0x20); + _key_scan = inp(KEYBRD_CTRL_PORT) | 0x82; + outp(KEYBRD_CTRL_PORT, _key_scan); + outp(KEYBRD_CTRL_PORT, _key_scan & 0x7f); + outp(PIC_CTRL_PORT, 0x20); } -END_OF_FUNCTION(kb_int_handler) static uword get_kb_flags(void) { - return *((uword*)(map_dos_memory(KEYBRD_FLAGS_ADDR))); + return *((uword*)KEYBRD_FLAGS_ADDR); } static void set_kb_flags(uword flags) { - *((uword*)(map_dos_memory(KEYBRD_FLAGS_ADDR))) = flags; + *((uword*)KEYBRD_FLAGS_ADDR) = flags; } // updates the keyboard indicator LEDs from the num/caps/scroll lock flags @@ -129,25 +124,18 @@ boolean keyboard_init(void) { return FALSE; } - LOCK_MEMORY(keys, 128); - LOCK_VARIABLE(_key_scan); - LOCK_VARIABLE(_key_last_scan); - LOCK_FUNCTION(kb_int_handler); - // preserve old flags _old_flags = get_kb_flags(); reset_key_states(); - if (!_install_irq(9, kb_int_handler, &_new_handler, &_old_handler)) { - dgl_set_error(DGL_KEYBOARD_IRQ_INSTALL_FAILURE); - return FALSE; - } + _old_handler = _dos_getvect(9); + _dos_setvect(9, kb_int_handler); // turn off keyboard LEDs since our interrupt handler does not currently // respect the num/caps/scroll lock statuses - _disable_interrupts(); + int_disable(); update_kb_led(0); - _enable_interrupts(); + int_enable(); _installed = TRUE; return TRUE; @@ -158,14 +146,11 @@ boolean keyboard_shutdown(void) { return TRUE; // don't care // reset keyboard LEDs to previous state - _disable_interrupts(); + int_disable(); update_kb_led(_old_flags); - _enable_interrupts(); + int_enable(); - if (!_restore_irq(9, &_new_handler, &_old_handler)) { - dgl_set_error(DGL_KEYBOARD_IRQ_RESTORE_FAILURE); - return FALSE; - } + _dos_setvect(9, _old_handler); reset_key_states(); // restore keyboard flags to previous state diff --git a/KEYBOARD.H b/DGLKBRD.H similarity index 78% rename from KEYBOARD.H rename to DGLKBRD.H index 372b518..003cb92 100644 --- a/KEYBOARD.H +++ b/DGLKBRD.H @@ -1,15 +1,15 @@ -#ifndef DGL_KEYBOARD_H_INCLUDED -#define DGL_KEYBOARD_H_INCLUDED +#ifndef DGL_DGLKYBRD_H_INCLUDED +#define DGL_DGLKYBRD_H_INCLUDED -#include "common.h" -#include "keys.h" +#include "dglcmn.h" +#include "dglkeys.h" typedef byte KEY; /* * Current state of the keyboard. */ -volatile extern ubyte keys[128]; +extern volatile ubyte keys[128]; /* * Installs a custom keyboard interrupt handler. diff --git a/KEYS.H b/DGLKEYS.H similarity index 94% rename from KEYS.H rename to DGLKEYS.H index b448d69..20da109 100644 --- a/KEYS.H +++ b/DGLKEYS.H @@ -1,5 +1,5 @@ -#ifndef DGL_KEYS_H_INCLUDED -#define DGL_KEYS_H_INCLUDED +#ifndef DGL_DGLKEYS_H_INCLUDED +#define DGL_DGLKEYS_H_INCLUDED #define KEY_ESC 0x01 #define KEY_1 0x02 diff --git a/MATHEXT.C b/DGLMATH.C similarity index 93% rename from MATHEXT.C rename to DGLMATH.C index 78227bb..3812a5d 100644 --- a/MATHEXT.C +++ b/DGLMATH.C @@ -1,4 +1,4 @@ -#include "mathext.h" +#include "dglmath.h" #include float angle_between_i(int x1, int y1, int x2, int y2) { diff --git a/MATHEXT.H b/DGLMATH.H similarity index 68% rename from MATHEXT.H rename to DGLMATH.H index d2c7c4e..413b4ce 100644 --- a/MATHEXT.H +++ b/DGLMATH.H @@ -1,12 +1,13 @@ -#ifndef DGL_MATH_H_INCLUDED -#define DGL_MATH_H_INCLUDED +#ifndef DGL_DGLMATH_H_INCLUDED +#define DGL_DGLMATH_H_INCLUDED -#include "common.h" -#include "vector2.h" +#include "dglcmn.h" +#include "dglvec2.h" #include #define TOLERANCE 0.00001f +#define PI 3.1415927f #define PI_OVER_180 (PI / 180.0f) #define RADIANS_0 0.0f @@ -33,41 +34,41 @@ float angle_between_f(float x1, float y1, float x2, float y2); int next_power_of_2(int n); void point_on_circle(float radius, float radians, float *x, float *y); -static inline VECTOR2F direction_from_angle(float radians); -static inline float round(float value); -static inline float symmetrical_round(float value); -static inline boolean close_enough(float a, float b, float tolerance); -static inline boolean power_of_2(int n); -static inline float smooth_step(float low, float high, float t); +static VECTOR2F direction_from_angle(float radians); +static float round(float value); +static float symmetrical_round(float value); +static boolean close_enough(float a, float b, float tolerance); +static boolean power_of_2(int n); +static float smooth_step(float low, float high, float t); // -------------------------------------------------------------------------- -static inline VECTOR2F direction_from_angle(float radians) { +static VECTOR2F direction_from_angle(float radians) { VECTOR2F direction; point_on_circle(1.0f, radians, &direction.x, &direction.y); return direction; } -static inline float round(float value) { +static float round(float value) { return ceil(value + 0.5f); } -static inline float symmetrical_round(float value) { +static float symmetrical_round(float value) { if (value > 0.0f) return floor(value + 0.5f); else return ceil(value - 0.5f); } -static inline boolean close_enough(float a, float b, float tolerance) { +static boolean close_enough(float a, float b, float tolerance) { return fabs((a - b) / ((b == 0.0f) ? 1.0f : b)) < tolerance; } -static inline boolean power_of_2(int n) { +static boolean power_of_2(int n) { return (n != 0) && !(n & (n - 1)); } -static inline float smooth_step(float low, float high, float t) { +static float smooth_step(float low, float high, float t) { float n = CLAMP(t, 0.0f, 1.0f); return LERP(low, high, (n * n) * (3.0f - (2.0f * n))); } diff --git a/DGLMOUSE.C b/DGLMOUSE.C new file mode 100644 index 0000000..a5f34b9 --- /dev/null +++ b/DGLMOUSE.C @@ -0,0 +1,159 @@ +#include "dglmouse.h" +#include "dglerror.h" +#include +#include + +static boolean _installed = FALSE; +static boolean _has_mouse = FALSE; + +volatile int mouse_x; +volatile int mouse_y; +volatile int mouse_buttons; +volatile int mouse_delta_x; +volatile int mouse_delta_y; + +static void reset_mouse_state(void) { + mouse_x = 0; + mouse_y = 0; + mouse_buttons = 0; + mouse_delta_x = 0; + mouse_delta_y = 0; +} + +static boolean init_mouse_driver(void) { + union REGS regs; + + memset(®s, 0, sizeof(regs)); + regs.w.ax = 0x00; + int386(0x33, ®s, ®s); + + return (regs.w.ax != 0); +} + +static void update_mouse_state(void) { + union REGS regs; + + memset(®s, 0, sizeof(regs)); + regs.w.ax = 0x03; + int386(0x33, ®s, ®s); + mouse_x = (regs.w.cx / 2); + mouse_y = regs.w.dx; + mouse_buttons = regs.w.bx; + mouse_delta_x = 0; + mouse_delta_y = 0; +} + +#pragma off (check_stack) +void __loadds far mouse_int_handler(int eax, int ebx, int ecx, int edx) { + #pragma aux mouse_int_handler parm [eax] [ebx] [ecx] [edx] + mouse_delta_x = (ecx / 2) - mouse_x; + mouse_delta_y = edx - mouse_y; + mouse_x = (ecx / 2); + mouse_y = edx; + mouse_buttons = ebx; +} +#pragma on (check_stack) + +boolean mouse_init(void) { + union REGS regs; + struct SREGS sregs; + + if (_installed) { + dgl_set_error(DGL_MOUSE_ALREADY_INITIALIZED); + return FALSE; + } + + reset_mouse_state(); + + _has_mouse = init_mouse_driver(); + if (!_has_mouse) { + _installed = TRUE; + return TRUE; + } + + update_mouse_state(); + + memset(®s, 0, sizeof(regs)); + memset(&sregs, 0, sizeof(sregs)); + regs.w.ax = 0x0c; + regs.w.cx = 31; + regs.x.edx = FP_OFF(mouse_int_handler); + sregs.es = FP_SEG(mouse_int_handler); + int386x(0x33, ®s, ®s, &sregs); + + _installed = TRUE; + return TRUE; +} + +boolean mouse_shutdown(void) { + union REGS regs; + + if (!_installed) + return TRUE; // don't care + + if (!_has_mouse) { + _installed = FALSE; + return TRUE; + } + + memset(®s, 0, sizeof(regs)); + regs.w.ax = 0x0c; + regs.w.cx = 0; + int386(0x33, ®s, ®s); + + reset_mouse_state(); + init_mouse_driver(); + + _installed = FALSE; + return TRUE; +} + +boolean mouse_is_initialized(void) { + return _installed; +} + +boolean mouse_is_present(void) { + return _has_mouse; +} + +void mouse_show(void) { + union REGS regs; + + if (!_has_mouse) + return; + + memset(®s, 0, sizeof(regs)); + regs.w.ax = 0x01; + int386(0x33, ®s, ®s); +} + +void mouse_hide(void) { + union REGS regs; + + if (!_has_mouse) + return; + + memset(®s, 0, sizeof(regs)); + regs.w.ax = 0x02; + int386(0x33, ®s, ®s); +} + +void mouse_set_bounds(int min_x, int min_y, int max_x, int max_y) { + union REGS regs; + + if (!_has_mouse) + return; + + memset(®s, 0, sizeof(regs)); + + regs.w.ax = 0x07; + regs.w.cx = min_x; + regs.w.dx = max_x; + int386(0x33, ®s, ®s); + + regs.w.ax = 0x08; + regs.w.cx = min_y; + regs.w.dx = max_y; + int386(0x33, ®s, ®s); +} + diff --git a/MOUSE.H b/DGLMOUSE.H similarity index 78% rename from MOUSE.H rename to DGLMOUSE.H index dd40536..bcc7399 100644 --- a/MOUSE.H +++ b/DGLMOUSE.H @@ -1,7 +1,7 @@ -#ifndef DGL_MOUSE_H_INCLUDED -#define DGL_MOUSE_H_INCLUDED +#ifndef DGL_DGLMOUSE_H_INCLUDED +#define DGL_DGLMOUSE_H_INCLUDED -#include "common.h" +#include "dglcmn.h" #define MOUSE_LEFTBUTTON 0x01 #define MOUSE_RIGHTBUTTON 0x02 @@ -10,27 +10,27 @@ /* * Current mouse cursor X position. */ -volatile extern int mouse_x; +extern volatile int mouse_x; /* * Current mouse cursor Y position. */ -volatile extern int mouse_y; +extern volatile int mouse_y; /* * Current state of mouse buttons. */ -volatile extern int mouse_buttons; +extern volatile int mouse_buttons; /* * Amount the cursor moved along the X-axis since the last update. */ -volatile extern int mouse_delta_x; +extern volatile int mouse_delta_x; /* * Amount the cursor moved along the Y-axis since the last update. */ -volatile extern int mouse_delta_y; +extern volatile int mouse_delta_y; /* * Installs a custom mouse handler. @@ -80,11 +80,11 @@ void mouse_set_bounds(int min_x, int min_y, int max_x, int max_y); * @param button The button to check the status of. * @return TRUE if the button is pressed. */ -static inline boolean mouse_button(int button); +static boolean mouse_button(int button); // -------------------------------------------------------------------------- -static inline boolean mouse_button(int button) { +static boolean mouse_button(int button) { return (mouse_buttons & button) != 0; } diff --git a/MATRIX33.H b/DGLMTX33.H similarity index 69% rename from MATRIX33.H rename to DGLMTX33.H index 7ef0e31..44d1f5d 100644 --- a/MATRIX33.H +++ b/DGLMTX33.H @@ -1,9 +1,9 @@ -#ifndef DGL_MATRIX33_H_INCLUDED -#define DGL_MATRIX33_H_INCLUDED +#ifndef DGL_DGLMAT33_H_INCLUDED +#define DGL_DGLMAT33_H_INCLUDED -#include "common.h" -#include "mathext.h" -#include "vector2.h" +#include "dglcmn.h" +#include "dglmath.h" +#include "dglvec2.h" #include #define _M33_11 0 @@ -20,33 +20,33 @@ typedef struct { float m[9]; } MATRIX33; -static inline MATRIX33 matrix33(float m11, float m12, float m13, - float m21, float m22, float m23, - float m31, float m32, float m33); -static inline void matrix33_set(MATRIX33 *m, - float m11, float m12, float m13, - float m21, float m22, float m23, - float m31, float m32, float m33); +static MATRIX33 matrix33(float m11, float m12, float m13, + float m21, float m22, float m23, + float m31, float m32, float m33); +static void matrix33_set(MATRIX33 *m, + float m11, float m12, float m13, + float m21, float m22, float m23, + float m31, float m32, float m33); -static inline MATRIX33 matrix33_from_euler_angles(float x, float y, float z); -static inline MATRIX33 matrix33_rotation_x(float radians); -static inline MATRIX33 matrix33_rotation_y(float radians); -static inline MATRIX33 matrix33_rotation_z(float radians); +static MATRIX33 matrix33_from_euler_angles(float x, float y, float z); +static MATRIX33 matrix33_rotation_x(float radians); +static MATRIX33 matrix33_rotation_y(float radians); +static MATRIX33 matrix33_rotation_z(float radians); -static inline MATRIX33 matrix33_add(MATRIX33 a, MATRIX33 b); -static inline MATRIX33 matrix33_sub(MATRIX33 a, MATRIX33 b); -static inline MATRIX33 matrix33_mul(MATRIX33 a, MATRIX33 b); -static inline MATRIX33 matrix33_scale(MATRIX33 m, float scale); +static MATRIX33 matrix33_add(MATRIX33 a, MATRIX33 b); +static MATRIX33 matrix33_sub(MATRIX33 a, MATRIX33 b); +static MATRIX33 matrix33_mul(MATRIX33 a, MATRIX33 b); +static MATRIX33 matrix33_scale(MATRIX33 m, float scale); -static inline float matrix33_determinant(MATRIX33 m); -static inline MATRIX33 matrix33_inverse(MATRIX33 m); -static inline MATRIX33 matrix33_transpose(MATRIX33 m); -static inline VECTOR2F matrix33_transform(MATRIX33 m, VECTOR2F v); +static float matrix33_determinant(MATRIX33 m); +static MATRIX33 matrix33_inverse(MATRIX33 m); +static MATRIX33 matrix33_transpose(MATRIX33 m); +static VECTOR2F matrix33_transform(MATRIX33 m, VECTOR2F v); -static inline MATRIX33 matrix33_translation_2d(float x, float y); -static inline MATRIX33 matrix33_scaling_2d(float x, float y); -static inline MATRIX33 matrix33_rotation_2d(float radians); -static inline VECTOR2F matrix33_transform_2d(MATRIX33 m, VECTOR2F v); +static MATRIX33 matrix33_translation_2d(float x, float y); +static MATRIX33 matrix33_scaling_2d(float x, float y); +static MATRIX33 matrix33_rotation_2d(float radians); +static VECTOR2F matrix33_transform_2d(MATRIX33 m, VECTOR2F v); #define IDENTITY_MATRIX33 matrix33(1.0f, 0.0f, 0.0f, \ 0.0f, 1.0f, 0.0f, \ @@ -54,9 +54,9 @@ static inline VECTOR2F matrix33_transform_2d(MATRIX33 m, VECTOR2F v); // -------------------------------------------------------------------------- -static inline MATRIX33 matrix33(float m11, float m12, float m13, - float m21, float m22, float m23, - float m31, float m32, float m33) { +static MATRIX33 matrix33(float m11, float m12, float m13, + float m21, float m22, float m23, + float m31, float m32, float m33) { MATRIX33 result; result.m[_M33_11] = m11; result.m[_M33_12] = m12; @@ -70,10 +70,10 @@ static inline MATRIX33 matrix33(float m11, float m12, float m13, return result; } -static inline void matrix33_set(MATRIX33 *m, - float m11, float m12, float m13, - float m21, float m22, float m23, - float m31, float m32, float m33) { +static void matrix33_set(MATRIX33 *m, + float m11, float m12, float m13, + float m21, float m22, float m23, + float m31, float m32, float m33) { m->m[_M33_11] = m11; m->m[_M33_12] = m12; m->m[_M33_13] = m13; @@ -85,7 +85,7 @@ static inline void matrix33_set(MATRIX33 *m, m->m[_M33_33] = m33; } -static inline MATRIX33 matrix33_from_euler_angles(float x, float y, float z) { +static MATRIX33 matrix33_from_euler_angles(float x, float y, float z) { MATRIX33 rx, ry, rz; rx = matrix33_rotation_x(x); ry = matrix33_rotation_y(y); @@ -93,7 +93,7 @@ static inline MATRIX33 matrix33_from_euler_angles(float x, float y, float z) { return matrix33_mul(matrix33_mul(rz, ry), rx); } -static inline MATRIX33 matrix33_rotation_x(float radians) { +static MATRIX33 matrix33_rotation_x(float radians) { MATRIX33 result; float s, c; @@ -115,7 +115,7 @@ static inline MATRIX33 matrix33_rotation_x(float radians) { return result; } -static inline MATRIX33 matrix33_rotation_y(float radians) { +static MATRIX33 matrix33_rotation_y(float radians) { MATRIX33 result; float s, c; @@ -137,7 +137,7 @@ static inline MATRIX33 matrix33_rotation_y(float radians) { return result; } -static inline MATRIX33 matrix33_rotation_z(float radians) { +static MATRIX33 matrix33_rotation_z(float radians) { MATRIX33 result; float s, c; @@ -159,7 +159,7 @@ static inline MATRIX33 matrix33_rotation_z(float radians) { return result; } -static inline MATRIX33 matrix33_add(MATRIX33 a, MATRIX33 b) { +static MATRIX33 matrix33_add(MATRIX33 a, MATRIX33 b) { MATRIX33 result; result.m[_M33_11] = a.m[_M33_11] + b.m[_M33_11]; @@ -175,7 +175,7 @@ static inline MATRIX33 matrix33_add(MATRIX33 a, MATRIX33 b) { return result; } -static inline MATRIX33 matrix33_sub(MATRIX33 a, MATRIX33 b) { +static MATRIX33 matrix33_sub(MATRIX33 a, MATRIX33 b) { MATRIX33 result; result.m[_M33_11] = a.m[_M33_11] - b.m[_M33_11]; @@ -191,7 +191,7 @@ static inline MATRIX33 matrix33_sub(MATRIX33 a, MATRIX33 b) { return result; } -static inline MATRIX33 matrix33_mul(MATRIX33 a, MATRIX33 b) { +static MATRIX33 matrix33_mul(MATRIX33 a, MATRIX33 b) { MATRIX33 result; result.m[_M33_11] = a.m[_M33_11] * b.m[_M33_11] + a.m[_M33_12] * b.m[_M33_21] + a.m[_M33_13] * b.m[_M33_31]; @@ -209,7 +209,7 @@ static inline MATRIX33 matrix33_mul(MATRIX33 a, MATRIX33 b) { return result; } -static inline MATRIX33 matrix33_scale(MATRIX33 m, float scale) { +static MATRIX33 matrix33_scale(MATRIX33 m, float scale) { MATRIX33 result; result.m[_M33_11] = m.m[_M33_11] * scale; @@ -225,7 +225,7 @@ static inline MATRIX33 matrix33_scale(MATRIX33 m, float scale) { return result; } -static inline float matrix33_determinant(MATRIX33 m) { +static float matrix33_determinant(MATRIX33 m) { return m.m[_M33_11] * m.m[_M33_22] * m.m[_M33_33] + m.m[_M33_12] * m.m[_M33_23] * m.m[_M33_31] + @@ -235,7 +235,7 @@ static inline float matrix33_determinant(MATRIX33 m) { m.m[_M33_13] * m.m[_M33_22] * m.m[_M33_31]; } -static inline MATRIX33 matrix33_inverse(MATRIX33 m) { +static MATRIX33 matrix33_inverse(MATRIX33 m) { float d; MATRIX33 result; d = matrix33_determinant(m); @@ -258,7 +258,7 @@ static inline MATRIX33 matrix33_inverse(MATRIX33 m) { } } -static inline MATRIX33 matrix33_transpose(MATRIX33 m) { +static MATRIX33 matrix33_transpose(MATRIX33 m) { MATRIX33 result; result.m[_M33_11] = m.m[_M33_11]; @@ -276,7 +276,7 @@ static inline MATRIX33 matrix33_transpose(MATRIX33 m) { return result; } -static inline VECTOR2F matrix33_transform(MATRIX33 m, VECTOR2F v) { +static VECTOR2F matrix33_transform(MATRIX33 m, VECTOR2F v) { VECTOR2F result; result.x = v.x * m.m[_M33_11] + v.y * m.m[_M33_12] + m.m[_M33_13]; @@ -285,7 +285,7 @@ static inline VECTOR2F matrix33_transform(MATRIX33 m, VECTOR2F v) { return result; } -static inline MATRIX33 matrix33_translation_2d(float x, float y) { +static MATRIX33 matrix33_translation_2d(float x, float y) { MATRIX33 result; result.m[_M33_11] = 1.0f; @@ -303,7 +303,7 @@ static inline MATRIX33 matrix33_translation_2d(float x, float y) { return result; } -static inline MATRIX33 matrix33_scaling_2d(float x, float y) { +static MATRIX33 matrix33_scaling_2d(float x, float y) { MATRIX33 result; result.m[_M33_11] = x; @@ -321,11 +321,11 @@ static inline MATRIX33 matrix33_scaling_2d(float x, float y) { return result; } -static inline MATRIX33 matrix33_rotation_2d(float radians) { +static MATRIX33 matrix33_rotation_2d(float radians) { return matrix33_rotation_z(radians); } -static inline VECTOR2F matrix33_transform_2d(MATRIX33 m, VECTOR2F v) { +static VECTOR2F matrix33_transform_2d(MATRIX33 m, VECTOR2F v) { VECTOR2F result; result.x = v.x * m.m[_M33_11] + v.y * m.m[_M33_12] + m.m[_M33_13]; diff --git a/DGLPAL.C b/DGLPAL.C new file mode 100644 index 0000000..00f74d5 --- /dev/null +++ b/DGLPAL.C @@ -0,0 +1,109 @@ +#include "dglpal.h" +#include "dglgfx.h" +#include +#include + +void pal_set_color(byte color, byte r, byte g, byte b) { + outp(0x3c6, 0xff); + outp(0x3c8, color); + outp(0x3c9, r); + outp(0x3c9, g); + outp(0x3c9, b); +} + +void pal_get_color(byte color, byte *r, byte *g, byte *b) { + outp(0x3c6, 0xff); + outp(0x3c7, color); + *r = inp(0x3c9); + *g = inp(0x3c9); + *b = inp(0x3c9); +} + +void pal_set(const byte *palette) { + int i = 0; + for (i = 0; i < 256; ++i) { + pal_set_color(i, palette[0], palette[1], palette[2]); + palette += 3; + } +} + +void pal_get(byte *palette) { + int i = 0; + for (i = 0; i < 256; ++i) { + pal_get_color(i, palette, palette + 1, palette + 2); + palette += 3; + } +} + +static boolean fade_color(int color, byte r, byte g, byte b, int step) { + byte red, green, blue; + byte diff_r, diff_g, diff_b; + boolean color_diff = FALSE; + + pal_get_color(color, &red, &green, &blue); + + if (red != r) { + color_diff = TRUE; + diff_r = abs(red - r); + if (red > r) + red -= min(step, diff_r); + else + red += min(step, diff_r); + } + + if (green != g) { + color_diff = TRUE; + diff_g = abs(green - g); + if (green > g) + green -= min(step, diff_g); + else + green += min(step, diff_g); + } + + if (blue != b) { + color_diff = TRUE; + diff_b = abs(blue - b); + if (blue > b) + blue -= min(step, diff_b); + else + blue += min(step, diff_b); + } + + if (color_diff) + pal_set_color(color, red, green, blue); + + return (red == r && green == g && blue == b); +} + +void pal_fade_range_to_color(int start, int end, byte r, byte g, byte b, int step) { + int i; + boolean done = FALSE; + + step = abs(step); + + while (!done) { + done = TRUE; + video_wait_vsync(); + for (i = start; i <= end; ++i) { + if (!fade_color(i, r, g, b, step)) + done = FALSE; + } + } +} + +void pal_fade_range_to_palette(int start, int end, const byte *palette, int step) { + int color, i; + boolean done = FALSE; + + step = abs(step); + + while (!done) { + done = TRUE; + video_wait_vsync(); + for (i = (start * 3), color = start; color <= end; ++color, i += 3) { + if (!fade_color(color, palette[i], palette[i + 1], palette[i + 2], step)) + done = FALSE; + } + } +} + diff --git a/DGLPAL.H b/DGLPAL.H new file mode 100644 index 0000000..69c1c1e --- /dev/null +++ b/DGLPAL.H @@ -0,0 +1,27 @@ +#ifndef DGL_DGLPAL_H_INCLUDED +#define DGL_DGLPAL_H_INCLUDED + +#include "dglcmn.h" + +void pal_set_color(byte color, byte r, byte g, byte b); +void pal_get_color(byte color, byte *r, byte *g, byte *b); +void pal_set(const byte *palette); +void pal_get(byte *palette); + +void pal_fade_range_to_color(int start, int end, byte r, byte g, byte b, int step); +void pal_fade_range_to_palette(int start, int end, const byte *palette, int step); +static void pal_fade_to_color(byte r, byte g, byte b, int step); +static void pal_fade_to_palette(const byte *palette, int step); + +// -------------------------------------------------------------------------- + +static void pal_fade_to_color(byte r, byte g, byte b, int step) { + pal_fade_range_to_color(0, 255, r, g, b, step); +} + +static void pal_fade_to_palette(const byte *palette, int step) { + pal_fade_range_to_palette(0, 255, palette, step); +} + +#endif + diff --git a/PCX.C b/DGLPCX.C similarity index 79% rename from PCX.C rename to DGLPCX.C index b46ff7e..1b802bc 100644 --- a/PCX.C +++ b/DGLPCX.C @@ -1,8 +1,10 @@ -#include "pcx.h" -#include "gfx.h" -#include "draw.h" -#include "error.h" +#include "dglpcx.h" +#include "dglgfx.h" +#include "dglpal.h" +#include "dgldraw.h" +#include "dglerror.h" #include +#include typedef struct { byte manufacturer; @@ -28,7 +30,7 @@ typedef struct { SURFACE* pcx_load(const char *filename, byte *pcx_palette) { FILE *fp; PCX_HEADER header; - int i, n, count; + int i, n, count, x, y; SURFACE *pcx; ubyte data; @@ -56,27 +58,32 @@ SURFACE* pcx_load(const char *filename, byte *pcx_palette) { pcx = surface_create(header.width + 1, header.height + 1); - // read pixel data - i = 0; - while (i < (header.width * header.height)) { - n = fread(&data, 1, 1, fp); - if (n == -1) - goto pcx_load_error; + i = 0; + for (y = 0; y < (header.height + 1); ++y) { + // write pixels out per-scanline (technically this is what the pcx + // standard specifies, though a lot of pcx loaders don't do this). + x = 0; + while (x < header.bytes_per_line) { + // read pixel (or RLE count...) + data = fgetc(fp); + if ((data & 0xc0) == 0xc0) { + // was an RLE count, pixel is next byte + count = data & 0x3f; + data = fgetc(fp); + } else { + count = 1; + } - if (data >= 192) { - count = data - 192; - n = fread(&data, 1, 1, fp); - if (n == -1) - goto pcx_load_error; - - while (count > 0) { - pcx->pixels[i++] = data; - count--; - } - } else { - pcx->pixels[i++] = data; - } - } + // store this pixel colour the specified number of times + while (count--) { + if (x < pcx->width) { + pcx->pixels[i] = data; + } + ++i; + ++x; + } + } + } // read palette (only if needed) if (pcx_palette) { @@ -100,7 +107,7 @@ pcx_load_error: return NULL; } -static inline boolean write_pcx_data(FILE *fp, int run_count, byte pixel) { +static boolean write_pcx_data(FILE *fp, int run_count, byte pixel) { int n; if ((run_count > 1) || ((pixel & 0xc0) == 0xc0)) { @@ -198,7 +205,7 @@ boolean pcx_save(const char *filename, const SURFACE *src, const byte *palette) } } else { for (i = 0; i < 256; ++i) { - video_get_color(i, &r, &g, &b); + pal_get_color(i, &r, &g, &b); n = fputc(r << 2, fp); if (n == -1) diff --git a/PCX.H b/DGLPCX.H similarity index 57% rename from PCX.H rename to DGLPCX.H index 2b7dc1f..36a8ad6 100644 --- a/PCX.H +++ b/DGLPCX.H @@ -1,8 +1,8 @@ -#ifndef DGL_PCX_H_INCLUDED -#define DGL_PCX_H_INCLUDED +#ifndef DGL_DGLPCX_H_INCLUDED +#define DGL_DGLPCX_H_INCLUDED -#include "common.h" -#include "gfx.h" +#include "dglcmn.h" +#include "dglgfx.h" SURFACE* pcx_load(const char *filename, byte *pcx_palette); boolean pcx_save(const char *filename, const SURFACE *src, const byte *palette); diff --git a/RECT.H b/DGLRECT.H similarity index 53% rename from RECT.H rename to DGLRECT.H index 61c807c..2632450 100644 --- a/RECT.H +++ b/DGLRECT.H @@ -1,5 +1,5 @@ -#ifndef DGL_RECT_H_INCLUDED -#define DGL_RECT_H_INCLUDED +#ifndef DGL_DGLRECT_H_INCLUDED +#define DGL_DGLRECT_H_INCLUDED typedef struct { int x; @@ -8,13 +8,13 @@ typedef struct { int height; } RECT; -static inline RECT rect(int x, int y, int width, int height); -static inline int rect_right(const RECT *r); -static inline int rect_bottom(const RECT *r); +static RECT rect(int x, int y, int width, int height); +static int rect_right(const RECT *r); +static int rect_bottom(const RECT *r); // -------------------------------------------------------------------------- -static inline RECT rect(int x, int y, int width, int height) { +static RECT rect(int x, int y, int width, int height) { RECT result; result.x = x; result.y = y; @@ -23,14 +23,14 @@ static inline RECT rect(int x, int y, int width, int height) { return result; } -static inline int rect_right(const RECT *r) { +static int rect_right(const RECT *r) { if (r->width) return r->x + r->width - 1; else return r->x; } -static inline int rect_bottom(const RECT *r) { +static int rect_bottom(const RECT *r) { if (r->height) return r->y + r->height - 1; else diff --git a/DGLUTIL.C b/DGLUTIL.C new file mode 100644 index 0000000..16360f0 --- /dev/null +++ b/DGLUTIL.C @@ -0,0 +1,22 @@ +#include "dglutil.h" +#include + +#define SYS_CLOCKS_PER_SEC (1000.0f / 55.0f) + + +int sys_clock() { + return *((int*)0x046c); +} + +float clock_ticks_to_seconds(int clocks) { + return clocks / (float)SYS_CLOCKS_PER_SEC; +} + +int rnd_int(int low, int high) { + return rand() % ((high - low) + 1) + low; +} + +float rnd_float(float low, float high) { + return low + (rand() / (float)RAND_MAX) * (high - low); +} + diff --git a/DGLUTIL.H b/DGLUTIL.H new file mode 100644 index 0000000..5c18a88 --- /dev/null +++ b/DGLUTIL.H @@ -0,0 +1,100 @@ +#ifndef DGL_DGLUTIL_H_INCLUDED +#define DGL_DGLUTIL_H_INCLUDED + +#include "dglcmn.h" + +#define SWAP(type, a, b) \ + do { \ + type __tmp = a; \ + a = b; \ + b = __tmp; \ + } while (0) + +#define SIGN(x) (((x) < 0) ? -1 : (((x) > 0) ? 1 : 0)) + +int sys_clock(); +float clock_ticks_to_seconds(int clocks); + +int rnd_int(int low, int high); +float rnd_float(float low, float high); + +void int_enable(void); +#pragma aux int_enable = "sti" + +void int_disable(void); +#pragma aux int_disable = "cli" + +int fill32(byte value); +#pragma aux fill32 = \ + "mov ah, al" \ + "shl eax, 8" \ + "mov al, ah" \ + "shl eax, 8" \ + "mov al, ah" \ + parm [eax] \ + value [eax]; + +void REP_MOVSD(const void *src, void *dest, int num_dwords); +#pragma aux REP_MOVSD = \ + "cld" \ + "rep movsd" \ + parm [esi] [edi] [ecx]; + +void REP_MOVSB(const void *src, void *dest, int num_bytes); +#pragma aux REP_MOVSB = \ + "cld" \ + "rep movsb" \ + parm [esi] [edi] [ecx]; + +void REP_STOSD(int value, void *dest, int num_dwords); +#pragma aux REP_STOSD = \ + "cld" \ + "rep stosd" \ + parm [eax] [edi] [ecx]; + +void REP_STOSB(int value, void *dest, int num_bytes); +#pragma aux REP_STOSB = \ + "cld" \ + "rep stosb" \ + parm [eax] [edi] [ecx]; + +void mem_fill(void *dest, byte value, int num_bytes); +#pragma aux mem_fill = \ + "mov ah, al" \ + "shl eax, 8" \ + "mov al, ah" \ + "shl eax, 8" \ + "mov al, ah" \ + "mov ebx, ecx" \ + "shr ecx, 2" \ + "and ebx, 3" \ + "rep stosd" \ + "mov ecx, ebx" \ + "rep stosb" \ + parm [edi] [eax] [ecx] \ + modify [eax ebx ecx edi]; + +void mem_fill32(void *dest, int value, int num_bytes); +#pragma aux mem_fill32 = \ + "mov ebx, ecx" \ + "shr ecx, 2" \ + "and ebx, 3" \ + "rep stosd" \ + "mov ecx, ebx" \ + "rep stosb" \ + parm [edi] [eax] [ecx] \ + modify [eax ebx ecx edi]; + +void mem_copy(void *dest, const void *src, int num_bytes); +#pragma aux mem_copy = \ + "mov ebx, ecx" \ + "shr ecx, 2" \ + "and ebx, 3" \ + "rep movsd" \ + "mov ecx, ebx" \ + "rep movsb" \ + parm [edi] [esi] [ecx] \ + modify [eax ebx ecx]; + +#endif + diff --git a/DGLVEC2.H b/DGLVEC2.H new file mode 100644 index 0000000..d410a5f --- /dev/null +++ b/DGLVEC2.H @@ -0,0 +1,436 @@ +#ifndef DGL_DGLVEC2_H_INCLUDED +#define DGL_DGLVEC2_H_INCLUDED + +#include +#include "dglcmn.h" +#include "dglfixp.h" + + +typedef struct { + int x; + int y; +} VECTOR2I; + +static VECTOR2I vector2i(int x, int y); +static void vector2i_set(VECTOR2I *v, int x, int y); +static boolean vector2i_equals(VECTOR2I a, VECTOR2I b); +static VECTOR2I vector2i_add(VECTOR2I a, VECTOR2I b); +static VECTOR2I vector2i_sub(VECTOR2I a, VECTOR2I b); +static VECTOR2I vector2i_mul(VECTOR2I a, VECTOR2I b); +static VECTOR2I vector2i_muls(VECTOR2I v, int n); +static VECTOR2I vector2i_div(VECTOR2I a, VECTOR2I b); +static VECTOR2I vector2i_divs(VECTOR2I v, int n); +static int vector2i_distance(VECTOR2I a, VECTOR2I b); +static int vector2i_distancesq(VECTOR2I a, VECTOR2I b); +static int vector2i_dot(VECTOR2I a, VECTOR2I b); +static int vector2i_length(VECTOR2I v); +static int vector2i_lengthsq(VECTOR2I v); +static VECTOR2I vector2i_lerp(VECTOR2I a, VECTOR2I b, float lerp); + +#define ZERO_VECTOR2I vector2i(0, 0) +#define UP_VECTOR2I vector2i(0, -1); +#define DOWN_VECTOR2I vector2i(0, 1); +#define LEFT_VECTOR2I vector2i(-1, 0); +#define RIGHT_VECTOR2I vector2i(1, 0); +#define UNIT_X_VECTOR2I vector2i(1, 0); +#define UNIT_Y_VECTOR2I vector2i(0, 1); + + +typedef struct { + float x; + float y; +} VECTOR2F; + +static VECTOR2F vector2f(float x, float y); +static void vector2f_set(VECTOR2F *v, float x, float y); +static boolean vector2f_equals(VECTOR2F a, VECTOR2F b); +static VECTOR2F vector2f_add(VECTOR2F a, VECTOR2F b); +static VECTOR2F vector2f_sub(VECTOR2F a, VECTOR2F b); +static VECTOR2F vector2f_mul(VECTOR2F a, VECTOR2F b); +static VECTOR2F vector2f_muls(VECTOR2F v, float n); +static VECTOR2F vector2f_div(VECTOR2F a, VECTOR2F b); +static VECTOR2F vector2f_divs(VECTOR2F v, float n); +static float vector2f_distance(VECTOR2F a, VECTOR2F b); +static float vector2f_distancesq(VECTOR2F a, VECTOR2F b); +static float vector2f_dot(VECTOR2F a, VECTOR2F b); +static float vector2f_length(VECTOR2F v); +static float vector2f_lengthsq(VECTOR2F v); +static VECTOR2F vector2f_normalize(VECTOR2F v); +static VECTOR2F vector2f_set_length(VECTOR2F v, float length); +static VECTOR2F vector2f_lerp(VECTOR2F a, VECTOR2F b, float lerp); + +#define ZERO_VECTOR2F vector2f(0.0f, 0.0f) +#define UP_VECTOR2F vector2f(0.0f, -1.0f); +#define DOWN_VECTOR2F vector2f(0.0f, 1.0f); +#define LEFT_VECTOR2F vector2f(-1.0f, 0.0f); +#define RIGHT_VECTOR2F vector2f(1.0f, 0.0f); +#define UNIT_X_VECTOR2F vector2f(1.0f, 0.0f); +#define UNIT_Y_VECTOR2F vector2f(0.0f, 1.0f); + + +typedef struct { + fixed x; + fixed y; +} VECTOR2FP; + +static VECTOR2FP vector2fp(fixed x, fixed y); +static void vector2fp_set(VECTOR2FP *v, fixed x, fixed y); +static boolean vector2fp_equals(VECTOR2FP a, VECTOR2FP b); +static VECTOR2FP vector2fp_add(VECTOR2FP a, VECTOR2FP b); +static VECTOR2FP vector2fp_sub(VECTOR2FP a, VECTOR2FP b); +static VECTOR2FP vector2fp_mul(VECTOR2FP a, VECTOR2FP b); +static VECTOR2FP vector2fp_muls(VECTOR2FP v, fixed n); +static VECTOR2FP vector2fp_div(VECTOR2FP a, VECTOR2FP b); +static VECTOR2FP vector2fp_divs(VECTOR2FP v, fixed n); +static fixed vector2fp_distance(VECTOR2FP a, VECTOR2FP b); +static fixed vector2fp_distancesq(VECTOR2FP a, VECTOR2FP b); +static fixed vector2fp_dot(VECTOR2FP a, VECTOR2FP b); +static fixed vector2fp_length(VECTOR2FP v); +static fixed vector2fp_lengthsq(VECTOR2FP v); +static VECTOR2FP vector2fp_normalize(VECTOR2FP v); +static VECTOR2FP vector2fp_set_length(VECTOR2FP v, fixed length); +static VECTOR2FP vector2fp_lerp(VECTOR2FP a, VECTOR2FP b, fixed lerp); + +#define ZERO_VECTOR2FP vector2fp(0, 0) +#define UP_VECTOR2FP vector2fp(0, (-1 << 16)); +#define DOWN_VECTOR2FP vector2fp(0, (1 << 16)); +#define LEFT_VECTOR2FP vector2fp((-1 << 16), 0); +#define RIGHT_VECTOR2FP vector2fp((1 << 16), 0); +#define UNIT_X_VECTOR2FP vector2fp((1 << 16), 0); +#define UNIT_Y_VECTOR2FP vector2fp(0, (1 << 16)); + +// -------------------------------------------------------------------------- + +static VECTOR2I vector2i(int x, int y) { + VECTOR2I v; + v.x = x; + v.y = y; + return v; +} + +static VECTOR2F vector2f(float x, float y) { + VECTOR2F v; + v.x = x; + v.y = y; + return v; +} + +static VECTOR2FP vector2fp(fixed x, fixed y) { + VECTOR2FP v; + v.x = x; + v.y = y; + return v; +} + +static void vector2i_set(VECTOR2I *v, int x, int y) { + v->x = x; + v->y = y; +} + +static void vector2f_set(VECTOR2F *v, float x, float y) { + v->x = x; + v->y = y; +} + +static void vector2fp_set(VECTOR2FP *v, fixed x, fixed y) { + v->x = x; + v->y = y; +} + +static boolean vector2i_equals(VECTOR2I a, VECTOR2I b) { + return (a.x == b.x && a.y == b.y); +} + +static boolean vector2f_equals(VECTOR2F a, VECTOR2F b) { + return (a.x == b.x && a.y == b.y); +} + +static boolean vector2fp_equals(VECTOR2FP a, VECTOR2FP b) { + return (a.x == b.x && a.y == b.y); +} + +static VECTOR2I vector2i_add(VECTOR2I a, VECTOR2I b) { + VECTOR2I result; + result.x = a.x + b.x; + result.y = a.y + b.y; + return result; +} + +static VECTOR2F vector2f_add(VECTOR2F a, VECTOR2F b) { + VECTOR2F result; + result.x = a.x + b.x; + result.y = a.y + b.y; + return result; +} + +static VECTOR2FP vector2fp_add(VECTOR2FP a, VECTOR2FP b) { + VECTOR2FP result; + result.x = a.x + b.x; + result.y = a.y + b.y; + return result; +} + +static VECTOR2I vector2i_sub(VECTOR2I a, VECTOR2I b) { + VECTOR2I result; + result.x = a.x - b.x; + result.y = a.y - b.y; + return result; +} + +static VECTOR2F vector2f_sub(VECTOR2F a, VECTOR2F b) { + VECTOR2F result; + result.x = a.x - b.x; + result.y = a.y - b.y; + return result; +} + +static VECTOR2FP vector2fp_sub(VECTOR2FP a, VECTOR2FP b) { + VECTOR2FP result; + result.x = a.x - b.x; + result.y = a.y - b.y; + return result; +} + +static VECTOR2I vector2i_mul(VECTOR2I a, VECTOR2I b) { + VECTOR2I result; + result.x = a.x * b.x; + result.y = a.y * b.y; + return result; +} + +static VECTOR2F vector2f_mul(VECTOR2F a, VECTOR2F b) { + VECTOR2F result; + result.x = a.x * b.x; + result.y = a.y * b.y; + return result; +} + +static VECTOR2FP vector2fp_mul(VECTOR2FP a, VECTOR2FP b) { + VECTOR2FP result; + result.x = fix_mul(a.x, b.x); + result.y = fix_mul(a.y, b.y); + return result; +} + +static VECTOR2I vector2i_muls(VECTOR2I v, int n) { + VECTOR2I result; + result.x = v.x * n; + result.y = v.y * n; + return result; +} + +static VECTOR2F vector2f_muls(VECTOR2F v, float n) { + VECTOR2F result; + result.x = v.x * n; + result.y = v.y * n; + return result; +} + +static VECTOR2FP vector2fp_muls(VECTOR2FP v, fixed n) { + VECTOR2FP result; + result.x = fix_mul(v.x, n); + result.y = fix_mul(v.y, n); + return result; +} + +static VECTOR2I vector2i_div(VECTOR2I a, VECTOR2I b) { + VECTOR2I result; + result.x = a.x / b.x; + result.y = a.y / b.y; + return result; +} + +static VECTOR2F vector2f_div(VECTOR2F a, VECTOR2F b) { + VECTOR2F result; + result.x = a.x / b.x; + result.y = a.y / b.y; + return result; +} + +static VECTOR2FP vector2fp_div(VECTOR2FP a, VECTOR2FP b) { + VECTOR2FP result; + result.x = fix_div(a.x, b.x); + result.y = fix_div(a.y, b.y); + return result; +} + +static VECTOR2I vector2i_divs(VECTOR2I v, int n) { + VECTOR2I result; + result.x = v.x / n; + result.y = v.y / n; + return result; +} + +static VECTOR2F vector2f_divs(VECTOR2F v, float n) { + VECTOR2F result; + result.x = v.x / n; + result.y = v.y / n; + return result; +} + +static VECTOR2FP vector2fp_divs(VECTOR2FP v, fixed n) { + VECTOR2FP result; + result.x = fix_div(v.x, n); + result.y = fix_div(v.y, n); + return result; +} + +static int vector2i_distance(VECTOR2I a, VECTOR2I b) { + return (int)sqrt( + ((b.x - a.x) * (b.x - a.x)) + + ((b.y - a.y) * (b.y - a.y)) + ); +} + +static float vector2f_distance(VECTOR2F a, VECTOR2F b) { + return (float)sqrt( + ((b.x - a.x) * (b.x - a.x)) + + ((b.y - a.y) * (b.y - a.y)) + ); +} + +static fixed vector2fp_distance(VECTOR2FP a, VECTOR2FP b) { + return fix_sqrt( + fix_mul((b.x - a.x), (b.x - a.x)) + + fix_mul((b.y - a.y), (b.y - a.y)) + ); +} + +static int vector2i_distancesq(VECTOR2I a, VECTOR2I b) { + return + ((b.x - a.x) * (b.x - a.x)) + + ((b.y - a.y) * (b.y - a.y)); +} + +static float vector2f_distancesq(VECTOR2F a, VECTOR2F b) { + return + ((b.x - a.x) * (b.x - a.x)) + + ((b.y - a.y) * (b.y - a.y)); +} + +static fixed vector2fp_distancesq(VECTOR2FP a, VECTOR2FP b) { + return + fix_mul((b.x - a.x), (b.x - a.x)) + + fix_mul((b.y - a.y), (b.y - a.y)); +} + +static int vector2i_dot(VECTOR2I a, VECTOR2I b) { + return + (a.x * b.x) + + (a.y * b.y); +} + +static float vector2f_dot(VECTOR2F a, VECTOR2F b) { + return + (a.x * b.x) + + (a.y * b.y); +} + +static fixed vector2fp_dot(VECTOR2FP a, VECTOR2FP b) { + return + fix_mul(a.x, b.x) + + fix_mul(a.y, b.y); +} + +static int vector2i_length(VECTOR2I v) { + return sqrt( + (v.x * v.x) + + (v.y * v.y) + ); +} + +static float vector2f_length(VECTOR2F v) { + return (float)sqrt( + (v.x * v.x) + + (v.y * v.y) + ); +} + +static fixed vector2fp_length(VECTOR2FP v) { + return fix_sqrt( + fix_mul(v.x, v.x) + + fix_mul(v.y, v.y) + ); +} + +static int vector2i_lengthsq(VECTOR2I v) { + return + (v.x * v.x) + + (v.y * v.y); +} + +static float vector2f_lengthsq(VECTOR2F v) { + return + (v.x * v.x) + + (v.y * v.y); +} + +static fixed vector2fp_lengthsq(VECTOR2FP v) { + return + fix_mul(v.x, v.x) + + fix_mul(v.y, v.y); +} + +static VECTOR2F vector2f_normalize(VECTOR2F v) { + float inverse_length; + VECTOR2F result; + + inverse_length = 1.0f / vector2f_length(v); + result.x = v.x * inverse_length; + result.y = v.y * inverse_length; + return result; +} + +static VECTOR2FP vector2fp_normalize(VECTOR2FP v) { + fixed inverse_length; + VECTOR2FP result; + + inverse_length = fix_div(FP_1, vector2fp_length(v)); + result.x = fix_mul(v.x, inverse_length); + result.y = fix_mul(v.y, inverse_length); + return result; +} + +static VECTOR2F vector2f_set_length(VECTOR2F v, float length) { + float scale_factor; + VECTOR2F result; + + scale_factor = length / vector2f_length(v); + result.x = v.x * scale_factor; + result.y = v.y * scale_factor; + return result; +} + +static VECTOR2FP vector2fp_set_length(VECTOR2FP v, fixed length) { + fixed scale_factor; + VECTOR2FP result; + + scale_factor = fix_div(length, vector2fp_length(v)); + result.x = fix_mul(v.x, scale_factor); + result.y = fix_mul(v.y, scale_factor); + return result; +} + +static VECTOR2I vector2i_lerp(VECTOR2I a, VECTOR2I b, float lerp) { + VECTOR2I result; + result.x = a.x + (b.x - a.x) * lerp; + result.y = a.y + (b.y - a.y) * lerp; + return result; +} + +static VECTOR2F vector2f_lerp(VECTOR2F a, VECTOR2F b, float lerp) { + VECTOR2F result; + result.x = a.x + (b.x - a.x) * lerp; + result.y = a.y + (b.y - a.y) * lerp; + return result; +} + +static VECTOR2FP vector2fp_lerp(VECTOR2FP a, VECTOR2FP b, fixed lerp) { + VECTOR2FP result; + result.x = a.x + fix_mul((b.x - a.x), lerp); + result.y = a.y + fix_mul((b.y - a.y), lerp); + return result; +} + +#endif + diff --git a/GFX.C b/GFX.C deleted file mode 100644 index ad4e892..0000000 --- a/GFX.C +++ /dev/null @@ -1,151 +0,0 @@ -#include "gfx.h" -#include "blit.h" -#include "util.h" -#include "internal.h" -#include "error.h" -#include -#include -#include -#include - -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); - } -} - diff --git a/GFX.H b/GFX.H deleted file mode 100644 index 2bb6a1c..0000000 --- a/GFX.H +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef DGL_GFX_H_INCLUDED -#define DGL_GFX_H_INCLUDED - -#include "common.h" -#include "rect.h" - -typedef struct { - int width; - int height; - byte *pixels; - boolean aliased; - RECT clip_region; -} SURFACE; - -extern SURFACE *screen; - -boolean video_init(void); -boolean video_shutdown(void); -boolean video_is_initialized(void); - -void video_wait_vsync(void); - -void video_set_color(ubyte color, ubyte r, ubyte g, ubyte b); -void video_get_color(ubyte color, ubyte *r, ubyte *g, ubyte *b); -void video_set_palette(const byte *palette); -void video_get_palette(byte *palette); - -SURFACE* surface_create(int width, int height); -void surface_free(SURFACE *surface); -void surface_clear(SURFACE *surface, int color); -void surface_copy(const SURFACE *src, SURFACE *dest); - -static inline int surface_offset(const SURFACE *surface, int x, int y); -static inline byte* surface_pointer(const SURFACE *surface, int x, int y); - -// -------------------------------------------------------------------------- - -static inline int surface_offset(const SURFACE *surface, int x, int y) { - return surface->width * y + x; -} - -static inline byte* surface_pointer(const SURFACE *surface, int x, int y) { - return surface->pixels + surface_offset(surface, x, y); -} - -#endif - diff --git a/INTERNAL.C b/INTERNAL.C deleted file mode 100644 index 40ce76d..0000000 --- a/INTERNAL.C +++ /dev/null @@ -1,36 +0,0 @@ -#include "internal.h" -#include -#include -#include - -boolean _install_irq(int irq, - void* irq_handler, - _go32_dpmi_seginfo* new_handler, - _go32_dpmi_seginfo* old_handler) { - memset((void*)new_handler, 0, sizeof(_go32_dpmi_seginfo)); - - if (_go32_dpmi_get_real_mode_interrupt_vector(irq, old_handler) != 0) - return FALSE; - - new_handler->pm_offset = (int)irq_handler; - new_handler->pm_selector = _go32_my_cs(); - - if (_go32_dpmi_allocate_iret_wrapper(new_handler) != 0) - return FALSE; - if (_go32_dpmi_set_protected_mode_interrupt_vector(irq, new_handler) != 0) - return FALSE; - - return TRUE; -} - -boolean _restore_irq(int irq, - _go32_dpmi_seginfo* new_handler, - _go32_dpmi_seginfo* old_handler) { - if (_go32_dpmi_set_real_mode_interrupt_vector(irq, old_handler) != 0) - return FALSE; - if (_go32_dpmi_free_iret_wrapper(new_handler) != 0) - return FALSE; - - return TRUE; -} - diff --git a/INTERNAL.H b/INTERNAL.H deleted file mode 100644 index 7960d56..0000000 --- a/INTERNAL.H +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef DGL_INTERNAL_H_INCLUDED -#define DGL_INTERNAL_H_INCLUDED - -#include "common.h" -#include - -#define END_OF_FUNCTION(x) void x##_end() {} -#define LOCK_VARIABLE(x) _go32_dpmi_lock_data((void*)&x, sizeof(x)) -#define LOCK_MEMORY(ptr, len) _go32_dpmi_lock_data((void*)(ptr), (len)) -#define LOCK_FUNCTION(x) _go32_dpmi_lock_code(x, (long)x##_end - (long)x) - -static inline void _enable_interrupts(void) { - asm volatile ("sti"); -} -static inline void _disable_interrupts(void) { - asm volatile ("cli"); -} - -boolean _install_irq(int irq, - void* irq_handler, - _go32_dpmi_seginfo* new_handler, - _go32_dpmi_seginfo* old_handler); -boolean _restore_irq(int irq, - _go32_dpmi_seginfo* new_handler, - _go32_dpmi_seginfo* old_handler); - -#define REP_MOVSL(src, dest, num_dwords) \ - __asm__ __volatile__ ( \ - "cld\n\t" \ - "rep\n\t" \ - "movsl" \ - : : "S" (src), "D" (dest), "c" (num_dwords) \ - : "%ecx", "%esi", "%edi" ) - -#define REP_MOVSB(src, dest, num_bytes) \ - __asm__ __volatile__ ( \ - "cld\n\t" \ - "rep\n\t" \ - "movsb" \ - : : "S" (src), "D" (dest), "c" (num_bytes) \ - : "%ecx", "%esi", "%edi" ) - -#define REP_STOSL(value, dest, num_dwords) \ - __asm__ __volatile__ ( \ - "cld\n\t" \ - "rep\n\t" \ - "stosl" \ - : : "a" (value), "D" (dest), "c" (num_dwords) \ - : "%ecx", "%edi" ) - -#define REP_STOSB(value, dest, num_bytes) \ - __asm__ __volatile__ ( \ - "cld\n\t" \ - "rep\n\t" \ - "stosb" \ - : : "a" (value), "D" (dest), "c" (num_bytes) \ - : "%ecx", "%edi" ) - -#endif - diff --git a/LIBDGL.GDT b/LIBDGL.GDT deleted file mode 100644 index e0b928a3f18c4ba64430565a95f6ab8ea33edfc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8545 zcmds6&u<$=6rN3LZ{mhJi75f6*c()!r0UwCNJtS%iUf!XDX9?RQY_0|Z#-5Ld$Vy{ zgAl!O=fn~I1vnr9f^wpN0#~kx|AFv*vpdd4F$6r8yy=tP&hGqr^WOK~{93V8ufPB9 z&9~mJH~oXVy>4)Ar@iaf>&1)W(SFeHIae+(m5Xa@rG4@G=6a#9u_Ekz-p<>B2p)b? zCg-M(Z8pVkE_?sutN zD(mucb-VnZ%hhKB*b;t22*|%;~H<@KIn-B6f_!+Pbjwpkq8NcgVnN_zHgv@*n zoN2apT`$`V8xLGB*Y5QEu+uvh9dT{+7Pzu(h+O4|>^Zs^KPYX{BLQy$5YM{s_7|5xBnx~x`b*k;hnWh<+%MUd!_sfaS0MdIY+mz{ZfuzhuY?=XN4eB!#~;5 z`h4mf(@}}Tt6Ap+?KDLb(b*Nz0gjtJ8dqVuW{Cmlx)v3)GUCv(L=6T@;Hu^;`2z%@ zcLPvqZceh302N{t74aMi)Zbw+n);++enU1{tCt!?>0VAQs3}uLMpFqW>JD(eiDMD77V-AbJ_?84N01{>Q{ixuoyFBO$6M-einMhEe?{ zAL*ZUqwS$NqFiE0CWzASOc15~kq{j=>qds5TAJDY8Hmwn2X2n2QWuX&BFcTm*bt2j zqtzOuX^GL}>*#!9XTRpbZ{Z^voWj-(3poc6IfT!-efKP09uR$>(`ZN zOE%m%EewmSRZJ@#!-4DAL(3QlY<{zlBWb&t{NsG%S*_yA$w$;B&g~= zoyaD4eEdc6gzSW|Oqzju!Y*eNPw&Y%*?c)}JiRl5XLA1@|4KAJ*=XG-xuD|zidlpX wv5eMhkfw9aOiJ22MyGtN;K2 diff --git a/LIBDGL.GPR b/LIBDGL.GPR deleted file mode 100644 index d0fc7e36d9b941154a366e9c99ed2a2090d232f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14310 zcmeHO`;Xg19^Xx3C)w?bX900{KO%vq<%&cFzZF`Jo(jtq=pv!Ya_mVmUB_d__CEU0 z_deelCo_J;SxU>@Nw<|_XTIN=`Mw|H^kxt|{`TSh2SKLfGaeOeE)pID9}Iro-yiRd z_Fha9F^d<;t#G>M;~&O{hkJW_ba}Y&eK6YdXNf3oMdl_qkl`2@bWJvxFAUCdiZP77 z06_n}c=6OM_2OpqPPDCDT3>Z!tgb zgCB^r;3^H1J|tg3ik%2g+ssRA}mO1ak@Uo~k zuI+SMzbr&=(EGh!ZL}1bo8#Bl;nQ?Ee%+3DyV5~>#!I#^VTqd*9BrN)I~>6d|8OUI3HfdI?&16QR-09Y994IRtAkhJUF~}F|B-U{VaqFW zl%DRV!^U+d6zR`?D|m_OzB{U1qQLpnD)rqW-&M=M#!j+BTPA!(=H}?D<5aP$_IPav zFWs8HME>}&Rh#EH>e+eF(+)6&SoL=Nmk6|%%nhzukaqkro%qt>um0P|C!O2Y2lT0M zedy5;SX9gCzxA}%Kz&kcVGMYG#|m^&=*IWa{@#Ec?eFgo@SRA(z%@3H!X)8}<>4vM zE#OT6a?a*5N#q%OR<1G!_=W-ICn96BL`EkL>;{|1d>)ob!Auus*F4l9?3KyPj_L_X zc)?>fQ(+n{E$DqV=jRzub8*U<%%Do~JS>Dvo&B)rJj@G52Nw`l#n)AgCNeBojuTXF zSGDabY zMb{0eLrc|aZABUBtp#7#6;z9zn(8t#-LA0@^sF69gIck)TnW4iQsIiju62iN*@PJa zBZKajGI0zDhK+H>RjDnDg>$?uVTpA8!YCk*mOL&K4i0kH?2Xdv&^vbH3S20jE{Y{~ zip$8^-w3Q&Djvp7=Qg4#Qw7&&hz*)7$C%CB3Qi)KuU8PTl{%l6 zP0&&YIU*p~HvVBr-OR&{w{wnJO|~iAcprfvx@?@CLg#Uq79z5=-q?&WeXj0^ZNSbf z-hdt3FK@EraIsK)5f&U;EJ~GHpa)=**r4|oJDx$G)(;RDE%p_598sVQ6R~g>Ijn|% zE5pPhzk$(Zh^$b~@<@rSaHyREh8Ki*jbZU=ahaZSl_OZzhIv}9Sd@gh6W7P=Sc||S zPS`O5Fk-kJ0%0OHGuht$;06Aw;C=weDoaEp9CWPEbnI5kB6LK4osywx9vl*&BgLhPxs&9ugRvk+ ztXNJUxqKPM(y>8U5`0JC9d{S&G~rAXZl;Dt^9#^!R|UHThnC22V?HYv3y9i+K}?~- zSWt3x4G*%z#tRi@ONSi@p-e>zY*_De9@}+5OPS)Ojxz-0Gf0Xf_tS}rUPk*Vokr7T z{dB+#EqOQ z6nJ?Sx;YAK#z;Y-%8~n+h~XMyE)Zd?j4)e=7i3+=e=EhQ1tAj|zwD+4$rT|XMqbSk z4MW6LmsSM&Ww}7fIiufsI2$6TphA=|LCT6JrJMUqz7C^^=Q#sY1rn&GXI)NpSH>o% zF4B_WVDk)q>+FgAXrf8NDdtwCjDujxkaa}tlD(-0QkkYDwAbPaVw4$20F;WQsAHV9 zVcpaiu!?KP%aAFXA;NMCV6hZXT+U7rwZfTO{9w&fSTST@EX&mG9S&J4@hbrQnB^14 zn6I$TNP(2om0Na%*{xwoM~LfSfi7$D9t+WaSkAPiQ%gjd11!MzBT-L!;1BAL8PW?9 znj0n2H$atP?(`UFNH8=jMN$YSahf8GY?Im|QNZvM*C>q6OOUn=gY>f%2tTfXl;tgV zFqFPE!Py2}pNQQk=4!1vVb?U7TNHT1)hmlKCpaAd%=!5KMx=lpY7`hakXGNjT$45MU62?S#jg0+ez{^Q$1h5~Knhdh`-TA;2~ddI>zr zxrS28mUBSOgI?AoKK*zq5pMBwv@1cde$)$`k(z>Hh*;<23ixkBNMsb2h4f)o81itF zYBZBF@n+};PDZE_xfhY;j%c<=#ar&7PI6MoTMN`rzIa(&88po z1ex)`N^THKKb9qY|4Mv;P$Qy%RvGam=Ogmw30g{B*!d=Ud&n!GMrYO`Dnx&-1XAs2 zfr4xx=Dv~p5D8$E$aFDYmD&cUI*d_186w>bQ(5@9!2M($=mt`GP%Mp9MVW83G|rSb zMe3ST<%8(YV?P7IBAP&T0tKHMS310*xNi3-{cASx>XHg{FJGeYn{Kr08-;pWnfUS? ziu94O(H$I`o0)CQ%QvOfWL-RsD3E&SR^-_T_Q!{Xx)_rYK*&DbMLeM!ajd_~xrbUw zrjxa+`o>PYl0w$F%H5+=iHU1l@y?bop5ZwJj0;kMOX;H&Dwp)1SKYUSNn}j26~^-@ z#BZ^HOo%vOqO{MT*jX)cQ(7S*u}G+>bj$cDs;Kb!1rs>LT(6-!IhZPbN5rxaJ2-h2 zFzty{Q#WDQ#pJpc1Q~B8Rf08JAP{WUVY$=1x!X{o8=hP8#vqw~ZD2>RhAw&8B6Cs) zC3({^RP9rJM$U@_2VBLM^=1caEwTv5TOtKygeHh2d+l57Mi&LY$-P-F6GSz7K(366 z;k_go-b>>Nt^gfH>fKW+ycpigSKe1J<8<RI%=l%~m5D$NlXVV{)jLbjJQ;9-%D5E#qNv@R;O+_K3&BA9*qSahc#!qn{w@!B2AZ z6Z~=XGujpJXGFwg^fNj-?@5@zd!K}A^hEHp@e|VkddK8>qhoY-!(Sw&Vr}&v*$rK` z5`ky5`fIqIF6mkT%Kp4yi@SH}Y>!T39b@xwuKD@r)lTqHQ_JALWw74ta(> z=gLV$rjObR1`jg?n7n@2Wq9ZY;P3`{5s{^KHc|<;6NWxAM<_z#+RSy1a!jw-gMhvQ z^1^m_*MJua#0nC&6$zGi;bn%1xD|>v$c1Xj*|o#eu|r5s_d;8?MYwXnja}=&#->oX zGqbiQiAt9AvPbjUShWFdEDJ%pb5Y{yGYTsT2r|D|&1ABLBU;{pcWmxJ8=FIr?%XC* znj4dUSbJR;+E^Es*sXPVYnO=D!;NLULT6m+F=M6bEX3UU$Ua4zZqYGP|(EOD}9 z;dJQJSV83V|uVFM_EX69ti^-=S6L_eRfP9r^t*;S^!ssde Q6yg_rjHti5fiF-04a1!^9smFU diff --git a/MAKEFILE b/MAKEFILE new file mode 100644 index 0000000..c7d02c8 --- /dev/null +++ b/MAKEFILE @@ -0,0 +1,80 @@ +target_config = release + +target_name = dgl + +object_files = & + dglblit.obj & + dglblita.obj & + dglclip.obj & + dgl.obj & + dgldraw.obj & + dgldrawa.obj & + dglgfx.obj & + dglpal.obj & + dglkbrd.obj & + dglmath.obj & + dglfixp.obj & + dglmouse.obj & + dglpcx.obj & + dglutil.obj + +test_object_files = test.obj + +cc_flags_debug = /d2 /zp4 /5r /fp3 /j +cc_flags_release = /d1+ /zp4 /5r /fp3 /onatx /oe=40 /j +cc_flags = /mf $(cc_flags_$(target_config)) + +link_flags_debug = debug all +link_flags_release = debug all +link_flags = $(link_flags_$(target_config)) + +asm_flags_debug = /zi +asm_flags_release = /zi +asm_flags = /m /ml $(asm_flags_$(target_config)) + +.c.obj: .AUTODEPEND + wcc386 $[. /zq $(cc_flags) + +.asm.obj: .AUTODEPEND + tasm $[. /t $(asm_flags) + +$(target_name).lnk: $(object_files) $(test_object_files) + %create $^@ + %append $^@ NAME $(target_name).exe + %append $^@ SYSTEM DOS4G + %append $^@ OPTION QUIET + @for %i in ($(object_files)) do %append $^@ FILE %i + @for %i in ($(test_object_files)) do %append $^@ FILE %i + +$(target_name).exe: $(object_files) $(test_object_files) $(target_name).lnk + wlink $(link_flags) @$(target_name).lnk + +$(target_name).lbc: $(object_files) + %create $^@ + @for %i in ($(object_files)) do %append $^@ +%i + +$(target_name).lib: $(object_files) $(target_name).lbc + wlib /n /q /b $(target_name).lib @$(target_name).lbc + +clean : .SYMBOLIC + del *.obj + del *.err + del $(target_name).exe + del $(target_name).lnk + del $(target_name).lbc + +.NOCHECK +build : $(target_name).lib +#build : $(target_name).exe + +.NOCHECK +library : $(target_name).lib + +.NOCHECK +run : $(target_name).exe + $(target_name).exe + +.NOCHECK +debug : $(target_name).exe + wd /swap /trap=rsi $(target_name).exe + diff --git a/MOUSE.C b/MOUSE.C deleted file mode 100644 index 266e2d3..0000000 --- a/MOUSE.C +++ /dev/null @@ -1,188 +0,0 @@ -#include "mouse.h" -#include "internal.h" -#include "error.h" -#include -#include - -static boolean _installed = FALSE; -static boolean _has_mouse = FALSE; - -volatile int mouse_x; -volatile int mouse_y; -volatile int mouse_buttons; -volatile int mouse_delta_x; -volatile int mouse_delta_y; - -__dpmi_regs _mouse_regs; -_go32_dpmi_seginfo _mouse_seg_info; - -static void reset_mouse_state(void) { - mouse_x = 0; - mouse_y = 0; - mouse_buttons = 0; - mouse_delta_x = 0; - mouse_delta_y = 0; -} - -static boolean init_mouse_driver(void) { - __dpmi_regs regs; - - memset(®s, 0, sizeof(__dpmi_regs)); - regs.x.ax = 0x00; - __dpmi_int(0x33, ®s); - - return (regs.x.ax != 0); -} - -static void update_mouse_state(void) { - __dpmi_regs regs; - - memset(®s, 0, sizeof(__dpmi_regs)); - regs.x.ax = 0x03; - __dpmi_int(0x33, ®s); - mouse_x = (regs.x.cx / 2); - mouse_y = regs.x.dx; - mouse_buttons = regs.x.bx; - mouse_delta_x = 0; - mouse_delta_y = 0; -} - -void mouse_int_handler(__dpmi_regs* regs) { - mouse_delta_x = (regs->x.cx / 2) - mouse_x; - mouse_delta_y = regs->x.dx - mouse_y; - mouse_x = (regs->x.cx / 2); - mouse_y = regs->x.dx; - mouse_buttons = regs->x.bx; -} -END_OF_FUNCTION(mouse_int_handler) - -boolean mouse_init(void) { - __dpmi_regs regs; - - if (_installed) { - dgl_set_error(DGL_MOUSE_ALREADY_INITIALIZED); - return FALSE; - } - - reset_mouse_state(); - - _has_mouse = init_mouse_driver(); - if (!_has_mouse) { - _installed = TRUE; - return TRUE; - } - - LOCK_FUNCTION(mouse_int_handler); - LOCK_VARIABLE(_mouse_regs); - LOCK_VARIABLE(_mouse_seg_info); - LOCK_VARIABLE(mouse_x); - LOCK_VARIABLE(mouse_y); - LOCK_VARIABLE(mouse_buttons); - LOCK_VARIABLE(mouse_delta_x); - LOCK_VARIABLE(mouse_delta_y); - - memset(&_mouse_regs, 0, sizeof(__dpmi_regs)); - memset(&_mouse_seg_info, 0, sizeof(_go32_dpmi_seginfo)); - - _mouse_seg_info.pm_offset = (int)mouse_int_handler; - _mouse_seg_info.pm_selector = _go32_my_cs(); - if (_go32_dpmi_allocate_real_mode_callback_retf(&_mouse_seg_info, &_mouse_regs) != 0) { - dgl_set_error(DGL_MOUSE_ALLOCATE_CALLBACK_FAILURE); - return FALSE; - } - - update_mouse_state(); - - memset(®s, 0, sizeof(__dpmi_regs)); - regs.x.ax = 0x0c; - regs.x.cx = 0x7f; - regs.x.dx = _mouse_seg_info.rm_offset; - regs.x.es = _mouse_seg_info.rm_segment; - if (__dpmi_int(0x33, ®s) != 0) { - dgl_set_error(DGL_MOUSE_INT_CALLBACK_SET_FAILURE); - return FALSE; - } - - _installed = TRUE; - return TRUE; -} - -boolean mouse_shutdown(void) { - __dpmi_regs regs; - - if (!_installed) - return TRUE; // don't care - - if (!_has_mouse) { - _installed = FALSE; - return TRUE; - } - - memset(®s, 0, sizeof(__dpmi_regs)); - regs.x.ax = 0x0c; - regs.x.cx = 0; - regs.x.dx = 0; - regs.x.es = 0; - if (__dpmi_int(0x33, ®s) != 0) { - dgl_set_error(DGL_MOUSE_INT_CALLBACK_RESTORE_FAILURE); - return FALSE; - } - - if (_go32_dpmi_free_real_mode_callback(&_mouse_seg_info) != 0) - dgl_set_error(DGL_MOUSE_FREE_CALLBACK_FAILURE); - - reset_mouse_state(); - - _installed = FALSE; - return TRUE; -} - -boolean mouse_is_initialized(void) { - return _installed; -} - -boolean mouse_is_present(void) { - return _has_mouse; -} - -void mouse_show(void) { - __dpmi_regs regs; - - if (!_has_mouse) - return; - - memset(®s, 0, sizeof(__dpmi_regs)); - regs.x.ax = 0x01; - __dpmi_int(0x33, ®s); -} - -void mouse_hide(void) { - __dpmi_regs regs; - - if (!_has_mouse) - return; - - memset(®s, 0, sizeof(__dpmi_regs)); - regs.x.ax = 0x02; - __dpmi_int(0x33, ®s); -} - -void mouse_set_bounds(int min_x, int min_y, int max_x, int max_y) { - __dpmi_regs regs; - - if (!_has_mouse) - return; - - memset(®s, 0, sizeof(__dpmi_regs)); - - regs.x.ax = 0x07; - regs.x.cx = min_x; - regs.x.dx = max_x; - __dpmi_int(0x33, ®s); - - regs.x.ax = 0x08; - regs.x.cx = min_y; - regs.x.dx = max_y; - __dpmi_int(0x33, ®s); -} - diff --git a/TEST.C b/TEST.C index 1e01ac6..eb2f76d 100644 --- a/TEST.C +++ b/TEST.C @@ -1,34 +1,1196 @@ #include -#include +#include +#include +#include +#include #include "dgl.h" -int main(void) { - SURFACE *backbuffer; +SURFACE *backbuffer = NULL; - if (!dgl_init()) { - printf("Failed to initialize DGL: %s\n", dgl_last_error_message()); +#define F_EQU(a, b) (close_enough((a), (b), TOLERANCE)) +#define FFIX_EQU(a, b) (close_enough((a), (b), 0.01f)) + +extern void _breakpoint(); +#pragma aux _breakpoint = "int 0x03"; + + +#define ASSERT(x) \ + do { \ + if (!(x)) { \ + printf("Assertion failed at %s:%d, %s\n", __FILE__, __LINE__, #x); \ + _breakpoint(); \ + } \ + } while (0) + +void break_handler(int sig) { + exit(0); +} + +SURFACE* get_sprite(int width, int height) { + int x_third, y_third; + SURFACE *sprite = surface_create(width, height); + ASSERT(sprite != NULL); + ASSERT(sprite->width == width); + ASSERT(sprite->height == height); + + x_third = width / 3; + y_third = height / 3; + + surface_filled_rect(sprite, 0, 0, x_third, y_third, 1); + surface_filled_rect(sprite, x_third * 2, y_third * 2, width - 1, height - 1, 2); + surface_filled_rect(sprite, 0, (y_third * 2), x_third, height - 1, 3); + surface_filled_rect(sprite, x_third * 2, 0, width - 1, y_third, 4); + surface_filled_rect(sprite, x_third, y_third, x_third * 2, y_third * 2, 5); + surface_rect(sprite, 0, 0, width - 1, height - 1, 6); + + return sprite; +} + +SURFACE* get_image(int width, int height) { + int x, y; + SURFACE *image = surface_create(width, height); + ASSERT(image != NULL); + ASSERT(image->width == width); + ASSERT(image->height == height); + + surface_filled_rect(image, 0, 0, width / 2, height / 2, 1); + surface_filled_rect(image, width / 2, 0, width - 1, height / 2, 2); + surface_filled_rect(image, 0, height / 2, width / 2, height - 1, 3); + surface_filled_rect(image, width / 2, height / 2, width - 1, height - 1, 4); + surface_rect(image, 0, 0, width - 1, height - 1, 5); + + return image; +} + +// --------------------------------------------------------------------------- + +void test_fixed(void) { + fixed a, b, c; + float af, bf, cf, f; + int i; + + a = FTOFIX(PI); + f = FIXTOF(a); + ASSERT(FFIX_EQU(PI, f)); + + a = FTOFIX(-0.37f); + f = FIXTOF(a); + ASSERT(FFIX_EQU(-0.38f, f)); + + a = ITOFIX(17); + i = FIXTOI(a); + ASSERT(17 == i); + + a = ITOFIX(-17); + i = FIXTOI(a); + ASSERT(-17 == i); + + a = FTOFIX(1.5f); + b = FTOFIX(2.3f); + c = a + b; + f = FIXTOF(c); + ASSERT(FFIX_EQU((1.5f + 2.3f), f)); + + a = FTOFIX(0.2f); + b = FTOFIX(1.7f); + c = a - b; + f = FIXTOF(c); + ASSERT(FFIX_EQU((0.2f - 1.7f), f)); + + a = FTOFIX(16.0f); + c = a >> 2; + f = FIXTOF(c); + ASSERT(FFIX_EQU((16 >> 2), f)); + + a = FTOFIX(7.1f); + b = ITOFIX(2); + c = fix_mul(a, b); + f = FIXTOF(c); + ASSERT(FFIX_EQU((7.1f * 2), f)); + + a = FTOFIX(77.7f); + b = ITOFIX(3); + c = fix_div(a, b); + f = FIXTOF(c); + ASSERT(FFIX_EQU((77.7f / 3), f)); + + for (i = 0; i <= 360; i += 45) { + f = DEG_TO_RAD(i + 1); + a = fix_sin(FTOFIX(f)); + af = sin(f); + b = fix_cos(FTOFIX(f)); + bf = cos(f); + c = fix_tan(FTOFIX(f)); + cf = tan(f); + ASSERT(FFIX_EQU(FIXTOF(a), af)); + ASSERT(FFIX_EQU(FIXTOF(b), bf)); + ASSERT(FFIX_EQU(FIXTOF(c), cf)); + } +} + +void test_vector2i(void) { + VECTOR2I a, b, c; + int i; + + c = vector2i(3, 7); + ASSERT(c.x == 3 && c.y == 7); + + vector2i_set(&c, 1, 2); + ASSERT(c.x == 1 && c.y == 2); + + a = vector2i(1, 2); + b = vector2i(1, 2); + ASSERT(vector2i_equals(a, b)); + + a = vector2i(3, 4); + b = vector2i(1, 2); + + c = vector2i_add(a, b); + ASSERT(c.x == 4 && c.y == 6); + + c = vector2i_sub(a, b); + ASSERT(c.x == 2 && c.y == 2); + + c = vector2i_mul(a, b); + ASSERT(c.x == 3 && c.y == 8); + + c = vector2i_muls(a, 2); + ASSERT(c.x == 6 && c.y == 8); + + c = vector2i_div(a, b); + ASSERT(c.x == 3 && c.y == 2); + + c = vector2i_divs(a, 2); + ASSERT(c.x == 1 && c.y == 2); + + a = vector2i(1, 1); + b = vector2i(1, 3); + i = vector2i_distance(a, b); + ASSERT(i == 2); + + i = vector2i_distancesq(a, b); + ASSERT(i == 4); + + a = vector2i(-12, 16); + b = vector2i(12, 9); + i = vector2i_dot(a, b); + ASSERT(i == 0); + + a = vector2i(-3, 0); + i = vector2i_length(a); + ASSERT(i == 3); + + i = vector2i_lengthsq(a); + ASSERT(i == 9); + + a = vector2i(5, 0); + b = vector2i(10, 0); + c = vector2i_lerp(a, b, 0.5f); + ASSERT(c.x == 7 && c.y == 0); +} + +void test_vector2f(void) { + VECTOR2F a, b, c; + float f; + + c = vector2f(3.0f, 7.0f); + ASSERT(F_EQU(c.x, 3.0f) && F_EQU(c.y, 7.0f)); + + vector2f_set(&c, 1.0f, 2.0f); + ASSERT(F_EQU(c.x, 1.0f) && F_EQU(c.y, 2.0f)); + + a = vector2f(1.0f, 2.0f); + b = vector2f(1.0f, 2.0f); + ASSERT(vector2f_equals(a, b)); + + a = vector2f(3.0f, 4.0f); + b = vector2f(1.0f, 2.0f); + + c = vector2f_add(a, b); + ASSERT(F_EQU(c.x, 4.0f) && F_EQU(c.y, 6.0f)); + + c = vector2f_sub(a, b); + ASSERT(F_EQU(c.x, 2.0f) && F_EQU(c.y, 2.0f)); + + c = vector2f_mul(a, b); + ASSERT(F_EQU(c.x, 3.0f) && F_EQU(c.y, 8.0f)); + + c = vector2f_muls(a, 0.5f); + ASSERT(F_EQU(c.x, 1.5f) && F_EQU(c.y, 2.0f)); + + c = vector2f_div(a, b); + ASSERT(F_EQU(c.x, 3.0f) && F_EQU(c.y, 2.0f)); + + c = vector2f_divs(a, 0.5f); + ASSERT(F_EQU(c.x, 6.0f) && F_EQU(c.y, 8.0f)); + + a = vector2f(1.0f, 1.0f); + b = vector2f(1.0f, 3.0f); + f = vector2f_distance(a, b); + ASSERT(F_EQU(f, 2.0f)); + + f = vector2f_distancesq(a, b); + ASSERT(F_EQU(f, 4.0f)); + + a = vector2f(-12.0f, 16.0f); + b = vector2f(12.0f, 9.0f); + f = vector2f_dot(a, b); + ASSERT(F_EQU(f, 0.0f)); + + a = vector2f(-3.0f, 0.0f); + f = vector2f_length(a); + ASSERT(F_EQU(f, 3.0f)); + + f = vector2f_lengthsq(a); + ASSERT(F_EQU(f, 9.0f)); + + a = vector2f(7.0f, 7.0f); + c = vector2f_normalize(a); + ASSERT(F_EQU(c.x, 0.70710f) && F_EQU(c.y, 0.70710f)); + + a = vector2f(10.0f, 0.0f); + c = vector2f_set_length(a, 2.0f); + ASSERT(F_EQU(c.x, 2.0f) && F_EQU(c.y, 0.0f)); + + a = vector2f(5.0f, 0.0f); + b = vector2f(10.0f, 0.0f); + c = vector2f_lerp(a, b, 0.5f); + ASSERT(F_EQU(c.x, 7.5f) && F_EQU(c.y, 0.0f)); +} + +// fill screen entirely with blue +void test_surface_clear(void) { + surface_clear(screen, 1); + + getch(); +} + +// fill screen entirely with green, using the backbuffer first +void test_surface_copy(void) { + surface_clear(backbuffer, 2); + surface_copy(backbuffer, screen); + + getch(); +} + +// pixel drawing done largely using pointers directly, with the assistance +// of helper functions to get correct initial pointer positions. +// starting at (10,10), draw 256 colour palette in a 16x16 pixel box. +// draw white "guide" lines from (0,0) to (10,10) +void test_pixels_1(void) { + byte *p; + int i, x, y; + + surface_clear(screen, 0); + + p = surface_pointer(screen, 10, 10); + ASSERT(p == (screen->pixels + (10 * screen->width) + 10)); + + i = 0; + for (y = 0; y < 16; ++y) { + for (x = 0; x < 16; ++x) { + *p = (byte)i; + ++p; + ++i; + } + p += (screen->width - 16); + } + + p = surface_pointer(screen, 0, 0); + for (i = 0; i < 10; ++i) { + *p = 15; + p += (screen->width + 1); + } + p = surface_pointer(screen, 10, 0); + for (i = 0; i < 10; ++i) { + *p = 15; + p += screen->width; + } + p = surface_pointer(screen, 0, 10); + for (i = 0; i < 10; ++i) { + *p = 15; + ++p; + } + + getch(); +} + +// pixel drawing using pset, and pixel getting using point +// draws two blue, green, cyan, red pixels each in each screen corner. +// the second pixel colour is drawn by sampling the first. +void test_pixels_2(void) { + byte c1, c2, c3, c4; + + surface_clear(screen, 0); + + surface_pset(screen, 0, 0, 1); + surface_pset(screen, 319, 0, 2); + surface_pset(screen, 0, 199, 3); + surface_pset(screen, 319, 199, 4); + + surface_pset_f(screen, 10, 0, 1); + surface_pset_f(screen, 309, 0, 2); + surface_pset_f(screen, 10, 199, 3); + surface_pset_f(screen, 309, 199, 4); + + c1 = surface_point(screen, 0, 0); + c2 = surface_point(screen, 319, 0); + c3 = surface_point(screen, 0, 199); + c4 = surface_point(screen, 319, 199); + ASSERT(c1 == 1 && c2 == 2 && c3 == 3 && c4 == 4); + + surface_pset(screen, 1, 1, c1); + surface_pset(screen, 318, 1, c2); + surface_pset(screen, 1, 198, c3); + surface_pset(screen, 318, 198, c4); + + c1 = surface_point_f(screen, 10, 0); + c2 = surface_point_f(screen, 309, 0); + c3 = surface_point_f(screen, 10, 199); + c4 = surface_point_f(screen, 309, 199); + ASSERT(c1 == 1 && c2 == 2 && c3 == 3 && c4 == 4); + + surface_pset_f(screen, 11, 1, c1); + surface_pset_f(screen, 308, 1, c2); + surface_pset_f(screen, 11, 198, c3); + surface_pset_f(screen, 308, 198, c4); + + getch(); +} + +// pixel drawing with clipping (using pset). +// draws 4 white lines 10 pixels long, going 5 pixels out of bounds off each +// edge (top, left, bottom, right) of the screen. red marker pixels are at +// the inside edge of each line to mark a known reference point +void test_pixels_clipping(void) { + int i, x, y; + + surface_clear(screen, 0); + + surface_pset(screen, 5, 100, 4); + surface_pset(screen, 314, 100, 4); + surface_pset(screen, 160, 5, 4); + surface_pset(screen, 160, 194, 4); + + for (i = 0; i < 10; ++i) { + surface_pset(screen, i - 5, 100, 15); + surface_pset(screen, 315 + i, 100, 15); + surface_pset(screen, 160, i - 5, 15); + surface_pset(screen, 160, 195 + i, 15); + } + + getch(); +} + +// draws two horizontal lines, with red pixels marking the extents of the +// lines. a third line is drawn using the "fast" variant. +void test_hline(void) { + int x1, x2, y; + + surface_clear(screen, 0); + + x1 = 10; x2 = 100; y = 20; + + surface_pset(screen, x1 - 1, y, 4); + surface_pset(screen, x2 + 1, y, 4); + surface_hline(screen, x1, x2, y, 1); + + y = 30; + + surface_pset(screen, x1 - 1, y, 4); + surface_pset(screen, x2 + 1, y, 4); + surface_hline(screen, x2, x1, y, 2); + + x1 = 200; x2 = 300; y = 20; + + surface_pset(screen, x1 - 1, y, 4); + surface_pset(screen, x2 + 1, y, 4); + surface_hline_f(screen, x1, x2, y, 1); + + getch(); +} + +// draws 4 horizontal lines. two are completely outside the bounds of +// the screen and should not be visible at all. the remaining two will be +// partly out of bounds off the left and right edges. red pixel markers are +// drawn marking the visible ends of the two partly clipped lines +void test_hline_clipping(void) { + int x1, x2, y; + + surface_clear(screen, 0); + + x1 = -50; x2 = 50; y = 6; + surface_pset(screen, x2 + 1, y, 4); + surface_hline(screen, x1, x2, y, 1); + + x1 = 300; x2 = 340; y = 130; + surface_pset(screen, x1 - 1, y, 4); + surface_hline(screen, x1, x2, y, 2); + + surface_hline(screen, 100, 200, -10, 3); + surface_hline(screen, 20, 80, 250, 5); + + getch(); +} + +// draws two vertical lines, with red pixels marking the extents of +// the lines. a third line is drawn using the "fast" variant. +void test_vline(void) { + int x, y1, y2; + + surface_clear(screen, 0); + + x = 50; y1 = 10; y2 = 100; + + surface_pset(screen, x, y1 - 1, 4); + surface_pset(screen, x, y2 + 1, 4); + surface_vline(screen, x, y1, y2, 1); + + x = 60; + + surface_pset(screen, x, y1 - 1, 4); + surface_pset(screen, x, y2 + 1, 4); + surface_vline(screen, x, y2, y1, 2); + + x = 150; y1 = 10; y2 = 100; + + surface_pset(screen, x, y1 - 1, 4); + surface_pset(screen, x, y2 + 1, 4); + surface_vline_f(screen, x, y1, y2, 1); + + getch(); +} + +// draws 4 vertical lines. two are completely outside the bounds of +// the screen and should not be visible at all. the remaining two will be +// partly out of bounds off the top and bottom edges. red pixel markers are +// drawn marking the visible ends of the two partly clipped lines +void test_vline_clipping(void) { + int x, y1, y2; + + surface_clear(screen, 0); + + x = 20; y1 = -32; y2 = 32; + surface_pset(screen, x, y2 + 1, 4); + surface_vline(screen, x, y1, y2, 1); + + x = 270; y1 = 245; y2 = 165; + surface_pset(screen, x, y2 - 1, 4); + surface_vline(screen, x, y1, y2, 2); + + surface_vline(screen, -17, 10, 20, 3); + surface_vline(screen, 400, 100, 300, 5); + + getch(); +} + +// draws a series of lines, both straight and diagonal as well as +// specifying the two line endpoints in either order (e.g. left-right +// and right-left). draws red marker pixels around the end points of each +// line. duplicates of some lines are drawn using the "fast" variant. +void test_line(void) { + int x1, x2, y1, y2; + + surface_clear(screen, 0); + + x1 = 10; y1 = 10; x2 = 20; y2 = 20; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_line(screen, x1, y1, x2, y2, 1); + + x1 = 10; y1 = 100; x2 = 20; y2 = 150; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_line(screen, x1, y1, x2, y2, 2); + + x1 = 60; y1 = 150; x2 = 50; y2 = 100; + surface_pset(screen, x1 + 1, y1, 4); + surface_pset(screen, x1, y1 + 1, 4); + surface_pset(screen, x2 - 1, y2, 4); + surface_pset(screen, x2, y2 - 1, 4); + surface_line(screen, x1, y1, x2, y2, 3); + + x1 = 50; y1 = 10; x2 = 100; y2 = 10; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x2 + 1, y1, 4); + surface_line(screen, x1, y1, x2, y2, 5); + + x1 = 100; y1 = 50; x2 = 20; y2 = 50; + surface_pset(screen, x1 + 1, y1, 4); + surface_pset(screen, x2 - 1, y1, 4); + surface_line(screen, x1, y1, x2, y2, 6); + + x1 = 290; y1 = 10; x2 = 290; y2 = 100; + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_line(screen, x1, y1, x2, y2, 7); + + x1 = 310; y1 = 100; x2 = 310; y2 = 10; + surface_pset(screen, x1, y1 + 1, 4); + surface_pset(screen, x2, y2 - 1, 4); + surface_line(screen, x1, y1, x2, y2, 8); + + + x1 = 30; y1 = 10; x2 = 40; y2 = 20; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_line_f(screen, x1, y1, x2, y2, 1); + + x1 = 30; y1 = 100; x2 = 40; y2 = 150; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_line_f(screen, x1, y1, x2, y2, 2); + + x1 = 50; y1 = 20; x2 = 100; y2 = 20; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x2 + 1, y1, 4); + surface_line_f(screen, x1, y1, x2, y2, 5); + + x1 = 300; y1 = 10; x2 = 300; y2 = 100; + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_line_f(screen, x1, y1, x2, y2, 7); + + getch(); +} + +// draws a series of lines fanned out in a circle originating from the +// center of the screen. each line extends well past the boundaries of the +// screen and so should be partially clipped. additionally, 4 straight lines +// are drawn completely outside the bounds of the screen and should not be +// visible. +void test_line_clipping(void) { + int angle, color; + float x, y; + + surface_clear(screen, 0); + + surface_line(screen, 10, -30, 100, -30, 1); + surface_line(screen, 70, 250, 170, 250, 2); + surface_line(screen, -100, 120, -100, 199, 3); + surface_line(screen, 320, 99, 320, 199, 5); + + for (angle = 0, color = 32; angle <= 360; angle += 10, ++color) { + point_on_circle(400, DEG_TO_RAD(angle), &x, &y); + surface_line(screen, 160, 100, (int)x + 160, (int)y + 100, color); + } + + getch(); +} + +// draws two rectangles. red pixels mark the extents of the rects. a +// duplicate of the first rectangle is drawn using the "fast" variant. +void test_rect(void) { + int x1, y1, x2, y2; + + surface_clear(screen, 0); + + x1 = 10; y1 = 10; x2 = 90; y2 = 90; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2 + 1, y1, 4); + surface_pset(screen, x2, y1 - 1, 4); + surface_pset(screen, x1 - 1, y2, 4); + surface_pset(screen, x1, y2 + 1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_rect(screen, x1, y1, x2, y2, 1); + + x1 = 10; y1 = 110; x2 = 90; y2 = 190; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2 + 1, y1, 4); + surface_pset(screen, x2, y1 - 1, 4); + surface_pset(screen, x1 - 1, y2, 4); + surface_pset(screen, x1, y2 + 1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_rect_f(screen, x1, y1, x2, y2, 1); + + x1 = 190; y1 = 90; x2 = 110; y2 = 10; + surface_pset(screen, x2 - 1, y2, 4); + surface_pset(screen, x2, y2 - 1, 4); + surface_pset(screen, x1 + 1, y2, 4); + surface_pset(screen, x1, y2 - 1, 4); + surface_pset(screen, x2 - 1, y1, 4); + surface_pset(screen, x2, y1 + 1, 4); + surface_pset(screen, x1 + 1, y1, 4); + surface_pset(screen, x1, y1 + 1, 4); + surface_rect(screen, x1, y1, x2, y2, 2); + + getch(); +} + +// draws 4 rects in each of the top-left and bottom-right corners (two in each +// corner will be completely out of bounds, so should not be visible). also, +// two long rects are drawn along the center of the screen and they each +// extend beyond the edges of the screen. red pixels are drawn to mark rect +// extents. +void test_rect_clipping(void) { + int x1, y1, x2, y2; + + surface_clear(screen, 0); + + x1 = -8; y1 = 10; x2 = 7; y2 = 25; + surface_pset(screen, x2, y1 - 1, 4); + surface_pset(screen, x2 + 1, y1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_rect(screen, x1, y1, x2, y2, 1); + + surface_rect(screen, -16, 30, -1, 46, 10); + + x1 = 20; y1 = -8; x2 = 35; y2 = 7; + surface_pset(screen, x1 - 1, y2, 4); + surface_pset(screen, x1, y2 + 1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_rect(screen, x1, y1, x2, y2, 2); + + surface_rect(screen, 40, -16, 55, -1, 11); + + x1 = 313; y1 = 170; x2 = 328; y2 = 185; + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1 - 1, y2, 4); + surface_pset(screen, x1, y2 + 1, 4); + surface_rect(screen, x1, y1, x2, y2, 3); + + surface_rect(screen, 320, 150, 335, 165, 12); + + x1 = 285; y1 = 193; x2 = 300; y2 = 208; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2 + 1, y1, 4); + surface_pset(screen, x2, y1 - 1, 4); + surface_rect(screen, x1, y1, x2, y2, 5); + + surface_rect(screen, 265, 200, 280, 215, 13); + + x1 = 150; y1 = -10; x2 = 170; y2 = 210; + surface_pset(screen, x1 - 1, 10, 4); + surface_pset(screen, x2 + 1, 10, 4); + surface_rect(screen, x1, y1, x2, y2, 7); + + x1 = -10; y1 = 90; x2 = 330; y2 = 110; + surface_pset(screen, 10, y1 - 1, 4); + surface_pset(screen, 10, y2 + 1, 4); + surface_rect(screen, x1, y1, x2, y2, 8); + + getch(); +} + +// draws two filled rectangles. red pixels mark the extents of the rects. a +// duplicate of the first rectangle is drawn using the "fast" variant. +void test_filled_rect(void) { + int x1, y1, x2, y2; + + surface_clear(screen, 0); + + x1 = 10; y1 = 10; x2 = 90; y2 = 90; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2 + 1, y1, 4); + surface_pset(screen, x2, y1 - 1, 4); + surface_pset(screen, x1 - 1, y2, 4); + surface_pset(screen, x1, y2 + 1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_filled_rect(screen, x1, y1, x2, y2, 1); + + x1 = 10; y1 = 110; x2 = 90; y2 = 190; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2 + 1, y1, 4); + surface_pset(screen, x2, y1 - 1, 4); + surface_pset(screen, x1 - 1, y2, 4); + surface_pset(screen, x1, y2 + 1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_filled_rect_f(screen, x1, y1, x2, y2, 1); + + x1 = 190; y1 = 90; x2 = 110; y2 = 10; + surface_pset(screen, x2 - 1, y2, 4); + surface_pset(screen, x2, y2 - 1, 4); + surface_pset(screen, x1 + 1, y2, 4); + surface_pset(screen, x1, y2 - 1, 4); + surface_pset(screen, x2 - 1, y1, 4); + surface_pset(screen, x2, y1 + 1, 4); + surface_pset(screen, x1 + 1, y1, 4); + surface_pset(screen, x1, y1 + 1, 4); + surface_filled_rect(screen, x1, y1, x2, y2, 2); + + getch(); +} + +// draws 4 rects in each of the top-left and bottom-right corners (two in each +// corner will be completely out of bounds, so should not be visible). also, +// two long rects are drawn along the center of the screen and they each +// extend beyond the edges of the screen. red pixels are drawn to mark rect +// extents. +void test_filled_rect_clipping(void) { + int x1, y1, x2, y2; + + surface_clear(screen, 0); + + x1 = -8; y1 = 10; x2 = 7; y2 = 25; + surface_pset(screen, x2, y1 - 1, 4); + surface_pset(screen, x2 + 1, y1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_filled_rect(screen, x1, y1, x2, y2, 1); + + surface_filled_rect(screen, -16, 30, -1, 46, 10); + + x1 = 20; y1 = -8; x2 = 35; y2 = 7; + surface_pset(screen, x1 - 1, y2, 4); + surface_pset(screen, x1, y2 + 1, 4); + surface_pset(screen, x2 + 1, y2, 4); + surface_pset(screen, x2, y2 + 1, 4); + surface_filled_rect(screen, x1, y1, x2, y2, 2); + + surface_filled_rect(screen, 40, -16, 55, -1, 11); + + x1 = 313; y1 = 170; x2 = 328; y2 = 185; + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1 - 1, y2, 4); + surface_pset(screen, x1, y2 + 1, 4); + surface_filled_rect(screen, x1, y1, x2, y2, 3); + + surface_filled_rect(screen, 320, 150, 335, 165, 12); + + x1 = 285; y1 = 193; x2 = 300; y2 = 208; + surface_pset(screen, x1 - 1, y1, 4); + surface_pset(screen, x1, y1 - 1, 4); + surface_pset(screen, x2 + 1, y1, 4); + surface_pset(screen, x2, y1 - 1, 4); + surface_filled_rect(screen, x1, y1, x2, y2, 5); + + surface_filled_rect(screen, 265, 200, 280, 215, 13); + + x1 = 150; y1 = -10; x2 = 170; y2 = 210; + surface_pset(screen, x1 - 1, 10, 4); + surface_pset(screen, x2 + 1, 10, 4); + surface_filled_rect(screen, x1, y1, x2, y2, 7); + + x1 = -10; y1 = 90; x2 = 330; y2 = 110; + surface_pset(screen, 10, y1 - 1, 4); + surface_pset(screen, 10, y2 + 1, 4); + surface_filled_rect(screen, x1, y1, x2, y2, 8); + + getch(); +} + +// blits a 5-color image in a few different sizes. first two test full +// image blits and partial image blits. remaining 4 blits test the shorthand +// blit function that simply blits the entire source image. +// a duplicate set of blits is done using the "fast" variants. +// the image sizes are chosen to ensure each different internal blitter is run. +void test_blit(void) { + int x, y; + + SURFACE *bmp16 = get_image(16, 16); + SURFACE *bmp12 = get_image(12, 12); + SURFACE *bmp21 = get_image(21, 21); + SURFACE *bmp3 = get_image(3, 3); + + surface_clear(screen, 0); + + x = 0; y = 0; + + surface_blit_region(bmp16, screen, 0, 0, 16, 16, x + 16, y + 16); + surface_blit_region(bmp16, screen, 8, 8, 8, 8, x + 48, y + 16); + + surface_blit(bmp16, screen, x + 16, y + 48); + surface_blit(bmp12, screen, x + 48, y + 48); + surface_blit(bmp21, screen, x + 80, y + 48); + surface_blit(bmp3, screen, x + 112, y + 48); + + x = 160; y = 0; + + surface_blit_region_f(bmp16, screen, 0, 0, 16, 16, x + 16, y + 16); + surface_blit_region_f(bmp16, screen, 8, 8, 8, 8, x + 48, y + 16); + + surface_blit_f(bmp16, screen, x + 16, y + 48); + surface_blit_f(bmp12, screen, x + 48, y + 48); + surface_blit_f(bmp21, screen, x + 80, y + 48); + surface_blit_f(bmp3, screen, x + 112, y + 48); + + surface_free(bmp16); + surface_free(bmp12); + surface_free(bmp21); + surface_free(bmp3); + getch(); +} + +// performs 7 blits along each edge of the screen, clipping the image by +// varying amounts. the 7th blit on each edge is completely out of bounds and +// should not be visible at all. +void test_blit_clipping(void) { + SURFACE *bmp = get_image(16, 16); + + surface_clear(screen, 0); + + surface_blit(bmp, screen, -3, 16); + surface_blit(bmp, screen, -4, 36); + surface_blit(bmp, screen, -8, 56); + surface_blit(bmp, screen, -12, 76); + surface_blit(bmp, screen, -13, 96); + surface_blit(bmp, screen, -14, 116); + surface_blit(bmp, screen, -16, 136); + + surface_blit(bmp, screen, 16, -3); + surface_blit(bmp, screen, 36, -4); + surface_blit(bmp, screen, 56, -8); + surface_blit(bmp, screen, 76, -12); + surface_blit(bmp, screen, 96, -13); + surface_blit(bmp, screen, 116, -14); + surface_blit(bmp, screen, 136, -16); + + surface_blit(bmp, screen, 307, 16); + surface_blit(bmp, screen, 308, 36); + surface_blit(bmp, screen, 312, 56); + surface_blit(bmp, screen, 316, 76); + surface_blit(bmp, screen, 317, 96); + surface_blit(bmp, screen, 318, 116); + surface_blit(bmp, screen, 320, 136); + + surface_blit(bmp, screen, 16, 187); + surface_blit(bmp, screen, 36, 188); + surface_blit(bmp, screen, 56, 192); + surface_blit(bmp, screen, 76, 196); + surface_blit(bmp, screen, 96, 197); + surface_blit(bmp, screen, 116, 198); + surface_blit(bmp, screen, 136, 200); + + surface_free(bmp); + getch(); +} + +// basically the exact same test as test_blit(), but uses sprite blitting +// instead and uses a grey background. no part of the screen buffer should be +// black as that colour is not used anywhere in the test sprite. +void test_sprite(void) { + int x, y; + SURFACE *bmp16 = get_sprite(16, 16); + SURFACE *bmp12 = get_sprite(12, 12); + SURFACE *bmp21 = get_sprite(21, 21); + SURFACE *bmp3 = get_sprite(3, 3); + + surface_clear(screen, 8); + + x = 0; y = 0; + + surface_blit_sprite_region(bmp16, screen, 0, 0, 16, 16, x + 16, y + 16); + surface_blit_sprite_region(bmp16, screen, 8, 8, 8, 8, x + 48, y + 16); + + surface_blit_sprite(bmp16, screen, x + 16, y + 48); + surface_blit_sprite(bmp12, screen, x + 48, y + 48); + surface_blit_sprite(bmp21, screen, x + 80, y + 48); + surface_blit_sprite(bmp3, screen, x + 112, y + 48); + + x = 160; y = 0; + + surface_blit_sprite_region_f(bmp16, screen, 0, 0, 16, 16, x + 16, y + 16); + surface_blit_sprite_region_f(bmp16, screen, 8, 8, 8, 8, x + 48, y + 16); + + surface_blit_sprite_f(bmp16, screen, x + 16, y + 48); + surface_blit_sprite_f(bmp12, screen, x + 48, y + 48); + surface_blit_sprite_f(bmp21, screen, x + 80, y + 48); + surface_blit_sprite_f(bmp3, screen, x + 112, y + 48); + + surface_free(bmp16); + surface_free(bmp12); + surface_free(bmp21); + surface_free(bmp3); + getch(); +} + +// basically the exact same test as test_blit_clipping(), but uses sprite +// blitting instead and uses a grey background. no part of the screen buffer +// should be black as that colour is not used anywhere in the test sprite. +void test_sprite_clipping(void) { + SURFACE *bmp = get_sprite(16, 16); + + surface_clear(screen, 8); + + surface_blit_sprite(bmp, screen, -3, 16); + surface_blit_sprite(bmp, screen, -4, 36); + surface_blit_sprite(bmp, screen, -8, 56); + surface_blit_sprite(bmp, screen, -12, 76); + surface_blit_sprite(bmp, screen, -13, 96); + surface_blit_sprite(bmp, screen, -14, 116); + surface_blit_sprite(bmp, screen, -16, 136); + + surface_blit_sprite(bmp, screen, 16, -3); + surface_blit_sprite(bmp, screen, 36, -4); + surface_blit_sprite(bmp, screen, 56, -8); + surface_blit_sprite(bmp, screen, 76, -12); + surface_blit_sprite(bmp, screen, 96, -13); + surface_blit_sprite(bmp, screen, 116, -14); + surface_blit_sprite(bmp, screen, 136, -16); + + surface_blit_sprite(bmp, screen, 307, 16); + surface_blit_sprite(bmp, screen, 308, 36); + surface_blit_sprite(bmp, screen, 312, 56); + surface_blit_sprite(bmp, screen, 316, 76); + surface_blit_sprite(bmp, screen, 317, 96); + surface_blit_sprite(bmp, screen, 318, 116); + surface_blit_sprite(bmp, screen, 320, 136); + + surface_blit_sprite(bmp, screen, 16, 187); + surface_blit_sprite(bmp, screen, 36, 188); + surface_blit_sprite(bmp, screen, 56, 192); + surface_blit_sprite(bmp, screen, 76, 196); + surface_blit_sprite(bmp, screen, 96, 197); + surface_blit_sprite(bmp, screen, 116, 198); + surface_blit_sprite(bmp, screen, 136, 200); + + surface_free(bmp); + getch(); +} + +// prints out some simple text messages, including ones with newlines in them. +// also prints out the entire 1-127 ASCII character set in a 16x8 grid. +// a duplicate set of text is drawn using the "fast" variants. +void test_text(void) { + int i, x, y; + char string[255]; + char *p; + + surface_clear(screen, 0); + memset(string, 0, 255); + + surface_text(screen, 10, 10, 15, "Hello, world!"); + surface_text_f(screen, 170, 10, 15, "Hello, world!"); + + surface_filled_rect(screen, 8, 28, 114, 40, 7); + surface_text(screen, 10, 30, 15, "transparency!"); + surface_filled_rect_f(screen, 168, 28, 274, 40, 7); + surface_text_f(screen, 170, 30, 15, "transparency!"); + + surface_text(screen, 10, 50, 15, "line 1\nline 2"); + surface_text_f(screen, 170, 50, 15, "line 1\nline 2"); + + surface_printf(screen, 10, 70, 15, "printf pi %.5f", PI); + surface_printf_f(screen, 170, 70, 15, "printf pi %.5f", PI); + + p = &string[0]; + for (i = 1; i <= 127; ++i, ++p) { + if (i % 16 == 0) { + *p = '\n'; + ++p; + } + if (i == 10) + *p = ' '; // will be interpreted as a \n (and hence, not shown) + else + *p = (char)i; + } + + surface_text(screen, 10, 100, 15, string); + surface_text_f(screen, 170, 100, 15, string); + + getch(); +} + +// text is drawn along each edge of the screen. two messages are drawn at each +// edge, but one is completely out of bounds so the second should not be +// visible. red rects are drawn marking the extents of the text. +void test_text_clipping(void) { + int x, y; + char message[] = "Hello, world!"; + int len = strlen(message); + int width = len * 8; + int height = 8; + + surface_clear(screen, 0); + + x = -32; y = 10; + surface_rect(screen, x - 1, y - 1, x + width, y + height, 4); + surface_text(screen, x, y, 9, message); + + x = 80; y = -4; + surface_rect(screen, x - 1, y - 1, x + width, y + height, 4); + surface_text(screen, x, y, 10, message); + + x = 288; y = 120; + surface_rect(screen, x - 1, y - 1, x + width, y + height, 4); + surface_text(screen, x, y, 11, message); + + x = 200; y = 196; + surface_rect(screen, x - 1, y - 1, x + width, y + height, 4); + surface_text(screen, x, y, 12, message); + + x = -232; y = 10; + surface_rect(screen, x - 1, y - 1, x + width, y + height, 4); + surface_text(screen, x, y, 5, message); + + x = 80; y = -24; + surface_rect(screen, x - 1, y - 1, x + width, y + height, 4); + surface_text(screen, x, y, 6, message); + + x = 360; y = 120; + surface_rect(screen, x - 1, y - 1, x + width, y + height, 4); + surface_text(screen, x, y, 7, message); + + x = 200; y = 240; + surface_rect(screen, x - 1, y - 1, x + width, y + height, 4); + surface_text(screen, x, y, 8, message); + + getch(); +} + +// displays the entire palette in a grid, waits for a keypress, then changes +// color 15's RGB values. +void test_palette(void) { + int i, x, y; + byte r, g, b; + + surface_clear(screen, 0); + + i = 0; + for (y = 0; y < 16; ++y) { + for (x = 0; x < 16; ++x) { + surface_filled_rect(screen, x * 8, y * 8, x * 8 + 7, y * 8 + 7, i); + ++i; + } + } + + getch(); + + pal_get_color(15, &r, &g, &b); + ASSERT(r == 63 && g == 63 && b == 63); + pal_set_color(15, r / 2, g / 2, b / 2); + + getch(); + pal_set_color(15, r, g, b); +} + +void test_palette_fading(void) { + int i, x, y; + byte palette[768]; + surface_clear(screen, 0); + + i = 0; + for (y = 0; y < 16; ++y) { + for (x = 0; x < 16; ++x) { + surface_filled_rect(screen, x * 8, y * 8, x * 8 + 7, y * 8 + 7, i); + ++i; + } + } + pal_get(palette); + + getch(); + + pal_fade_range_to_color(16, 31, 0, 0, 0, 1); + + getch(); + + pal_fade_range_to_palette(16, 31, palette, 1); + + getch(); + + pal_fade_to_color(0, 0, 0, 1); + + getch(); + + pal_fade_to_palette(palette, 1); + + getch(); +} + +void test_pcx(void) { + SURFACE *pcx; + DGL_ERROR err; + byte pcx_palette[768]; + byte original_palette[768]; + + surface_clear(screen, 0); + pal_get(original_palette); + + pcx = pcx_load("notreal.pcx", NULL); + err = dgl_last_error(); + ASSERT(pcx == NULL); + ASSERT(err != DGL_NONE); + + pcx = pcx_load("test.pcx", NULL); + ASSERT(pcx != NULL); + + surface_blit(pcx, screen, 0, 0); + getch(); + + surface_clear(screen, 0); + surface_free(pcx); + pcx = pcx_load("test.pcx", pcx_palette); + ASSERT(pcx != NULL); + + pal_set(pcx_palette); + surface_blit(pcx, screen, 0, 0); + + getch(); + pal_set(original_palette); +} + +// --------------------------------------------------------------------------- + +int main(void) { + signal(SIGINT, break_handler); + + dgl_init(); + + ASSERT(screen == NULL); + + if (!video_init()) { + printf("Error initializing video: %s\n", dgl_last_error_message()); return 1; } + ASSERT(screen != NULL); + ASSERT(screen->width == 320 && screen->height == 200); + backbuffer = surface_create(320, 200); + ASSERT(backbuffer != NULL); + ASSERT(backbuffer->width == 320 && backbuffer->height == 200); - - while (!keys[KEY_ESC]) { - surface_clear(backbuffer, 0); - - surface_text(backbuffer, 100, 100, 15, "Hello, world!"); - - - video_wait_vsync(); - surface_copy(backbuffer, screen); - } + test_fixed(); + test_vector2i(); + test_vector2f(); + test_surface_clear(); + test_surface_copy(); + test_pixels_1(); + test_pixels_2(); + test_pixels_clipping(); + test_hline(); + test_hline_clipping(); + test_vline(); + test_vline_clipping(); + test_line(); + test_line_clipping(); + test_rect(); + test_rect_clipping(); + test_filled_rect(); + test_filled_rect_clipping(); + test_blit(); + test_blit_clipping(); + test_sprite(); + test_sprite_clipping(); + test_text(); + test_text_clipping(); + test_palette(); + test_palette_fading(); + test_pcx(); surface_free(backbuffer); - if (!dgl_shutdown()) { - printf("Failed to close DGL: %s\n", dgl_last_error_message()); - return 1; - } return 0; } diff --git a/UTIL.C b/UTIL.C deleted file mode 100644 index 6a776e5..0000000 --- a/UTIL.C +++ /dev/null @@ -1,37 +0,0 @@ -#include "util.h" -#include -#include -#include - -#define SYS_CLOCKS_PER_SEC (1000.0f / 55.0f) - -void* map_dos_memory(long physical_addr) { - return (void*)(__djgpp_conventional_base + physical_addr); -} - -int sys_clock() { - //return *((int*)(map_dos_memory(0x046c))); - return (int)clock(); -} - -int sys_ticks() { - return (int)uclock(); -} - -float clock_ticks_to_seconds(int clocks) { - //return clocks / SYS_CLOCKS_PER_SEC; - return clocks / (float)CLOCKS_PER_SEC; -} - -float ticks_to_seconds(int ticks) { - return (float)ticks / UCLOCKS_PER_SEC; -} - -int rnd_int(int low, int high) { - return rand() % ((high - low) + 1) + low; -} - -float rnd_float(float low, float high) { - return low + (rand() / (float)RAND_MAX) * (high - low); -} - diff --git a/UTIL.H b/UTIL.H deleted file mode 100644 index 2b1cf12..0000000 --- a/UTIL.H +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef DGL_UTIL_H_INCLUDED -#define DGL_UTIL_H_INCLUDED - -#include "common.h" - -#define SWAP(type, a, b) \ - do { \ - type __tmp = a; \ - a = b; \ - b = __tmp; \ - } while (0) - -#define SIGN(x) (((x) < 0) ? -1 : (((x) > 0) ? 1 : 0)) - -void* map_dos_memory(long physical_addr); - -int sys_clock(); -int sys_ticks(); -float clock_ticks_to_seconds(int clocks); -float ticks_to_seconds(int ticks); - -int rnd_int(int low, int high); -float rnd_float(float low, float high); - -#endif - diff --git a/VECTOR2.H b/VECTOR2.H deleted file mode 100644 index ab5f95d..0000000 --- a/VECTOR2.H +++ /dev/null @@ -1,284 +0,0 @@ -#ifndef DGL_VECTOR2_H_INCLUDED -#define DGL_VECTOR2_H_INCLUDED - -#include -#include "common.h" - -typedef struct { - int x; - int y; -} VECTOR2I; - -static inline VECTOR2I vector2i(int x, int y); -static inline void vector2i_set(VECTOR2I *v, int x, int y); -static inline boolean vector2i_equals(VECTOR2I a, VECTOR2I b); -static inline VECTOR2I vector2i_add(VECTOR2I a, VECTOR2I b); -static inline VECTOR2I vector2i_sub(VECTOR2I a, VECTOR2I b); -static inline VECTOR2I vector2i_mul(VECTOR2I a, VECTOR2I b); -static inline VECTOR2I vector2i_muls(VECTOR2I v, int n); -static inline VECTOR2I vector2i_div(VECTOR2I a, VECTOR2I b); -static inline VECTOR2I vector2i_divs(VECTOR2I v, int n); -static inline int vector2i_distance(VECTOR2I a, VECTOR2I b); -static inline int vector2i_distancesq(VECTOR2I a, VECTOR2I b); -static inline int vector2i_dot(VECTOR2I a, VECTOR2I b); -static inline int vector2i_length(VECTOR2I v); -static inline int vector2i_lengthsq(VECTOR2I v); -static inline VECTOR2I vector2i_lerp(VECTOR2I a, VECTOR2I b, float lerp); - -#define ZERO_VECTOR2I vector2i(0, 0) -#define UP_VECTOR2I vector2i(0, -1); -#define DOWN_VECTOR2I vector2i(0, 1); -#define LEFT_VECTOR2I vector2i(-1, 0); -#define RIGHT_VECTOR2I vector2i(1, 0); -#define UNIT_X_VECTOR2I vector2i(1, 0); -#define UNIT_Y_VECTOR2I vector2i(0, 1); - -typedef struct { - float x; - float y; -} VECTOR2F; - -static inline VECTOR2F vector2f(float x, float y); -static inline void vector2f_set(VECTOR2F *v, float x, float y); -static inline boolean vector2f_equals(VECTOR2F a, VECTOR2F b); -static inline VECTOR2F vector2f_add(VECTOR2F a, VECTOR2F b); -static inline VECTOR2F vector2f_sub(VECTOR2F a, VECTOR2F b); -static inline VECTOR2F vector2f_mul(VECTOR2F a, VECTOR2F b); -static inline VECTOR2F vector2f_muls(VECTOR2F v, float n); -static inline VECTOR2F vector2f_div(VECTOR2F a, VECTOR2F b); -static inline VECTOR2F vector2f_divs(VECTOR2F v, float n); -static inline float vector2f_distance(VECTOR2F a, VECTOR2F b); -static inline float vector2f_distancesq(VECTOR2F a, VECTOR2F b); -static inline float vector2f_dot(VECTOR2F a, VECTOR2F b); -static inline float vector2f_length(VECTOR2F v); -static inline float vector2f_lengthsq(VECTOR2F v); -static inline VECTOR2F vector2f_normalize(VECTOR2F v); -static inline VECTOR2F vector2f_set_length(VECTOR2F v, float length); -static inline VECTOR2F vector2f_lerp(VECTOR2F a, VECTOR2F b, float lerp); - -#define ZERO_VECTOR2F vector2f(0.0f, 0.0f) -#define UP_VECTOR2F vector2f(0.0f, -1.0f); -#define DOWN_VECTOR2F vector2f(0.0f, 1.0f); -#define LEFT_VECTOR2F vector2f(-1.0f, 0.0f); -#define RIGHT_VECTOR2F vector2f(1.0f, 0.0f); -#define UNIT_X_VECTOR2F vector2f(1.0f, 0.0f); -#define UNIT_Y_VECTOR2F vector2f(0.0f, 1.0f); - -// -------------------------------------------------------------------------- - -static inline VECTOR2I vector2i(int x, int y) { - VECTOR2I v; - v.x = x; - v.y = y; - return v; -} - -static inline VECTOR2F vector2f(float x, float y) { - VECTOR2F v; - v.x = x; - v.y = y; - return v; -} - -static inline void vector2i_set(VECTOR2I *v, int x, int y) { - v->x = x; - v->y = y; -} - -static inline void vector2f_set(VECTOR2F *v, float x, float y) { - v->x = x; - v->y = y; -} - -static inline boolean vector2i_equals(VECTOR2I a, VECTOR2I b) { - return (a.x == b.x && a.y == b.y); -} - -static inline boolean vector2f_equals(VECTOR2F a, VECTOR2F b) { - return (a.x == b.x && a.y == b.y); -} - -static inline VECTOR2I vector2i_add(VECTOR2I a, VECTOR2I b) { - VECTOR2I result; - result.x = a.x + b.x; - result.y = a.y + b.y; - return result; -} - -static inline VECTOR2F vector2f_add(VECTOR2F a, VECTOR2F b) { - VECTOR2F result; - result.x = a.x + b.x; - result.y = a.y + b.y; - return result; -} - -static inline VECTOR2I vector2i_sub(VECTOR2I a, VECTOR2I b) { - VECTOR2I result; - result.x = a.x - b.x; - result.y = a.y - b.y; - return result; -} - -static inline VECTOR2F vector2f_sub(VECTOR2F a, VECTOR2F b) { - VECTOR2F result; - result.x = a.x - b.x; - result.y = a.y - b.y; - return result; -} - -static inline VECTOR2I vector2i_mul(VECTOR2I a, VECTOR2I b) { - VECTOR2I result; - result.x = a.x * b.x; - result.y = a.y * b.y; - return result; -} - -static inline VECTOR2F vector2f_mul(VECTOR2F a, VECTOR2F b) { - VECTOR2F result; - result.x = a.x * b.x; - result.y = a.y * b.y; - return result; -} - -static inline VECTOR2I vector2i_muls(VECTOR2I v, int n) { - VECTOR2I result; - result.x = v.x * n; - result.y = v.y * n; - return result; -} - -static inline VECTOR2F vector2f_muls(VECTOR2F v, float n) { - VECTOR2F result; - result.x = v.x * n; - result.y = v.y * n; - return result; -} - -static inline VECTOR2I vector2i_div(VECTOR2I a, VECTOR2I b) { - VECTOR2I result; - result.x = a.x / b.x; - result.y = a.y / b.y; - return result; -} - -static inline VECTOR2F vector2f_div(VECTOR2F a, VECTOR2F b) { - VECTOR2F result; - result.x = a.x / b.x; - result.y = a.y / b.y; - return result; -} - -static inline VECTOR2I vector2i_divs(VECTOR2I v, int n) { - VECTOR2I result; - result.x = v.x / n; - result.y = v.y / n; - return result; -} - -static inline VECTOR2F vector2f_divs(VECTOR2F v, float n) { - VECTOR2F result; - result.x = v.x / n; - result.y = v.y / n; - return result; -} - -static inline int vector2i_distance(VECTOR2I a, VECTOR2I b) { - return (int)sqrt( - ((b.x - a.x) * (b.x - a.x)) + - ((b.y - a.y) * (b.y - a.y)) - ); -} - -static inline float vector2f_distance(VECTOR2F a, VECTOR2F b) { - return (float)sqrt( - ((b.x - a.x) * (b.x - a.x)) + - ((b.y - a.y) * (b.y - a.y)) - ); -} - -static inline int vector2i_distancesq(VECTOR2I a, VECTOR2I b) { - return - ((b.x - a.x) * (b.x - a.x)) + - ((b.y - a.y) * (b.y - a.y)); -} - -static inline float vector2f_distancesq(VECTOR2F a, VECTOR2F b) { - return - ((b.x - a.x) * (b.x - a.x)) + - ((b.y - a.y) * (b.y - a.y)); -} - -static inline int vector2i_dot(VECTOR2I a, VECTOR2I b) { - return - (a.x * b.x) + - (a.y * b.y); -} - -static inline float vector2f_dot(VECTOR2F a, VECTOR2F b) { - return - (a.x * b.x) + - (a.y * b.y); -} - -static inline int vector2i_length(VECTOR2I v) { - return sqrt( - (v.x * v.x) + - (v.y * v.y) - ); -} - -static inline float vector2f_length(VECTOR2F v) { - return (float)sqrt( - (v.x * v.x) + - (v.y * v.y) - ); -} - -static inline int vector2i_lengthsq(VECTOR2I v) { - return - (v.x * v.x) + - (v.y * v.y); -} - -static inline float vector2f_lengthsq(VECTOR2F v) { - return - (v.x * v.x) + - (v.y * v.y); -} - -static inline VECTOR2F vector2f_normalize(VECTOR2F v) { - float inverse_length; - VECTOR2F result; - - inverse_length = 1.0f / vector2f_length(v); - result.x = v.x * inverse_length; - result.y = v.y * inverse_length; - return result; -} - -static inline VECTOR2F vector2f_set_length(VECTOR2F v, float length) { - float scale_factor; - VECTOR2F result; - - scale_factor = length / vector2f_length(v); - result.x = v.x * scale_factor; - result.y = v.y * scale_factor; - return result; -} - -static inline VECTOR2I vector2i_lerp(VECTOR2I a, VECTOR2I b, float lerp) { - VECTOR2I result; - result.x = a.x + (b.x - a.x) * lerp; - result.y = a.y + (b.y - a.y) * lerp; - return result; -} - -static inline VECTOR2F vector2f_lerp(VECTOR2F a, VECTOR2F b, float lerp) { - VECTOR2F result; - result.x = a.x + (b.x - a.x) * lerp; - result.y = a.y + (b.y - a.y) * lerp; - return result; -} - -#endif -