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 e0b928a..0000000 Binary files a/LIBDGL.GDT and /dev/null differ diff --git a/LIBDGL.GPR b/LIBDGL.GPR deleted file mode 100644 index d0fc7e3..0000000 Binary files a/LIBDGL.GPR and /dev/null differ 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 -