rayzor
changeset 0:2a5340a6eee4
rayzor first commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 05 Apr 2014 08:46:27 +0300 |
parents | |
children | a826bf0fb169 |
files | .hgignore Makefile src/camera.cc src/camera.h src/dpmi.c src/dpmi.h src/gfx.c src/gfx.h src/inttypes.h src/keyb.c src/keyb.h src/light.cc src/light.h src/logger.c src/logger.h src/m3dimpl.h src/main.cc src/min3d.c src/min3d.h src/mouse.c src/mouse.h src/object.cc src/object.h src/pit8254.h src/rend.cc src/rend.h src/scancode.h src/scene.cc src/scene.h src/timer.c src/timer.h src/vbe.c src/vbe.h src/vmath.cc src/vmath.h src/vmathmat.h |
diffstat | 36 files changed, 2199 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Sat Apr 05 08:46:27 2014 +0300 1.3 @@ -0,0 +1,4 @@ 1.4 +\.o$ 1.5 +\.swp$ 1.6 +\.obj$ 1.7 +\.exe$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Sat Apr 05 08:46:27 2014 +0300 2.3 @@ -0,0 +1,29 @@ 2.4 +modelobj = main.obj min3d.obj logger.obj 2.5 +rendobj = rend.obj vmath.obj 2.6 +scnobj = scene.obj object.obj 2.7 +sysobj = gfx.obj vbe.obj dpmi.obj timer.obj mouse.obj keyb.obj 2.8 +obj = $(modelobj) $(rendobj) $(scnobj) $(sysobj) 2.9 +bin = rayzor.exe 2.10 + 2.11 +CC = wcc386 2.12 +CXX = wpp386 2.13 +CFLAGS = -5 -fp5 -otexan -zq -bt=dos -Isrc\stl 2.14 +CXXFLAGS = $(CFLAGS) 2.15 +LD = wlink 2.16 + 2.17 +$(bin): $(obj) 2.18 + %write objects.lnk file { $(obj) } 2.19 + $(LD) name $@ @objects $(LDFLAGS) 2.20 + 2.21 +.c: src\ 2.22 +.cc: src\ 2.23 + 2.24 +.c.obj: .autodepend 2.25 + $(CC) $(CFLAGS) $[* 2.26 + 2.27 +.cc.obj: .autodepend 2.28 + $(CXX) $(CXXFLAGS) $[* 2.29 + 2.30 +clean: .symbolic 2.31 + del *.obj 2.32 + del $(bin)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/camera.cc Sat Apr 05 08:46:27 2014 +0300 3.3 @@ -0,0 +1,50 @@ 3.4 +#include "camera.h" 3.5 + 3.6 +Camera::Camera() 3.7 + : pos(0, 0, 10) 3.8 +{ 3.9 + fov = M_PI; 3.10 +} 3.11 + 3.12 +void Camera::set_position(const Vector3 &pos) 3.13 +{ 3.14 + this->pos = pos; 3.15 +} 3.16 + 3.17 +const Vector3 &Camera::get_position() const 3.18 +{ 3.19 + return pos; 3.20 +} 3.21 + 3.22 +void Camera::set_target(const Vector3 &target) 3.23 +{ 3.24 + this->target = target; 3.25 +} 3.26 + 3.27 +const Vector3 &Camera::get_target() const 3.28 +{ 3.29 + return target; 3.30 +} 3.31 + 3.32 +void Camera::set_fov(float fov) 3.33 +{ 3.34 + this->fov = fov; 3.35 +} 3.36 + 3.37 +float Camera::get_fov() const 3.38 +{ 3.39 + return fov; 3.40 +} 3.41 + 3.42 +Matrix4x4 Camera::get_matrix() const 3.43 +{ 3.44 + Matrix4x4 res; 3.45 + res.lookat(pos, target, Vector3(0, 1, 0)); 3.46 + return res; 3.47 +} 3.48 + 3.49 +Matrix4x4 Camera::get_inv_matrix() const 3.50 +{ 3.51 + Matrix4x4 res; 3.52 + return res; // TODO 3.53 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/camera.h Sat Apr 05 08:46:27 2014 +0300 4.3 @@ -0,0 +1,28 @@ 4.4 +#ifndef CAMERA_H_ 4.5 +#define CAMERA_H_ 4.6 + 4.7 +#include "vmath.h" 4.8 + 4.9 +class Camera { 4.10 +private: 4.11 + Vector3 pos; 4.12 + Vector3 target; 4.13 + float fov; 4.14 + 4.15 +public: 4.16 + Camera(); 4.17 + 4.18 + void set_position(const Vector3 &pos); 4.19 + const Vector3 &get_position() const; 4.20 + 4.21 + void set_target(const Vector3 &target); 4.22 + const Vector3 &get_target() const; 4.23 + 4.24 + void set_fov(float fov); 4.25 + float get_fov() const; 4.26 + 4.27 + Matrix4x4 get_matrix() const; 4.28 + Matrix4x4 get_inv_matrix() const; 4.29 +}; 4.30 + 4.31 +#endif // CAMERA_H_
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/dpmi.c Sat Apr 05 08:46:27 2014 +0300 5.3 @@ -0,0 +1,55 @@ 5.4 +#include "dpmi.h" 5.5 + 5.6 +void dpmi_real_int(int inum, struct dpmi_real_regs *regs) 5.7 +{ 5.8 + unsigned char int_num = (unsigned char)inum; 5.9 + __asm { 5.10 + mov eax, 0x300 5.11 + mov edi, regs 5.12 + mov bl, int_num 5.13 + mov bh, 0 5.14 + xor ecx, ecx 5.15 + int 0x31 5.16 + } 5.17 +} 5.18 + 5.19 +void *dpmi_mmap(uint32_t phys_addr, unsigned int size) 5.20 +{ 5.21 + uint16_t mem_high, mem_low; 5.22 + uint16_t phys_high = phys_addr >> 16; 5.23 + uint16_t phys_low = phys_addr & 0xffff; 5.24 + uint16_t size_high = size >> 16; 5.25 + uint16_t size_low = size & 0xffff; 5.26 + unsigned int err, res = 0; 5.27 + 5.28 + __asm { 5.29 + mov eax, 0x800 5.30 + mov bx, phys_high 5.31 + mov cx, phys_low 5.32 + mov si, size_high 5.33 + mov di, size_low 5.34 + int 0x31 5.35 + add res, 1 5.36 + mov err, eax 5.37 + mov mem_high, bx 5.38 + mov mem_low, cx 5.39 + } 5.40 + 5.41 + if(res == 2) { 5.42 + return 0; 5.43 + } 5.44 + return (void*)(((uint32_t)mem_high << 16) | ((uint32_t)mem_low)); 5.45 +} 5.46 + 5.47 +void dpmi_munmap(void *addr) 5.48 +{ 5.49 + uint16_t mem_high = (uint32_t)addr >> 16; 5.50 + uint16_t mem_low = (uint16_t)addr; 5.51 + 5.52 + __asm { 5.53 + mov eax, 0x801 5.54 + mov bx, mem_high 5.55 + mov cx, mem_low 5.56 + int 0x31 5.57 + } 5.58 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/dpmi.h Sat Apr 05 08:46:27 2014 +0300 6.3 @@ -0,0 +1,26 @@ 6.4 +#ifndef DPMI_H_ 6.5 +#define DPMI_H_ 6.6 + 6.7 +#include "inttypes.h" 6.8 + 6.9 +struct dpmi_real_regs { 6.10 + uint32_t edi, esi, ebp; 6.11 + uint32_t reserved; 6.12 + uint32_t ebx, edx, ecx, eax; 6.13 + uint16_t flags; 6.14 + uint16_t es, ds, fs, gs; 6.15 + uint16_t ip, cs, sp, ss; 6.16 +}; 6.17 + 6.18 +unsigned short dpmi_alloc(unsigned int par); 6.19 +#pragma aux dpmi_alloc = \ 6.20 + "mov eax, 0x100" \ 6.21 + "int 0x31" \ 6.22 + value[ax] parm[ebx]; 6.23 + 6.24 +void dpmi_real_int(int inum, struct dpmi_real_regs *regs); 6.25 + 6.26 +void *dpmi_mmap(uint32_t phys_addr, unsigned int size); 6.27 +void dpmi_munmap(void *addr); 6.28 + 6.29 +#endif /* DPMI_H_ */
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/gfx.c Sat Apr 05 08:46:27 2014 +0300 7.3 @@ -0,0 +1,152 @@ 7.4 +#ifndef GFX_H_ 7.5 +#define GFX_H_ 7.6 + 7.7 +#include <stdio.h> 7.8 +#include <stdlib.h> 7.9 +#include <string.h> 7.10 +#include "vbe.h" 7.11 + 7.12 +#define REALPTR(s, o) (void*)(((uint32_t)(s) << 4) + (uint32_t)(o)) 7.13 +#define VBEPTR(x) REALPTR(((x) & 0xffff0000) >> 16, (x) & 0xffff) 7.14 +#define VBEPTR_SEG(x) (((x) & 0xffff0000) >> 16) 7.15 +#define VBEPTR_OFF(x) ((x) & 0xffff) 7.16 + 7.17 +#define SAME_BPP(a, b) \ 7.18 + ((a) == (b) || (a) == 16 && (b) == 15 || (a) == 15 && (b) == 16 || (a) == 32 && (b) == 24 || (a) == 24 && (b) == 32) 7.19 + 7.20 +static unsigned int make_mask(int sz, int pos); 7.21 + 7.22 +static struct vbe_info *vbe_info; 7.23 +static struct vbe_mode_info *mode_info; 7.24 +static int pal_bits = 6; 7.25 + 7.26 +void *set_video_mode(int xsz, int ysz, int bpp) 7.27 +{ 7.28 + int i; 7.29 + uint16_t *modes, best = 0; 7.30 + unsigned int fbsize; 7.31 + 7.32 + /* check for VBE2 support and output some info */ 7.33 + if(!vbe_info) { 7.34 + if(!(vbe_info = vbe_get_info())) { 7.35 + fprintf(stderr, "VESA BIOS Extensions not available\n"); 7.36 + return 0; 7.37 + } 7.38 + 7.39 + printf("VBE Version: %x.%x\n", vbe_info->version >> 8, vbe_info->version & 0xff); 7.40 + if(vbe_info->version < 0x200) { 7.41 + fprintf(stderr, "This program requires VBE 2.0 or greater. Try running UniVBE\n"); 7.42 + return 0; 7.43 + } 7.44 + 7.45 + printf("Graphics adapter: %s, %s (%s)\n", VBEPTR(vbe_info->oem_vendor_name_ptr), 7.46 + VBEPTR(vbe_info->oem_product_name_ptr), VBEPTR(vbe_info->oem_product_rev_ptr)); 7.47 + printf("Video memory: %dmb\n", vbe_info->total_mem << 6); 7.48 + 7.49 + modes = VBEPTR(vbe_info->vid_mode_ptr); 7.50 + } 7.51 + 7.52 + for(i=0; i<1024; i++) { /* impose an upper limit to avoid inf-loops */ 7.53 + if(modes[i] == 0xffff) { 7.54 + break; /* reached the end */ 7.55 + } 7.56 + 7.57 + mode_info = vbe_get_mode_info(modes[i] | VBE_MODE_LFB); 7.58 + if(!mode_info || mode_info->xres != xsz || mode_info->yres != ysz) { 7.59 + continue; 7.60 + } 7.61 + if(SAME_BPP(mode_info->bpp, bpp)) { 7.62 + best = modes[i]; 7.63 + } 7.64 + } 7.65 + 7.66 + if(best) { 7.67 + mode_info = vbe_get_mode_info(best); 7.68 + } else { 7.69 + fprintf(stderr, "Requested video mode (%dx%d %dbpp) is unavailable\n", xsz, ysz, bpp); 7.70 + return 0; 7.71 + } 7.72 + 7.73 + if(vbe_set_mode(best | VBE_MODE_LFB) == -1) { 7.74 + fprintf(stderr, "Failed to set video mode %dx%d %dbpp\n", mode_info->xres, mode_info->yres, mode_info->bpp); 7.75 + return 0; 7.76 + } 7.77 + 7.78 + /* attempt to set 8 bits of color per component in palettized modes */ 7.79 + if(bpp <= 8) { 7.80 + pal_bits = vbe_set_palette_bits(8); 7.81 + printf("palette bits per color primary: %d\n", pal_bits); 7.82 + } 7.83 + 7.84 + fbsize = xsz * ysz * mode_info->num_img_pages * (bpp / CHAR_BIT); 7.85 + return (void*)dpmi_mmap(mode_info->fb_addr, fbsize); 7.86 +} 7.87 + 7.88 +int set_text_mode(void) 7.89 +{ 7.90 + vbe_set_mode(0x3); 7.91 + return 0; 7.92 +} 7.93 + 7.94 +int get_color_depth(void) 7.95 +{ 7.96 + if(!mode_info) { 7.97 + return -1; 7.98 + } 7.99 + return mode_info->bpp; 7.100 +} 7.101 + 7.102 +int get_color_bits(int *rbits, int *gbits, int *bbits) 7.103 +{ 7.104 + if(!mode_info) { 7.105 + return -1; 7.106 + } 7.107 + *rbits = mode_info->rmask_size; 7.108 + *gbits = mode_info->gmask_size; 7.109 + *bbits = mode_info->bmask_size; 7.110 + return 0; 7.111 +} 7.112 + 7.113 +int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask) 7.114 +{ 7.115 + if(!mode_info) { 7.116 + return -1; 7.117 + } 7.118 + *rmask = make_mask(mode_info->rmask_size, mode_info->rpos); 7.119 + *gmask = make_mask(mode_info->gmask_size, mode_info->gpos); 7.120 + *bmask = make_mask(mode_info->bmask_size, mode_info->bpos); 7.121 + return 0; 7.122 +} 7.123 + 7.124 +int get_color_shift(int *rshift, int *gshift, int *bshift) 7.125 +{ 7.126 + if(!mode_info) { 7.127 + return -1; 7.128 + } 7.129 + *rshift = mode_info->rpos; 7.130 + *gshift = mode_info->gpos; 7.131 + *bshift = mode_info->bpos; 7.132 + return 0; 7.133 +} 7.134 + 7.135 +void set_palette(int idx, int r, int g, int b) 7.136 +{ 7.137 + int col[3]; 7.138 + col[0] = r; 7.139 + col[1] = g; 7.140 + col[2] = b; 7.141 + vbe_set_palette(idx, col, 1, pal_bits); 7.142 +} 7.143 + 7.144 +static unsigned int make_mask(int sz, int pos) 7.145 +{ 7.146 + unsigned int i, mask = 0; 7.147 + 7.148 + for(i=0; i<sz; i++) { 7.149 + mask |= 1 << i; 7.150 + } 7.151 + return mask << pos; 7.152 +} 7.153 + 7.154 + 7.155 +#endif /* GFX_H_ */
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/gfx.h Sat Apr 05 08:46:27 2014 +0300 8.3 @@ -0,0 +1,22 @@ 8.4 +#ifndef GFX_H_ 8.5 +#define GFX_H_ 8.6 + 8.7 +#ifdef __cplusplus 8.8 +extern "C" { 8.9 +#endif 8.10 + 8.11 +void *set_video_mode(int xsz, int ysz, int bpp); 8.12 +int set_text_mode(void); 8.13 + 8.14 +int get_color_depth(void); 8.15 +int get_color_bits(int *rbits, int *gbits, int *bbits); 8.16 +int get_color_shift(int *rshift, int *gshift, int *bshift); 8.17 +int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask); 8.18 + 8.19 +void set_palette(int idx, int r, int g, int b); 8.20 + 8.21 +#ifdef __cplusplus 8.22 +} 8.23 +#endif 8.24 + 8.25 +#endif /* GFX_H_ */
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/inttypes.h Sat Apr 05 08:46:27 2014 +0300 9.3 @@ -0,0 +1,16 @@ 9.4 +#ifndef INT_TYPES_H_ 9.5 +#define INT_TYPES_H_ 9.6 + 9.7 +#if defined(__DOS__) || defined(WIN32) 9.8 +typedef char int8_t; 9.9 +typedef short int16_t; 9.10 +typedef long int32_t; 9.11 + 9.12 +typedef unsigned char uint8_t; 9.13 +typedef unsigned short uint16_t; 9.14 +typedef unsigned long uint32_t; 9.15 +#else 9.16 +#include <stdint.h> 9.17 +#endif 9.18 + 9.19 +#endif /* INT_TYPES_H_ */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/keyb.c Sat Apr 05 08:46:27 2014 +0300 10.3 @@ -0,0 +1,194 @@ 10.4 +/* 10.5 +DOS interrupt-based keyboard driver. 10.6 +Copyright (C) 2013 John Tsiombikas <nuclear@member.fsf.org> 10.7 + 10.8 +This program is free software: you can redistribute it and/or modify 10.9 +it under the terms of the GNU General Public License as published by 10.10 +the Free Software Foundation, either version 3 of the License, or 10.11 +(at your option) any later version. 10.12 + 10.13 +This program is distributed in the hope that it will be useful, 10.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 10.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10.16 +GNU General Public License for more details. 10.17 + 10.18 +You should have received a copy of the GNU General Public License 10.19 +along with the program. If not, see <http://www.gnu.org/licenses/> 10.20 +*/ 10.21 +#define KEYB_C_ 10.22 + 10.23 +#include <stdio.h> 10.24 +#include <stdlib.h> 10.25 +#include <string.h> 10.26 +#include <conio.h> 10.27 +#include <dos.h> 10.28 +#include <i86.h> 10.29 +#include "keyb.h" 10.30 +#include "scancode.h" 10.31 + 10.32 +#define KB_INTR 0x9 10.33 +#define KB_PORT 0x60 10.34 + 10.35 +#define PIC1_CMD_PORT 0x20 10.36 +#define OCW2_EOI (1 << 5) 10.37 + 10.38 +#define DONE_INIT (prev_handler) 10.39 + 10.40 +static void __interrupt __far kbintr(); 10.41 + 10.42 +static void (__interrupt __far *prev_handler)(); 10.43 + 10.44 +static int *buffer; 10.45 +static int buffer_size, buf_ridx, buf_widx; 10.46 +static int last_key; 10.47 + 10.48 +static unsigned int num_pressed; 10.49 +static unsigned char keystate[256]; 10.50 + 10.51 +#define ADVANCE(x) ((x) = ((x) + 1) % buffer_size) 10.52 + 10.53 +int kb_init(int bufsz) 10.54 +{ 10.55 + if(DONE_INIT) { 10.56 + fprintf(stderr, "keyboard driver already initialized!\n"); 10.57 + return 0; 10.58 + } 10.59 + 10.60 + buffer_size = bufsz; 10.61 + if(buffer_size && !(buffer = malloc(buffer_size * sizeof *buffer))) { 10.62 + fprintf(stderr, "failed to allocate input buffer, continuing without\n"); 10.63 + buffer_size = 0; 10.64 + } 10.65 + buf_ridx = buf_widx = 0; 10.66 + last_key = -1; 10.67 + 10.68 + memset(keystate, 0, sizeof keystate); 10.69 + num_pressed = 0; 10.70 + 10.71 + /* set our interrupt handler */ 10.72 + _disable(); 10.73 + prev_handler = _dos_getvect(KB_INTR); 10.74 + _dos_setvect(KB_INTR, kbintr); 10.75 + _enable(); 10.76 + 10.77 + return 0; 10.78 +} 10.79 + 10.80 +void kb_shutdown(void) 10.81 +{ 10.82 + if(!DONE_INIT) { 10.83 + return; 10.84 + } 10.85 + 10.86 + /* restore the original interrupt handler */ 10.87 + _disable(); 10.88 + _dos_setvect(KB_INTR, prev_handler); 10.89 + _enable(); 10.90 + 10.91 + free(buffer); 10.92 +} 10.93 + 10.94 +int kb_isdown(int key) 10.95 +{ 10.96 + if(key == KB_ANY) { 10.97 + return num_pressed; 10.98 + } 10.99 + return (int)keystate[key]; 10.100 +} 10.101 + 10.102 +void kb_wait(void) 10.103 +{ 10.104 + int key; 10.105 + while((key = kb_getkey()) == -1) { 10.106 + /* put the processor to sleep while waiting for keypresses, but first 10.107 + * make sure interrupts are enabled, or we'll sleep forever 10.108 + */ 10.109 + __asm { 10.110 + sti 10.111 + hlt 10.112 + } 10.113 + } 10.114 + kb_putback(key); 10.115 +} 10.116 + 10.117 +int kb_getkey(void) 10.118 +{ 10.119 + int res; 10.120 + 10.121 + if(buffer) { 10.122 + if(buf_ridx == buf_widx) { 10.123 + return -1; 10.124 + } 10.125 + res = buffer[buf_ridx]; 10.126 + ADVANCE(buf_ridx); 10.127 + } else { 10.128 + res = last_key; 10.129 + last_key = -1; 10.130 + } 10.131 + return res; 10.132 +} 10.133 + 10.134 +void kb_putback(int key) 10.135 +{ 10.136 + if(buffer) { 10.137 + /* go back a place */ 10.138 + if(--buf_ridx < 0) { 10.139 + buf_ridx += buffer_size; 10.140 + } 10.141 + 10.142 + /* if the write end hasn't caught up with us, go back one place 10.143 + * and put it there, otherwise just overwrite the oldest key which 10.144 + * is right where we were. 10.145 + */ 10.146 + if(buf_ridx == buf_widx) { 10.147 + ADVANCE(buf_ridx); 10.148 + } 10.149 + 10.150 + buffer[buf_ridx] = key; 10.151 + } else { 10.152 + last_key = key; 10.153 + } 10.154 +} 10.155 + 10.156 +static void __interrupt __far kbintr() 10.157 +{ 10.158 + unsigned char code; 10.159 + int key, press; 10.160 + 10.161 + code = inp(KB_PORT); 10.162 + 10.163 + if(code >= 128) { 10.164 + press = 0; 10.165 + code -= 128; 10.166 + 10.167 + if(num_pressed > 0) { 10.168 + num_pressed--; 10.169 + } 10.170 + } else { 10.171 + press = 1; 10.172 + 10.173 + num_pressed++; 10.174 + } 10.175 + 10.176 + key = scantbl[code]; 10.177 + 10.178 + if(press) { 10.179 + /* append to buffer */ 10.180 + last_key = key; 10.181 + if(buffer_size > 0) { 10.182 + buffer[buf_widx] = key; 10.183 + ADVANCE(buf_widx); 10.184 + /* if the write end overtook the read end, advance the read end 10.185 + * too, to discard the oldest keypress from the buffer 10.186 + */ 10.187 + if(buf_widx == buf_ridx) { 10.188 + ADVANCE(buf_ridx); 10.189 + } 10.190 + } 10.191 + } 10.192 + 10.193 + /* and update keystate table */ 10.194 + keystate[key] = press; 10.195 + 10.196 + outp(PIC1_CMD_PORT, OCW2_EOI); /* send end-of-interrupt */ 10.197 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/keyb.h Sat Apr 05 08:46:27 2014 +0300 11.3 @@ -0,0 +1,48 @@ 11.4 +/* 11.5 +DOS interrupt-based keyboard driver. 11.6 +Copyright (C) 2013 John Tsiombikas <nuclear@member.fsf.org> 11.7 + 11.8 +This program is free software: you can redistribute it and/or modify 11.9 +it under the terms of the GNU General Public License as published by 11.10 +the Free Software Foundation, either version 3 of the License, or 11.11 +(at your option) any later version. 11.12 + 11.13 +This program is distributed in the hope that it will be useful, 11.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 11.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11.16 +GNU General Public License for more details. 11.17 + 11.18 +You should have received a copy of the GNU General Public License 11.19 +along with the program. If not, see <http://www.gnu.org/licenses/> 11.20 +*/ 11.21 +#ifndef KEYB_H_ 11.22 +#define KEYB_H_ 11.23 + 11.24 +#define KB_ANY (-1) 11.25 + 11.26 +#ifdef __cplusplus 11.27 +extern "C" { 11.28 +#endif 11.29 + 11.30 +int kb_init(int bufsz); /* bufsz can be 0 for no buffered keys */ 11.31 +void kb_shutdown(void); /* don't forget to call this at the end! */ 11.32 + 11.33 +/* Boolean predicate for testing the current state of a particular key. 11.34 + * You may also pass KB_ANY to test if any key is held down. 11.35 + */ 11.36 +int kb_isdown(int key); 11.37 + 11.38 +/* waits for any keypress */ 11.39 +void kb_wait(void); 11.40 + 11.41 +/* removes and returns a single key from the input buffer. 11.42 + * If buffering is disabled (initialized with kb_init(0)), then it always 11.43 + * returns the last key pressed. 11.44 + */ 11.45 +int kb_getkey(void); 11.46 + 11.47 +#ifdef __cplusplus 11.48 +} 11.49 +#endif 11.50 + 11.51 +#endif /* KEYB_H_ */
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/src/light.cc Sat Apr 05 08:46:27 2014 +0300 12.3 @@ -0,0 +1,41 @@ 12.4 +#include "light.h" 12.5 + 12.6 +Light::Light() 12.7 +{ 12.8 + color.x = color.y = color.z = 1.0; 12.9 + atten.x = 1.0; 12.10 + atten.y = 0.0; 12.11 + atten.z = 0.0; 12.12 +} 12.13 + 12.14 +void Light::set_position(const Vector3 &pos) 12.15 +{ 12.16 + this->pos = pos; 12.17 +} 12.18 + 12.19 +const Vector3 &Light::get_position() const 12.20 +{ 12.21 + return pos; 12.22 +} 12.23 + 12.24 + 12.25 +void Light::set_color(const Vector3 &color) 12.26 +{ 12.27 + this->color = color; 12.28 +} 12.29 + 12.30 +const Vector3 &Light::get_color() const 12.31 +{ 12.32 + return color; 12.33 +} 12.34 + 12.35 + 12.36 +void Light::set_attenuation(const Vector3 &atten) 12.37 +{ 12.38 + this->atten = atten; 12.39 +} 12.40 + 12.41 +const Vector3 &Light::get_attenuation() const 12.42 +{ 12.43 + return atten; 12.44 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/src/light.h Sat Apr 05 08:46:27 2014 +0300 13.3 @@ -0,0 +1,25 @@ 13.4 +#ifndef LIGHT_H_ 13.5 +#define LIGHT_H_ 13.6 + 13.7 +#include "vmath.h" 13.8 + 13.9 +class Light { 13.10 +private: 13.11 + Vector3 pos; 13.12 + Vector3 color; 13.13 + Vector3 atten; 13.14 + 13.15 +public: 13.16 + Light(); 13.17 + 13.18 + void set_position(const Vector3 &pos); 13.19 + const Vector3 &get_position() const; 13.20 + 13.21 + void set_color(const Vector3 &color); 13.22 + const Vector3 &get_color() const; 13.23 + 13.24 + void set_attenuation(const Vector3 &atten); 13.25 + const Vector3 &get_attenuation() const; 13.26 +}; 13.27 + 13.28 +#endif // LIGHT_H_
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/src/logger.c Sat Apr 05 08:46:27 2014 +0300 14.3 @@ -0,0 +1,23 @@ 14.4 +#include <stdio.h> 14.5 +#include <stdarg.h> 14.6 +#include "logger.h" 14.7 + 14.8 +#define LOGFNAME "rayzor.log" 14.9 + 14.10 +static FILE *logfile; 14.11 + 14.12 +void printlog(const char *fmt, ...) 14.13 +{ 14.14 + va_list ap; 14.15 + 14.16 + if(!logfile) { 14.17 + if(!(logfile = fopen(LOGFNAME, "w"))) { 14.18 + return; 14.19 + } 14.20 + setvbuf(logfile, 0, _IOLBF, 0); 14.21 + } 14.22 + 14.23 + va_start(ap, fmt); 14.24 + vfprintf(logfile, fmt, ap); 14.25 + va_end(ap); 14.26 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/src/logger.h Sat Apr 05 08:46:27 2014 +0300 15.3 @@ -0,0 +1,14 @@ 15.4 +#ifndef LOGGER_H_ 15.5 +#define LOGGER_H_ 15.6 + 15.7 +#ifdef __cplusplus 15.8 +extern "C" { 15.9 +#endif 15.10 + 15.11 +void printlog(const char *fmt, ...); 15.12 + 15.13 +#ifdef __cplusplus 15.14 +} 15.15 +#endif 15.16 + 15.17 +#endif /* LOGGER_H_ */
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/src/m3dimpl.h Sat Apr 05 08:46:27 2014 +0300 16.3 @@ -0,0 +1,23 @@ 16.4 +#ifndef M3DIMPL_H_ 16.5 +#define M3DIMPL_H_ 16.6 + 16.7 +#include "min3d.h" 16.8 + 16.9 +#define MSTACK_SIZE 16 16.10 + 16.11 +struct min3d_mstack { 16.12 + float m[MSTACK_SIZE][16]; 16.13 + int top; 16.14 +}; 16.15 + 16.16 +struct min3d_context { 16.17 + struct m3d_image *cbuf; 16.18 + uint16_t *zbuf; 16.19 + 16.20 + unsigned long state; 16.21 + 16.22 + int mmode; /* matrix mode */ 16.23 + struct min3d_mstack mstack[2]; 16.24 +} *m3dctx; 16.25 + 16.26 +#endif /* M3DIMPL_H_ */
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/src/main.cc Sat Apr 05 08:46:27 2014 +0300 17.3 @@ -0,0 +1,212 @@ 17.4 +#include <stdio.h> 17.5 +#include <stdlib.h> 17.6 +#include <string.h> 17.7 +#include <math.h> 17.8 +#include "inttypes.h" 17.9 +#include "gfx.h" 17.10 +#include "keyb.h" 17.11 +#include "mouse.h" 17.12 +#include "logger.h" 17.13 + 17.14 +static void display(); 17.15 +static void swap_buffers(); 17.16 +static void handle_keyboard(); 17.17 +static void handle_mouse(); 17.18 +static bool parse_args(int argc, char **argv); 17.19 + 17.20 +static int xsz = 800; 17.21 +static int ysz = 600; 17.22 +static int bpp = 16; 17.23 +static int bytespp; 17.24 +static unsigned char *fb; 17.25 +static unsigned char *backbuf; 17.26 +static int rbits, gbits, bbits; 17.27 +static int rshift, gshift, bshift; 17.28 +static unsigned int rmask, gmask, bmask; 17.29 + 17.30 +static bool quit; 17.31 + 17.32 +int main(int argc, char **argv) 17.33 +{ 17.34 + if(!parse_args(argc, argv)) { 17.35 + return 1; 17.36 + } 17.37 + if(kb_init(32) == -1) { 17.38 + fprintf(stderr, "failed to initialize keyboard driver\n"); 17.39 + return 1; 17.40 + } 17.41 + if(!(fb = (unsigned char*)set_video_mode(xsz, ysz, bpp))) { 17.42 + set_text_mode(); 17.43 + fprintf(stderr, "failed to set video mode: %dx%d %dbpp\n", xsz, ysz, bpp); 17.44 + return 1; 17.45 + } 17.46 + bpp = get_color_depth(); 17.47 + get_color_bits(&rbits, &gbits, &bbits); 17.48 + get_color_shift(&rshift, &gshift, &bshift); 17.49 + get_color_mask(&rmask, &gmask, &bmask); 17.50 + bytespp = (int)ceil(bpp / 8.0); 17.51 + 17.52 + printlog("bpp: %d (%d %d %d)\n", bpp, rbits, gbits, bbits); 17.53 + printlog("shift: %d %d %d\n", rshift, gshift, bshift); 17.54 + printlog("mask: %x %x %x\n", rmask, gmask, bmask); 17.55 + 17.56 + backbuf = new unsigned char[xsz * ysz * 3]; 17.57 + 17.58 + // main loop 17.59 + for(;;) { 17.60 + handle_keyboard(); 17.61 + handle_mouse(); 17.62 + if(quit) break; 17.63 + 17.64 + display(); 17.65 + } 17.66 + 17.67 + delete [] backbuf; 17.68 + 17.69 + set_text_mode(); 17.70 + kb_shutdown(); 17.71 + 17.72 + printf("Thank you for using Rayzor!\n"); 17.73 + return 0; 17.74 +} 17.75 + 17.76 +static void display() 17.77 +{ 17.78 + unsigned char *fbptr = backbuf; 17.79 + 17.80 + for(int i=0; i<ysz; i++) { 17.81 + for(int j=0; j<xsz; j++) { 17.82 + bool chess = ((i / 16) & 1) == ((j / 16) & 1); 17.83 + fbptr[chess ? 0 : 2] = 255; 17.84 + fbptr[1] = 128; 17.85 + fbptr[chess ? 2 : 0] = 32; 17.86 + fbptr += 3; 17.87 + } 17.88 + } 17.89 + 17.90 + swap_buffers(); 17.91 +} 17.92 + 17.93 +#define PACK_RGB(r, g, b) \ 17.94 + ((((r) << rshift) & rmask) | \ 17.95 + (((g) << gshift) & gmask) | \ 17.96 + (((b) << bshift) & bmask)) 17.97 + 17.98 +static void swap_buffers() 17.99 +{ 17.100 + unsigned char *src = backbuf; 17.101 + int num_pixels = xsz * ysz; 17.102 + 17.103 + switch(bpp) { 17.104 + case 32: 17.105 + { 17.106 + uint32_t *dest = (uint32_t*)fb; 17.107 + for(int i=0; i<num_pixels; i++) { 17.108 + *dest++ = PACK_RGB(src[0], src[1], src[2]); 17.109 + src += 3; 17.110 + } 17.111 + } 17.112 + break; 17.113 + 17.114 + case 24: 17.115 + memcpy(fb, backbuf, num_pixels * 3); 17.116 + break; 17.117 + 17.118 + case 16: 17.119 + case 15: 17.120 + { 17.121 + int srs = 8 - rbits; 17.122 + int sgs = 8 - gbits; 17.123 + int sbs = 8 - bbits; 17.124 + uint16_t *dest = (uint16_t*)fb; 17.125 + for(int i=0; i<num_pixels; i++) { 17.126 + *dest++ = PACK_RGB(src[0] >> srs, src[1] >> sgs, src[2] >> sbs); 17.127 + src += 3; 17.128 + } 17.129 + } 17.130 + break; 17.131 + 17.132 + default: 17.133 + break; 17.134 + } 17.135 +} 17.136 + 17.137 +static void handle_keyboard() 17.138 +{ 17.139 + if(!kb_isdown(KB_ANY)) 17.140 + return; 17.141 + 17.142 + int c = kb_getkey(); 17.143 + switch(c) { 17.144 + case 27: 17.145 + quit = true; 17.146 + return; 17.147 + } 17.148 +} 17.149 + 17.150 +static void handle_mouse() 17.151 +{ 17.152 +} 17.153 + 17.154 +static struct { 17.155 + int opt; 17.156 + const char *lopt; 17.157 + const char *desc; 17.158 +} options[] = { 17.159 + {'s', "size", "resolution <xres>x<yres>[:bpp]"}, 17.160 + {'h', "help", "print usage information and exit"}, 17.161 + {-1, 0, 0} 17.162 +}; 17.163 + 17.164 +static void print_usage(const char *argv0) 17.165 +{ 17.166 + printf("%s usage\n", argv0); 17.167 + for(int i=0; options[i].opt != -1; i++) { 17.168 + printf(" -%c, -%s: %s\n", options[i].opt, options[i].lopt, options[i].desc); 17.169 + } 17.170 + exit(0); 17.171 +} 17.172 + 17.173 +static bool parse_args(int argc, char **argv) 17.174 +{ 17.175 + for(int i=1; i<argc; i++) { 17.176 + if(argv[i][0] == '-') { 17.177 + int opt = -1; 17.178 + 17.179 + for(int j=0; options[j].opt != -1; j++) { 17.180 + if(argv[i][2] == 0) { 17.181 + if(argv[i][1] == options[j].opt) { 17.182 + opt = options[j].opt; 17.183 + break; 17.184 + } 17.185 + } else { 17.186 + if(strcmp(argv[i] + 1, options[j].lopt) == 0) { 17.187 + opt = options[j].opt; 17.188 + break; 17.189 + } 17.190 + } 17.191 + } 17.192 + 17.193 + switch(opt) { 17.194 + case 's': 17.195 + if(sscanf(argv[++i], "%dx%d:%d", &xsz, &ysz, &bpp) < 2) { 17.196 + fprintf(stderr, "%s must be followed by a resolution: WxH\n", argv[i - 1]); 17.197 + return false; 17.198 + } 17.199 + break; 17.200 + 17.201 + case 'h': 17.202 + print_usage(argv[0]); // doesn't return 17.203 + break; 17.204 + 17.205 + default: 17.206 + fprintf(stderr, "unknown option: %s\n", argv[i]); 17.207 + return false; 17.208 + } 17.209 + } else { 17.210 + fprintf(stderr, "unexpected argument: %s\n", argv[i]); 17.211 + return false; 17.212 + } 17.213 + } 17.214 + return true; 17.215 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/src/min3d.c Sat Apr 05 08:46:27 2014 +0300 18.3 @@ -0,0 +1,178 @@ 18.4 +#include <stdlib.h> 18.5 +#include "min3d.h" 18.6 +#include "m3dimpl.h" 18.7 + 18.8 +#ifndef M_PI 18.9 +#define M_PI 3.141592653 18.10 +#endif 18.11 + 18.12 +int m3d_init(void) 18.13 +{ 18.14 + if(!(m3dctx = malloc(sizeof *m3dctx))) { 18.15 + return -1; 18.16 + } 18.17 + memset(m3dctx, 0, sizeof *m3dctx); 18.18 + 18.19 + m3d_matrix_mode(M3D_PROJECTION); 18.20 + m3d_load_identity(); 18.21 + m3d_matrix_mode(M3D_MODELVIEW); 18.22 + m3d_load_identity(); 18.23 + return 0; 18.24 +} 18.25 + 18.26 +void m3d_shutdown(void) 18.27 +{ 18.28 + free(m3dctx); 18.29 +} 18.30 + 18.31 +void m3d_set_buffers(struct m3d_image *cbuf, uint16_t *zbuf) 18.32 +{ 18.33 + m3dctx->cbuf = cbuf; 18.34 + m3dctx->zbuf = zbuf; 18.35 +} 18.36 + 18.37 +void m3d_clear(unsigned int bmask) 18.38 +{ 18.39 + int num_pixels = m3dctx->cbuf->xsz * m3dctx->cbuf->ysz; 18.40 + if(bmask & M3D_COLOR_BUFFER_BIT) { 18.41 + memset(m3dctx->cbuf->pixels, 0, num_pixels * 3); 18.42 + } 18.43 + if(bmask & M3D_DEPTH_BUFFER_BIT) { 18.44 + memset(m3dctx->zbuf, 0xff, num_pixels * sizeof *m3dctx->zbuf); 18.45 + } 18.46 +} 18.47 + 18.48 + 18.49 +void m3d_enable(int bit) 18.50 +{ 18.51 + m3dctx->state |= (1 << bit); 18.52 +} 18.53 + 18.54 +void m3d_disable(int bit) 18.55 +{ 18.56 + m3dctx->state &= ~(1 << bit); 18.57 +} 18.58 + 18.59 + 18.60 +/* matrix stack */ 18.61 +void m3d_matrix_mode(int mode) 18.62 +{ 18.63 + m3dctx->mmode = mode; 18.64 +} 18.65 + 18.66 +void m3d_load_identity(void) 18.67 +{ 18.68 + static const float mid[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 18.69 + m3d_load_matrix(mid); 18.70 +} 18.71 + 18.72 +void m3d_load_matrix(const float *m) 18.73 +{ 18.74 + int top = m3dctx->mstack[m3dctx->mmode].top; 18.75 + memcpy(m3dctx->mstack[m3dctx->mmode].m[top], m, 16 * sizeof *m); 18.76 +} 18.77 + 18.78 +#define M(i,j) (((i) << 2) + (j)) 18.79 +void m3d_mult_matrix(const float *m2) 18.80 +{ 18.81 + int i, j, top = m3dctx->mstack[m3dctx->mmode].top; 18.82 + float m1[16]; 18.83 + float *dest = m3dctx->mstack[m3dctx->mmode].m[top]; 18.84 + 18.85 + memcpy(m1, dest, sizeof m1); 18.86 + 18.87 + for(i=0; i<4; i++) { 18.88 + for(j=0; j<4; j++) { 18.89 + dest[M(i,j)] = m1[M(0,j)] * m2[M(i,0)] + 18.90 + m1[M(1,j)] * m2[M(i,1)] + 18.91 + m1[M(2,j)] * m2[M(i,2)] + 18.92 + m1[M(3,j)] * m2[M(i,3)]; 18.93 + } 18.94 + } 18.95 +} 18.96 + 18.97 +void m3d_translate(float x, float y, float z) 18.98 +{ 18.99 + float m[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 18.100 + m[12] = x; 18.101 + m[13] = y; 18.102 + m[14] = z; 18.103 + m3d_mult_matrix(m); 18.104 +} 18.105 + 18.106 +void m3d_rotate(float deg, float x, float y, float z) 18.107 +{ 18.108 + float xform[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 18.109 + 18.110 + float angle = M_PI * deg / 180.0f; 18.111 + float sina = sin(angle); 18.112 + float cosa = cos(angle); 18.113 + float one_minus_cosa = 1.0f - cosa; 18.114 + float nxsq = x * x; 18.115 + float nysq = y * y; 18.116 + float nzsq = z * z; 18.117 + 18.118 + xform[0] = nxsq + (1.0f - nxsq) * cosa; 18.119 + xform[4] = x * y * one_minus_cosa - z * sina; 18.120 + xform[8] = x * z * one_minus_cosa + y * sina; 18.121 + xform[1] = x * y * one_minus_cosa + z * sina; 18.122 + xform[5] = nysq + (1.0 - nysq) * cosa; 18.123 + xform[9] = y * z * one_minus_cosa - x * sina; 18.124 + xform[2] = x * z * one_minus_cosa - y * sina; 18.125 + xform[6] = y * z * one_minus_cosa + x * sina; 18.126 + xform[10] = nzsq + (1.0 - nzsq) * cosa; 18.127 + 18.128 + m3d_mult_matrix(xform); 18.129 +} 18.130 + 18.131 +void m3d_scale(float x, float y, float z) 18.132 +{ 18.133 + static float m[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 18.134 + m[0] = x; 18.135 + m[5] = y; 18.136 + m[10] = z; 18.137 + m3d_mult_matrix(m); 18.138 +} 18.139 + 18.140 +void m3d_frustum(float left, float right, float bottom, float top, float nr, float fr) 18.141 +{ 18.142 + float xform[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 18.143 + 18.144 + float dx = right - left; 18.145 + float dy = top - bottom; 18.146 + float dz = fr - nr; 18.147 + 18.148 + float a = (right + left) / dx; 18.149 + float b = (top + bottom) / dy; 18.150 + float c = -(fr + nr) / dz; 18.151 + float d = -2.0 * fr * nr / dz; 18.152 + 18.153 + xform[0] = 2.0 * nr / dx; 18.154 + xform[5] = 2.0 * nr / dy; 18.155 + xform[8] = a; 18.156 + xform[9] = b; 18.157 + xform[10] = c; 18.158 + xform[11] = -1.0f; 18.159 + xform[14] = d; 18.160 + 18.161 + m3d_mult_matrix(xform); 18.162 +} 18.163 + 18.164 +void m3d_perspective(float vfov, float aspect, float nr, float fr) 18.165 +{ 18.166 + float vfov_rad = M_PI * vfov / 180.0; 18.167 + float x = nr * tan(vfov_rad / 2.0); 18.168 + m3d_frustum(-aspect * x, aspect * x, -x, x, nr, fr); 18.169 +} 18.170 + 18.171 +/* drawing */ 18.172 +void m3d_draw(int prim, const float *varr, int vcount) 18.173 +{ 18.174 + /* TODO */ 18.175 +} 18.176 + 18.177 +void m3d_draw_indexed(int prim, const float *varr, const int *idxarr, int icount) 18.178 +{ 18.179 + /* TODO */ 18.180 +} 18.181 +
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/src/min3d.h Sat Apr 05 08:46:27 2014 +0300 19.3 @@ -0,0 +1,73 @@ 19.4 +#ifndef MIN3D_H_ 19.5 +#define MIN3D_H_ 19.6 + 19.7 +#include "inttypes.h" 19.8 + 19.9 +/* state toggles */ 19.10 +enum { 19.11 + M3D_DEPTH_TEST, 19.12 + M3D_CULL_FACE, 19.13 + M3D_LIGHTING, 19.14 + M3D_LIGHT0, 19.15 + M3D_LIGHT1, 19.16 + M3D_LIGHT2, 19.17 + M3D_LIGHT3 19.18 +}; 19.19 + 19.20 +/* buffer bits */ 19.21 +enum { 19.22 + M3D_COLOR_BUFFER_BIT = 1, 19.23 + M3D_DEPTH_BUFFER_BIT = 2 19.24 +}; 19.25 + 19.26 +/* primitives */ 19.27 +enum { 19.28 + M3D_POINTS = 1, 19.29 + M3D_LINES = 2, 19.30 + M3D_TRIANGLES = 3, 19.31 + M3D_QUADS = 4 19.32 +}; 19.33 + 19.34 +/* matrix mode */ 19.35 +enum { 19.36 + M3D_MODELVIEW, 19.37 + M3D_PROJECTION 19.38 +}; 19.39 + 19.40 +struct m3d_image { 19.41 + int xsz, ysz; 19.42 + unsigned char *pixels; 19.43 +}; 19.44 + 19.45 +#ifdef __cplusplus 19.46 +extern "C" { 19.47 +#endif 19.48 + 19.49 +void m3d_set_buffers(struct m3d_image *cbuf, uint16_t *zbuf); 19.50 +void m3d_clear(unsigned int bmask); 19.51 + 19.52 +void m3d_enable(int bit); 19.53 +void m3d_disable(int bit); 19.54 + 19.55 +/* matrix stack */ 19.56 +void m3d_matrix_mode(int mode); 19.57 +void m3d_load_identity(void); 19.58 +void m3d_load_matrix(const float *m); 19.59 +void m3d_mult_matrix(const float *m); 19.60 +void m3d_translate(float x, float y, float z); 19.61 +void m3d_rotate(float angle, float x, float y, float z); 19.62 +void m3d_scale(float x, float y, float z); 19.63 +void m3d_frustum(float left, float right, float bottom, float top, float nr, float fr); 19.64 +void m3d_perspective(float vfov, float aspect, float znear, float zfar); 19.65 + 19.66 +/* drawing */ 19.67 +void m3d_draw(int prim, const float *varr, int vcount); 19.68 +void m3d_draw_indexed(int prim, const float *varr, const int *idxarr, int icount); 19.69 + 19.70 +/* TODO immediate mode */ 19.71 + 19.72 +#ifdef __cplusplus 19.73 +} 19.74 +#endif 19.75 + 19.76 +#endif /* MIN3D_H_ */
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/src/mouse.c Sat Apr 05 08:46:27 2014 +0300 20.3 @@ -0,0 +1,72 @@ 20.4 +/* TODO: try NOT using the v8086 interrupts to avoid the overhead */ 20.5 +#include "mouse.h" 20.6 +#include "inttypes.h" 20.7 +#include "dpmi.h" 20.8 + 20.9 +#define INTR 0x33 20.10 + 20.11 +#define QUERY 0 20.12 +#define SHOW 1 20.13 +#define HIDE 2 20.14 +#define READ 3 20.15 +#define WRITE 4 20.16 + 20.17 +#define XLIM 7 20.18 +#define YLIM 8 20.19 + 20.20 +int have_mouse(void) 20.21 +{ 20.22 + struct dpmi_real_regs regs; 20.23 + memset(®s, 0, sizeof regs); 20.24 + regs.eax = QUERY; 20.25 + dpmi_real_int(INTR, ®s); 20.26 + return regs.eax & 0xffff; 20.27 +} 20.28 + 20.29 +void show_mouse(int show) 20.30 +{ 20.31 + struct dpmi_real_regs regs; 20.32 + memset(®s, 0, sizeof regs); 20.33 + regs.eax = show ? SHOW : HIDE; 20.34 + dpmi_real_int(INTR, ®s); 20.35 +} 20.36 + 20.37 +int read_mouse(int *xp, int *yp) 20.38 +{ 20.39 + struct dpmi_real_regs regs; 20.40 + memset(®s, 0, sizeof regs); 20.41 + 20.42 + regs.eax = READ; 20.43 + dpmi_real_int(INTR, ®s); 20.44 + 20.45 + if(xp) *xp = regs.ecx & 0xffff; 20.46 + if(yp) *yp = regs.edx & 0xffff; 20.47 + return regs.ebx & 0xffff; 20.48 +} 20.49 + 20.50 +void set_mouse(int x, int y) 20.51 +{ 20.52 + struct dpmi_real_regs regs; 20.53 + memset(®s, 0, sizeof regs); 20.54 + 20.55 + regs.eax = WRITE; 20.56 + regs.ecx = x; 20.57 + regs.edx = y; 20.58 + dpmi_real_int(INTR, ®s); 20.59 +} 20.60 + 20.61 +void set_mouse_limits(int xmin, int ymin, int xmax, int ymax) 20.62 +{ 20.63 + struct dpmi_real_regs regs; 20.64 + memset(®s, 0, sizeof regs); 20.65 + regs.eax = XLIM; 20.66 + regs.ecx = xmin; 20.67 + regs.edx = xmax; 20.68 + dpmi_real_int(INTR, ®s); 20.69 + 20.70 + memset(®s, 0, sizeof regs); 20.71 + regs.eax = YLIM; 20.72 + regs.ecx = ymin; 20.73 + regs.edx = ymax; 20.74 + dpmi_real_int(INTR, ®s); 20.75 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/src/mouse.h Sat Apr 05 08:46:27 2014 +0300 21.3 @@ -0,0 +1,22 @@ 21.4 +#ifndef MOUSE_H_ 21.5 +#define MOUSE_H_ 21.6 + 21.7 +#define MOUSE_LEFT 1 21.8 +#define MOUSE_RIGHT 2 21.9 +#define MOUSE_MIDDLE 4 21.10 + 21.11 +#ifdef __cplusplus 21.12 +extern "C" { 21.13 +#endif 21.14 + 21.15 +int have_mouse(void); 21.16 +void show_mouse(int show); 21.17 +int read_mouse(int *xp, int *yp); 21.18 +void set_mouse(int x, int y); 21.19 +void set_mouse_limits(int xmin, int ymin, int xmax, int ymax); 21.20 + 21.21 +#ifdef __cplusplus 21.22 +} 21.23 +#endif 21.24 + 21.25 +#endif /* MOUSE_H_ */
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/src/object.cc Sat Apr 05 08:46:27 2014 +0300 22.3 @@ -0,0 +1,53 @@ 22.4 +#include "object.h" 22.5 +#include "vmath.h" 22.6 +#include "min3d.h" 22.7 + 22.8 +Object::Object() 22.9 +{ 22.10 +} 22.11 + 22.12 +Object::~Object() 22.13 +{ 22.14 +} 22.15 + 22.16 +// ---- sphere ---- 22.17 +Sphere::Sphere() 22.18 +{ 22.19 +} 22.20 + 22.21 +Sphere::~Sphere() 22.22 +{ 22.23 +} 22.24 + 22.25 +#define USUB 16 22.26 +#define VSUB 8 22.27 + 22.28 +void Sphere::draw() const 22.29 +{ 22.30 + static Vector3 *varr; 22.31 + static int num_verts; 22.32 + if(!varr) { 22.33 + int uverts = USUB; 22.34 + int vverts = VSUB + 1; 22.35 + num_verts = uverts * vverts; 22.36 + varr = new Vector3[num_verts]; 22.37 + 22.38 + Vector3 *vptr = varr; 22.39 + for(int i=0; i<uverts; i++) { 22.40 + float u = (float)i / (float)USUB; 22.41 + float theta = u * M_PI * 2.0; 22.42 + for(int j=0; j<vverts; j++) { 22.43 + float v = (float)j / (float)VSUB; 22.44 + float phi = (v - 0.5) * M_PI; 22.45 + 22.46 + float x = sin(theta) * cos(phi); 22.47 + float y = sin(phi); 22.48 + float z = cos(theta) * cos(phi); 22.49 + 22.50 + *vptr++ = Vector3(x, y, z); 22.51 + } 22.52 + } 22.53 + } 22.54 + 22.55 + m3d_draw(M3D_POINTS, &varr->x, num_verts); 22.56 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/src/object.h Sat Apr 05 08:46:27 2014 +0300 23.3 @@ -0,0 +1,20 @@ 23.4 +#ifndef OBJECT_H_ 23.5 +#define OBJECT_H_ 23.6 + 23.7 +class Object { 23.8 +public: 23.9 + Object(); 23.10 + virtual ~Object(); 23.11 + 23.12 + virtual void draw() const = 0; 23.13 +}; 23.14 + 23.15 +class Sphere { 23.16 +public: 23.17 + Sphere(); 23.18 + ~Sphere(); 23.19 + 23.20 + void draw() const; 23.21 +}; 23.22 + 23.23 +#endif // OBJECT_H_
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/src/pit8254.h Sat Apr 05 08:46:27 2014 +0300 24.3 @@ -0,0 +1,34 @@ 24.4 +#ifndef PIT8254_H_ 24.5 +#define PIT8254_H_ 24.6 + 24.7 +/* frequency of the oscillator driving the 8254 timer */ 24.8 +#define OSC_FREQ_HZ 1193182 24.9 + 24.10 +/* I/O ports connected to the 8254 */ 24.11 +#define PORT_DATA0 0x40 24.12 +#define PORT_DATA1 0x41 24.13 +#define PORT_DATA2 0x42 24.14 +#define PORT_CMD 0x43 24.15 + 24.16 +/* command bits */ 24.17 +#define CMD_CHAN0 0 24.18 +#define CMD_CHAN1 (1 << 6) 24.19 +#define CMD_CHAN2 (2 << 6) 24.20 +#define CMD_RDBACK (3 << 6) 24.21 + 24.22 +#define CMD_LATCH 0 24.23 +#define CMD_ACCESS_LOW (1 << 4) 24.24 +#define CMD_ACCESS_HIGH (2 << 4) 24.25 +#define CMD_ACCESS_BOTH (3 << 4) 24.26 + 24.27 +#define CMD_OP_INT_TERM 0 24.28 +#define CMD_OP_ONESHOT (1 << 1) 24.29 +#define CMD_OP_RATE (2 << 1) 24.30 +#define CMD_OP_SQWAVE (3 << 1) 24.31 +#define CMD_OP_SW_STROBE (4 << 1) 24.32 +#define CMD_OP_HW_STROBE (5 << 1) 24.33 + 24.34 +#define CMD_MODE_BIN 0 24.35 +#define CMD_MODE_BCD 1 24.36 + 24.37 +#endif /* PIT8254_H_ */
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/src/rend.cc Sat Apr 05 08:46:27 2014 +0300 25.3 @@ -0,0 +1,10 @@ 25.4 +#include "rend.h" 25.5 + 25.6 +bool rend_init() 25.7 +{ 25.8 + return false; 25.9 +} 25.10 + 25.11 +void rend_shutdown() 25.12 +{ 25.13 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/src/rend.h Sat Apr 05 08:46:27 2014 +0300 26.3 @@ -0,0 +1,7 @@ 26.4 +#ifndef REND_H_ 26.5 +#define REND_H_ 26.6 + 26.7 +bool rend_init(); 26.8 +void rend_shutdown(); 26.9 + 26.10 +#endif // REND_H_
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/src/scancode.h Sat Apr 05 08:46:27 2014 +0300 27.3 @@ -0,0 +1,31 @@ 27.4 +#ifndef KEYB_C_ 27.5 +#error "do not include scancode.h anywhere..." 27.6 +#endif 27.7 + 27.8 +/* special keys */ 27.9 +enum { 27.10 + LALT, RALT, 27.11 + LCTRL, RCTRL, 27.12 + LSHIFT, RSHIFT, 27.13 + F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, 27.14 + CAPSLK, NUMLK, SCRLK, SYSRQ, 27.15 + ESC = 27, 27.16 + INSERT, DEL, HOME, END, PGUP, PGDN, LEFT, RIGHT, UP, DOWN, 27.17 + NUM_DOT, NUM_ENTER, NUM_PLUS, NUM_MINUS, NUM_MUL, NUM_DIV, 27.18 + NUM_0, NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9, 27.19 + BACKSP = 127 27.20 +}; 27.21 + 27.22 +/* table with rough translations from set 1 scancodes to ASCII-ish */ 27.23 +static int scantbl[] = { 27.24 + 0, ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', /* 0 - e */ 27.25 + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* f - 1c */ 27.26 + LCTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', /* 1d - 29 */ 27.27 + LSHIFT, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', RSHIFT, /* 2a - 36 */ 27.28 + NUM_MUL, LALT, ' ', CAPSLK, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, /* 37 - 44 */ 27.29 + NUMLK, SCRLK, NUM_7, NUM_8, NUM_9, NUM_MINUS, NUM_4, NUM_5, NUM_6, NUM_PLUS, /* 45 - 4e */ 27.30 + NUM_1, NUM_2, NUM_3, NUM_0, NUM_DOT, SYSRQ, 0, 0, F11, F12, /* 4d - 58 */ 27.31 + 0, 0, 0, 0, 0, 0, 0, /* 59 - 5f */ 27.32 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6f */ 27.33 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 70 - 7f */ 27.34 +};
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/src/scene.cc Sat Apr 05 08:46:27 2014 +0300 28.3 @@ -0,0 +1,43 @@ 28.4 +#include "scene.h" 28.5 + 28.6 +Scene::Scene() 28.7 +{ 28.8 + name = 0; 28.9 +} 28.10 + 28.11 +Scene::~Scene() 28.12 +{ 28.13 + clear(); 28.14 +} 28.15 + 28.16 +void Scene::clear() 28.17 +{ 28.18 + delete [] name; 28.19 + 28.20 + size_t i; 28.21 + for(i=0; i<objects.size(); i++) { 28.22 + delete objects[i]; 28.23 + } 28.24 + for(i=0; i<lights.size(); i++) { 28.25 + delete lights[i]; 28.26 + } 28.27 + for(i=0; i<cameras.size(); i++) { 28.28 + delete cameras[i]; 28.29 + } 28.30 +} 28.31 + 28.32 +void Scene::set_name(const char *name) 28.33 +{ 28.34 + delete [] this->name; 28.35 + this->name = new char[strlen(name) + 1]; 28.36 + strcpy(this->name, name); 28.37 +} 28.38 + 28.39 +const char *Scene::get_name() const 28.40 +{ 28.41 + return name ? name : "<unknown>"; 28.42 +} 28.43 + 28.44 +void Scene::draw() const 28.45 +{ 28.46 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/src/scene.h Sat Apr 05 08:46:27 2014 +0300 29.3 @@ -0,0 +1,29 @@ 29.4 +#ifndef SCENE_H_ 29.5 +#define SCENE_H_ 29.6 + 29.7 +#include <string> 29.8 +#include <vector.h> 29.9 +#include "object.h" 29.10 +#include "light.h" 29.11 +#include "camera.h" 29.12 + 29.13 +class Scene { 29.14 +private: 29.15 + char *name; 29.16 + vector<Object*> objects; 29.17 + vector<Light*> lights; 29.18 + vector<Camera*> cameras; 29.19 + 29.20 +public: 29.21 + Scene(); 29.22 + ~Scene(); 29.23 + 29.24 + void clear(); 29.25 + 29.26 + void set_name(const char *name); 29.27 + const char *get_name() const; 29.28 + 29.29 + void draw() const; 29.30 +}; 29.31 + 29.32 +#endif // SCENE_H_
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/src/timer.c Sat Apr 05 08:46:27 2014 +0300 30.3 @@ -0,0 +1,131 @@ 30.4 +/* 30.5 +256-color 3D graphics hack for real-mode DOS. 30.6 +Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org> 30.7 + 30.8 +This program is free software: you can redistribute it and/or modify 30.9 +it under the terms of the GNU General Public License as published by 30.10 +the Free Software Foundation, either version 3 of the License, or 30.11 +(at your option) any later version. 30.12 + 30.13 +This program is distributed in the hope that it will be useful, 30.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 30.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30.16 +GNU General Public License for more details. 30.17 + 30.18 +You should have received a copy of the GNU General Public License 30.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 30.20 +*/ 30.21 +#include <stdio.h> 30.22 +#include <stdlib.h> 30.23 +#include <conio.h> 30.24 +#include <dos.h> 30.25 +#include <i86.h> 30.26 +#include "pit8254.h" 30.27 + 30.28 +#define PIT_TIMER_INTR 8 30.29 +#define DOS_TIMER_INTR 0x1c 30.30 + 30.31 +/* macro to divide and round to the nearest integer */ 30.32 +#define DIV_ROUND(a, b) \ 30.33 + ((a) / (b) + ((a) % (b)) / ((b) / 2)) 30.34 + 30.35 +static void set_timer_reload(int reload_val); 30.36 +static void cleanup(void); 30.37 +static void __interrupt __far timer_irq(); 30.38 +static void __interrupt __far dos_timer_intr(); 30.39 + 30.40 +static void (__interrupt __far *prev_timer_intr)(); 30.41 + 30.42 +static unsigned long ticks; 30.43 +static unsigned long tick_interval, ticks_per_dos_intr; 30.44 +static int inum; 30.45 + 30.46 +void init_timer(int res_hz) 30.47 +{ 30.48 + _disable(); 30.49 + 30.50 + if(res_hz > 0) { 30.51 + int reload_val = DIV_ROUND(OSC_FREQ_HZ, res_hz); 30.52 + set_timer_reload(reload_val); 30.53 + 30.54 + tick_interval = DIV_ROUND(1000, res_hz); 30.55 + ticks_per_dos_intr = DIV_ROUND(65535L, reload_val); 30.56 + 30.57 + inum = PIT_TIMER_INTR; 30.58 + prev_timer_intr = _dos_getvect(inum); 30.59 + _dos_setvect(inum, timer_irq); 30.60 + } else { 30.61 + tick_interval = 55; 30.62 + 30.63 + inum = DOS_TIMER_INTR; 30.64 + prev_timer_intr = _dos_getvect(inum); 30.65 + _dos_setvect(inum, dos_timer_intr); 30.66 + } 30.67 + _enable(); 30.68 + 30.69 + atexit(cleanup); 30.70 +} 30.71 + 30.72 +static void cleanup(void) 30.73 +{ 30.74 + if(!prev_timer_intr) { 30.75 + return; /* init hasn't ran, there's nothing to cleanup */ 30.76 + } 30.77 + 30.78 + _disable(); 30.79 + if(inum == PIT_TIMER_INTR) { 30.80 + /* restore the original timer frequency */ 30.81 + set_timer_reload(65535); 30.82 + } 30.83 + 30.84 + /* restore the original interrupt handler */ 30.85 + _dos_setvect(inum, prev_timer_intr); 30.86 + _enable(); 30.87 +} 30.88 + 30.89 +void reset_timer(void) 30.90 +{ 30.91 + ticks = 0; 30.92 +} 30.93 + 30.94 +unsigned long get_msec(void) 30.95 +{ 30.96 + return ticks * tick_interval; 30.97 +} 30.98 + 30.99 +static void set_timer_reload(int reload_val) 30.100 +{ 30.101 + outp(PORT_CMD, CMD_CHAN0 | CMD_ACCESS_BOTH | CMD_OP_SQWAVE); 30.102 + outp(PORT_DATA0, reload_val & 0xff); 30.103 + outp(PORT_DATA0, (reload_val >> 8) & 0xff); 30.104 +} 30.105 + 30.106 +static void __interrupt __far dos_timer_intr() 30.107 +{ 30.108 + ticks++; 30.109 + _chain_intr(prev_timer_intr); /* DOES NOT RETURN */ 30.110 +} 30.111 + 30.112 +/* first PIC command port */ 30.113 +#define PIC1_CMD 0x20 30.114 +/* end of interrupt control word */ 30.115 +#define OCW2_EOI (1 << 5) 30.116 + 30.117 +static void __interrupt __far timer_irq() 30.118 +{ 30.119 + static unsigned long dos_ticks; 30.120 + 30.121 + ticks++; 30.122 + 30.123 + if(++dos_ticks >= ticks_per_dos_intr) { 30.124 + /* I suppose the dos irq handler does the EOI so I shouldn't 30.125 + * do it if I am to call the previous function 30.126 + */ 30.127 + dos_ticks = 0; 30.128 + _chain_intr(prev_timer_intr); /* XXX DOES NOT RETURN */ 30.129 + return; /* just for clarity */ 30.130 + } 30.131 + 30.132 + /* send EOI to the PIC */ 30.133 + outp(PIC1_CMD, OCW2_EOI); 30.134 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/src/timer.h Sat Apr 05 08:46:27 2014 +0300 31.3 @@ -0,0 +1,29 @@ 31.4 +/* 31.5 +256-color 3D graphics hack for real-mode DOS. 31.6 +Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org> 31.7 + 31.8 +This program is free software: you can redistribute it and/or modify 31.9 +it under the terms of the GNU General Public License as published by 31.10 +the Free Software Foundation, either version 3 of the License, or 31.11 +(at your option) any later version. 31.12 + 31.13 +This program is distributed in the hope that it will be useful, 31.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 31.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31.16 +GNU General Public License for more details. 31.17 + 31.18 +You should have received a copy of the GNU General Public License 31.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 31.20 +*/ 31.21 +#ifndef TIMER_H_ 31.22 +#define TIMER_H_ 31.23 + 31.24 +/* expects the required timer resolution in hertz 31.25 + * if res_hz is 0, the current resolution is retained 31.26 + */ 31.27 +void init_timer(int res_hz); 31.28 + 31.29 +void reset_timer(void); 31.30 +unsigned long get_msec(void); 31.31 + 31.32 +#endif /* TIMER_H_ */
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/src/vbe.c Sat Apr 05 08:46:27 2014 +0300 32.3 @@ -0,0 +1,153 @@ 32.4 +#include <stdio.h> 32.5 +#include <string.h> 32.6 +#include "vbe.h" 32.7 +#include "dpmi.h" 32.8 + 32.9 +/* VGA DAC registers used for palette setting in 8bpp modes */ 32.10 +#define VGA_DAC_STATE 0x3c7 32.11 +#define VGA_DAC_ADDR_RD 0x3c7 32.12 +#define VGA_DAC_ADDR_WR 0x3c8 32.13 +#define VGA_DAC_DATA 0x3c9 32.14 + 32.15 +#define MODE_LFB (1 << 14) 32.16 + 32.17 + 32.18 +struct vbe_info *vbe_get_info(void) 32.19 +{ 32.20 + static unsigned short info_block_seg; 32.21 + static struct vbe_info *info; 32.22 + struct dpmi_real_regs regs; 32.23 + 32.24 + if(!info) { 32.25 + /* allocate 32 paragraphs (512 bytes) */ 32.26 + info_block_seg = dpmi_alloc(32); 32.27 + info = (struct vbe_info*)(info_block_seg << 4); 32.28 + } 32.29 + 32.30 + memcpy(info->sig, "VBE2", 4); 32.31 + 32.32 + memset(®s, 0, sizeof regs); 32.33 + regs.es = info_block_seg; 32.34 + regs.eax = 0x4f00; 32.35 + 32.36 + dpmi_real_int(0x10, ®s); 32.37 + 32.38 + return info; 32.39 +} 32.40 + 32.41 +struct vbe_mode_info *vbe_get_mode_info(int mode) 32.42 +{ 32.43 + static unsigned short mode_info_seg; 32.44 + static struct vbe_mode_info *mi; 32.45 + struct dpmi_real_regs regs; 32.46 + 32.47 + if(!mi) { 32.48 + /* allocate 16 paragraphs (256 bytes) */ 32.49 + mode_info_seg = dpmi_alloc(16); 32.50 + mi = (struct vbe_mode_info*)(mode_info_seg << 4); 32.51 + } 32.52 + 32.53 + memset(®s, 0, sizeof regs); 32.54 + regs.es = mode_info_seg; 32.55 + regs.eax = 0x4f01; 32.56 + regs.ecx = mode; 32.57 + regs.es = mode_info_seg; 32.58 + 32.59 + dpmi_real_int(0x10, ®s); 32.60 + if(regs.eax & 0xff00) { 32.61 + return 0; 32.62 + } 32.63 + 32.64 + return mi; 32.65 +} 32.66 + 32.67 +int vbe_set_mode(int mode) 32.68 +{ 32.69 + struct dpmi_real_regs regs; 32.70 + 32.71 + memset(®s, 0, sizeof regs); 32.72 + regs.eax = 0x4f02; 32.73 + regs.ebx = mode; 32.74 + dpmi_real_int(0x10, ®s); 32.75 + 32.76 + if(regs.eax == 0x100) { 32.77 + return -1; 32.78 + } 32.79 + return 0; 32.80 +} 32.81 + 32.82 +int vbe_set_palette_bits(int bits) 32.83 +{ 32.84 + struct dpmi_real_regs regs; 32.85 + 32.86 + memset(®s, 0, sizeof regs); 32.87 + regs.eax = 0x4f08; 32.88 + regs.ebx = bits << 8; /* bits in bh */ 32.89 + dpmi_real_int(0x10, ®s); 32.90 + 32.91 + if((regs.eax >> 8) & 0xff == 3) { 32.92 + return -1; 32.93 + } 32.94 + return regs.ebx >> 8 & 0xff; /* new color bits in bh */ 32.95 +} 32.96 + 32.97 +/* TODO: implement palette setting through the VBE2 interface for 32.98 + * non-VGA displays (actually don't). 32.99 + */ 32.100 +void vbe_set_palette(int idx, int *col, int count, int bits) 32.101 +{ 32.102 + int i, shift = 8 - bits; 32.103 + 32.104 + __asm { 32.105 + mov dx, VGA_DAC_ADDR_WR 32.106 + mov eax, idx 32.107 + out dx, al 32.108 + } 32.109 + 32.110 + for(i=0; i<count; i++) { 32.111 + unsigned char r = *col++; 32.112 + unsigned char g = *col++; 32.113 + unsigned char b = *col++; 32.114 + 32.115 + if(shift) { 32.116 + r >>= shift; 32.117 + g >>= shift; 32.118 + b >>= shift; 32.119 + } 32.120 + 32.121 + __asm { 32.122 + mov dx, VGA_DAC_DATA 32.123 + mov al, r 32.124 + out dx, al 32.125 + mov al, g 32.126 + out dx, al 32.127 + mov al, b 32.128 + out dx, al 32.129 + } 32.130 + } 32.131 +} 32.132 + 32.133 +static unsigned int get_mask(int sz, int pos) 32.134 +{ 32.135 + unsigned int i, mask = 0; 32.136 + 32.137 + for(i=0; i<sz; i++) { 32.138 + mask |= 1 << i; 32.139 + } 32.140 + return mask << pos; 32.141 +} 32.142 + 32.143 +void print_mode_info(FILE *fp, struct vbe_mode_info *mi) 32.144 +{ 32.145 + fprintf(fp, "resolution: %dx%d\n", mi->xres, mi->yres); 32.146 + fprintf(fp, "color depth: %d\n", mi->bpp); 32.147 + fprintf(fp, "mode attributes: %x\n", mi->mode_attr); 32.148 + fprintf(fp, "bytes per scanline: %d\n", mi->scanline_bytes); 32.149 + fprintf(fp, "number of planes: %d\n", (int)mi->num_planes); 32.150 + fprintf(fp, "number of banks: %d\n", (int)mi->num_banks); 32.151 + fprintf(fp, "mem model: %d\n", (int)mi->mem_model); 32.152 + fprintf(fp, "red bits: %d (mask: %x)\n", (int)mi->rmask_size, get_mask(mi->rmask_size, mi->rpos)); 32.153 + fprintf(fp, "green bits: %d (mask: %x)\n", (int)mi->gmask_size, get_mask(mi->gmask_size, mi->gpos)); 32.154 + fprintf(fp, "blue bits: %d (mask: %x)\n", (int)mi->bmask_size, get_mask(mi->bmask_size, mi->bpos)); 32.155 + fprintf(fp, "framebuffer address: %x\n", mi->fb_addr); 32.156 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/src/vbe.h Sat Apr 05 08:46:27 2014 +0300 33.3 @@ -0,0 +1,70 @@ 33.4 +#ifndef VBE_H_ 33.5 +#define VBE_H_ 33.6 + 33.7 +#include "inttypes.h" 33.8 + 33.9 +#define VBE_ATTR_LFB (1 << 7) 33.10 +#define VBE_MODE_LFB (1 << 14) 33.11 + 33.12 +#pragma pack (push, 0) 33.13 +struct vbe_info { 33.14 + uint8_t sig[4]; 33.15 + uint16_t version; 33.16 + uint32_t oem_str_ptr; 33.17 + uint8_t caps[4]; /* capabilities */ 33.18 + uint32_t vid_mode_ptr; /* vbefarptr to video mode list */ 33.19 + uint16_t total_mem; /* num of 64k mem blocks */ 33.20 + uint16_t oem_sw_rev; /* VBE implementation software revision */ 33.21 + uint32_t oem_vendor_name_ptr; 33.22 + uint32_t oem_product_name_ptr; 33.23 + uint32_t oem_product_rev_ptr; 33.24 + uint8_t reserved[222]; 33.25 + uint8_t oem_data[256]; 33.26 +}; 33.27 + 33.28 +struct vbe_mode_info { 33.29 + uint16_t mode_attr; 33.30 + uint8_t wina_attr, winb_attr; 33.31 + uint16_t win_gran, win_size; 33.32 + uint16_t wina_seg, winb_seg; 33.33 + uint32_t win_func; 33.34 + uint16_t scanline_bytes; 33.35 + 33.36 + /* VBE 1.2 and above */ 33.37 + uint16_t xres, yres; 33.38 + uint8_t xcharsz, ycharsz; 33.39 + uint8_t num_planes; 33.40 + uint8_t bpp; 33.41 + uint8_t num_banks; 33.42 + uint8_t mem_model; 33.43 + uint8_t bank_size; /* bank size in KB */ 33.44 + uint8_t num_img_pages; 33.45 + uint8_t reserved1; 33.46 + 33.47 + /* direct color fields */ 33.48 + uint8_t rmask_size, rpos; 33.49 + uint8_t gmask_size, gpos; 33.50 + uint8_t bmask_size, bpos; 33.51 + uint8_t xmask_size, xpos; 33.52 + uint8_t cmode_info; /* direct color mode attributes */ 33.53 + 33.54 + /* VBE 2.0 and above */ 33.55 + uint32_t fb_addr; /* physical address of the linear framebuffer */ 33.56 + uint32_t reserved2; 33.57 + uint16_t reserved3; 33.58 + 33.59 + uint8_t reserved4[206]; 33.60 +}; 33.61 +#pragma pack (pop) 33.62 + 33.63 +struct vbe_info *vbe_get_info(void); 33.64 +struct vbe_mode_info *vbe_get_mode_info(unsigned int mode); 33.65 + 33.66 +int vbe_set_mode(unsigned int mode); 33.67 + 33.68 +int vbe_set_palette_bits(int bits); 33.69 +void vbe_set_palette(int idx, int *col, int count, int bits); 33.70 + 33.71 +void print_mode_info(FILE *fp, struct vbe_mode_info *modei); 33.72 + 33.73 +#endif /* VBE_H_ */
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/src/vmath.cc Sat Apr 05 08:46:27 2014 +0300 34.3 @@ -0,0 +1,18 @@ 34.4 +#include "vmathmat.h" 34.5 +#include "vmath.h" 34.6 + 34.7 +void Matrix4x4::lookat(const Vector3 &pos, const Vector3 &targ, const Vector3 &up) 34.8 +{ 34.9 + Vector3 vk = normalize(targ - pos); 34.10 + Vector3 vj = normalize(up); 34.11 + Vector3 vi = normalize(cross(vk, vj)); 34.12 + vj = cross(vi, vk); 34.13 + 34.14 + Matrix4x4 m( 34.15 + vi.x, vi.y, vi.z, 0, 34.16 + vj.x, vj.y, vj.z, 0, 34.17 + -vk.x, -vk.y, -vk.z, 0, 34.18 + 0, 0, 0, 1); 34.19 + translate(-pos.x, -pos.y, -pos.z); 34.20 + *this = *this * m; 34.21 +}
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/src/vmath.h Sat Apr 05 08:46:27 2014 +0300 35.3 @@ -0,0 +1,148 @@ 35.4 +#ifndef VMATH_H_ 35.5 +#define VMATH_H_ 35.6 + 35.7 +#include <math.h> 35.8 +#include "vmathmat.h" 35.9 + 35.10 +class Vector3 { 35.11 +public: 35.12 + float x, y, z; 35.13 + 35.14 + Vector3() : x(0), y(0), z(0) {} 35.15 + Vector3(float xx, float yy, float zz) : x(xx), y(yy), z(zz) {} 35.16 + 35.17 + float length_sq() const { return x * x + y * y + z * z; } 35.18 + float length() const { return sqrt(x * x + y * y + z * z); } 35.19 + 35.20 + void normalize() 35.21 + { 35.22 + float len = length(); 35.23 + if(len != 0.0) { 35.24 + x /= len; 35.25 + y /= len; 35.26 + z /= len; 35.27 + } 35.28 + } 35.29 + 35.30 + float &operator [](int idx) { return idx == 2 ? z : (idx == 1 ? y : x); } 35.31 + const float &operator [](int idx) const { return idx == 2 ? z : (idx == 1 ? y : x); } 35.32 +}; 35.33 + 35.34 +inline Vector3 normalize(const Vector3 &v) 35.35 +{ 35.36 + float len = v.length(); 35.37 + if(len != 0.0) { 35.38 + return Vector3(v.x / len, v.y / len, v.z / len); 35.39 + } 35.40 + return v; 35.41 +} 35.42 + 35.43 +inline Vector3 operator +(const Vector3 &a, const Vector3 &b) 35.44 +{ 35.45 + return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); 35.46 +} 35.47 + 35.48 +inline Vector3 operator -(const Vector3 &a, const Vector3 &b) 35.49 +{ 35.50 + return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); 35.51 +} 35.52 + 35.53 +inline Vector3 operator *(const Vector3 &v, float s) 35.54 +{ 35.55 + return Vector3(v.x * s, v.y * s, v.z * s); 35.56 +} 35.57 + 35.58 +inline Vector3 operator /(const Vector3 &v, float s) 35.59 +{ 35.60 + return Vector3(v.x / s, v.y / s, v.z / s); 35.61 +} 35.62 + 35.63 +inline float dot(const Vector3 &a, const Vector3 &b) 35.64 +{ 35.65 + return a.x * b.x + a.y * b.y + a.z * b.z; 35.66 +} 35.67 + 35.68 +inline Vector3 cross(const Vector3 &a, const Vector3 &b) 35.69 +{ 35.70 + return Vector3(a.y * b.z - a.z * b.y, 35.71 + a.z * b.z - a.x * b.z, 35.72 + a.x * b.y - a.y * b.x); 35.73 +} 35.74 + 35.75 +inline Vector3 transform(const Matrix4x4 &m, const Vector3 &v) 35.76 +{ 35.77 + float x = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3]; 35.78 + float y = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3]; 35.79 + float z = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3]; 35.80 + return Vector3(x, y, z); 35.81 +} 35.82 + 35.83 +// ---- Vector4 ---- 35.84 + 35.85 +class Vector4 { 35.86 +public: 35.87 + float x, y, z, w; 35.88 + 35.89 + Vector4() : x(0), y(0), z(0), w(1.0) {} 35.90 + Vector4(const Vector3 &v) : x(v.x), y(v.y), z(v.z), w(1.0) {} 35.91 + Vector4(float xx, float yy, float zz, float ww) : x(xx), y(yy), z(zz), w(ww) {} 35.92 + 35.93 + float length_sq() const { return x * x + y * y + z * z + w * w; } 35.94 + float length() const { return sqrt(x * x + y * y + z * z + w * w); } 35.95 + 35.96 + void normalize() 35.97 + { 35.98 + float len = length(); 35.99 + if(len != 0.0) { 35.100 + x /= len; 35.101 + y /= len; 35.102 + z /= len; 35.103 + w /= len; 35.104 + } 35.105 + } 35.106 + 35.107 + float &operator [](int idx) 35.108 + { 35.109 + return idx == 3 ? w : (idx == 2 ? z : (idx == 1 ? y : x)); 35.110 + } 35.111 + const float &operator [](int idx) const 35.112 + { 35.113 + return idx == 3 ? w : (idx == 2 ? z : (idx == 1 ? y : x)); 35.114 + } 35.115 +}; 35.116 + 35.117 +inline Vector4 operator +(const Vector4 &a, const Vector4 &b) 35.118 +{ 35.119 + return Vector4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); 35.120 +} 35.121 + 35.122 +inline Vector4 operator -(const Vector4 &a, const Vector4 &b) 35.123 +{ 35.124 + return Vector4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); 35.125 +} 35.126 + 35.127 +inline Vector4 operator *(const Vector4 &v, float s) 35.128 +{ 35.129 + return Vector4(v.x * s, v.y * s, v.z * s, v.w * s); 35.130 +} 35.131 + 35.132 +inline Vector4 operator /(const Vector4 &v, float s) 35.133 +{ 35.134 + return Vector4(v.x / s, v.y / s, v.z / s, v.w / s); 35.135 +} 35.136 + 35.137 +inline float dot(const Vector4 &a, const Vector4 &b) 35.138 +{ 35.139 + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; 35.140 +} 35.141 + 35.142 +inline Vector4 transform(const Matrix4x4 &m, const Vector4 &v) 35.143 +{ 35.144 + float x = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3] * v.w; 35.145 + float y = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3] * v.w; 35.146 + float z = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3] * v.w; 35.147 + float w = m.m[3][0] * v.x + m.m[3][1] * v.y + m.m[3][2] * v.z + m.m[3][3] * v.w; 35.148 + return Vector4(x, y, z, w); 35.149 +} 35.150 + 35.151 +#endif // VMATH_H_
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/src/vmathmat.h Sat Apr 05 08:46:27 2014 +0300 36.3 @@ -0,0 +1,116 @@ 36.4 +#ifndef VMATH_MATRIX_H_ 36.5 +#define VMATH_MATRIX_H_ 36.6 + 36.7 +#include <math.h> 36.8 + 36.9 +#ifndef M_PI 36.10 +#define M_PI 3.141592653 36.11 +#endif 36.12 + 36.13 +class Vector3; 36.14 + 36.15 +class Matrix4x4 { 36.16 +public: 36.17 + float m[4][4]; 36.18 + 36.19 + Matrix4x4() 36.20 + { 36.21 + set_identity(); 36.22 + } 36.23 + 36.24 + Matrix4x4(float m00, float m01, float m02, float m03, 36.25 + float m10, float m11, float m12, float m13, 36.26 + float m20, float m21, float m22, float m23, 36.27 + float m30, float m31, float m32, float m33) 36.28 + { 36.29 + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; 36.30 + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; 36.31 + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; 36.32 + m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; 36.33 + } 36.34 + 36.35 + inline void set_identity(); 36.36 + inline void translate(float x, float y, float z); 36.37 + inline void rotate(float angle, float x, float y, float z); 36.38 + inline void scale(float x, float y, float z); 36.39 + inline void perspective(float vfov, float aspect, float znear, float zfar); 36.40 + inline void lookat(const Vector3 &pos, const Vector3 &targ, const Vector3 &up); 36.41 + 36.42 + float *operator [](int idx) { return m[idx]; } 36.43 + const float *operator [](int idx) const { return m[idx]; } 36.44 +}; 36.45 + 36.46 +inline Matrix4x4 operator *(const Matrix4x4 &a, const Matrix4x4 &b) 36.47 +{ 36.48 + Matrix4x4 res; 36.49 + for(int i=0; i<4; i++) { 36.50 + for(int j=0; j<4; j++) { 36.51 + res[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + 36.52 + a[i][2] * b[2][j] + a[i][3] * b[3][j]; 36.53 + } 36.54 + } 36.55 + return res; 36.56 +} 36.57 + 36.58 +inline void Matrix4x4::set_identity() 36.59 +{ 36.60 + m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0; 36.61 + m[0][1] = m[0][2] = m[0][3] = m[1][2] = m[1][3] = m[2][3] = 0.0; 36.62 + m[1][0] = m[2][0] = m[3][0] = m[2][1] = m[3][1] = m[3][2] = 0.0; 36.63 +} 36.64 + 36.65 +inline void Matrix4x4::translate(float x, float y, float z) 36.66 +{ 36.67 + Matrix4x4 m(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1); 36.68 + *this = *this * m; 36.69 +} 36.70 + 36.71 +inline void Matrix4x4::rotate(float angle, float x, float y, float z) 36.72 +{ 36.73 + float sina = (float)sin(angle); 36.74 + float cosa = (float)cos(angle); 36.75 + float rcosa = 1.0f - cosa; 36.76 + float nxsq = x * x; 36.77 + float nysq = y * y; 36.78 + float nzsq = z * z; 36.79 + 36.80 + Matrix4x4 m; 36.81 + m[0][0] = nxsq + (1.0f - nxsq) * cosa; 36.82 + m[0][1] = x * y * rcosa - z * sina; 36.83 + m[0][2] = x * z * rcosa + y * sina; 36.84 + 36.85 + m[1][0] = x * y * rcosa + z * sina; 36.86 + m[1][1] = nysq + (1.0f - nysq) * cosa; 36.87 + m[1][2] = y * z * rcosa - x * sina; 36.88 + 36.89 + m[2][0] = x * z * rcosa - y * sina; 36.90 + m[2][1] = y * z * rcosa + x * sina; 36.91 + m[2][2] = nzsq + (1.0f - nzsq) * cosa; 36.92 + 36.93 + *this = *this * m; 36.94 +} 36.95 + 36.96 +inline void Matrix4x4::scale(float x, float y, float z) 36.97 +{ 36.98 + Matrix4x4 m(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1); 36.99 + *this = *this * m; 36.100 +} 36.101 + 36.102 +inline void Matrix4x4::perspective(float vfov, float aspect, float znear, float zfar) 36.103 +{ 36.104 + float f = 1.0f / tan(vfov * 0.5f); 36.105 + float dz = znear - zfar; 36.106 + 36.107 + Matrix4x4 m; 36.108 + m[0][0] = f / aspect; 36.109 + m[1][1] = f; 36.110 + m[2][2] = (zfar + znear) / dz; 36.111 + m[3][2] = -1.0f; 36.112 + m[2][3] = 2.0f * zfar * znear / dz; 36.113 + m[3][3] = 0.0f; 36.114 + 36.115 + *this = *this * m; 36.116 +} 36.117 + 36.118 + 36.119 +#endif // VMATH_MATRIX_H_