many updates. moved project over to watcom

This commit is contained in:
Gered 2018-04-28 11:30:53 -04:00
parent e5415c977c
commit 123d3b8256
44 changed files with 3497 additions and 1292 deletions

68
DGL.C
View file

@ -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 <stdlib.h>
#include <go32.h>
#include <sys/nearptr.h>
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);
}

33
DGL.H
View file

@ -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

View file

@ -1,8 +1,7 @@
#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,
static boolean clip_blit(const RECT *dest_clip_region,
RECT *src_blit_region,
int *dest_x,
int *dest_y) {
@ -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;
}
} 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;
}
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 {
while (lines_left) {
for (x = 0; x < width; ++x) {
if ((pixel = psrc[x]))
pdest[x] = pixel;
// width is a multiple of 4 (no remainder)
direct_blit_sprite_4(width_4, lines_left, pdest, psrc, dest_y_inc, src_y_inc);
}
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 {
// width is <= 3
direct_blit_sprite_r(width_remainder, lines_left, pdest, psrc, dest_y_inc, src_y_inc);
}
}

View file

@ -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);
}

535
DGLBLITA.ASM Normal file
View file

@ -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

View file

@ -1,8 +1,8 @@
#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,
static boolean is_in_bounds(int clip_x,
int clip_y,
int clip_right,
int clip_bottom,

View file

@ -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.

View file

@ -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))

View file

@ -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 <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
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);
// 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);
// 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 (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 == 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.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,7 +292,7 @@ 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,
static void print_char(SURFACE *surface,
int dest_x,
int dest_y,
const RECT *dest_clipped,
@ -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,7 +328,7 @@ static inline void print_char(SURFACE *surface,
}
}
static inline void print_text(SURFACE *surface,
static void print_text(SURFACE *surface,
int x,
int y,
int color,
@ -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))

View file

@ -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))

159
DGLDRAWA.ASM Normal file
View file

@ -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

View file

@ -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,

20
DGLFIXP.C Normal file
View file

@ -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;
}

89
DGLFIXP.H Normal file
View file

@ -0,0 +1,89 @@
#ifndef DGL_DGLFIXP_H_INCLUDED
#define DGL_DGLFIXP_H_INCLUDED
#include "dglcmn.h"
#include <math.h>
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

103
DGLGFX.C Normal file
View file

@ -0,0 +1,103 @@
#include "dglgfx.h"
#include "dglblit.h"
#include "dglutil.h"
#include "dglerror.h"
#include <stdlib.h>
#include <string.h>
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);
}
}

44
DGLGFX.H Normal file
View file

@ -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

View file

@ -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 <string.h>
#include <dpmi.h>
#include <pc.h>
#include <sys/nearptr.h>
#include <dos.h>
#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

View file

@ -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.

View file

@ -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

View file

@ -1,4 +1,4 @@
#include "mathext.h"
#include "dglmath.h"
#include <math.h>
float angle_between_i(int x1, int y1, int x2, int y2) {

View file

@ -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 <math.h>
#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)));
}

159
DGLMOUSE.C Normal file
View file

@ -0,0 +1,159 @@
#include "dglmouse.h"
#include "dglerror.h"
#include <string.h>
#include <dos.h>
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(&regs, 0, sizeof(regs));
regs.w.ax = 0x00;
int386(0x33, &regs, &regs);
return (regs.w.ax != 0);
}
static void update_mouse_state(void) {
union REGS regs;
memset(&regs, 0, sizeof(regs));
regs.w.ax = 0x03;
int386(0x33, &regs, &regs);
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(&regs, 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, &regs, &regs, &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(&regs, 0, sizeof(regs));
regs.w.ax = 0x0c;
regs.w.cx = 0;
int386(0x33, &regs, &regs);
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(&regs, 0, sizeof(regs));
regs.w.ax = 0x01;
int386(0x33, &regs, &regs);
}
void mouse_hide(void) {
union REGS regs;
if (!_has_mouse)
return;
memset(&regs, 0, sizeof(regs));
regs.w.ax = 0x02;
int386(0x33, &regs, &regs);
}
void mouse_set_bounds(int min_x, int min_y, int max_x, int max_y) {
union REGS regs;
if (!_has_mouse)
return;
memset(&regs, 0, sizeof(regs));
regs.w.ax = 0x07;
regs.w.cx = min_x;
regs.w.dx = max_x;
int386(0x33, &regs, &regs);
regs.w.ax = 0x08;
regs.w.cx = min_y;
regs.w.dx = max_y;
int386(0x33, &regs, &regs);
}

View file

@ -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;
}

View file

@ -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 <math.h>
#define _M33_11 0
@ -20,33 +20,33 @@ typedef struct {
float m[9];
} MATRIX33;
static inline MATRIX33 matrix33(float m11, float m12, float m13,
static 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,
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,7 +54,7 @@ static inline VECTOR2F matrix33_transform_2d(MATRIX33 m, VECTOR2F v);
// --------------------------------------------------------------------------
static inline MATRIX33 matrix33(float m11, float m12, float m13,
static MATRIX33 matrix33(float m11, float m12, float m13,
float m21, float m22, float m23,
float m31, float m32, float m33) {
MATRIX33 result;
@ -70,7 +70,7 @@ static inline MATRIX33 matrix33(float m11, float m12, float m13,
return result;
}
static inline void matrix33_set(MATRIX33 *m,
static void matrix33_set(MATRIX33 *m,
float m11, float m12, float m13,
float m21, float m22, float m23,
float m31, float m32, float m33) {
@ -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];

109
DGLPAL.C Normal file
View file

@ -0,0 +1,109 @@
#include "dglpal.h"
#include "dglgfx.h"
#include <stdlib.h>
#include <dos.h>
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;
}
}
}

27
DGLPAL.H Normal file
View file

@ -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

View file

@ -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 <stdio.h>
#include <string.h>
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,25 +58,30 @@ 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;
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--;
}
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 {
pcx->pixels[i++] = data;
count = 1;
}
// store this pixel colour the specified number of times
while (count--) {
if (x < pcx->width) {
pcx->pixels[i] = data;
}
++i;
++x;
}
}
}
@ -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)

View file

@ -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);

View file

@ -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

22
DGLUTIL.C Normal file
View file

@ -0,0 +1,22 @@
#include "dglutil.h"
#include <stdlib.h>
#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);
}

100
DGLUTIL.H Normal file
View file

@ -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

436
DGLVEC2.H Normal file
View file

@ -0,0 +1,436 @@
#ifndef DGL_DGLVEC2_H_INCLUDED
#define DGL_DGLVEC2_H_INCLUDED
#include <math.h>
#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

151
GFX.C
View file

@ -1,151 +0,0 @@
#include "gfx.h"
#include "blit.h"
#include "util.h"
#include "internal.h"
#include "error.h"
#include <stdlib.h>
#include <string.h>
#include <dpmi.h>
#include <pc.h>
static boolean _initialized = FALSE;
SURFACE *screen = NULL;
static SURFACE* surface_create_internal(int width, int height, byte *pixels) {
SURFACE *surface = malloc(sizeof(SURFACE));
surface->width = width;
surface->height = height;
surface->clip_region = rect(0, 0, width, height);
if (pixels != NULL) {
surface->aliased = TRUE;
surface->pixels = pixels;
} else {
surface->aliased = FALSE;
surface->pixels = malloc(width * height);
memset(surface->pixels, 0, width * height);
}
return surface;
}
boolean video_init(void) {
__dpmi_regs regs;
void *framebuffer;
if (_initialized) {
dgl_set_error(DGL_VIDEO_ALREADY_INITIALIZED);
return FALSE;
}
memset(&regs, 0, sizeof(__dpmi_regs));
regs.h.ah = 0x00;
regs.h.al = 0x13;
if (__dpmi_int(0x10, &regs)) {
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(&regs, 0, sizeof(__dpmi_regs));
regs.h.ah = 0x00;
regs.h.al = 0x03;
if (__dpmi_int(0x10, &regs)) {
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);
}
}

47
GFX.H
View file

@ -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

View file

@ -1,36 +0,0 @@
#include "internal.h"
#include <dpmi.h>
#include <go32.h>
#include <string.h>
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;
}

View file

@ -1,60 +0,0 @@
#ifndef DGL_INTERNAL_H_INCLUDED
#define DGL_INTERNAL_H_INCLUDED
#include "common.h"
#include <dpmi.h>
#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

Binary file not shown.

Binary file not shown.

80
MAKEFILE Normal file
View file

@ -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

188
MOUSE.C
View file

@ -1,188 +0,0 @@
#include "mouse.h"
#include "internal.h"
#include "error.h"
#include <string.h>
#include <go32.h>
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(&regs, 0, sizeof(__dpmi_regs));
regs.x.ax = 0x00;
__dpmi_int(0x33, &regs);
return (regs.x.ax != 0);
}
static void update_mouse_state(void) {
__dpmi_regs regs;
memset(&regs, 0, sizeof(__dpmi_regs));
regs.x.ax = 0x03;
__dpmi_int(0x33, &regs);
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(&regs, 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, &regs) != 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(&regs, 0, sizeof(__dpmi_regs));
regs.x.ax = 0x0c;
regs.x.cx = 0;
regs.x.dx = 0;
regs.x.es = 0;
if (__dpmi_int(0x33, &regs) != 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(&regs, 0, sizeof(__dpmi_regs));
regs.x.ax = 0x01;
__dpmi_int(0x33, &regs);
}
void mouse_hide(void) {
__dpmi_regs regs;
if (!_has_mouse)
return;
memset(&regs, 0, sizeof(__dpmi_regs));
regs.x.ax = 0x02;
__dpmi_int(0x33, &regs);
}
void mouse_set_bounds(int min_x, int min_y, int max_x, int max_y) {
__dpmi_regs regs;
if (!_has_mouse)
return;
memset(&regs, 0, sizeof(__dpmi_regs));
regs.x.ax = 0x07;
regs.x.cx = min_x;
regs.x.dx = max_x;
__dpmi_int(0x33, &regs);
regs.x.ax = 0x08;
regs.x.cx = min_y;
regs.x.dx = max_y;
__dpmi_int(0x33, &regs);
}

1200
TEST.C

File diff suppressed because it is too large Load diff

37
UTIL.C
View file

@ -1,37 +0,0 @@
#include "util.h"
#include <stdlib.h>
#include <time.h>
#include <sys/nearptr.h>
#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);
}

26
UTIL.H
View file

@ -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

284
VECTOR2.H
View file

@ -1,284 +0,0 @@
#ifndef DGL_VECTOR2_H_INCLUDED
#define DGL_VECTOR2_H_INCLUDED
#include <math.h>
#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