removed clang-format and clang_complete files from the repo master
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 16 May 2022 05:02:27 +0000 (08:02 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 16 May 2022 05:02:27 +0000 (08:02 +0300)
70 files changed:
.clang_complete [deleted file]
.gitignore
GNUmakefile
Makefile
Makefile.dj
README.md
libs/imago/src/conv.c
libs/imago/src/filetga.c
libs/imago/src/inttypes.h [new file with mode: 0644]
libs/imago/src/types.h [deleted file]
libs/mikmod/GNUmakefile
pull.bat
push.bat [new file with mode: 0644]
src/3dgfx/3dgfx.c
src/3dgfx/mesh.c
src/3dgfx/mesh.h
src/3dgfx/polytmpl.h
src/bsptree.c
src/cpuid.c [new file with mode: 0644]
src/cpuid.h [new file with mode: 0644]
src/cpuid_s.asm [new file with mode: 0644]
src/darray.c [new file with mode: 0644]
src/darray.h [new file with mode: 0644]
src/demo.c
src/demo.h
src/dos/audos.c
src/dos/cdpmi.h
src/dos/dosutil.h [new file with mode: 0644]
src/dos/gfx.c
src/dos/gfx.h
src/dos/keyb.c
src/dos/logger.c
src/dos/logger.h
src/dos/main.c
src/dos/pci.c [new file with mode: 0644]
src/dos/pci.h [new file with mode: 0644]
src/dos/sball.c
src/dos/timer.c
src/dos/vbe.c
src/dos/vga.c
src/dos/vga.h
src/dos/vgaregs.h [new file with mode: 0644]
src/glut/audio.c
src/glut/main.c
src/glut/w32_dirent.c [deleted file]
src/glut/w32_dirent.h [deleted file]
src/glut/w32dir.c [new file with mode: 0644]
src/glut/w32dir.h [new file with mode: 0644]
src/noise.c
src/rlebmap.c [new file with mode: 0644]
src/rlebmap.h [new file with mode: 0644]
src/sball.h
src/scr/cybersun.c [new file with mode: 0644]
src/scr/grise.c
src/scr/minifx.c [new file with mode: 0644]
src/scr/raytrace.c [new file with mode: 0644]
src/scr/rt.c [new file with mode: 0644]
src/scr/rt.h [new file with mode: 0644]
src/scr/thunder.c
src/screen.c
src/sdl/main.c
src/tinyfps.c
src/treestor.c
src/util.c
src/util.h
src/util_s.asm [new file with mode: 0644]
tools/csprite/src/main.c
tools/img2bin/Makefile
tools/scripts/fixmknam [new file with mode: 0755]
tools/scripts/pceminst

diff --git a/.clang_complete b/.clang_complete
deleted file mode 100644 (file)
index e2c26a4..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
--x c
--Isrc
--Isrc/dos
--Isrc/dos/stl
index e86dd42..ac97839 100644 (file)
@@ -21,6 +21,7 @@ Release
 *sdf
 demo
 *.zip
+*.ZIP
 data
 *.a
 *.dll
index 8b0f6fb..767026f 100644 (file)
@@ -8,15 +8,15 @@ bin = demo
 asmsrc += cspr/dbgfont.asm cspr/confont.asm
 bindata = data/loading.img
 
-inc = -I/usr/local/include -Isrc -Isrc/3dgfx -Isrc/scr -Isrc/glut -Ilibs \
+inc = -I/usr/local/include -Isrc -Isrc/3dgfx -Isrc/scr -Isrc/utils -Isrc/glut -Ilibs \
          -Ilibs/imago/src -Ilibs/mikmod/include
 def = -DMINIGLUT_USE_LIBC -DMIKMOD_STATIC
-warn = -pedantic -Wall -Wno-unused-variable -Wno-unused-function
+warn = -pedantic -Wall -Wno-unused-variable -Wno-unused-function -Wno-address
 #opt = -O3 -ffast-math
 dbg = -g
 
-CFLAGS = $(arch) $(warn) -MMD $(opt) -fno-strict-aliasing $(dbg) $(inc)
-LDFLAGS = $(arch) -Llibs/imago -Llibs/mikmod -limago -lmikmod \
+CFLAGS = $(arch) $(warn) -MMD $(opt) -fno-pie -fno-strict-aliasing $(dbg) $(inc)
+LDFLAGS = $(arch) -no-pie -Llibs/imago -Llibs/mikmod -limago -lmikmod \
                  $(sndlib_$(sys)) -lm
 
 cpu ?= $(shell uname -m | sed 's/i.86/i386/')
@@ -27,7 +27,7 @@ endif
 
 sys ?= $(shell uname -s | sed 's/MINGW.*/mingw/; s/IRIX.*/IRIX/')
 ifeq ($(sys), mingw)
-       obj = $(src:.c=.w32.o)
+       obj = $(src:.c=.w32.o) $(asmsrc:.asm=.w32.o)
 
        bin = demo_win32.exe
 
@@ -52,6 +52,9 @@ $(bin): $(obj) imago mikmod
 %.o: %.asm
        nasm -f elf -o $@ $<
 
+%.w32.o: %.asm
+       nasm -f coff -o $@ $<
+
 %.w32.o: %.c
        $(CC) -o $@ $(CFLAGS) -c $<
 
index 562b0d6..1f6ab07 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,18 +1,21 @@
 !ifdef __UNIX__
 dosobj = src/dos/audos.obj src/dos/djdpmi.obj src/dos/gfx.obj src/dos/keyb.obj &
        src/dos/logger.obj src/dos/main.obj src/dos/sball.obj src/dos/timer.obj &
-       src/dos/vbe.obj src/dos/vga.obj src/dos/watdpmi.obj src/dos/mouse.obj
+       src/dos/vbe.obj src/dos/vga.obj src/dos/watdpmi.obj src/dos/mouse.obj &
+       src/dos/pci.obj
 3dobj = src/3dgfx/3dgfx.obj src/3dgfx/mesh.obj src/3dgfx/meshload.obj &
        src/3dgfx/polyclip.obj src/3dgfx/polyfill.obj
 srcobj = src/bsptree.obj src/cfgopt.obj src/console.obj src/demo.obj &
        src/dynarr.obj src/gfxutil.obj src/metasurf.obj src/noise.obj &
        src/rbtree.obj src/screen.obj src/tinyfps.obj src/treestor.obj &
-       src/ts_text.obj src/util.obj src/data.obj
+       src/image.obj src/ts_text.obj src/util.obj src/util_s.obj src/cpuid.obj &
+       src/cpuid_s.obj src/darray.obj src/data.obj src/rlebmap.obj
 scrobj = src/scr/bump.obj src/scr/fract.obj src/scr/greets.obj &
        src/scr/grise.obj src/scr/hairball.obj src/scr/infcubes.obj &
        src/scr/metaball.obj src/scr/plasma.obj src/scr/polytest.obj &
        src/scr/smoketxt.obj src/scr/thunder.obj src/scr/tilemaze.obj &
-       src/scr/tunnel.obj
+       src/scr/tunnel.obj src/scr/cybersun.obj src/scr/raytrace.obj &
+       src/scr/rt.obj src/scr/minifx.obj
 csprobj = cspr/dbgfont.obj cspr/confont.obj
 
 incpath = -Isrc -Isrc/dos -Isrc/3dgfx -Ilibs -Ilibs/imago/src -Ilibs/anim/src &
@@ -22,18 +25,21 @@ libpath = libpath libs/imago libpath libs/anim libpath libs/midas
 
 dosobj = src\dos\audos.obj src\dos\djdpmi.obj src\dos\gfx.obj src\dos\keyb.obj &
        src\dos\logger.obj src\dos\main.obj src\dos\sball.obj src\dos\timer.obj &
-       src\dos\vbe.obj src\dos\vga.obj src\dos\watdpmi.obj src\dos\mouse.obj
+       src\dos\vbe.obj src\dos\vga.obj src\dos\watdpmi.obj src\dos\mouse.obj &
+       src\dos\pci.obj
 3dobj = src\3dgfx\3dgfx.obj src\3dgfx\mesh.obj src\3dgfx\meshload.obj &
        src\3dgfx\polyclip.obj src\3dgfx\polyfill.obj
 srcobj = src\bsptree.obj src\cfgopt.obj src\console.obj src\demo.obj &
        src\dynarr.obj src\gfxutil.obj src\metasurf.obj src\noise.obj &
        src\rbtree.obj src\screen.obj src\tinyfps.obj src\treestor.obj &
-       src\ts_text.obj src\util.obj src\data.obj
+       src\image.obj src\ts_text.obj src\util.obj src\util_s.obj src\cpuid.obj &
+       src\cpuid_s.obj src\darray.obj src\data.obj src\rlebmap.obj
 scrobj = src\scr\bump.obj src\scr\fract.obj src\scr\greets.obj &
        src\scr\grise.obj src\scr\hairball.obj src\scr\infcubes.obj &
        src\scr\metaball.obj src\scr\plasma.obj src\scr\polytest.obj &
        src\scr\smoketxt.obj src\scr\thunder.obj src\scr\tilemaze.obj &
-       src\scr\tunnel.obj
+       src\scr\tunnel.obj src\scr\cybersun.obj src\scr\raytrace.obj &
+       src\scr\rt.obj src\scr\minifx.obj
 csprobj = cspr\dbgfont.obj cspr\confont.obj
 
 incpath = -Isrc -Isrc\dos -Isrc\3dgfx -Ilibs -Ilibs\imago\src -Ilibs\anim\src &
index e249553..59d4042 100644 (file)
@@ -1,7 +1,8 @@
-src = $(wildcard src/*.c) $(wildcard src/scr/*.c) $(wildcard src/dos/*.c)
+src = $(wildcard src/*.c) $(wildcard src/3dgfx/*.c) $(wildcard src/scr/*.c) \
+         $(wildcard src/dos/*.c)
 asmsrc = $(wildcard src/*.asm) $(wildcard src/scr/*.asm) $(wildcard src/dos/*.asm)
 obj = $(src:.c=.odj) $(asmsrc:.asm=.odj)
-dep = $(obj:.odj=.dep)
+dep = $(src:.c=.d)
 bin = demo.exe
 
 asmsrc += cspr/dbgfont.asm cspr/confont.asm
@@ -14,22 +15,24 @@ else
        TOOLPREFIX = i586-pc-msdosdjgpp-
 endif
 
-inc = -Isrc -Isrc/scr -Isrc/dos -Ilibs -Ilibs/imago/src -Ilibs/anim/src
+inc = -Isrc -Isrc/3dgfx -Isrc/scr -Isrc/dos -Ilibs \
+         -Ilibs/imago/src -Ilibs/anim/src -Ilibs/midas
 opt = -O3 -ffast-math -fno-strict-aliasing
 warn = -pedantic -Wall -Wno-unused-function -Wno-unused-variable
 
 ifdef RELEASE
        dbg = -g
-       def = -DNDEBUG -DNO_MUSIC
+       def = -DNDEBUG -DNO_SOUND
 else
-       def = -DNO_MUSIC
+       def = -DNO_SOUND
 endif
 #prof = -pg
 
 CC = $(TOOLPREFIX)gcc
 AR = $(TOOLPREFIX)ar
-CFLAGS = $(warn) -march=pentium $(dbg) $(opt) $(prof) $(inc) $(def)
+CFLAGS = -march=pentium $(warn) -MMD $(dbg) $(opt) $(prof) $(inc) $(def)
 LDFLAGS = libs/imago/imago.dja libs/anim/anim.dja
+#libs/midas/libmidas.a
 
 ifneq ($(hostsys), dos)
 .PHONY: all
@@ -44,29 +47,23 @@ $(bin): $(obj) imago anim
 
 src/data.odj: src/data.asm $(bindata)
 
-ifneq ($(hostsys), dos)
 -include $(dep)
-endif
 
 %.odj: %.c
        $(CC) $(CFLAGS) -o $@ -c $<
 
-%.dep: %.c
-       @echo dep $@
-       @$(CPP) $(CFLAGS) $< -MM -MT $(@:.dep=.odj) >$@
-
 .PHONY: imago
 imago:
-       $(MAKE) -C libs/imago -f Makefile
+       $(MAKE) -C libs/imago -f Makefile.dj
 
 .PHONY: anim
 anim:
-       $(MAKE) -C libs/anim -f Makefile
+       $(MAKE) -C libs/anim -f Makefile.dj
 
 .PHONY: cleanlibs
 cleanlibs:
-       $(MAKE) -C libs/imago -f Makefile clean
-       $(MAKE) -C libs/anim -f Makefile clean
+       $(MAKE) -C libs/imago clean -f Makefile.dj
+       $(MAKE) -C libs/anim clean -f Makefile.dj
 
 .PHONY: clean
 .PHONY: cleandep
@@ -74,12 +71,14 @@ cleanlibs:
 ifeq ($(hostsys), dos)
 clean:
        del src\*.odj
+       del src\3dgfx\*.odj
        del src\dos\*.odj
        del $(bin)
 
 cleandep:
-       del src\*.dep
-       del src\dos\*.dep
+       del src\*.d
+       del src\3dgfx\*.d
+       del src\dos\*.d
 else
 clean:
        rm -f $(obj) $(bin)
index b3a41a1..6d34b63 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,26 +1,49 @@
-Unnamed Mindlapse DOS demo for Pentium 133
-------------------------------------------
-The demo requires VESA Bios Extensions (VBE) 2.0. If your graphics card doesn't
-support VBE 2.0 or greater, then make sure to load the `univbe` TSR first.
+Unnamed Mindlapse DOS demo for Pentium-era PCs
+----------------------------------------------
+The demo uses VBE 320x240 16bpp. Some VBE implementations do not expose
+double-scan video modes (240 lines), but can be made to work with a third-party
+VBE TSR like `univbe` or `s3vbe`. Linear framebuffer (VBE 2.0) support is
+recommended, but not necessary. The demo will fallback to VBE 1.2 banked modes
+if LFB modes are not available.
 
 Source structure
 ----------------
  - src/          cross-platform demo framework and miscellaneous utility code
  - src/scr/      demo screens (parts) and effects support code
  - src/dos/      DOS platform code
+ - src/glut/     GLUT platform code (windows/UNIX version)
  - src/sdl/      SDL 1.x platform code (windows/UNIX version)
  - libs/cgmath/  math library, header-file only
  - libs/imago/   image loading library (includes libpng, zlib, libjpeg)
  - libs/anim/    keyframe animation library
 
+Coding style conventions
+------------------------
+Very few style issues are mandated:
+
+  - All filenames should be lowercase unless convention says otherwise
+    (`Makefile`, `README`, etc).
+  - All filenames under `src/` and of any tools necessary to build from MS-DOS
+    will have to use maximum 8.3 characters.
+  - Source code should be C89-compliant. Any compiler-specific features beyond
+    that will have to be ifdefed.
+  - Use tabs for indentation, where each tab is equivalent to 4 spaces.
+
+Everything else is left to the discretion of each individual, but also if
+you're editing an existing file, try to match the style of the surrounding code.
+
+Some general style suggestions, which will not be enforced:
+
+  - Don't use overly long names, abbreviate wherever it makes sense.
+  - Don't cast the return value of malloc. `void*` are converted implicitly, and
+    the cast hides forgetting to include `stdlib.h`.
+  - Preferably use lowercase with underscores for everything.
+  - Preferably use the K&R brace style if possible.
+
+This section will be expanded as necessary.
+
 Building on DOS with Watcom
 ---------------------------
-NOTE: Don't. Watcom produces significantly worse code than GCC, and at the
-moment watcom-compiled version of the demo crashes on 3D scenes for some reason
-which I need to investigate at some point. Suspect either inline assembly with
-missing "modify" part, or more likely some FPU optimization which fucks up the
-clipper.
-
 Make sure you have Watcom or OpenWatcom installed, and the appropriate env-vars
 set (the watcom installer automatically adds them to autoexec.bat by default).
 
@@ -147,3 +170,71 @@ defined in `cdpmi.h`:
 
     #define virt_to_phys(v)    ((v) + __djgpp_base_address)
     #define phys_to_virt(p)    ((p) - __djgpp_base_address)
+
+Notes about moving code to/from a DOS computer
+----------------------------------------------
+The easiest way to move code back and forth to a DOS computer, is to connect it
+to the local network. For this you need a DOS packet driver for your NIC, which
+thankfully most NIC vendors seem to provide, and a number of useful network
+utilities which come with their own TCP/IP stack (mTCP and WATTCP). The
+following are recommended:
+
+ - mTCP: http://www.brutman.com/mTCP
+ - WATTCP: http://www.watt-32.net
+ - ssh2dos: http://sshdos.sourceforge.net
+ - rsync: http://www.2net.co.uk/rsync.html
+
+Here's an example batch file I'm using to set up the network:
+
+    @echo off
+    c:\net\rtspkt\rtspkt 0x61
+    set MTCPCFG=c:\net\mtcp\mtcp.cfg
+    set WATT_ROOT=c:\net\watt
+    set WATTCP.CFG=c:\net\watt\bin
+    set ETC=c:\net\watt\bin
+    set PATH=%PATH%;c:\net\mtcp;c:\net\watt\bin
+
+The rtspkt program is the packet driver for my realtek NIC, and I'm instructing
+it to use interrupt 61h. The rest are environment variables needed by mTCP and
+WATTCP. If you run out of environment space you might need to increase it with
+`SHELL=C:\DOS\COMMAND.COM /e:1024 /p` in `config.sys`, or just put all binaries
+in a single place instead of adding multiple directories to the `PATH`.
+
+### mTCP configuration
+The `mtcp.cfg` file configures the mTCP TCP/IP stack. Go through the file, which
+comes with mTCP, and make any necessary changes. For instance I've set
+`packetint 0x61` to match the packet driver interrupt, and I'm using static IP
+assignments, so I've set it up like this:
+
+    ipaddr 192.168.0.21
+    netmask 255.255.0.0
+    gateway 192.168.1.1
+    nameserver 1.1.1.1
+
+### WATTCP configuration
+The `wattcp.cfg` file is in the wattcp bin directory, and includes similar
+configuration options:
+
+    my_ip = 192.168.0.21
+    hostname = "retrop1"
+    netmask = 255.255.0.0
+    nameserver = 1.1.1.1
+    gateway = 192.168.1.1
+    domain.suffix = localdomain
+    pkt.vector = 0x61
+    hosts = $(ETC)\hosts
+
+### Server-side configuration
+The `pull.bat` file in the demo repo uses rsync to get the source code from the
+git repo on my main GNU/Linux computer. To avoid having to type passwords all
+the time, I've configures rsyncd to allow access to the demo directory in the
+`/etc/rsyncd.conf` file:
+
+    [dosdemo]
+    path = /home/nuclear/code/demoscene/dosdemo
+    comment = DOS demo project
+
+Since the DOS rsync utility is unfortunately read-only, the `push.bat` relies on
+ssh2dos instead, which does require a password. The sshd on the server might
+need to be configured to allow older encryption algorithms, depending on your
+current setup.
index 756469c..94fb87f 100644 (file)
@@ -17,7 +17,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include <string.h>
 #include "imago2.h"
-#include "types.h"
+#include "inttypes.h"
 
 /* pixel-format conversions are sub-optimal at the moment to avoid
  * writing a lot of code. optimize at some point ?
index 2192ff4..97504ca 100644 (file)
@@ -20,7 +20,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <string.h>
 #include <stdlib.h>
-#include "types.h"
+#include "inttypes.h"
 #include "imago2.h"
 #include "ftmodule.h"
 
diff --git a/libs/imago/src/inttypes.h b/libs/imago/src/inttypes.h
new file mode 100644 (file)
index 0000000..cbcc4d0
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+colcycle - color cycling image viewer
+Copyright (C) 2016  John Tsiombikas <nuclear@member.fsf.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef INT_TYPES_H_
+#define INT_TYPES_H_
+
+#if defined(__DOS__) || defined(__MSDOS__)
+typedef char int8_t;
+typedef short int16_t;
+typedef long int32_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+
+typedef unsigned long intptr_t;
+#else
+
+#ifdef _MSC_VER
+typedef __int8 int8_t;
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+
+#ifdef _WIN64
+typedef __int64 intptr_t;
+#else
+typedef __int32 intptr_t;
+#endif
+#else  /* not msvc */
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199900
+#include <stdint.h>
+#else
+#include <sys/types.h>
+#endif
+
+#endif /* end !msvc */
+#endif /* end !dos */
+
+#endif /* INT_TYPES_H_ */
diff --git a/libs/imago/src/types.h b/libs/imago/src/types.h
deleted file mode 100644 (file)
index d06e5c0..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-colcycle - color cycling image viewer
-Copyright (C) 2016  John Tsiombikas <nuclear@member.fsf.org>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef INT_TYPES_H_
-#define INT_TYPES_H_
-
-#if defined(__DOS__) || defined(__MSDOS__)
-typedef char int8_t;
-typedef short int16_t;
-typedef long int32_t;
-
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned long uint32_t;
-
-typedef unsigned long intptr_t;
-#else
-
-#ifdef _MSC_VER
-typedef __int8 int8_t;
-typedef __int16 int16_t;
-typedef __int32 int32_t;
-typedef unsigned __int8 uint8_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int32 uint32_t;
-
-#ifdef _WIN64
-typedef __int64 intptr_t;
-#else
-typedef __int32 intptr_t;
-#endif
-#else  /* not msvc */
-
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199900
-#include <stdint.h>
-#else
-#include <inttypes.h>
-#endif
-
-#endif /* end !msvc */
-#endif /* end !dos */
-
-#endif /* INT_TYPES_H_ */
index 9f472ff..7fcc00e 100644 (file)
@@ -10,7 +10,7 @@ alib = libmikmod.a
 def = -DHAVE_CONFIG_H -DMIKMOD_BUILD
 inc = -I. -Iinclude
 warn = -pedantic -Wall -Wno-unused-variable -Wno-unused-function
-CFLAGS = -m32 $(warn) -g $(def) $(inc) `pkg-config --cflags sdl`
+CFLAGS = -m32 $(warn) -g $(def) $(inc)
 
 $(alib): $(obj)
        $(AR) rcs $@ $(obj)
index 96498c0..a099a39 100644 (file)
--- a/pull.bat
+++ b/pull.bat
@@ -1,4 +1,30 @@
-ssh2dos -g -i c:\prog\ssh2dos\doskey -S -B nuclear 192.168.0.4 cd code/demoscene/dosdemo && git archive -o dd.zip master\r
-scp2dos -r -g -i c:\prog\ssh2dos\doskey nuclear@192.168.0.4:code/demoscene/dosdemo/dd.zip .\r
-unzip32 -o dd.zip\r
-del dd.zip\r
+mkdir src
+rsync -v 192.168.0.4::dosdemo/Makefile Makefile
+rsync -v 192.168.0.4::dosdemo/src/*.c src
+rsync -v 192.168.0.4::dosdemo/src/*.h src
+rsync -v 192.168.0.4::dosdemo/src/*.asm src
+mkdir src\dos
+rsync -v 192.168.0.4::dosdemo/src/dos/*.c src/dos
+rsync -v 192.168.0.4::dosdemo/src/dos/*.h src/dos
+rsync -v 192.168.0.4::dosdemo/src/dos/*.asm src/dos
+mkdir src\glut
+rsync -v 192.168.0.4::dosdemo/src/glut/*.c src/glut
+rsync -v 192.168.0.4::dosdemo/src/glut/*.h src/glut
+mkdir src\sdl
+rsync -v 192.168.0.4::dosdemo/src/sdl/*.c src/sdl
+mkdir src\scr
+rsync -v 192.168.0.4::dosdemo/src/scr/*.c src/scr
+rsync -v 192.168.0.4::dosdemo/src/scr/*.h src/scr
+mkdir src\3dgfx
+rsync -v 192.168.0.4::dosdemo/src/3dgfx/*.c src/3dgfx
+rsync -v 192.168.0.4::dosdemo/src/3dgfx/*.h src/3dgfx
+
+mkdir tools
+mkdir tools\csprite
+rsync -v 192.168.0.4::dosdemo/tools/csprite/Makefile tools/csprite/Makefile
+rsync -v 192.168.0.4::dosdemo/tools/csprite/src/*.c tools/csprite/src
+rsync -v 192.168.0.4::dosdemo/tools/csprite/src/*.h tools/csprite/src
+
+mkdir tools\img2bin
+rsync -v 192.168.0.4::dosdemo/tools/img2bin/Makefile tools/img2bin/Makefile
+rsync -v 192.168.0.4::dosdemo/tools/img2bin/*.c tools/img2bin
diff --git a/push.bat b/push.bat
new file mode 100644 (file)
index 0000000..f541c4d
--- /dev/null
+++ b/push.bat
@@ -0,0 +1,3 @@
+del ddsrc.zip
+zip -r ddsrc.zip . -i *.c -i *.h -i *.asm -i *.s -i *.S -i *.inl -i *akefile* -i *.bat -i packsrc -i unpsrc -x *.swp -x libs/*
+scp2dos -g ddsrc.zip nuclear@192.168.0.4:code/demoscene/dosdemo
index ef569e6..dcd28c6 100644 (file)
@@ -503,6 +503,8 @@ void g3d_draw(int prim, const struct g3d_vertex *varr, int varr_size)
        g3d_draw_indexed(prim, varr, varr_size, 0, 0);
 }
 
+#define NEED_NORMALS   (st->opt & (G3D_LIGHTING | G3D_TEXTURE_GEN))
+
 void g3d_draw_indexed(int prim, const struct g3d_vertex *varr, int varr_size,
                const uint16_t *iarr, int iarr_size)
 {
@@ -516,8 +518,10 @@ void g3d_draw_indexed(int prim, const struct g3d_vertex *varr, int varr_size,
        tmpv = alloca(prim * 6 * sizeof *tmpv);
 
        /* calc the normal matrix */
-       memcpy(st->norm_mat, st->mat[G3D_MODELVIEW][mvtop], 16 * sizeof(float));
-       st->norm_mat[12] = st->norm_mat[13] = st->norm_mat[14] = 0.0f;
+       if(NEED_NORMALS) {
+               memcpy(st->norm_mat, st->mat[G3D_MODELVIEW][mvtop], 16 * sizeof(float));
+               st->norm_mat[12] = st->norm_mat[13] = st->norm_mat[14] = 0.0f;
+       }
 
        nfaces = (iarr ? iarr_size : varr_size) / prim;
 
@@ -528,14 +532,16 @@ void g3d_draw_indexed(int prim, const struct g3d_vertex *varr, int varr_size,
                        v[i] = iarr ? varr[*iarr++] : *varr++;
 
                        xform4_vec3(st->mat[G3D_MODELVIEW][mvtop], &v[i].x);
-                       xform3_vec3(st->norm_mat, &v[i].nx);
 
-                       if(st->opt & G3D_LIGHTING) {
-                               shade(v + i);
-                       }
-                       if(st->opt & G3D_TEXTURE_GEN) {
-                               v[i].u = v[i].nx * 0.5 + 0.5;
-                               v[i].v = 0.5 - v[i].ny * 0.5;
+                       if(NEED_NORMALS) {
+                               xform3_vec3(st->norm_mat, &v[i].nx);
+                               if(st->opt & G3D_LIGHTING) {
+                                       shade(v + i);
+                               }
+                               if(st->opt & G3D_TEXTURE_GEN) {
+                                       v[i].u = v[i].nx * 0.5 + 0.5;
+                                       v[i].v = 0.5 - v[i].ny * 0.5;
+                               }
                        }
                        if(st->opt & G3D_TEXTURE_MAT) {
                                float *mat = st->mat[G3D_TEXTURE][st->mtop[G3D_TEXTURE]];
index b8bb9c1..c40b491 100644 (file)
@@ -364,8 +364,8 @@ int gen_plane_mesh(struct g3d_mesh *m, float width, float height, int usub, int
        nfaces = usub * vsub;
        uverts = usub + 1;
        vverts = vsub + 1;
-       du = (float)width / (float)usub;
-       dv = (float)height / (float)vsub;
+       du = 1.0f / (float)usub;
+       dv = 1.0f / (float)vsub;
 
        nverts = uverts * vverts;
        nidx = nfaces * 4;
index 5357cb0..e02cf55 100644 (file)
@@ -10,6 +10,8 @@ struct g3d_mesh {
        int vcount, icount;
 };
 
+int init_mesh(struct g3d_mesh *mesh, int prim, int num_verts, int num_idx);
+
 void free_mesh(struct g3d_mesh *mesh);
 void destroy_mesh(struct g3d_mesh *mesh);
 
index 167d5e1..f601623 100644 (file)
@@ -101,9 +101,6 @@ void POLYFILL(struct pvertex *pv, int nverts)
 #if defined(GOURAUD) || defined(TEXMAP) || defined(ZBUF)
        int mid;
        int32_t dx, tmp;
-#else
-       /* flat version, just pack the color now */
-       color = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b);
 #endif
 #ifdef GOURAUD
        int32_t r, g, b, dr, dg, db, rslope, gslope, bslope;
@@ -118,6 +115,11 @@ void POLYFILL(struct pvertex *pv, int nverts)
        int32_t z, dz, zslope;
 #endif
 
+#if !defined(GOURAUD) && !defined(TEXMAP)
+       /* flat version, just pack the color now */
+       color = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b);
+#endif
+
        for(i=1; i<nverts; i++) {
                if(pv[i].y < pv[topidx].y) topidx = i;
                if(pv[i].y > pv[botidx].y) botidx = i;
index f286ac7..d6417b9 100644 (file)
@@ -6,8 +6,12 @@
 #if defined(__WATCOMC__) || defined(_MSC_VER) || defined(__DJGPP__)
 #include <malloc.h>
 #else
+#ifdef WIN32
+#include <malloc.h>
+#else
 #include <alloca.h>
 #endif
+#endif
 #include "bsptree.h"
 #include "dynarr.h"
 #include "inttypes.h"
@@ -248,7 +252,9 @@ static int choose_poly(struct bsppoly *polyarr, int num_polys)
                struct cplane *plane = &polyarr[i].plane;
                int num_splits = 0;
 
+#ifdef USE_OPENMP
 #pragma omp parallel for reduction(+:num_splits)
+#endif
                for(j=0; j<num_polys; j++) {
                        if(i == j) continue;
 
diff --git a/src/cpuid.c b/src/cpuid.c
new file mode 100644 (file)
index 0000000..5a09fc4
--- /dev/null
@@ -0,0 +1,151 @@
+#include <stdio.h>
+#include <string.h>
+#include "cpuid.h"
+
+static const char *cpuname(struct cpuid_info *cpu);
+static const char *cpuvendor(struct cpuid_info *cpu);
+
+struct cpuid_info cpuid;
+
+void print_cpuid(struct cpuid_info *cpu)
+{
+       int i, col, len;
+       char buf[64];
+       static const char *featstr[32] = {
+               "fpu", "vme", "dbgext", "pse", "tsc", "msr", "pae", "mce",
+               "cx8", "apic", "?", "sep", "mtrr", "pge", "mca", "cmov",
+               "pat", "pse36", "psn", "clf", "?", "dtes", "acpi", "mmx",
+               "fxsr", "sse", "sse2", "ss", "htt", "tm1", "ia64", "pbe"};
+       static const char *feat2str[32] = {
+               "sse3", "pclmul", "dtes64", "monitor", "ds-cpl", "vmx", "smx", "est",
+               "tm2", "ssse3", "cid", "sdbg", "fma", "cx16", "etprd", "pdcm",
+               "?", "pcid", "dca", "sse41", "sse42", "x2apic", "movbe", "popcnt",
+               "?", "aes", "xsave", "osxsave", "avx", "f16c", "rdrand", "?"};
+
+       printf("CPU: %s - %s\n", cpuvendor(cpu), cpuname(cpu));
+       printf("features:\n   ");
+       col = 3;
+       for(i=0; i<32; i++) {
+               if(cpu->feat & (1 << i)) {
+                       len = strlen(featstr[i]) + 1;
+                       if(col + len >= 80) {
+                               fputs("\n   ", stdout);
+                               col = 3;
+                       }
+                       col += printf(" %s", featstr[i]);
+               }
+       }
+       for(i=0; i<32; i++) {
+               if(cpu->feat2 & (1 << i)) {
+                       len = strlen(feat2str[i]) + 1;
+                       if(col + len >= 80) {
+                               fputs("\n   ", stdout);
+                               col = 3;
+                       }
+                       col += printf(" %s", feat2str[i]);
+               }
+       }
+       putchar('\n');
+}
+
+static const char *fam4_models[16] = {
+       "486 DX 25/33", "486 DX 50", "486 SX", "486 DX/2", "486 SL", "486 SX/2",
+       0, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB"
+};
+static const char *fam5_models[16] = {
+       "Pentium 60/66", "Pentium 60/66", "Pentium 75-200", "OverDrive", "Pentium MMX",
+       0, 0, "Mobile Pentium 75-200", "Mobile Pentium MMX", "Quark"
+};
+static const char *fam6_models[16] = {
+       "Pentium Pro", "Pentium Pro", 0, "Pentium 2", "Pentium 2", "Pentium 2",
+       "Mobile Pentium 2", "Pentium 3", "Pentium 3", 0, "Pentium 3", "Pentium 3"
+};
+
+
+static const char *cpuname(struct cpuid_info *cpu)
+{
+       int model, family;
+       char *rd, *wr;
+
+       if(*cpu->brandstr) {
+               /* unwank the string */
+               rd = wr = cpu->brandstr;
+               while(*rd) {
+                       if(rd[0] == '(' && rd[1] == 'T' && rd[2] == 'M' && rd[3] == ')')
+                               rd += 4;
+                       else if(rd[0] == '(' && rd[1] == 'R' && rd[2] == ')')
+                               rd += 3;
+                       if(rd != wr) *wr = *rd;
+                       wr++;
+                       rd++;
+               }
+               return cpu->brandstr;
+       }
+
+       if(CPUID_EXTMODEL(cpu->id)) {
+               /* processors new enough to have an extended model, should also provide
+                * a brand string. If we end up here, we don't know what it is
+                */
+               return "unknown";
+       }
+
+       model = CPUID_MODEL(cpu->id);
+       family = CPUID_FAMILY(cpu->id) | (CPUID_EXTFAMILY(cpu->id) << 4);
+
+       switch(family) {
+       case 3: return "386";
+       case 4: return fam4_models[model] ? fam4_models[model] : "486";
+       case 5: return fam5_models[model] ? fam5_models[model] : "Pentium";
+       case 6: return fam6_models[model] ? fam6_models[model] : "unknown";
+       case 15: return "Pentium 4";
+       default:
+               break;
+       }
+       return "unknown";
+}
+
+static const char *cpuvendor(struct cpuid_info *cpu)
+{
+       static char other[16];
+       static const struct { const char *wank, *vendor; } unwanktab[] = {
+               {"GenuineIntel", "intel"},
+               {"AuthenticAMD", "AMD"},
+               {"AMDisbetter!", "AMD"},
+               {"CentaurHauls", "IDT"},
+               {"CyrixInstead", "Cyrix"},
+               {"TransmetaCPU", "Transmeta"},
+               {"GenuineTMx86", "Transmeta"},
+               {"Geode by NSC", "NatSemi"},
+               {"NexGenDriven", "NexGen"},
+               {"RiseRiseRise", "Rise"},
+               {"SiS SiS SiS ", "SiS"},
+               {"UMC UMC UMC ", "UMC"},
+               {"VIA VIA VIA ", "VIA"},
+               {"Vortex86 SoC", "DM&P"},
+               {"  Shanghai  ", "Zhaoxin"},
+               {"HygonGenuine", "Hygon"},
+               {"E2K MACHINE", "MCST Elbrus"},
+               {"MiSTer A0486", "ao486"},
+               {"bhyve bhyve ", "bhyve"},
+               {" KVMKVMKVM  ", "KVM"},
+               {"TCGTCGTCGTCG", "qemu"},
+               {"Microsoft Hv", "MS Hyper-V"},
+               {" lrpepyh  vr", "Parallels"},
+               {"VMwareVMware", "VMware"},
+               {"XenVMMXenVMM", "Xen"},
+               {"ACRNACRNACRN", "ACRN"},
+               {" QNXQVMBSQG ", "QNX Hypervisor"},
+               {0, 0}
+       };
+
+       int i;
+       for(i=0; unwanktab[i].wank; i++) {
+               if(memcmp(cpu->vendor, unwanktab[i].wank, 12) == 0) {
+                       return unwanktab[i].vendor;
+               }
+       }
+
+       memcpy(other, cpu->vendor, 12);
+       other[12] = 0;
+       return other;
+}
diff --git a/src/cpuid.h b/src/cpuid.h
new file mode 100644 (file)
index 0000000..5566f69
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef CPUID_H_
+#define CPUID_H_
+
+#include "inttypes.h"
+
+struct cpuid_info {
+       uint32_t maxidx;        /* 0: eax */
+       char vendor[12];        /* 0: ebx, edx, ecx */
+       uint32_t id;            /* 1: eax */
+       uint32_t rsvd0;         /* 1: ebx */
+       uint32_t feat;          /* 1: edx */
+       uint32_t feat2;         /* 1: ecx */
+
+       char brandstr[48];      /* 80000002h-80000004h */
+};
+
+extern struct cpuid_info cpuid;
+
+#define CPU_HAVE_MMX           (cpuid.feat & CPUID_FEAT_MMX)
+#define CPU_HAVE_MTRR          (cpuid.feat & CPUID_FEAT_MTRR)
+
+#define CPUID_STEPPING(id)     ((id) & 0xf)
+#define CPUID_MODEL(id)                (((id) >> 4) & 0xf)
+#define CPUID_FAMILY(id)       (((id) >> 8) & 0xf)
+#define CPUID_EXTMODEL(id)     (((id) >> 16) & 0xf)
+#define CPUID_EXTFAMILY(id)    (((id) >> 20) & 0xff)
+
+#define CPUID_FEAT_FPU                 0x00000001
+#define CPUID_FEAT_VME                 0x00000002
+#define CPUID_FEAT_DBGEXT              0x00000004
+#define CPUID_FEAT_PSE                 0x00000008
+#define CPUID_FEAT_TSC                 0x00000010
+#define CPUID_FEAT_MSR                 0x00000020
+#define CPUID_FEAT_PAE                 0x00000040
+#define CPUID_FEAT_MCE                 0x00000080
+#define CPUID_FEAT_CX8                 0x00000100
+#define CPUID_FEAT_APIC                        0x00000200
+
+#define CPUID_FEAT_SEP                 0x00000800
+#define CPUID_FEAT_MTRR                        0x00001000
+#define CPUID_FEAT_PGE                 0x00002000
+#define CPUID_FEAT_MCA                 0x00004000
+#define CPUID_FEAT_CMOV                        0x00008000
+#define CPUID_FEAT_PAT                 0x00010000
+#define CPUID_FEAT_PSE36               0x00020000
+#define CPUID_FEAT_PSN                 0x00040000
+#define CPUID_FEAT_CLF                 0x00080000
+
+#define CPUID_FEAT_DTES                        0x00200000
+#define CPUID_FEAT_ACPI                        0x00400000
+#define CPUID_FEAT_MMX                 0x00800000
+#define CPUID_FEAT_FXSR                        0x01000000
+#define CPUID_FEAT_SSE                 0x02000000
+#define CPUID_FEAT_SSE2                        0x04000000
+#define CPUID_FEAT_SS                  0x08000000
+#define CPUID_FEAT_HTT                 0x10000000
+#define CPUID_FEAT_TM1                 0x20000000
+#define CPUID_FEAT_IA64                        0x40000000
+#define CPUID_FEAT_PBE                 0x80000000
+
+#define CPUID_FEAT2_SSE3               0x00000001
+#define CPUID_FEAT2_PCLMUL             0x00000002
+#define CPUID_FEAT2_DTES64             0x00000004
+#define CPUID_FEAT2_MONITOR            0x00000008
+#define CPUID_FEAT2_DS_CPL             0x00000010
+#define CPUID_FEAT2_VMX                        0x00000020
+#define CPUID_FEAT2_SMX                        0x00000040
+#define CPUID_FEAT2_EST                        0x00000080
+#define CPUID_FEAT2_TM2                        0x00000100
+#define CPUID_FEAT2_SSSE3              0x00000200
+#define CPUID_FEAT2_CID                        0x00000400
+#define CPUID_FEAT2_SDBG               0x00000800
+#define CPUID_FEAT2_FMA                        0x00001000
+#define CPUID_FEAT2_CX16               0x00002000
+#define CPUID_FEAT2_ETPRD              0x00004000
+#define CPUID_FEAT2_PDCM               0x00008000
+
+#define CPUID_FEAT2_PCID               0x00020000
+#define CPUID_FEAT2_DCA                        0x00040000
+#define CPUID_FEAT2_SSE41              0x00080000
+#define CPUID_FEAT2_SSE42              0x00100000
+#define CPUID_FEAT2_X2APIC             0x00200000
+#define CPUID_FEAT2_MOVBE              0x00400000
+#define CPUID_FEAT2_POPCNT             0x00800000
+
+#define CPUID_FEAT2_AES                        0x02000000
+#define CPUID_FEAT2_XSAVE              0x04000000
+#define CPUID_FEAT2_OSXSAVE            0x08000000
+#define CPUID_FEAT2_AVX                        0x10000000
+#define CPUID_FEAT2_F16C               0x20000000
+#define CPUID_FEAT2_RDRAND             0x40000000
+
+int read_cpuid(struct cpuid_info *info);
+void print_cpuid(struct cpuid_info *info);
+
+#endif /* CPUID_H_ */
diff --git a/src/cpuid_s.asm b/src/cpuid_s.asm
new file mode 100644 (file)
index 0000000..b936168
--- /dev/null
@@ -0,0 +1,132 @@
+       section .text
+       bits 32
+; foo_ are watcom functions, _foo are djgpp functions
+
+F_ID equ 0x200000
+
+       global read_cpuid
+       global _read_cpuid
+       global read_cpuid_
+read_cpuid_:
+       push eax
+       call check_cpuid
+       pop eax
+       jnc read_cpuid_nocheck
+       mov eax, -1
+       ret
+
+_read_cpuid:
+read_cpuid:
+       call check_cpuid
+       mov eax, [esp + 4]
+       jnc read_cpuid_nocheck
+       mov eax, -1
+       ret
+
+       ; determine if cpuid is available. avail: cf=0, not avail: cf=1
+check_cpuid:
+       pushf
+       pop eax
+       mov edx, eax    ; keep a copy of the original eflags in edx
+       xor eax, F_ID
+       push eax
+       popf
+       pushf
+       pop eax
+       clc
+       cmp eax, edx
+       jnz .noerr
+       stc
+.noerr:        ret
+
+       ; enter with the cpuid_info structure pointer in eax
+read_cpuid_nocheck:
+       push ebp
+       mov ebp, esp
+       push ebx
+       push edi
+       push esi
+       push eax        ; save the original struct pointer
+       sub esp, 8
+       mov edi, eax    ; struct pointer -> edi
+
+       ; clear struct
+       cld
+       push edi
+       mov ecx, (32+48)/4
+       xor eax, eax
+       rep stosd
+       pop edi
+
+       xor eax, eax
+       mov [esp], eax  ; current index
+       cpuid
+
+       mov [edi], eax          ; maxidx
+       ; clamp to the size of our cpuid_info structure
+       cmp eax, 1
+       jbe .skipclamp
+       mov eax, 1
+.skipclamp:
+       mov [esp + 4], eax      ; maximum index
+
+       mov [edi + 4], ebx      ; vendor name
+       mov [edi + 8], edx
+       mov [edi + 12], ecx
+       add edi, 16
+
+.loop: mov eax, [esp]
+       inc eax
+       cmp eax, [esp + 4]
+       ja .loopend
+       mov [esp], eax
+       cpuid
+       mov [edi], eax
+       mov [edi + 4], ebx
+       mov [edi + 8], edx
+       mov [edi + 12], ecx
+       add edi, 16
+       jmp .loop
+.loopend:
+       ; try to retrieve the brand string (avail on P4 or newer)
+       mov eax, 80000000h
+       cpuid
+       test eax, 80000000h
+       jz .done        ; no extended cpuid functions
+       cmp eax, 80000004h
+       jb .done        ; no brand string available
+
+       ; brand string available
+       mov esi, esp            ; save esp to esi
+       mov esp, [esp + 8]      ; esp <- original struct pointer
+       add esp, 32+48          ; offset to end of brandstr
+       mov eax, 80000004h
+       cpuid
+       push edx
+       push ecx
+       push ebx
+       push eax
+       mov eax, 80000003h
+       cpuid
+       push edx
+       push ecx
+       push ebx
+       push eax
+       mov eax, 80000002h
+       cpuid
+       push edx
+       push ecx
+       push ebx
+       push eax
+       mov esp, esi    ; done restore esp
+
+.done: add esp, 8
+       pop eax
+       pop esi
+       pop edi
+       pop ebx
+       pop ebp
+       xor eax, eax
+       ret
+       
+; vi:ft=nasm:
diff --git a/src/darray.c b/src/darray.c
new file mode 100644 (file)
index 0000000..66c0715
--- /dev/null
@@ -0,0 +1,122 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "darray.h"
+#include "util.h"
+
+
+/* The array descriptor keeps auxilliary information needed to manipulate
+ * the dynamic array. It's allocated adjacent to the array buffer.
+ */
+struct arrdesc {
+       int nelem, szelem;
+       int max_elem;
+       int bufsz;      /* not including the descriptor */
+};
+
+#define DESC(x)                ((struct arrdesc*)((char*)(x) - sizeof(struct arrdesc)))
+
+void *darr_alloc(int elem, int szelem)
+{
+       struct arrdesc *desc;
+
+       desc = malloc_nf(elem * szelem + sizeof *desc);
+       desc->nelem = desc->max_elem = elem;
+       desc->szelem = szelem;
+       desc->bufsz = elem * szelem;
+       return (char*)desc + sizeof *desc;
+}
+
+void darr_free(void *da)
+{
+       if(da) {
+               free(DESC(da));
+       }
+}
+
+void *darr_resize_impl(void *da, int elem)
+{
+       int newsz;
+       struct arrdesc *desc;
+
+       if(!da) return 0;
+       desc = DESC(da);
+
+       newsz = desc->szelem * elem;
+       desc = realloc_nf(desc, newsz + sizeof *desc);
+
+       desc->nelem = desc->max_elem = elem;
+       desc->bufsz = newsz;
+       return (char*)desc + sizeof *desc;
+}
+
+int darr_empty(void *da)
+{
+       return DESC(da)->nelem ? 0 : 1;
+}
+
+int darr_size(void *da)
+{
+       return DESC(da)->nelem;
+}
+
+
+void *darr_clear_impl(void *da)
+{
+       return darr_resize_impl(da, 0);
+}
+
+/* stack semantics */
+void *darr_push_impl(void *da, void *item)
+{
+       struct arrdesc *desc;
+       int nelem;
+
+       desc = DESC(da);
+       nelem = desc->nelem;
+
+       if(nelem >= desc->max_elem) {
+               /* need to resize */
+               int newsz = desc->max_elem ? desc->max_elem * 2 : 1;
+
+               da = darr_resize_impl(da, newsz);
+               desc = DESC(da);
+               desc->nelem = nelem;
+       }
+
+       if(item) {
+               memcpy((char*)da + desc->nelem * desc->szelem, item, desc->szelem);
+       }
+       desc->nelem++;
+       return da;
+}
+
+void *darr_pop_impl(void *da)
+{
+       struct arrdesc *desc;
+       int nelem;
+
+       desc = DESC(da);
+       nelem = desc->nelem;
+
+       if(!nelem) return da;
+
+       if(nelem <= desc->max_elem / 3) {
+               /* reclaim space */
+               int newsz = desc->max_elem / 2;
+
+               da = darr_resize_impl(da, newsz);
+               desc = DESC(da);
+               desc->nelem = nelem;
+       }
+       desc->nelem--;
+
+       return da;
+}
+
+void *darr_finalize(void *da)
+{
+       struct arrdesc *desc = DESC(da);
+       memmove(desc, da, desc->bufsz);
+       return desc;
+}
diff --git a/src/darray.h b/src/darray.h
new file mode 100644 (file)
index 0000000..b9a7051
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef DYNAMIC_ARRAY_H_
+#define DYNAMIC_ARRAY_H_
+
+void *darr_alloc(int elem, int szelem);
+void darr_free(void *da);
+void *darr_resize_impl(void *da, int elem);
+#define darr_resize(da, elem)  do { (da) = darr_resize_impl(da, elem); } while(0)
+
+int darr_empty(void *da);
+int darr_size(void *da);
+
+void *darr_clear_impl(void *da);
+#define darr_clear(da)                 do { (da) = darr_clear_impl(da); } while(0)
+
+/* stack semantics */
+void *darr_push_impl(void *da, void *item);
+#define darr_push(da, item)            do { (da) = darr_push_impl(da, item); } while(0)
+void *darr_pop_impl(void *da);
+#define darr_pop(da)                   do { (da) = darr_pop_impl(da); } while(0)
+
+/* Finalize the array. No more resizing is possible after this call.
+ * Use free() instead of dynarr_free() to deallocate a finalized array.
+ * Returns pointer to the finalized array.
+ * Complexity: O(n)
+ */
+void *darr_finalize(void *da);
+
+/* utility macros to push characters to a string. assumes and maintains
+ * the invariant that the last element is always a zero
+ */
+#define darr_strpush(da, c) \
+       do { \
+               char cnull = 0, ch = (char)(c); \
+               (da) = dynarr_pop_impl(da); \
+               (da) = dynarr_push_impl((da), &ch); \
+               (da) = dynarr_push_impl((da), &cnull); \
+       } while(0)
+
+#define darr_strpop(da) \
+       do { \
+               char cnull = 0; \
+               (da) = dynarr_pop_impl(da); \
+               (da) = dynarr_pop_impl(da); \
+               (da) = dynarr_push_impl((da), &cnull); \
+       } while(0)
+
+
+#endif /* DYNAMIC_ARRAY_H_ */
index f9d4900..2479c42 100644 (file)
@@ -17,7 +17,7 @@
 #define MOUSE_TIMEOUT  1200
 
 #define GUARD_XPAD     0
-#define GUARD_YPAD     32
+#define GUARD_YPAD     64
 
 int fb_width, fb_height, fb_bpp, fb_scan_size;
 float fb_aspect;
@@ -42,10 +42,21 @@ static int con_active;
 
 extern uint16_t loading_pixels[];      /* data.asm */
 
-
 int demo_init(int argc, char **argv)
 {
-       struct screen *scr;
+       if(demo_init1(argc, argv) == -1) {
+               return -1;
+       }
+       if(demo_init2() == -1) {
+               return -1;
+       }
+       return 0;
+}
+
+static struct screen *scr;
+
+int demo_init1(int argc, char **argv)
+{
        char *env;
 
        if(load_config("demo.cfg") == -1) {
@@ -57,13 +68,11 @@ int demo_init(int argc, char **argv)
        if(parse_args(argc, argv) == -1) {
                return -1;
        }
+       return 0;
+}
 
-       /* reuse the loading image as our back buffer.
-        * adjust fb_pixels to leave 4 pixels guard band top/bottom. We have enough
-        * space since the loading image is 8 pixels taller.
-        */
-       fb_pixels = loading_pixels + 320 * 4;
-
+int demo_init2(void)
+{
        con_init();
        initFpsFonts();
 
@@ -81,6 +90,7 @@ int demo_init(int argc, char **argv)
        if(scr_init() == -1) {
                return -1;
        }
+
        if(opt.start_scr) {
                scr = scr_lookup(opt.start_scr);
        } else {
index de0654b..af4870f 100644 (file)
@@ -54,6 +54,8 @@ enum {
 extern float sball_matrix[16];
 
 int demo_init(int argc, char **argv);
+int demo_init1(int argc, char **argv);
+int demo_init2(void);
 void demo_cleanup(void);
 
 int demo_resizefb(int width, int height, int bpp);
@@ -66,6 +68,7 @@ void demo_keyboard(int key, int press);
 
 /* defined in main_*.c */
 void demo_quit(void);
+void demo_abort(void);
 unsigned long get_msec(void);
 void set_palette(int idx, int r, int g, int b);
 
index 74376c6..2e6f376 100644 (file)
@@ -1,5 +1,6 @@
-#ifndef NO_SOUND
 #include <stdio.h>
+
+#ifndef NO_SOUND
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
index 71138b6..e8a6950 100644 (file)
@@ -29,6 +29,17 @@ struct dpmi_regs {
 } PACKED;
 #pragma pack (pop)
 
+enum {
+       FLAGS_CF        = 0x000001,
+       FLAGS_PF        = 0x000004,
+       FLAGS_ZF        = 0x000040,
+       FLAGS_SF        = 0x000080,
+       FLAGS_IF        = 0x000020,
+       FLAGS_DF        = 0x000040,
+       FLAGS_VM        = 0x020000,
+       FLAGS_ID        = 0x200000,
+};
+
 uint16_t dpmi_alloc(unsigned int par, uint16_t *sel);
 void dpmi_free(uint16_t sel);
 void dpmi_int(int inum, struct dpmi_regs *regs);
diff --git a/src/dos/dosutil.h b/src/dos/dosutil.h
new file mode 100644 (file)
index 0000000..4e4c8c3
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef DOSUTIL_H_
+#define DOSUTIL_H_
+
+#include <dos.h>
+#include <conio.h>
+
+#ifdef __DJGPP__
+#include <pc.h>
+
+#define outp(p, v)     outportb(p, v)
+#define outpw(p, v)    outportw(p, v)
+#define outpd(p, v)    outportl(p, v)
+
+#define inp(p)         inportb(p)
+#define inpw(p)                inportw(p)
+#define inpd(p)                inportl(p)
+#endif
+
+#endif /* DOSUTIL_H_ */
index 48b5c20..2f67bad 100644 (file)
@@ -1,12 +1,20 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <dos.h>
 #include "demo.h"
 #include "cdpmi.h"
 #include "gfx.h"
 #include "vbe.h"
 #include "vga.h"
 #include "util.h"
+#include "cpuid.h"
+
+#ifdef __DJGPP__
+#define VMEM_PTR       ((void*)(0xa0000 + __djgpp_conventional_base))
+#else
+#define VMEM_PTR       ((void*)0xa0000)
+#endif
 
 #define SAME_BPP(a, b) \
        ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \
@@ -18,6 +26,10 @@ static void blit_frame_lfb(void *pixels, int vsync);
 static void blit_frame_banked(void *pixels, int vsync);
 static uint32_t calc_mask(int sz, int pos);
 
+static void enable_wrcomb(uint32_t addr, int len);
+static const char *mtrr_type_name(int type);
+static void print_mtrr(void);
+
 static struct video_mode *vmodes;
 static int num_vmodes;
 
@@ -85,17 +97,13 @@ int init_video(void)
                        vmptr->rmask = calc_mask(minf.rsize, minf.rpos);
                        vmptr->gmask = calc_mask(minf.gsize, minf.gpos);
                        vmptr->bmask = calc_mask(minf.bsize, minf.bpos);
-                       vmptr->bpp = vmptr->rbits + vmptr->gbits + vmptr->bbits;
+                       /*vmptr->bpp = vmptr->rbits + vmptr->gbits + vmptr->bbits;*/
                }
                if(minf.attr & VBE_ATTR_LFB) {
                        vmptr->fb_addr = minf.fb_addr;
-               } else {
-                       vmptr->bank_size = (uint32_t)minf.bank_size * 1024;
-                       if(!vmptr->bank_size) {
-                               vmptr->bank_size = 65536;
-                       }
                }
                vmptr->max_pages = minf.num_img_pages;
+               vmptr->win_gran = minf.win_gran;
 
                printf("%04x: ", vbe.modes[i]);
                vbe_print_mode_info(stdout, &minf);
@@ -184,7 +192,7 @@ void *set_video_mode(int idx, int nbuf)
        }
 
        /* unmap previous video memory mapping, if there was one (switching modes) */
-       if(vpgaddr[0] && vpgaddr[0] != (void*)0xa0000) {
+       if(vpgaddr[0] && vpgaddr[0] != VMEM_PTR) {
                dpmi_munmap(vpgaddr[0]);
                vpgaddr[0] = vpgaddr[1] = 0;
        }
@@ -192,12 +200,19 @@ void *set_video_mode(int idx, int nbuf)
        curmode = vm;
        if(nbuf < 1) nbuf = 1;
        if(nbuf > 2) nbuf = 2;
-       pgcount = nbuf > vm->max_pages ? vm->max_pages : nbuf;
+       pgcount = nbuf > vm->max_pages + 1 ? vm->max_pages + 1 : nbuf;
        pgsize = vm->ysz * vm->pitch;
        fbsize = pgcount * pgsize;
 
+       if(vm->bpp > 8) {
+               printf("rgb mask: %x %x %x\n", (unsigned int)vm->rmask,
+                               (unsigned int)vm->gmask, (unsigned int)vm->bmask);
+               printf("rgb shift: %d %d %d\n", vm->rshift, vm->gshift, vm->bshift);
+       }
        printf("pgcount: %d, pgsize: %d, fbsize: %d\n", pgcount, pgsize, fbsize);
-       printf("phys addr: %p\n", (void*)vm->fb_addr);
+       if(vm->fb_addr) {
+               printf("phys addr: %p\n", (void*)vm->fb_addr);
+       }
        fflush(stdout);
 
        if(vm->fb_addr) {
@@ -221,11 +236,48 @@ void *set_video_mode(int idx, int nbuf)
 
                blit_frame = blit_frame_lfb;
 
+               /* only attempt to set up write combining if the CPU we're running on
+                * supports memory type range registers, and we're running on ring 0
+                */
+               if(CPU_HAVE_MTRR) {
+                       int cpl = get_cpl();
+                       if(cpl > 0) {
+                               fprintf(stderr, "Can't set framebuffer range to write-combining, running in ring %d\n", cpl);
+                       } else {
+                               uint32_t len = (uint32_t)vbe.vmem_blk << 16;
+
+                               /* if vmem_blk is 0 or if the reported size is absurd (more than
+                                * 256mb), just use the framebuffer size for this mode to setup the
+                                * mtrr
+                                */
+                               if(!len || len > 0x10000000) {
+                                       printf("reported vmem too large or overflowed, using fbsize for wrcomb setup\n");
+                                       len = fbsize;
+                               }
+                               print_mtrr();
+                               enable_wrcomb(vm->fb_addr, len);
+                       }
+               }
+
        } else {
-               vpgaddr[0] = (void*)0xa0000;
+               vpgaddr[0] = VMEM_PTR;
                vpgaddr[1] = 0;
 
                blit_frame = blit_frame_banked;
+
+               /* calculate window granularity shift */
+               vm->win_gran_shift = 0;
+               vm->win_64k_step = 1;
+               if(vm->win_gran > 0 && vm->win_gran < 64) {
+                       int gran = vm->win_gran;
+                       while(gran < 64) {
+                               vm->win_gran_shift++;
+                               gran <<= 1;
+                       }
+                       vm->win_64k_step = 1 << vm->win_gran_shift;
+               }
+
+               printf("granularity: %dk (step: %d)\n", vm->win_gran, vm->win_64k_step);
        }
 
        /* allocate main memory framebuffer */
@@ -236,13 +288,14 @@ void *set_video_mode(int idx, int nbuf)
                return 0;
        }
 
+       fflush(stdout);
        return vpgaddr[0];
 }
 
 int set_text_mode(void)
 {
        /* unmap previous video memory mapping, if there was one (switching modes) */
-       if(vpgaddr[0] && vpgaddr[0] != (void*)0xa0000) {
+       if(vpgaddr[0] && vpgaddr[0] != VMEM_PTR) {
                dpmi_munmap(vpgaddr[0]);
                vpgaddr[0] = vpgaddr[1] = 0;
        }
@@ -277,8 +330,7 @@ static void blit_frame_lfb(void *pixels, int vsync)
 
 static void blit_frame_banked(void *pixels, int vsync)
 {
-       int i, sz, offs;
-       unsigned int pending;
+       int sz, offs, pending;
        unsigned char *pptr = pixels;
 
        demo_post_draw(pixels);
@@ -289,23 +341,168 @@ static void blit_frame_banked(void *pixels, int vsync)
        offs = 0;
        pending = pgsize;
        while(pending > 0) {
-               sz = pending > curmode->bank_size ? curmode->bank_size : pending;
-               //memcpy64((void*)0xa0000, pptr, sz >> 3);
-               memcpy((void*)0xa0000, pptr, sz);
+               sz = pending > 65536 ? 65536 : pending;
+               /*memcpy64(VMEM_PTR, pptr, sz >> 3);*/
+               memcpy(VMEM_PTR, pptr, sz);
                pptr += sz;
                pending -= sz;
-               vbe_setwin(0, ++offs);
+               offs += curmode->win_64k_step;
+               vbe_setwin(0, offs);
        }
-
        vbe_setwin(0, 0);
 }
 
 static uint32_t calc_mask(int sz, int pos)
 {
-       int i;
        uint32_t mask = 0;
        while(sz-- > 0) {
                mask = (mask << 1) | 1;
        }
        return mask << pos;
 }
+
+#define MSR_MTRRCAP                    0xfe
+#define MSR_MTRRDEFTYPE                0x2ff
+#define MSR_MTRRBASE(x)                (0x200 | ((x) << 1))
+#define MSR_MTRRMASK(x)                (0x201 | ((x) << 1))
+#define MTRRDEF_EN                     0x800
+#define MTRRCAP_HAVE_WC                0x400
+#define MTRRMASK_VALID         0x800
+
+#define MTRR_WC                                1
+
+static int get_page_memtype(uint32_t addr, int num_ranges)
+{
+       int i;
+       uint32_t rlow, rhigh;
+       uint32_t base, mask;
+
+       for(i=0; i<num_ranges; i++) {
+               get_msr(MSR_MTRRMASK(i), &rlow, &rhigh);
+               if(!(rlow & MTRRMASK_VALID)) {
+                       continue;
+               }
+               mask = rlow & 0xfffff000;
+
+               get_msr(MSR_MTRRBASE(i), &rlow, &rhigh);
+               base = rlow & 0xfffff000;
+
+               if((addr & mask) == (base & mask)) {
+                       return rlow & 0xff;
+               }
+       }
+
+       get_msr(MSR_MTRRDEFTYPE, &rlow, &rhigh);
+       return rlow & 0xff;
+}
+
+static int check_wrcomb_enabled(uint32_t addr, int len, int num_ranges)
+{
+       while(len > 0) {
+               if(get_page_memtype(addr, num_ranges) != MTRR_WC) {
+                       return 0;
+               }
+               addr += 4096;
+               len -= 4096;
+       }
+       return 1;
+}
+
+static int alloc_mtrr(int num_ranges)
+{
+       int i;
+       uint32_t rlow, rhigh;
+
+       for(i=0; i<num_ranges; i++) {
+               get_msr(MSR_MTRRMASK(i), &rlow, &rhigh);
+               if(!(rlow & MTRRMASK_VALID)) {
+                       return i;
+               }
+       }
+       return -1;
+}
+
+static void enable_wrcomb(uint32_t addr, int len)
+{
+       int num_ranges, mtrr;
+       uint32_t rlow, rhigh;
+       uint32_t def, mask;
+
+       if(len <= 0 || (addr | (uint32_t)len) & 0xfff) {
+               fprintf(stderr, "failed to enable write combining, unaligned range: %p/%x\n",
+                               (void*)addr, (unsigned int)len);
+               return;
+       }
+
+       get_msr(MSR_MTRRCAP, &rlow, &rhigh);
+       num_ranges = rlow & 0xff;
+
+       printf("enable_wrcomb: addr=%p len=%x\n", (void*)addr, (unsigned int)len);
+
+       if(!(rlow & MTRRCAP_HAVE_WC)) {
+               fprintf(stderr, "failed to enable write combining, processor doesn't support it\n");
+               return;
+       }
+
+       if(check_wrcomb_enabled(addr, len, num_ranges)) {
+               return;
+       }
+
+       if((mtrr = alloc_mtrr(num_ranges)) == -1) {
+               fprintf(stderr, "failed to enable write combining, no free MTRRs\n");
+               return;
+       }
+
+       mask = len - 1;
+       mask |= mask >> 1;
+       mask |= mask >> 2;
+       mask |= mask >> 4;
+       mask |= mask >> 8;
+       mask |= mask >> 16;
+       mask = ~mask & 0xfffff000;
+
+       printf("  ... mask: %08x\n", (unsigned int)mask);
+
+       _disable();
+       get_msr(MSR_MTRRDEFTYPE, &def, &rhigh);
+       set_msr(MSR_MTRRDEFTYPE, def & ~MTRRDEF_EN, rhigh);
+
+       set_msr(MSR_MTRRBASE(mtrr), addr | MTRR_WC, 0);
+       set_msr(MSR_MTRRMASK(mtrr), mask | MTRRMASK_VALID, 0);
+
+       set_msr(MSR_MTRRDEFTYPE, def | MTRRDEF_EN, 0);
+       _enable();
+}
+
+static const char *mtrr_names[] = { "N/A", "W C", "N/A", "N/A", "W T", "W P", "W B" };
+
+static const char *mtrr_type_name(int type)
+{
+       if(type < 0 || type >= sizeof mtrr_names / sizeof *mtrr_names) {
+               return mtrr_names[0];
+       }
+       return mtrr_names[type];
+}
+
+static void print_mtrr(void)
+{
+       int i, num_ranges;
+       uint32_t rlow, rhigh, base, mask;
+
+       get_msr(MSR_MTRRCAP, &rlow, &rhigh);
+       num_ranges = rlow & 0xff;
+
+       for(i=0; i<num_ranges; i++) {
+               get_msr(MSR_MTRRBASE(i), &base, &rhigh);
+               get_msr(MSR_MTRRMASK(i), &mask, &rhigh);
+
+               if(mask & MTRRMASK_VALID) {
+                       printf("mtrr%d: base %p, mask %08x type %s\n", i, (void*)(base & 0xfffff000),
+                                       (unsigned int)(mask & 0xfffff000), mtrr_type_name(base & 0xff));
+               } else {
+                       printf("mtrr%d unused (%08x/%08x)\n", i, (unsigned int)base,
+                                       (unsigned int)mask);
+               }
+       }
+       fflush(stdout);
+}
index 1f5d90c..4724f41 100644 (file)
@@ -11,7 +11,7 @@ struct video_mode {
        uint32_t rmask, gmask, bmask;
        uint32_t fb_addr;
        short max_pages;
-       uint32_t bank_size;
+       short win_gran, win_gran_shift, win_64k_step;
 };
 
 #ifdef __cplusplus
index ac200b3..e35cb7b 100644 (file)
@@ -36,6 +36,7 @@ along with the program. If not, see <http://www.gnu.org/licenses/>
 #include "keyb.h"
 #include "scancode.h"
 #include "inttypes.h"
+#include "dosutil.h"
 
 #define KB_INTR                0x9
 #define KB_PORT                0x60
@@ -55,9 +56,6 @@ static void (INTERRUPT *prev_handler)();
 
 #define DONE_INIT prev_intr.pm_offset
 static _go32_dpmi_seginfo intr, prev_intr;
-
-#define outp(p, v)     outportb(p, v)
-#define inp(p) inportb(p)
 #endif
 
 static void INTERRUPT kbintr();
index 70489ad..1976770 100644 (file)
@@ -5,17 +5,64 @@
 #include <fcntl.h>
 #include "logger.h"
 
+static int logfd = -1, orig_fd1 = -1;
+
 int init_logger(const char *fname)
 {
-       int fd;
-       if((fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
+       if(logfd != -1) return -1;
+
+       if((logfd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
                fprintf(stderr, "init_logger: failed to open %s: %s\n", fname, strerror(errno));
                return -1;
        }
 
+       orig_fd1 = dup(1);
        close(1);
        close(2);
-       dup(fd);
-       dup(fd);
+       dup(logfd);
+       dup(logfd);
+       return 0;
+}
+
+void stop_logger(void)
+{
+       if(logfd >= 0) {
+               close(logfd);
+               logfd = -1;
+       }
+       if(orig_fd1 >= 0) {
+               close(1);
+               close(2);
+               dup(orig_fd1);
+               dup(orig_fd1);
+               orig_fd1 = -1;
+       }
+}
+
+int print_tail(const char *fname)
+{
+       FILE *fp;
+       char buf[64];
+       long lineoffs[16];
+       int wr, rd, c;
+
+       if(!(fp = fopen(fname, "r"))) {
+               return -1;
+       }
+       wr = rd = 0;
+       lineoffs[wr++] = 0;
+       while(fgets(buf, sizeof buf, fp)) {
+               lineoffs[wr] = ftell(fp);
+               wr = (wr + 1) & 0xf;
+               if(wr == rd) {
+                       rd = (rd + 1) & 0xf;
+               }
+       }
+
+       fseek(fp, lineoffs[rd], SEEK_SET);
+       while((c = fgetc(fp)) != -1) {
+               fputc(c, stdout);
+       }
+       fclose(fp);
        return 0;
 }
index 9ef9a85..56f6be7 100644 (file)
@@ -6,6 +6,9 @@ extern "C" {
 #endif
 
 int init_logger(const char *fname);
+void stop_logger(void);
+
+int print_tail(const char *fname);
 
 #ifdef __cplusplus
 }
index 566d47e..7f67e85 100644 (file)
@@ -8,8 +8,10 @@
 #include "logger.h"
 #include "cdpmi.h"
 #include "audio.h"
+#include "mouse.h"
 #include "sball.h"
 #include "vmath.h"
+#include "cpuid.h"
 
 static int handle_sball_event(sball_event *ev);
 static void recalc_sball_matrix(float *xform);
@@ -40,6 +42,16 @@ int main(int argc, char **argv)
 
        init_logger("demo.log");
 
+#ifdef __WATCOMC__
+       printf("watcom build\n");
+#elif defined(__DJGPP__)
+       printf("djgpp build\n");
+#endif
+
+       if(read_cpuid(&cpuid) == 0) {
+               print_cpuid(&cpuid);
+       }
+
        /* au_init needs to be called early, before init_timer, and also before
         * we enter graphics mode, to use the midas configuration tool if necessary
         */
@@ -50,6 +62,10 @@ int main(int argc, char **argv)
        init_timer(100);
        kb_init(32);
 
+       if(init_pci() != -1) {
+               /* TODO detect and initialize S3 virge */
+       }
+
        if(init_video() == -1) {
                return 1;
        }
@@ -119,6 +135,15 @@ void demo_quit(void)
        quit = 1;
 }
 
+void demo_abort(void)
+{
+       set_text_mode();
+       stop_logger();
+       printf("demo_abort called. see demo.log for details. Last lines:\n\n");
+       print_tail("demo.log");
+       abort();
+}
+
 #define TX(ev) ((ev)->motion.motion[0])
 #define TY(ev) ((ev)->motion.motion[1])
 #define TZ(ev) ((ev)->motion.motion[2])
diff --git a/src/dos/pci.c b/src/dos/pci.c
new file mode 100644 (file)
index 0000000..19a2e4d
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+S3 Virge driver hack
+Copyright (C) 2021 John Tsiombikas <nuclear@member.fsf.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <conio.h>
+#include "dosutil.h"
+#include "inttypes.h"
+#include "pci.h"
+#include "cdpmi.h"
+
+#define CONFIG_ADDR_PORT       0xcf8
+#define CONFIG_DATA_PORT       0xcfc
+
+#define ADDR_ENABLE            0x80000000
+#define ADDR_BUSID(x)  (((uint32_t)(x) & 0xff) << 16)
+#define ADDR_DEVID(x)  (((uint32_t)(x) & 0x1f) << 11)
+#define ADDR_FUNC(x)   (((uint32_t)(x) & 3) << 8)
+
+/* signature returned in edx by the PCI BIOS present function: FOURCC "PCI " */
+#define PCI_SIG                0x20494350
+
+#define TYPE_MULTIFUNC 0x80
+
+
+static struct pci_device *pcidev;
+static int num_pcidevs, max_pcidevs;
+
+
+static int enum_bus(int busid);
+static int enum_dev(int busid, int dev);
+static int read_dev_info(struct pci_config_data *res, int bus, int dev, int func);
+static void print_dev_info(struct pci_config_data *info, int bus, int dev, int func);
+
+static uint32_t cfg_read32_m1(int bus, int dev, int func, int reg);
+static uint32_t cfg_read32_m2(int bus, int dev, int func, int reg);
+static const char *class_str(int cc);
+static const char *subclass_str(int cc, int sub);
+
+static uint32_t (*cfg_read32)(int, int, int, int);
+
+static void clear_devices(void);
+static void add_device(struct pci_device *dev);
+
+int init_pci(void)
+{
+       int i, count = 0;
+       struct dpmi_regs regs = {0};
+
+       clear_devices();
+
+       regs.eax = 0xb101;
+       dpmi_int(0x1a, &regs);
+
+       /* PCI BIOS present if CF=0, AH=0, and EDX has the "PCI " sig FOURCC */
+       if((regs.flags & FLAGS_CF)  || (regs.eax & 0xff00) || regs.edx != PCI_SIG) {
+               fprintf(stderr, "No PCI BIOS present\n");
+               return -1;
+       }
+
+       printf("PCI BIOS v%x.%x found\n", (regs.ebx & 0xff00) >> 8, regs.ebx & 0xff);
+       if(regs.eax & 1) {
+               cfg_read32 = cfg_read32_m1;
+       } else {
+               if(!(regs.eax & 2)) {
+                       fprintf(stderr, "Failed to find supported PCI mess mechanism\n");
+                       return -1;
+               }
+               printf("PCI mess mechanism #1 unsupported, falling back to mechanism #2\n");
+               cfg_read32 = cfg_read32_m2;
+       }
+
+       for(i=0; i<256; i++) {
+               count += enum_bus(i);
+       }
+       printf("found %d PCI devices\n\n", count);
+       return 0;
+}
+
+static int enum_bus(int busid)
+{
+       int i, count = 0;
+
+       for(i=0; i<32; i++) {
+               count += enum_dev(busid, i);
+       }
+
+       return count;
+}
+
+static int enum_dev(int busid, int devid)
+{
+       int i, count;
+       struct pci_device dev;
+
+       dev.bus = busid;
+       dev.dev = devid;
+       dev.func = 0;
+
+       /* vendor id ffff is invalid */
+       if((cfg_read32(busid, devid, 0, 0) & 0xffff) == 0xffff) {
+               return 0;
+       }
+       if(read_dev_info(&dev.cfg, busid, devid, 0) == -1) {
+               return 0;
+       }
+       print_dev_info(&dev.cfg, busid, devid, 0);
+       add_device(&dev);
+
+       count = 1;
+
+       if(dev.cfg.hdr_type & TYPE_MULTIFUNC) {
+               for(i=1; i<8; i++) {
+                       if(read_dev_info(&dev.cfg, busid, devid, i) == -1) {
+                               continue;
+                       }
+                       print_dev_info(&dev.cfg, busid, devid, i);
+                       dev.func = i;
+                       add_device(&dev);
+                       count++;
+               }
+       }
+       return count;
+}
+
+static int read_dev_info(struct pci_config_data *res, int bus, int dev, int func)
+{
+       int i;
+       uint32_t *ptr = (uint32_t*)res;
+
+       *ptr++ = cfg_read32(bus, dev, func, 0);
+       if(res->vendor == 0xffff) {
+               return -1;
+       }
+
+       for(i=1; i<16; i++) {
+               *ptr++ = cfg_read32(bus, dev, func, i * 4);
+       }
+       return 0;
+}
+
+static void print_dev_info(struct pci_config_data *info, int bus, int dev, int func)
+{
+       printf("- (%d:%d,%d) Device %04x:%04x: ", bus, dev, func, info->vendor, info->device);
+       printf("\"%s\" (%d) - %s-func\n", class_str(info->class), info->class,
+                       info->hdr_type & TYPE_MULTIFUNC ? "multi" : "single");
+       printf("    subclass: \"%s\" (%d), iface: %d\n", subclass_str(info->class, info->subclass),
+                       info->subclass, info->iface);
+}
+
+static uint32_t cfg_read32_m1(int bus, int dev, int func, int reg)
+{
+       uint32_t addr = ADDR_ENABLE | ADDR_BUSID(bus) | ADDR_DEVID(dev) |
+               ADDR_FUNC(func) | reg;
+
+       outpd(CONFIG_ADDR_PORT, addr);
+       return inpd(CONFIG_DATA_PORT);
+}
+
+static uint32_t cfg_read32_m2(int bus, int dev, int func, int reg)
+{
+       fprintf(stderr, "BUG: PCI mess mechanism #2 not implemented yet!");
+       demo_abort();
+       return 0;
+}
+
+static const char *class_names[] = {
+       "unknown",
+       "mass storage controller",
+       "network controller",
+       "display controller",
+       "multimedia device",
+       "memory controller",
+       "bridge device",
+       "simple communication controller",
+       "base system peripheral",
+       "input device",
+       "docking station",
+       "processor",
+       "serial bus controller",
+       "wireless controller",
+       "intelligent I/O controller",
+       "satellite communication controller",
+       "encryption/decryption controller",
+       "data acquisition & signal processing controller"
+};
+
+static const char *class_mass_names[] = {
+       "SCSI bus controller",
+       "IDE controller",
+       "floppy disk controller",
+       "IPI bus controller",
+       "RAID controller"
+};
+
+static const char *class_net_names[] = {
+       "ethernet controller",
+       "token ring controller",
+       "FDDI controller",
+       "ATM controller",
+       "ISDN controller"
+};
+
+static const char *class_disp_names[] = {
+       "VGA-compatible controller",
+       "XGA controller",
+       "3D controller"
+};
+
+static const char *class_mm_names[] = {
+       "video device",
+       "audio device",
+       "telephony device"
+};
+
+static const char *class_bridge_names[] = {
+       "host bridge",
+       "ISA bridge",
+       "EISA bridge",
+       "MCA bridge",
+       "PCI-to-PCI bridge",
+       "Subtractive decode PCI-to-PCI bridge",
+       "PCMCIA bridge",
+       "NuBus bridge",
+       "CardBus bridge",
+       "RACEway bridge"
+};
+
+static const char *class_comm_names[] = {
+       "serial controller",
+       "parallel/IEEE1284",
+       "multiport serial controller",
+       "modem"
+};
+
+static const char *class_base_names[] = {
+       "interrupt controller",
+       "DMA controller",
+       "timer",
+       "RTC",
+       "PCI hot-plug controller"
+};
+
+static const char *class_input_names[] = {
+       "keyboard controller",
+       "digitizer",
+       "mouse controller",
+       "scanner controller",
+       "gameport controller"
+};
+
+static const char *class_ser_names[] = {
+       "firewire",
+       "ACCESS.bus",
+       "SSA",
+       "USB",
+       "Fibre Channel",
+       "SMBus"
+};
+
+static const char *class_sat_names[] = {
+       "TV",
+       "audio",
+       "voice",
+       "data"
+};
+
+
+static const char *class_str(int cc)
+{
+       if(cc == 0xff) {
+               return "other";
+       }
+       if(cc >= 0x12) {
+               return "unknown";
+       }
+       return class_names[cc];
+}
+
+static const char *subclass_str(int cc, int sub)
+{
+       if(sub == 0x80) return "other";
+
+       switch(cc) {
+       case 0:
+               if(sub == 1) return "VGA-compatible device";
+               return "unknown";
+
+       case 1:
+               if(sub > 4) return "unknown";
+               return class_mass_names[sub];
+
+       case 2:
+               if(sub > 4) return "unknown";
+               return class_net_names[sub];
+
+       case 3:
+               if(sub > 2) return "unknown";
+               return class_disp_names[sub];
+
+       case 4:
+               if(sub > 2) return "unknown";
+               return class_mm_names[sub];
+
+       case 5:
+               if(sub == 0) return "RAM";
+               if(sub == 1) return "flash";
+               return "unknown";
+
+       case 6:
+               if(sub > 8) return "unknown";
+               return class_bridge_names[sub];
+
+       case 7:
+               if(sub > 3) return "unknown";
+               return class_comm_names[sub];
+
+       case 8:
+               if(sub > 4) return "unknown";
+               return class_base_names[sub];
+
+       case 9:
+               if(sub > 4) return "unknown";
+               return class_input_names[sub];
+
+       case 10:
+               if(sub == 0) return "generic docking station";
+               return "unknown";
+
+       case 11:
+               switch(sub) {
+               case 0: return "386";
+               case 1: return "486";
+               case 2: return "pentium";
+               case 0x10: return "alpha";
+               case 0x20: return "powerpc";
+               case 0x30: return "mips";
+               case 0x40: return "co-processor";
+               default:
+                       break;
+               }
+               return "unknown";
+
+       case 12:
+               if(sub > 5) return "unknown";
+               return class_ser_names[sub];
+
+       case 13:
+               if(sub == 0) return "irda controller";
+               if(sub == 1) return "IR controller";
+               if(sub == 0x10) return "RF controller";
+               return "unknonw";
+
+       case 15:
+               if(sub > 4) return "unknown";
+               return class_sat_names[sub];
+
+       case 16:
+               if(sub == 0) return "network & computing crypto";
+               if(sub == 1) return "entertainment crypto";
+               return "unknown";
+
+       case 17:
+               if(sub == 0) return "DPIO module";
+               return "unknown";
+
+       default:
+               break;
+       }
+       return "unknown";
+}
+
+static void clear_devices(void)
+{
+       free(pcidev);
+       pcidev = 0;
+       num_pcidevs = max_pcidevs = 0;
+}
+
+static void add_device(struct pci_device *dev)
+{
+       if(num_pcidevs >= max_pcidevs) {
+               void *newarr;
+               int newsz = max_pcidevs ? max_pcidevs << 1 : 8;
+
+               if(!(newarr = realloc(pcidev, newsz * sizeof *pcidev))) {
+                       fprintf(stderr, "failed to resize PCI device array (%d)\n", newsz);
+                       return;
+               }
+               pcidev = newarr;
+               max_pcidevs = newsz;
+       }
+
+       pcidev[num_pcidevs++] = *dev;
+}
+
+struct pci_device *find_pci_dev(uint16_t vendorid, uint16_t devid)
+{
+       int i;
+       for(i=0; i<num_pcidevs; i++) {
+               if(pcidev[i].cfg.vendor == vendorid && pcidev[i].cfg.device == devid) {
+                       return pcidev + i;
+               }
+       }
+       return 0;
+}
diff --git a/src/dos/pci.h b/src/dos/pci.h
new file mode 100644 (file)
index 0000000..6025831
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+S3 Virge driver hack
+Copyright (C) 2021 John Tsiombikas <nuclear@member.fsf.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef PCI_H_
+#define PCI_H_
+
+#include "inttypes.h"
+#include "util.h"
+
+#pragma pack (push, 1)
+struct pci_config_data {
+       uint16_t vendor, device;
+       uint16_t cmd, status;
+       uint8_t rev, iface, subclass, class;
+       uint8_t cacheline_size;
+       uint8_t latency_timer;
+       uint8_t hdr_type;
+       uint8_t bist;
+       uint32_t base_addr[6];
+       uint32_t cardbus_cis;
+       uint16_t subsys_vendor;
+       uint16_t subsys;
+       uint32_t rom_addr;
+       uint32_t reserved1, reserved2;
+       uint8_t intr_line, intr_pin;
+       uint8_t min_grant, max_latency;
+} PACKED;
+#pragma pop (push)
+
+struct pci_device {
+       int bus, dev, func;
+       struct pci_config_data cfg;
+};
+
+int init_pci(void);
+
+struct pci_device *find_pci_dev(uint16_t vendorid, uint16_t devid);
+
+#endif /* PCI_H_ */
index 7eb1fd9..6261f1b 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "sball.h"
 #include "inttypes.h"
+#include "dosutil.h"
 
 struct motion {
        int x, y, z;
@@ -142,9 +143,6 @@ static void (INTERRUPT *prev_recv_intr)(void);
 #define INTERRUPT
 
 static _go32_dpmi_seginfo intr, prev_intr;
-
-#define outp(port, val)        outportb(port, val)
-#define inp(port) inportb(port)
 #endif
 
 static void INTERRUPT recv_intr(void);
index 2440bd5..5492f0b 100644 (file)
@@ -22,6 +22,7 @@
 #include "pit8254.h"
 #include "inttypes.h"
 #include "util.h"
+#include "dosutil.h"
 
 #define PIT_TIMER_INTR 8
 #define DOS_TIMER_INTR 0x1c
@@ -45,8 +46,6 @@ static void (INTERRUPT *prev_timer_intr)();
 #define INTERRUPT
 
 static _go32_dpmi_seginfo intr, prev_intr;
-
-#define outp(p, v)     outportb(p, v)
 #endif
 
 static void INTERRUPT timer_irq();
index 05a5883..cb37ca1 100644 (file)
@@ -207,7 +207,7 @@ void vbe_print_mode_info(FILE *fp, struct vbe_mode_info *minf)
        if(minf->attr & VBE_ATTR_LFB) {
                fprintf(fp, " lfb@%lx", (unsigned long)minf->fb_addr);
        } else {
-               fprintf(fp, " %xkb/bank", (unsigned int)minf->bank_size);
+               fprintf(fp, " (%dk gran)", (int)minf->win_gran);
        }
 
        fprintf(fp, " [");
index c829684..f2f8142 100644 (file)
@@ -1,5 +1,11 @@
+#include <string.h>
 #include "vga.h"
+#include "vgaregs.h"
 #include "cdpmi.h"
+#include "dosutil.h"
+
+static void crtc_write(int reg, unsigned char val);
+static unsigned char crtc_read(int reg);
 
 int vga_setmode(int mode)
 {
@@ -9,3 +15,57 @@ int vga_setmode(int mode)
        dpmi_int(0x10, &regs);
        return 0;
 }
+
+static unsigned short crtc_modex_regs[] = {
+       0x0d06, /* vertical total */
+       0x3e07, /* vcount overflow bit */
+       0x4109, /* double-scan */
+       0xea10, /* vsync start */
+       0xac11, /* vsync end & protect */
+       0xdf12, /* vertical visible */
+       0x0014, /* no dword mode */
+       0xe715, /* vblank start */
+       0x0616, /* vblank end */
+       0xe317, /* byte mode */
+       0
+};
+
+int vga_setmodex(void)
+{
+       int i;
+       unsigned char val;
+
+       vga_setmode(0x13);
+
+       /* disable chain-4 (C4=0, O/E=1 (sequential), EM=1 (extmem), A/G=0 (gfx) */
+       outpw(VGA_SC_ADDR_PORT, VGA_SC_MEMMODE_REG | 0x0600);
+       /* pull reset low */
+       outpw(VGA_SC_ADDR_PORT, VGA_SC_RESET_REG | 0x0100);
+       /* 25mhz dot clock, 60hz scan */
+       outp(VGA_MISC_PORT, VGA_MISC_480 | VGA_MISC_PG1 | VGA_MISC_CLK25 |
+                       VGA_MISC_CPUEN | VGA_MISC_COLOR);
+       /* return reset high */
+       outpw(VGA_SC_ADDR_PORT, VGA_SC_RESET_REG | 0x0300);
+
+       /* disable CRTC write-protect */
+       crtc_write(CRTC_VRETEND_REG, crtc_read(CRTC_VRETEND_REG) & ~CRTC_VRETEND_PR);
+       /* change CRTC registers */
+       for(i=0; crtc_modex_regs[i]; i++) {
+               outpw(VGA_CRTC_PORT, crtc_modex_regs[i]);
+       }
+
+       vga_planemask(0xf);
+       memset(VGA_FBADDR, 3, 320 * 240 / 4);
+       return 0;
+}
+
+static void crtc_write(int reg, unsigned char val)
+{
+       outpw(VGA_CRTC_ADDR_PORT, reg | ((unsigned int)val << 8));
+}
+
+static unsigned char crtc_read(int reg)
+{
+       outp(VGA_CRTC_ADDR_PORT, reg);
+       return inp(VGA_CRTC_DATA_PORT);
+}
index c6d7070..99738eb 100644 (file)
@@ -2,8 +2,17 @@
 #define VGA_H_
 
 #include "inttypes.h"
+#include "dosutil.h"
+#include "cdpmi.h"
+#include "vgaregs.h"
+
+#define VGA_FBADDR     ((void*)phys_to_virt(0xa0000))
 
 int vga_setmode(int mode);
+int vga_setmodex(void);
+
+#define vga_planemask(mask) \
+       outpw(VGA_SC_ADDR_PORT, VGA_SC_MAPMASK_REG | ((unsigned short)(mask) << 8))
 
 #ifdef __WATCOMC__
 void vga_setpal(int16_t idx, uint8_t r, uint8_t g, uint8_t b);
diff --git a/src/dos/vgaregs.h b/src/dos/vgaregs.h
new file mode 100644 (file)
index 0000000..15c4090
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef VGAREGS_H_
+#define VGAREGS_H_
+
+/* ---- VGA registers ---- */
+#define VGA_AC_PORT            0x3c0
+#define VGA_AC_RD_PORT         0x3c1
+#define VGA_SC_ADDR_PORT       0x3c4
+#define VGA_SC_DATA_PORT       0x3c5
+#define VGA_GC_ADDR_PORT       0x3ce
+#define VGA_GC_DATA_PORT       0x3cf
+#define VGA_CRTC_PORT          0x3d4
+#define VGA_CRTC_ADDR_PORT     0x3d4
+#define VGA_CRTC_DATA_PORT     0x3d5
+#define VGA_STAT0_PORT         0x3c2
+#define VGA_STAT1_PORT         0x3da
+#define VGA_MISC_PORT          0x3c2
+#define VGA_MISC_RD_PORT       0x3cc
+
+/* attribute controller registers */
+#define VGA_AC_EN              0x20
+#define VGA_AC_MODE_REG                0x10
+
+/* sequence controller registers */
+#define VGA_SC_RESET_REG       0x00
+#define VGA_SC_CLOCK_REG       0x01
+#define VGA_SC_MAPMASK_REG     0x02
+#define VGA_SC_MEMMODE_REG     0x04
+
+/* graphics controller registers */
+#define VGA_GC_SR_REG          0x00
+#define VGA_GC_SREN_REG                0x01
+#define VGA_GC_ROT_REG         0x03
+#define VGA_GC_MODE_REG                0x05
+#define VGA_GC_MASK_REG                0x08
+
+/* attribute controller mode register (10h) bits */
+#define VGA_AC_MODE_GFX                0x01
+#define VGA_AC_MODE_MONO       0x02
+#define VGA_AC_MODE_LGE                0x04
+#define VGA_AC_MODE_BLINK      0x08
+#define VGA_AC_MODE_PIXPAN     0x20
+#define VGA_AC_MODE_8BIT       0x40
+
+/* misc register bits */
+#define VGA_MISC_COLOR         0x01
+#define VGA_MISC_CPUEN         0x02
+#define VGA_MISC_CLK25         0
+#define VGA_MISC_CLK28         0x04
+#define VGA_MISC_PG1           0x20
+#define VGA_MISC_400           0
+#define VGA_MISC_350           0x40
+#define VGA_MISC_480           0xc0
+
+
+/* CRTC registers */
+#define CRTC_HTOTAL_REG                0x00
+#define CRTC_HEND_REG          0x01
+#define CRTC_HBLSTART_REG      0x02
+#define CRTC_HBLEND_REG                0x03
+#define CRTC_HRETSTART_REG     0x04
+#define CRTC_HRETEND_REG       0x05
+#define CRTC_VTOTAL_REG                0x06
+#define CRTC_OVF_REG           0x07
+#define CRTC_PRESET_REG                0x08
+#define CRTC_MAXSCAN_REG       0x09
+#define CRTC_CURSTART_REG      0x0a
+#define CRTC_CUREND_REG                0x0b
+#define CRTC_STARTH_REG                0x0c
+#define CRTC_STARTL_REG                0x0d
+#define CRTC_CURH_REG          0x0e
+#define CRTC_CURL_REG          0x0f
+#define CRTC_VRETSTART_REG     0x10
+#define CRTC_VRETEND_REG       0x11
+#define CRTC_VEND_REG          0x12
+#define CRTC_OFFSET_REG                0x13
+#define CRTC_UL_REG            0x14
+#define CRTC_VBLSTART_REG      0x15
+#define CRTC_VBLEND_REG                0x16
+#define CRTC_MODE_REG          0x17
+#define CRTC_LCMP_REG          0x18
+
+/* CRTC register bits */
+#define CRTC_VRETEND_PR                0x80
+
+#endif /* VGAREGS_H_ */
index c776d3b..6a7b96c 100644 (file)
@@ -9,6 +9,7 @@
 #endif
 #include "mikmod.h"
 #include "audio.h"
+#include "cfgopt.h"
 
 #ifdef _WIN32
 #include <windows.h>
@@ -37,6 +38,8 @@ int au_init(void)
        curmod = 0;
        vol_master = vol_mus = vol_sfx = 255;
 
+       if(!opt.music) return 0;
+
 #if defined(__linux__)
        MikMod_RegisterDriver(&drv_alsa);
 #elif defined(__FreeBSD__)
@@ -63,7 +66,7 @@ int au_init(void)
        {
 #ifdef _WIN32
                HANDLE thr;
-               if((thr = CreateThread(0, 0, update, 0, 0, 0))) {
+               if((thr = CreateThread(0, 0, upd_thread, 0, 0, 0))) {
                        CloseHandle(thr);
                }
 #else
@@ -78,8 +81,10 @@ int au_init(void)
 
 void au_shutdown(void)
 {
-       curmod = 0;
-       MikMod_Exit();
+       if(opt.music) {
+               curmod = 0;
+               MikMod_Exit();
+       }
 }
 
 struct au_module *au_load_module(const char *fname)
@@ -169,7 +174,7 @@ void au_update(void)
 }
 
 #ifdef _WIN32
-static DWORD WINAPI upd_thread(void *cls);
+static DWORD WINAPI upd_thread(void *cls)
 #else
 static void *update(void *cls)
 #endif
index abe25cc..a552832 100644 (file)
@@ -11,6 +11,7 @@
 #include "cfgopt.h"
 #include "cgmath/cgmath.h"
 #include "util.h"
+#include "cpuid.h"
 
 static void display(void);
 static void idle(void);
@@ -101,6 +102,9 @@ int main(int argc, char **argv)
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_CULL_FACE);
 
+       if(read_cpuid(&cpuid) == 0) {
+               print_cpuid(&cpuid);
+       }
 
        if(!set_video_mode(match_video_mode(FB_WIDTH, FB_HEIGHT, FB_BPP), 1)) {
                return 1;
@@ -118,21 +122,26 @@ int main(int argc, char **argv)
        wgl_swap_interval_ext = wglGetProcAddress("wglSwapIntervalEXT");
 #endif
 
-       reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
-
        if(au_init() == -1) {
                return 1;
        }
        time_msec = 0;
-       if(demo_init(argc, argv) == -1) {
+       if(demo_init1(argc, argv) == -1) {
                return 1;
        }
-       atexit(demo_cleanup);
 
        if(opt.fullscreen) {
                set_fullscreen(opt.fullscreen);
+               reshape(glutGet(GLUT_SCREEN_WIDTH), glutGet(GLUT_SCREEN_HEIGHT));
+       } else {
+               reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
        }
 
+       if(demo_init2() == -1) {
+               return 1;
+       }
+       atexit(demo_cleanup);
+
        reset_timer();
 
        glutMainLoop();
@@ -144,6 +153,11 @@ void demo_quit(void)
        exit(0);
 }
 
+void demo_abort(void)
+{
+       abort();
+}
+
 struct video_mode *video_modes(void)
 {
        return vmodes;
diff --git a/src/glut/w32_dirent.c b/src/glut/w32_dirent.c
deleted file mode 100644 (file)
index d399023..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * dirent.c
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
- *
- * Derived from DIRLIB.C by Matt J. Weinstein 
- * This note appears in the DIRLIB.H
- * DIRLIB.H by M. J. Weinstein   Released to public domain 1-Jan-89
- *
- * Updated by Jeremy Bettis <jeremy@hksys.com>
- * Significantly revised and rewinddir, seekdir and telldir added by Colin
- * Peters <colin@fu.is.saga-u.ac.jp>
- *     
- */
-#ifdef _MSC_VER
-
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <io.h>
-#include <direct.h>
-#include "w32_dirent.h"
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h> /* for GetFileAttributes */
-
-#define SUFFIX "*"
-#define        SLASH   "\\"
-
-/*
- * opendir
- *
- * Returns a pointer to a DIR structure appropriately filled in to begin
- * searching a directory.
- */
-DIR * opendir (const char *szPath)
-{
-  DIR *nd;
-  unsigned int rc;
-  char szFullPath[MAX_PATH];
-       
-  errno = 0;
-
-  if (!szPath)
-    {
-      errno = EFAULT;
-      return (DIR *) 0;
-    }
-
-  if (szPath[0] == ('\0'))
-    {
-      errno = ENOTDIR;
-      return (DIR *) 0;
-    }
-
-  /* Attempt to determine if the given path really is a directory. */
-  rc = GetFileAttributes (szPath);
-  if (rc == (unsigned int)-1)
-    {
-      /* call GetLastError for more error info */
-      errno = ENOENT;
-      return (DIR *) 0;
-    }
-  if (!(rc & FILE_ATTRIBUTE_DIRECTORY))
-    {
-      /* Error, entry exists but not a directory. */
-      errno = ENOTDIR;
-      return (DIR *) 0;
-    }
-
-  /* Make an absolute pathname.  */
-  _fullpath (szFullPath, szPath, MAX_PATH);
-
-  /* Allocate enough space to store DIR structure and the complete
-   * directory path given. */
-  nd = (DIR *) malloc (sizeof (DIR) + (strlen (szFullPath)
-                                          + strlen (SLASH)
-                                          + strlen (SUFFIX) + 1)
-                                         * sizeof (char));
-
-  if (!nd)
-    {
-      /* Error, out of memory. */
-      errno = ENOMEM;
-      return (DIR *) 0;
-    }
-
-  /* Create the search expression. */
-  strcpy (nd->dd_name, szFullPath);
-
-  /* Add on a slash if the path does not end with one. */
-  if (nd->dd_name[0] != ('\0')
-      && strrchr (nd->dd_name, ('/')) != nd->dd_name
-                                           + strlen (nd->dd_name) - 1
-      && strrchr (nd->dd_name, ('\\')) != nd->dd_name
-                                            + strlen (nd->dd_name) - 1)
-    {
-      strcat (nd->dd_name, SLASH);
-    }
-
-  /* Add on the search pattern */
-  strcat (nd->dd_name, SUFFIX);
-
-  /* Initialize handle to -1 so that a premature closedir doesn't try
-   * to call _findclose on it. */
-  nd->dd_handle = -1;
-
-  /* Initialize the status. */
-  nd->dd_stat = 0;
-
-  /* Initialize the dirent structure. ino and reclen are invalid under
-   * Win32, and name simply points at the appropriate part of the
-   * findfirst structure. */
-  nd->dd_dir.d_ino = 0;
-  nd->dd_dir.d_reclen = 0;
-  nd->dd_dir.d_namlen = 0;
-  memset (nd->dd_dir.d_name, 0, FILENAME_MAX);
-
-  return nd;
-}
-
-
-/*
- * readdir
- *
- * Return a pointer to a dirent structure filled with the information on the
- * next entry in the directory.
- */
-struct dirent *
-readdir (DIR * dirp)
-{
-  errno = 0;
-
-  /* Check for valid DIR struct. */
-  if (!dirp)
-    {
-      errno = EFAULT;
-      return (struct dirent *) 0;
-    }
-
-  if (dirp->dd_stat < 0)
-    {
-      /* We have already returned all files in the directory
-       * (or the structure has an invalid dd_stat). */
-      return (struct dirent *) 0;
-    }
-  else if (dirp->dd_stat == 0)
-    {
-      /* We haven't started the search yet. */
-      /* Start the search */
-      dirp->dd_handle = (long)_findfirst (dirp->dd_name, &(dirp->dd_dta));
-
-      if (dirp->dd_handle == -1)
-       {
-         /* Whoops! Seems there are no files in that
-          * directory. */
-         dirp->dd_stat = -1;
-       }
-      else
-       {
-         dirp->dd_stat = 1;
-       }
-    }
-  else
-    {
-      /* Get the next search entry. */
-      if (_findnext (dirp->dd_handle, &(dirp->dd_dta)))
-       {
-         /* We are off the end or otherwise error.     
-            _findnext sets errno to ENOENT if no more file
-            Undo this. */ 
-         DWORD winerr = GetLastError ();
-         if (winerr == ERROR_NO_MORE_FILES)
-           errno = 0;  
-         _findclose (dirp->dd_handle);
-         dirp->dd_handle = -1;
-         dirp->dd_stat = -1;
-       }
-      else
-       {
-         /* Update the status to indicate the correct
-          * number. */
-         dirp->dd_stat++;
-       }
-    }
-
-  if (dirp->dd_stat > 0)
-    {
-      /* Successfully got an entry. Everything about the file is
-       * already appropriately filled in except the length of the
-       * file name. */
-      dirp->dd_dir.d_namlen = (unsigned short)strlen (dirp->dd_dta.name);
-      strcpy (dirp->dd_dir.d_name, dirp->dd_dta.name);
-      return &dirp->dd_dir;
-    }
-
-  return (struct dirent *) 0;
-}
-
-
-/*
- * closedir
- *
- * Frees up resources allocated by opendir.
- */
-int
-closedir (DIR * dirp)
-{
-  int rc;
-
-  errno = 0;
-  rc = 0;
-
-  if (!dirp)
-    {
-      errno = EFAULT;
-      return -1;
-    }
-
-  if (dirp->dd_handle != -1)
-    {
-      rc = _findclose (dirp->dd_handle);
-    }
-
-  /* Delete the dir structure. */
-  free (dirp);
-
-  return rc;
-}
-
-/*
- * rewinddir
- *
- * Return to the beginning of the directory "stream". We simply call findclose
- * and then reset things like an opendir.
- */
-void
-rewinddir (DIR * dirp)
-{
-  errno = 0;
-
-  if (!dirp)
-    {
-      errno = EFAULT;
-      return;
-    }
-
-  if (dirp->dd_handle != -1)
-    {
-      _findclose (dirp->dd_handle);
-    }
-
-  dirp->dd_handle = -1;
-  dirp->dd_stat = 0;
-}
-
-/*
- * telldir
- *
- * Returns the "position" in the "directory stream" which can be used with
- * seekdir to go back to an old entry. We simply return the value in stat.
- */
-long
-telldir (DIR * dirp)
-{
-  errno = 0;
-
-  if (!dirp)
-    {
-      errno = EFAULT;
-      return -1;
-    }
-  return dirp->dd_stat;
-}
-
-/*
- * seekdir
- *
- * Seek to an entry previously returned by telldir. We rewind the directory
- * and call readdir repeatedly until either dd_stat is the position number
- * or -1 (off the end). This is not perfect, in that the directory may
- * have changed while we weren't looking. But that is probably the case with
- * any such system.
- */
-void
-seekdir (DIR * dirp, long lPos)
-{
-  errno = 0;
-
-  if (!dirp)
-    {
-      errno = EFAULT;
-      return;
-    }
-
-  if (lPos < -1)
-    {
-      /* Seeking to an invalid position. */
-      errno = EINVAL;
-      return;
-    }
-  else if (lPos == -1)
-    {
-      /* Seek past end. */
-      if (dirp->dd_handle != -1)
-       {
-         _findclose (dirp->dd_handle);
-       }
-      dirp->dd_handle = -1;
-      dirp->dd_stat = -1;
-    }
-  else
-    {
-      /* Rewind and read forward to the appropriate index. */
-      rewinddir (dirp);
-
-      while ((dirp->dd_stat < lPos) && readdir (dirp))
-       ;
-    }
-}
-
-#else
-
-int _utk_w32_dirent_c_shut_up_stupid_compiler_warning;
-
-#endif /* WIN32 */
diff --git a/src/glut/w32_dirent.h b/src/glut/w32_dirent.h
deleted file mode 100644 (file)
index 5b256bc..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * DIRENT.H (formerly DIRLIB.H)
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
- *
- */
-#ifndef W32_DIRENT_H_
-#define W32_DIRENT_H_
-
-#include <stdio.h>
-#include <io.h>
-
-#ifndef RC_INVOKED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct dirent
-{
-       long            d_ino;          /* Always zero. */
-       unsigned short  d_reclen;       /* Always zero. */
-       unsigned short  d_namlen;       /* Length of name in d_name. */
-       char            d_name[FILENAME_MAX]; /* File name. */
-};
-
-/*
- * This is an internal data structure. Good programmers will not use it
- * except as an argument to one of the functions below.
- * dd_stat field is now int (was short in older versions).
- */
-typedef struct
-{
-       /* disk transfer area for this dir */
-       struct _finddata_t      dd_dta;
-
-       /* dirent struct to return from dir (NOTE: this makes this thread
-        * safe as long as only one thread uses a particular DIR struct at
-        * a time) */
-       struct dirent           dd_dir;
-
-       /* _findnext handle */
-       long                    dd_handle;
-
-       /*
-         * Status of search:
-        *   0 = not started yet (next entry to read is first entry)
-        *  -1 = off the end
-        *   positive = 0 based index of next entry
-        */
-       int                     dd_stat;
-
-       /* given path for dir with search pattern (struct is extended) */
-       char                    dd_name[1];
-} DIR;
-
-DIR* __cdecl opendir (const char*);
-struct dirent* __cdecl readdir (DIR*);
-int __cdecl closedir (DIR*);
-void __cdecl rewinddir (DIR*);
-long __cdecl telldir (DIR*);
-void __cdecl seekdir (DIR*, long);
-
-
-/* wide char versions */
-
-struct _wdirent
-{
-       long            d_ino;          /* Always zero. */
-       unsigned short  d_reclen;       /* Always zero. */
-       unsigned short  d_namlen;       /* Length of name in d_name. */
-       wchar_t         d_name[FILENAME_MAX]; /* File name. */
-};
-
-/*
- * This is an internal data structure. Good programmers will not use it
- * except as an argument to one of the functions below.
- */
-typedef struct
-{
-       /* disk transfer area for this dir */
-       struct _wfinddata_t     dd_dta;
-
-       /* dirent struct to return from dir (NOTE: this makes this thread
-        * safe as long as only one thread uses a particular DIR struct at
-        * a time) */
-       struct _wdirent         dd_dir;
-
-       /* _findnext handle */
-       long                    dd_handle;
-
-       /*
-         * Status of search:
-        *   0 = not started yet (next entry to read is first entry)
-        *  -1 = off the end
-        *   positive = 0 based index of next entry
-        */
-       int                     dd_stat;
-
-       /* given path for dir with search pattern (struct is extended) */
-       wchar_t                 dd_name[1];
-} _WDIR;
-
-
-
-_WDIR* __cdecl _wopendir (const wchar_t*);
-struct _wdirent*  __cdecl _wreaddir (_WDIR*);
-int __cdecl _wclosedir (_WDIR*);
-void __cdecl _wrewinddir (_WDIR*);
-long __cdecl _wtelldir (_WDIR*);
-void __cdecl _wseekdir (_WDIR*, long);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* Not RC_INVOKED */
-
-#endif /* Not _DIRENT_H_ */
diff --git a/src/glut/w32dir.c b/src/glut/w32dir.c
new file mode 100644 (file)
index 0000000..fc4541e
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * dirent.c
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is a part of the mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER within the package.
+ *
+ * Derived from DIRLIB.C by Matt J. Weinstein 
+ * This note appears in the DIRLIB.H
+ * DIRLIB.H by M. J. Weinstein   Released to public domain 1-Jan-89
+ *
+ * Updated by Jeremy Bettis <jeremy@hksys.com>
+ * Significantly revised and rewinddir, seekdir and telldir added by Colin
+ * Peters <colin@fu.is.saga-u.ac.jp>
+ *     
+ */
+#ifdef _MSC_VER
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <io.h>
+#include <direct.h>
+#include "w32dir.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h> /* for GetFileAttributes */
+
+#define SUFFIX "*"
+#define        SLASH   "\\"
+
+/*
+ * opendir
+ *
+ * Returns a pointer to a DIR structure appropriately filled in to begin
+ * searching a directory.
+ */
+DIR * opendir (const char *szPath)
+{
+  DIR *nd;
+  unsigned int rc;
+  char szFullPath[MAX_PATH];
+       
+  errno = 0;
+
+  if (!szPath)
+    {
+      errno = EFAULT;
+      return (DIR *) 0;
+    }
+
+  if (szPath[0] == ('\0'))
+    {
+      errno = ENOTDIR;
+      return (DIR *) 0;
+    }
+
+  /* Attempt to determine if the given path really is a directory. */
+  rc = GetFileAttributes (szPath);
+  if (rc == (unsigned int)-1)
+    {
+      /* call GetLastError for more error info */
+      errno = ENOENT;
+      return (DIR *) 0;
+    }
+  if (!(rc & FILE_ATTRIBUTE_DIRECTORY))
+    {
+      /* Error, entry exists but not a directory. */
+      errno = ENOTDIR;
+      return (DIR *) 0;
+    }
+
+  /* Make an absolute pathname.  */
+  _fullpath (szFullPath, szPath, MAX_PATH);
+
+  /* Allocate enough space to store DIR structure and the complete
+   * directory path given. */
+  nd = (DIR *) malloc (sizeof (DIR) + (strlen (szFullPath)
+                                          + strlen (SLASH)
+                                          + strlen (SUFFIX) + 1)
+                                         * sizeof (char));
+
+  if (!nd)
+    {
+      /* Error, out of memory. */
+      errno = ENOMEM;
+      return (DIR *) 0;
+    }
+
+  /* Create the search expression. */
+  strcpy (nd->dd_name, szFullPath);
+
+  /* Add on a slash if the path does not end with one. */
+  if (nd->dd_name[0] != ('\0')
+      && strrchr (nd->dd_name, ('/')) != nd->dd_name
+                                           + strlen (nd->dd_name) - 1
+      && strrchr (nd->dd_name, ('\\')) != nd->dd_name
+                                            + strlen (nd->dd_name) - 1)
+    {
+      strcat (nd->dd_name, SLASH);
+    }
+
+  /* Add on the search pattern */
+  strcat (nd->dd_name, SUFFIX);
+
+  /* Initialize handle to -1 so that a premature closedir doesn't try
+   * to call _findclose on it. */
+  nd->dd_handle = -1;
+
+  /* Initialize the status. */
+  nd->dd_stat = 0;
+
+  /* Initialize the dirent structure. ino and reclen are invalid under
+   * Win32, and name simply points at the appropriate part of the
+   * findfirst structure. */
+  nd->dd_dir.d_ino = 0;
+  nd->dd_dir.d_reclen = 0;
+  nd->dd_dir.d_namlen = 0;
+  memset (nd->dd_dir.d_name, 0, FILENAME_MAX);
+
+  return nd;
+}
+
+
+/*
+ * readdir
+ *
+ * Return a pointer to a dirent structure filled with the information on the
+ * next entry in the directory.
+ */
+struct dirent *
+readdir (DIR * dirp)
+{
+  errno = 0;
+
+  /* Check for valid DIR struct. */
+  if (!dirp)
+    {
+      errno = EFAULT;
+      return (struct dirent *) 0;
+    }
+
+  if (dirp->dd_stat < 0)
+    {
+      /* We have already returned all files in the directory
+       * (or the structure has an invalid dd_stat). */
+      return (struct dirent *) 0;
+    }
+  else if (dirp->dd_stat == 0)
+    {
+      /* We haven't started the search yet. */
+      /* Start the search */
+      dirp->dd_handle = (long)_findfirst (dirp->dd_name, &(dirp->dd_dta));
+
+      if (dirp->dd_handle == -1)
+       {
+         /* Whoops! Seems there are no files in that
+          * directory. */
+         dirp->dd_stat = -1;
+       }
+      else
+       {
+         dirp->dd_stat = 1;
+       }
+    }
+  else
+    {
+      /* Get the next search entry. */
+      if (_findnext (dirp->dd_handle, &(dirp->dd_dta)))
+       {
+         /* We are off the end or otherwise error.     
+            _findnext sets errno to ENOENT if no more file
+            Undo this. */ 
+         DWORD winerr = GetLastError ();
+         if (winerr == ERROR_NO_MORE_FILES)
+           errno = 0;  
+         _findclose (dirp->dd_handle);
+         dirp->dd_handle = -1;
+         dirp->dd_stat = -1;
+       }
+      else
+       {
+         /* Update the status to indicate the correct
+          * number. */
+         dirp->dd_stat++;
+       }
+    }
+
+  if (dirp->dd_stat > 0)
+    {
+      /* Successfully got an entry. Everything about the file is
+       * already appropriately filled in except the length of the
+       * file name. */
+      dirp->dd_dir.d_namlen = (unsigned short)strlen (dirp->dd_dta.name);
+      strcpy (dirp->dd_dir.d_name, dirp->dd_dta.name);
+      return &dirp->dd_dir;
+    }
+
+  return (struct dirent *) 0;
+}
+
+
+/*
+ * closedir
+ *
+ * Frees up resources allocated by opendir.
+ */
+int
+closedir (DIR * dirp)
+{
+  int rc;
+
+  errno = 0;
+  rc = 0;
+
+  if (!dirp)
+    {
+      errno = EFAULT;
+      return -1;
+    }
+
+  if (dirp->dd_handle != -1)
+    {
+      rc = _findclose (dirp->dd_handle);
+    }
+
+  /* Delete the dir structure. */
+  free (dirp);
+
+  return rc;
+}
+
+/*
+ * rewinddir
+ *
+ * Return to the beginning of the directory "stream". We simply call findclose
+ * and then reset things like an opendir.
+ */
+void
+rewinddir (DIR * dirp)
+{
+  errno = 0;
+
+  if (!dirp)
+    {
+      errno = EFAULT;
+      return;
+    }
+
+  if (dirp->dd_handle != -1)
+    {
+      _findclose (dirp->dd_handle);
+    }
+
+  dirp->dd_handle = -1;
+  dirp->dd_stat = 0;
+}
+
+/*
+ * telldir
+ *
+ * Returns the "position" in the "directory stream" which can be used with
+ * seekdir to go back to an old entry. We simply return the value in stat.
+ */
+long
+telldir (DIR * dirp)
+{
+  errno = 0;
+
+  if (!dirp)
+    {
+      errno = EFAULT;
+      return -1;
+    }
+  return dirp->dd_stat;
+}
+
+/*
+ * seekdir
+ *
+ * Seek to an entry previously returned by telldir. We rewind the directory
+ * and call readdir repeatedly until either dd_stat is the position number
+ * or -1 (off the end). This is not perfect, in that the directory may
+ * have changed while we weren't looking. But that is probably the case with
+ * any such system.
+ */
+void
+seekdir (DIR * dirp, long lPos)
+{
+  errno = 0;
+
+  if (!dirp)
+    {
+      errno = EFAULT;
+      return;
+    }
+
+  if (lPos < -1)
+    {
+      /* Seeking to an invalid position. */
+      errno = EINVAL;
+      return;
+    }
+  else if (lPos == -1)
+    {
+      /* Seek past end. */
+      if (dirp->dd_handle != -1)
+       {
+         _findclose (dirp->dd_handle);
+       }
+      dirp->dd_handle = -1;
+      dirp->dd_stat = -1;
+    }
+  else
+    {
+      /* Rewind and read forward to the appropriate index. */
+      rewinddir (dirp);
+
+      while ((dirp->dd_stat < lPos) && readdir (dirp))
+       ;
+    }
+}
+
+#else
+
+int _utk_w32_dirent_c_shut_up_stupid_compiler_warning;
+
+#endif /* WIN32 */
diff --git a/src/glut/w32dir.h b/src/glut/w32dir.h
new file mode 100644 (file)
index 0000000..5b256bc
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * DIRENT.H (formerly DIRLIB.H)
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is a part of the mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER within the package.
+ *
+ */
+#ifndef W32_DIRENT_H_
+#define W32_DIRENT_H_
+
+#include <stdio.h>
+#include <io.h>
+
+#ifndef RC_INVOKED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct dirent
+{
+       long            d_ino;          /* Always zero. */
+       unsigned short  d_reclen;       /* Always zero. */
+       unsigned short  d_namlen;       /* Length of name in d_name. */
+       char            d_name[FILENAME_MAX]; /* File name. */
+};
+
+/*
+ * This is an internal data structure. Good programmers will not use it
+ * except as an argument to one of the functions below.
+ * dd_stat field is now int (was short in older versions).
+ */
+typedef struct
+{
+       /* disk transfer area for this dir */
+       struct _finddata_t      dd_dta;
+
+       /* dirent struct to return from dir (NOTE: this makes this thread
+        * safe as long as only one thread uses a particular DIR struct at
+        * a time) */
+       struct dirent           dd_dir;
+
+       /* _findnext handle */
+       long                    dd_handle;
+
+       /*
+         * Status of search:
+        *   0 = not started yet (next entry to read is first entry)
+        *  -1 = off the end
+        *   positive = 0 based index of next entry
+        */
+       int                     dd_stat;
+
+       /* given path for dir with search pattern (struct is extended) */
+       char                    dd_name[1];
+} DIR;
+
+DIR* __cdecl opendir (const char*);
+struct dirent* __cdecl readdir (DIR*);
+int __cdecl closedir (DIR*);
+void __cdecl rewinddir (DIR*);
+long __cdecl telldir (DIR*);
+void __cdecl seekdir (DIR*, long);
+
+
+/* wide char versions */
+
+struct _wdirent
+{
+       long            d_ino;          /* Always zero. */
+       unsigned short  d_reclen;       /* Always zero. */
+       unsigned short  d_namlen;       /* Length of name in d_name. */
+       wchar_t         d_name[FILENAME_MAX]; /* File name. */
+};
+
+/*
+ * This is an internal data structure. Good programmers will not use it
+ * except as an argument to one of the functions below.
+ */
+typedef struct
+{
+       /* disk transfer area for this dir */
+       struct _wfinddata_t     dd_dta;
+
+       /* dirent struct to return from dir (NOTE: this makes this thread
+        * safe as long as only one thread uses a particular DIR struct at
+        * a time) */
+       struct _wdirent         dd_dir;
+
+       /* _findnext handle */
+       long                    dd_handle;
+
+       /*
+         * Status of search:
+        *   0 = not started yet (next entry to read is first entry)
+        *  -1 = off the end
+        *   positive = 0 based index of next entry
+        */
+       int                     dd_stat;
+
+       /* given path for dir with search pattern (struct is extended) */
+       wchar_t                 dd_name[1];
+} _WDIR;
+
+
+
+_WDIR* __cdecl _wopendir (const wchar_t*);
+struct _wdirent*  __cdecl _wreaddir (_WDIR*);
+int __cdecl _wclosedir (_WDIR*);
+void __cdecl _wrewinddir (_WDIR*);
+long __cdecl _wtelldir (_WDIR*);
+void __cdecl _wseekdir (_WDIR*, long);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Not RC_INVOKED */
+
+#endif /* Not _DIRENT_H_ */
index 4401e5a..63bfa82 100644 (file)
@@ -186,12 +186,12 @@ float noise3(float x, float y, float z)
        c = lerp(a, b, sy);
 
        /* interpolate along the bottom slice of the cell */
-       u = dotgrad3(grad3[b00 + bz0], rx0, ry0, rz1);
-       v = dotgrad3(grad3[b10 + bz0], rx1, ry0, rz1);
+       u = dotgrad3(grad3[b00 + bz1], rx0, ry0, rz1);
+       v = dotgrad3(grad3[b10 + bz1], rx1, ry0, rz1);
        a = lerp(u, v, sx);
 
-       u = dotgrad3(grad3[b01 + bz0], rx0, ry1, rz1);
-       v = dotgrad3(grad3[b11 + bz0], rx1, ry1, rz1);
+       u = dotgrad3(grad3[b01 + bz1], rx0, ry1, rz1);
+       v = dotgrad3(grad3[b11 + bz1], rx1, ry1, rz1);
        b = lerp(u, v, sx);
 
        d = lerp(a, b, sy);
@@ -298,12 +298,12 @@ float pnoise3(float x, float y, float z, int per_x, int per_y, int per_z)
        c = lerp(a, b, sy);
 
        /* interpolate along the bottom slice of the cell */
-       u = dotgrad3(grad3[b00 + bz0], rx0, ry0, rz1);
-       v = dotgrad3(grad3[b10 + bz0], rx1, ry0, rz1);
+       u = dotgrad3(grad3[b00 + bz1], rx0, ry0, rz1);
+       v = dotgrad3(grad3[b10 + bz1], rx1, ry0, rz1);
        a = lerp(u, v, sx);
 
-       u = dotgrad3(grad3[b01 + bz0], rx0, ry1, rz1);
-       v = dotgrad3(grad3[b11 + bz0], rx1, ry1, rz1);
+       u = dotgrad3(grad3[b01 + bz1], rx0, ry1, rz1);
+       v = dotgrad3(grad3[b11 + bz1], rx1, ry1, rz1);
        b = lerp(u, v, sx);
 
        d = lerp(a, b, sy);
diff --git a/src/rlebmap.c b/src/rlebmap.c
new file mode 100644 (file)
index 0000000..de5e168
--- /dev/null
@@ -0,0 +1,309 @@
+#include <stdlib.h>
+#include <string.h>
+#include "rlebmap.h"
+
+/* Number of numbers per scanline. Each streak has 2 numbers (start, length) */
+#define RLE_ELEMENTS_PER_SCANLINE RLE_STREAKS_PER_SCANLINE * 2
+
+/* Two RLE_TYPE elements per streak (= start,length) */
+#define RLE_BYTES_PER_SCANLINE RLE_ELEMENTS_PER_SCANLINE * sizeof(RLE_TYPE)
+
+/* RLE_TYPE count required for storing an RLE of w,h */
+static int rleWorstCaseElementCount(int w, int h) {
+       /* Allocate an extra worst case for one scanline, which is w/2 streaks = w
+        * (start,length) elements */
+       return h * RLE_ELEMENTS_PER_SCANLINE + w;
+}
+
+/* Byte count of the 'scans' buffer */
+static int rleScansByteCount(RleBitmap *rle) {
+       return rleWorstCaseElementCount(rle->w, rle->h) * sizeof(RLE_TYPE);
+}
+
+RleBitmap *rleCreate(unsigned int w, unsigned int h) {
+       RleBitmap *ret = malloc(sizeof(RleBitmap));
+       ret->w = w;
+       ret->h = h;
+
+       /* Allocate scans */
+       ret->scans = calloc(rleWorstCaseElementCount(w, h), sizeof(RLE_TYPE));
+
+       return ret;
+}
+
+void rleDestroy(RleBitmap *b) {
+       if (!b)
+               return;
+       free(b->scans);
+       free(b);
+}
+
+void rleClear(RleBitmap *rle) { memset(rle->scans, 0, rleScansByteCount(rle)); }
+
+RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW,
+                    unsigned int pixelsH) {
+       int x = 0;
+       int y = 0;
+       int streakActive = 0;
+       int currentStreakLength = 0;
+       RLE_TYPE *output = 0;
+       unsigned char *currentInputPixel = pixels;
+
+       /* https://www.youtube.com/watch?v=RKMR02o1I88&feature=youtu.be&t=55 */
+       if (!rle)
+               rle = rleCreate(pixelsW, pixelsH);
+       else
+               rleClear(rle); /* The following code assumes cleared array */
+
+       for (y = 0; y < pixelsH; y++) {
+               /* Go to the beginning of the RLE scan */
+               output = rle->scans + y * RLE_ELEMENTS_PER_SCANLINE;
+
+               for (x = 0; x < pixelsW; x++) {
+                       if (*currentInputPixel++) {
+                               if (streakActive) {
+                                       if (currentStreakLength >= RLE_MAX_STREAK_LENGTH) {
+                                               /* Do not allow streaks of more than max length -
+                                                * close current streak */
+                                               *output++ = (RLE_TYPE)currentStreakLength;
+
+                                               /* Begin new streak at current x */
+                                               *output++ = (RLE_TYPE)x;
+                                               currentStreakLength = 0;
+                                       }
+                               } else {
+                                       /* Begin new streak */
+                                       *output++ = (RLE_TYPE)x;
+                                       currentStreakLength = 0;
+                                       streakActive = 1;
+                               }
+                               currentStreakLength++;
+                       } else {
+                               if (streakActive) {
+                                       /* Close current streak */
+                                       *output++ = (RLE_TYPE)currentStreakLength;
+                                       currentStreakLength = 0;
+                                       streakActive = 0;
+                               }
+                       } /* End if (current pixel on) */
+               }         /* End for (all x) */
+
+               /* We reached the end of the scan - close any active streak */
+               if (streakActive) {
+                       *output++ = (RLE_TYPE)currentStreakLength;
+               }
+               streakActive = 0;
+               currentStreakLength = 0;
+       } /* End for (all scans */
+
+       return rle;
+}
+
+void rleDistributeStreaks(RleBitmap *rle) {
+       int scanline = 0;
+       int halfW = rle->w >> 1;
+       RLE_TYPE *ptr = 0;
+       RLE_TYPE tmp = 0;
+
+#define LAST_STREAK RLE_STREAKS_PER_SCANLINE
+
+       ptr = rle->scans;
+       for (scanline = 0; scanline < rle->h; scanline++) {
+               if (ptr[0] >= halfW) {
+                       /* Exchange first with last streak */
+                       tmp = ptr[0];
+                       ptr[0] = ptr[LAST_STREAK * 2 - 2];
+                       ptr[LAST_STREAK * 2 - 2] = tmp;
+                       tmp = ptr[1];
+                       ptr[1] = ptr[LAST_STREAK * 2 - 1];
+                       ptr[LAST_STREAK * 2 - 1] = tmp;
+               }
+
+               ptr += 8;
+       }
+}
+
+void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX,
+            int blitY) {
+       int scanline = 0;
+       int streakPos = 0;
+       int streakLength = 0;
+       int streak = 0;
+       RLE_TYPE *input = rle->scans;
+       unsigned short *output;
+       unsigned int *output32;
+
+       dst += blitX + blitY * dstStride;
+
+       for (scanline = blitY; scanline < blitY + rle->h; scanline++) {
+               if (scanline < 0 || scanline >= dstH)
+                       continue;
+               for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) {
+                       streakPos = (int)*input++;
+                       streakLength = (int)*input++;
+
+                       if ((streakPos + blitX) <= 0)
+                               continue;
+
+                       output = dst + streakPos;
+
+                       /* Check if we need to write the first pixel as 16bit */
+                       if (streakLength % 2) {
+                               *output++ = RLE_FILL_COLOR;
+                       }
+
+                       /* Then, write 2 pixels at a time */
+                       streakLength >>= 1;
+                       output32 = (unsigned int *)output;
+                       while (streakLength--) {
+                               *output32++ = RLE_FILL_COLOR_32;
+                       }
+               }
+
+               dst += dstStride;
+       }
+}
+
+/* This is madness. We could at least check that we are not interpolating from 0 -> something
+ * (length). This could remove the need for 'distributeScans' */
+void interpolateScan(RLE_TYPE *output, RLE_TYPE *a, RLE_TYPE *b, float t) {
+       static int div = 1 << 23;
+       int ti, i;
+
+       t += 1.0f;
+       ti = (*((unsigned int *)&t)) & 0x7FFFFF;
+
+       for (i = 0; i < RLE_ELEMENTS_PER_SCANLINE; i++) {
+               if (*a == 0) {
+                       *output++ = *b++;
+                       a++;
+               } else {
+                       if (*b == 0) {
+                               *output++ = *a++;
+                               b++;
+                       } else {
+                               *output++ = ((*b++ * ti) + (*a++ * (div - ti))) >> 23;
+                       }
+               }
+       }
+}
+
+void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX,
+                 int blitY, float scaleX, float scaleY) {
+       int scanline = 0;
+       int streakPos = 0;
+       int streakLength = 0;
+       int streak = 0;
+       unsigned short *output;
+       unsigned int *output32;
+       unsigned char *input;
+       int scanlineCounter = 0;
+       int scaleXFixed;
+       static unsigned char scan[512];
+
+       /*int blitW = (int)(rle->w * scaleX + 0.5f);*/
+       int blitH = (int)(rle->h * scaleY + 0.5f);
+
+       /* From this point on, scaleY will be inverted */
+       scaleY = 1.0f / scaleY;
+
+       scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f);
+
+       dst += blitX + blitY * dstStride;
+
+       for (scanline = blitY; scanline < blitY + blitH; scanline++) {
+               float normalScan = scanlineCounter * scaleY; /* ScaleY  is inverted */
+               unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan;
+               unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE;
+               normalScan -= (int)normalScan;
+               interpolateScan(scan, scan0, scan1, normalScan);
+               input = scan;
+               scanlineCounter++;
+
+               if (scanline < 0 || scanline >= dstH)
+                       continue;
+               for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) {
+                       streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS;
+                       streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS;
+
+                       if ((streakPos + blitX) <= 0)
+                               continue;
+
+                       output = dst + streakPos;
+
+                       /* Check if we need to write the first pixel as 16bit */
+                       if (streakLength % 2) {
+                               *output++ = RLE_FILL_COLOR;
+                       }
+
+                       /* Then, write 2 pixels at a time */
+                       streakLength >>= 1;
+                       output32 = (unsigned int *)output;
+                       while (streakLength--) {
+                               *output32++ = RLE_FILL_COLOR_32;
+                       }
+               }
+
+               dst += dstStride;
+       }
+}
+
+void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride,
+                    int blitX, int blitY, float scaleX, float scaleY) {
+       int scanline = 0;
+       int streakPos = 0;
+       int streakLength = 0;
+       int streak = 0;
+       unsigned short *output;
+       unsigned int *output32;
+       unsigned char *input;
+       int scanlineCounter = 0;
+       int scaleXFixed;
+       static unsigned char scan[512];
+
+       /*int blitW = (int)(rle->w * scaleX + 0.5f);*/
+       int blitH = (int)(rle->h * scaleY + 0.5f);
+
+       /* From this point on, scaleY will be inverted */
+       scaleY = 1.0f / scaleY;
+
+       scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f);
+
+       dst += blitX + blitY * dstStride;
+
+       for (scanline = blitY; scanline > blitY - blitH; scanline--) {
+               float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */
+               unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan;
+               unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE;
+               normalScan -= (int)normalScan;
+               interpolateScan(scan, scan0, scan1, normalScan);
+               input = scan;
+               scanlineCounter++;
+
+               if (scanline < 0 || scanline >= dstH)
+                       continue;
+               for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) {
+                       streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS;
+                       streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS;
+
+                       if ((streakPos + blitX) <= 0)
+                               continue;
+
+                       output = dst + streakPos;
+
+                       /* Check if we need to write the first pixel as 16bit */
+                       if (streakLength % 2) {
+                               *output++ = RLE_FILL_COLOR;
+                       }
+
+                       /* Then, write 2 pixels at a time */
+                       streakLength >>= 1;
+                       output32 = (unsigned int *)output;
+                       while (streakLength--) {
+                               *output32++ = RLE_FILL_COLOR_32;
+                       }
+               }
+
+               dst -= dstStride;
+       }
+}
diff --git a/src/rlebmap.h b/src/rlebmap.h
new file mode 100644 (file)
index 0000000..3f36b16
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __RLE_BITMAP_H__
+#define __RLE_BITMAP_H__
+
+/* Limit streak count per scanline so we can directly jump to specific scanline
+ */
+#define RLE_STREAKS_PER_SCANLINE 4
+
+/* Streaks will not exceed this many pixels. This allows us to optimize with a
+ * padded framebuffer. If a streak start position happens to lie within
+ * framebuffer, we will blit it without checking for out of bounds */
+#define RLE_MAX_STREAK_LENGTH 32
+
+/* Using the following type for storing start and for storing length in (start,
+ * length) pairs. */
+#define RLE_TYPE unsigned char
+
+/* For now, keep a static fill color. We can change this. Not that much about
+ * speed, but let's keep function definitions more compact. */
+#define RLE_FILL_COLOR 0
+
+/* Two entries of RLE_FILL_COLOR (16 bits) packed one after the other. */
+#define RLE_FILL_COLOR_32 ((RLE_FILL_COLOR << 16) | RLE_FILL_COLOR)
+
+/* For fixed-point arithmetic. Used for scaling. */
+#define RLE_FIXED_BITS 16
+
+/* This is a bitmap (image in 1bpp), encoded as streaks of consecutive pixels.
+ */
+typedef struct {
+       unsigned int w, h;
+
+       /* Each scan is RLE_BYTES_PER_SCANLINE long and contains pairs of
+        * (start, length). */
+       RLE_TYPE *scans;
+} RleBitmap;
+
+/* Constructor */
+RleBitmap *rleCreate(unsigned int w, unsigned int h);
+
+/* Destructor */
+void rleDestroy(RleBitmap *rle);
+
+/* Clears 'rle' to "all transparent" */
+void rleClear(RleBitmap *rle);
+
+/* Encode 'pixels' into 'rle' and also return it. Pixels are either 0 or 1. This
+ * will create an RleBitmap of 'h' scanlines. */
+RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW,
+                    unsigned int pixelsH);
+
+/* Rearranges the streaks to make it less frequent that they produce garbege when interpolated */
+void rleDistributeStreaks(RleBitmap *rle);
+
+/* Blits without scaling */
+void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX,
+            int blitY);
+
+/* Scaled blit */
+void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX,
+                 int blitY, float scaleX, float scaleY);
+
+/* Inverted blit (upside down) */
+void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride,
+                    int blitX, int blitY, float scaleX, float scaleY);
+
+#endif // __RLE_BITMAP_H__
index e12b12c..e26d336 100644 (file)
@@ -1,36 +1,36 @@
-#ifndef SBALL_H_\r
-#define SBALL_H_\r
-\r
-enum {\r
-       SBALL_EV_NONE,\r
-       SBALL_EV_MOTION,\r
-       SBALL_EV_BUTTON\r
-};\r
-\r
-struct sball_event_motion {\r
-       int type;\r
-       int motion[6];\r
-};\r
-\r
-struct sball_event_button {\r
-       int type;\r
-       int id;\r
-       int pressed;\r
-       unsigned int state;\r
-};\r
-\r
-typedef union sball_event {\r
-       int type;\r
-       struct sball_event_motion motion;\r
-       struct sball_event_button button;\r
-} sball_event;\r
-\r
-int sball_init(void);\r
-void sball_shutdown(void);\r
-\r
-int sball_getdev(void);\r
-\r
-int sball_pending(void);\r
-int sball_getevent(sball_event *ev);\r
-\r
-#endif /* SBALL_H_ */\r
+#ifndef SBALL_H_
+#define SBALL_H_
+
+enum {
+       SBALL_EV_NONE,
+       SBALL_EV_MOTION,
+       SBALL_EV_BUTTON
+};
+
+struct sball_event_motion {
+       int type;
+       int motion[6];
+};
+
+struct sball_event_button {
+       int type;
+       int id;
+       int pressed;
+       unsigned int state;
+};
+
+typedef union sball_event {
+       int type;
+       struct sball_event_motion motion;
+       struct sball_event_button button;
+} sball_event;
+
+int sball_init(void);
+void sball_shutdown(void);
+
+int sball_getdev(void);
+
+int sball_pending(void);
+int sball_getevent(sball_event *ev);
+
+#endif /* SBALL_H_ */
diff --git a/src/scr/cybersun.c b/src/scr/cybersun.c
new file mode 100644 (file)
index 0000000..fde29ab
--- /dev/null
@@ -0,0 +1,215 @@
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include "demo.h"
+#include "3dgfx.h"
+#include "screen.h"
+#include "gfxutil.h"
+#include "mesh.h"
+#include "image.h"
+#include "util.h"
+#include "cgmath/cgmath.h"
+
+#define TM_RIPPLE_START                1.0f
+#define TM_RIPPLE_TRANS_LEN    3.0f
+
+#define VFOV   50.0f
+#define HFOV   (VFOV * 1.333333f)
+
+static int init(void);
+static void destroy(void);
+static void start(long trans_time);
+static void draw(void);
+static void draw_mountains(void);
+
+static struct screen scr = {
+       "cybersun",
+       init,
+       destroy,
+       start,
+       0,
+       draw
+};
+
+static float cam_theta = 0, cam_phi = 0;
+static float cam_dist = 0;
+
+static struct g3d_mesh gmesh;
+#define GMESH_GRIDSZ   25
+#define GMESH_SIZE             128
+static struct image gtex;
+
+#define MOUNTIMG_WIDTH 512
+#define MOUNTIMG_HEIGHT        64
+static struct image mountimg;
+static int mountimg_skip[MOUNTIMG_WIDTH];
+
+static long part_start;
+
+
+struct screen *cybersun_screen(void)
+{
+       return &scr;
+}
+
+static int init(void)
+{
+       int i, j;
+
+       if(gen_plane_mesh(&gmesh, GMESH_SIZE, GMESH_SIZE, GMESH_GRIDSZ, GMESH_GRIDSZ) == -1) {
+               return -1;
+       }
+       for(i=0; i<gmesh.vcount; i++) {
+               gmesh.varr[i].u *= GMESH_GRIDSZ;
+               gmesh.varr[i].v *= GMESH_GRIDSZ;
+       }
+       if(load_image(&gtex, "data/pgrid.png") == -1) {
+               return -1;
+       }
+       if(load_image(&mountimg, "data/cybmount.png") == -1) {
+               return -1;
+       }
+       assert(mountimg.width == MOUNTIMG_WIDTH);
+       assert(mountimg.height == MOUNTIMG_HEIGHT);
+
+       for(i=0; i<MOUNTIMG_WIDTH; i++) {
+               uint16_t *pptr = mountimg.pixels + i;
+               for(j=0; j<MOUNTIMG_HEIGHT; j++) {
+                       if(*pptr != 0x7e0) {
+                               mountimg_skip[i] = j;
+                               break;
+                       }
+                       pptr += MOUNTIMG_WIDTH;
+               }
+       }
+       destroy_image(&mountimg);
+       mountimg.pixels = 0;
+
+       return 0;
+}
+
+static void destroy(void)
+{
+       destroy_mesh(&gmesh);
+       destroy_image(&gtex);
+}
+
+static void start(long trans_time)
+{
+       g3d_matrix_mode(G3D_PROJECTION);
+       g3d_load_identity();
+       g3d_perspective(VFOV, 1.3333333, 0.5, 500.0);
+
+       g3d_enable(G3D_CULL_FACE);
+
+       g3d_clear_color(85, 70, 136);
+
+       part_start = time_msec;
+}
+
+static void update(void)
+{
+       int i, j;
+       float t = (time_msec - part_start) / 1000.0f;
+       struct g3d_vertex *vptr;
+
+       float ampl = cgm_smoothstep(TM_RIPPLE_START, TM_RIPPLE_START + TM_RIPPLE_TRANS_LEN, t);
+
+       mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist);
+
+       /* update mesh */
+       vptr = gmesh.varr;
+       for(i=0; i<GMESH_GRIDSZ + 1; i++) {
+               for(j=0; j<GMESH_GRIDSZ + 1; j++) {
+                       float u = (float)j / GMESH_GRIDSZ - 0.5f;
+                       float v = (float)i / GMESH_GRIDSZ - 0.5f;
+                       float x = u * 32.0f;
+                       float y = v * 32.0f;
+                       float r = sqrt(x * x + y * y);
+
+                       vptr->z = sin(x * 0.5 + t) + cos(x * 0.8f) * 0.5f;
+                       vptr->z += cos(y * 0.5 + t);
+                       vptr->z += sin(r + t) * 0.5f;
+                       vptr->z *= r * 0.1f > 1.0f ? 1.0f : r * 0.1f;
+                       vptr->z *= ampl;
+                       vptr++;
+               }
+       }
+}
+
+static void draw(void)
+{
+       int i;
+
+       update();
+
+       g3d_matrix_mode(G3D_MODELVIEW);
+       g3d_load_identity();
+       g3d_translate(0, -2, -cam_dist);
+       g3d_rotate(cam_phi, 1, 0, 0);
+       g3d_rotate(cam_theta, 0, 1, 0);
+       if(opt.sball) {
+               g3d_mult_matrix(sball_matrix);
+       }
+
+       g3d_clear(G3D_COLOR_BUFFER_BIT | G3D_DEPTH_BUFFER_BIT);
+       draw_mountains();
+
+       g3d_set_texture(gtex.width, gtex.height, gtex.pixels);
+       g3d_enable(G3D_TEXTURE_2D);
+       g3d_enable(G3D_DEPTH_TEST);
+
+       g3d_push_matrix();
+       g3d_rotate(-90, 1, 0, 0);
+       draw_mesh(&gmesh);
+       g3d_pop_matrix();
+
+       g3d_disable(G3D_DEPTH_TEST);
+       g3d_disable(G3D_TEXTURE_2D);
+
+       swap_buffers(fb_pixels);
+}
+
+/* XXX all the sptr calculations assume mountimg.width == 512 */
+static void draw_mountains(void)
+{
+       int i, j, horizon_y, y;
+       int32_t x, xstart, xend, dx;
+       uint16_t *dptr, *sptr;
+
+       /* 24.8 fixed point, 512 width, 90deg arc */
+       xstart = cround64(cam_theta * (256.0 * MOUNTIMG_WIDTH / 90.0));
+       xend = cround64((cam_theta + HFOV) * (256.0 * MOUNTIMG_WIDTH / 90.0));
+       dx = (xend - xstart) / FB_WIDTH;
+       x = xstart;
+
+       horizon_y = cround64(-cam_phi * (FB_HEIGHT / 45.0)) + FB_HEIGHT / 2;
+       y = horizon_y - MOUNTIMG_HEIGHT;
+
+       if(y >= FB_HEIGHT) {
+               /* TODO draw gradient for the sky */
+               return;
+       }
+       if(horizon_y < 0) {
+               memset(fb_pixels, 0, FB_WIDTH * FB_HEIGHT * 2);
+               return;
+       }
+
+       for(i=0; i<FB_WIDTH; i++) {
+               int skip = mountimg_skip[(x >> 8) & 0x1ff];
+               int vspan = MOUNTIMG_HEIGHT - skip;
+
+               dptr = fb_pixels + (y + skip) * FB_WIDTH + i;
+
+               for(j=0; j<vspan; j++) {
+                       *dptr = 0;      /* black mountains */
+                       dptr += FB_WIDTH;
+               }
+
+               x += dx;
+       }
+
+       if(horizon_y < FB_HEIGHT) {
+               memset(fb_pixels + horizon_y * FB_WIDTH, 0, (FB_HEIGHT - horizon_y) * FB_WIDTH * 2);
+       }
+}
index 1295a07..c4a2e28 100644 (file)
@@ -1,35 +1,22 @@
+#include "demo.h"
+#include "imago2.h"
+#include "screen.h"
+#include <assert.h>
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <math.h>
-#include <assert.h>
-#include "imago2.h"
-#include "demo.h"
-#include "screen.h"
 
-/* APPROX. 170 FPS Minimum */
+#include "rlebmap.h"
 
-typedef struct {
-       unsigned int w, h;
-       unsigned char *scans;
-} RLEBitmap;
-
-static RLEBitmap *rleCreate(unsigned int w, unsigned int h);
-static void rleDestroy(RLEBitmap *b);
-static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride,
-       RLEBitmap *bitmap, int blitX, int blitY);
-static void rleBlitScale(unsigned short *dst, int dstW, int dstH, int dstStride,
-       RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY);
-static void rleBlitScaleInv(unsigned short *dst, int dstW, int dstH, int dstStride,
-       RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY);
-static RLEBitmap *rleEncode(RLEBitmap *b, unsigned char *pixels, unsigned int w, unsigned int h);
+/* APPROX. 170 FPS Minimum */
 
 static void updatePropeller(float t);
 
 #define BG_FILENAME "data/grise.png"
 #define GROBJ_01_FILENAME "data/grobj_01.png"
 
-#define BB_SIZE 512    /* Let's use a power of 2. Maybe we'll zoom/rotate the effect */
+#define BB_SIZE 512 /* Let's use a power of 2. Maybe we'll zoom/rotate the effect */
 
 /* Every backBuffer scanline is guaranteed to have that many dummy pixels before and after */
 #define PIXEL_PADDING 32
@@ -59,8 +46,6 @@ static void processNormal();
 static void initScrollTables();
 static void updateScrollTables(float dt);
 
-
-
 static unsigned short *background = 0;
 static int backgroundW = 0;
 static int backgroundH = 0;
@@ -80,42 +65,37 @@ static float nearScrollAmount = 0.0f;
 
 static unsigned char miniFXBuffer[1024];
 
-static RLEBitmap *grobj = 0;
-static RLEBitmap *rlePropeller = 0;
+static RleBitmap *grobj = 0;
+static RleBitmap *rlePropeller = 0;
 
-static struct screen scr = {
-       "galaxyrise",
-       init,
-       destroy,
-       start,
-       0,
-       draw
-};
+static struct screen scr = {"galaxyrise", init, destroy, start, 0, draw};
 
-struct screen *grise_screen(void)
-{
+struct screen *grise_screen(void) {
        return &scr;
 }
 
-static int init(void)
-{
+static int init(void) {
        unsigned char *tmpBitmap;
        int tmpBitmapW, tmpBitmapH;
 
        /* Allocate back buffer */
-       backBuffer = (unsigned short*) calloc(BB_SIZE * BB_SIZE, sizeof(unsigned short));
+       backBuffer = (unsigned short *)calloc(BB_SIZE * BB_SIZE, sizeof(unsigned short));
 
-       /* grise.png contains the background (horizon), baked reflection and normalmap for displacement */
-       if (!(background = img_load_pixels(BG_FILENAME, &backgroundW, &backgroundH, IMG_FMT_RGBA32))) {
+       /* grise.png contains the background (horizon), baked reflection and normalmap for
+        * displacement */
+       if (!(background =
+                 img_load_pixels(BG_FILENAME, &backgroundW, &backgroundH, IMG_FMT_RGBA32))) {
                fprintf(stderr, "failed to load image " BG_FILENAME "\n");
                return -1;
        }
 
        /* Convert to 16bpp */
-       convert32To16((unsigned int*)background, background, backgroundW * NORMALMAP_SCANLINE); /* Normalmap will keep its 32 bit color */
+       convert32To16((unsigned int *)background, background,
+                     backgroundW * NORMALMAP_SCANLINE); /* Normalmap will keep its 32 bit color */
 
        /* Load reflected objects */
-       if (!(tmpBitmap = img_load_pixels(GROBJ_01_FILENAME, &tmpBitmapW, &tmpBitmapH, IMG_FMT_GREY8))) {
+       if (!(tmpBitmap =
+                 img_load_pixels(GROBJ_01_FILENAME, &tmpBitmapW, &tmpBitmapH, IMG_FMT_GREY8))) {
                fprintf(stderr, "failed to load image " GROBJ_01_FILENAME "\n");
                return -1;
        }
@@ -131,8 +111,7 @@ static int init(void)
        return 0;
 }
 
-static void destroy(void)
-{
+static void destroy(void) {
        free(backBuffer);
        backBuffer = 0;
 
@@ -141,14 +120,9 @@ static void destroy(void)
        rleDestroy(grobj);
 }
 
-static void start(long trans_time)
-{
-       lastFrameTime = time_msec;
-}
-
+static void start(long trans_time) { lastFrameTime = time_msec; }
 
-static void draw(void)
-{
+static void draw(void) {
        int scroll = MIN_SCROLL + (MAX_SCROLL - MIN_SCROLL) * mouse_x / FB_WIDTH;
        unsigned short *dst = backBuffer + PIXEL_PADDING;
        unsigned short *src = background + scroll;
@@ -188,7 +162,9 @@ static void draw(void)
        }
 
        /* Blit reflections first, to be  displaced */
-       for (i = 0; i < 5; i++) rleBlitScaleInv(backBuffer + PIXEL_PADDING, FB_WIDTH, FB_HEIGHT, BB_SIZE, rlePropeller, 134 + (i-3) * 60, 200, 1.0f, 1.8f);
+       for (i = 0; i < 5; i++)
+               rleBlitScaleInv(rlePropeller, backBuffer + PIXEL_PADDING, FB_WIDTH, FB_HEIGHT,
+                               BB_SIZE, 134 + (i - 3) * 60, 200, 1.0f, 1.8f);
 
        /* Perform displacement */
        dst = backBuffer + HORIZON_HEIGHT * BB_SIZE + PIXEL_PADDING;
@@ -202,9 +178,11 @@ static void draw(void)
 
                for (i = 0; i < FB_WIDTH; i++) {
                        /* Try to immitate modulo without the division */
-                       if (i == md) accum += md;
+                       if (i == md)
+                               accum += md;
                        scrolledIndex = i - accum + sc;
-                       if (scrolledIndex >= md) scrolledIndex -= md;
+                       if (scrolledIndex >= md)
+                               scrolledIndex -= md;
 
                        /* Displace */
                        d = dispScanline[scrolledIndex];
@@ -216,7 +194,9 @@ static void draw(void)
        }
 
        /* Then after displacement, blit the objects */
-       for (i = 0; i < 5; i++) rleBlit(backBuffer + PIXEL_PADDING, FB_WIDTH, FB_HEIGHT, BB_SIZE, rlePropeller, 134 + (i-3) * 60, 100);
+       for (i = 0; i < 5; i++)
+               rleBlit(rlePropeller, backBuffer + PIXEL_PADDING, FB_WIDTH, FB_HEIGHT, BB_SIZE,
+                       134 + (i - 3) * 60, 100);
 
        /* Blit effect to framebuffer */
        src = backBuffer + PIXEL_PADDING;
@@ -235,9 +215,9 @@ static void convert32To16(unsigned int *src32, unsigned short *dst16, unsigned i
        unsigned int p;
        while (pixelCount) {
                p = *src32++;
-               *dst16++ =      ((p << 8) & 0xF800)             /* R */
-                       |               ((p >> 5) & 0x07E0)             /* G */
-                       |               ((p >> 19) & 0x001F);   /* B */
+               *dst16++ = ((p << 8) & 0xF800)     /* R */
+                          | ((p >> 5) & 0x07E0)   /* G */
+                          | ((p >> 19) & 0x001F); /* B */
                pixelCount--;
        }
 }
@@ -252,20 +232,22 @@ static void processNormal() {
        short minDisplacement = 256;
        unsigned short *dst;
        short *dst2;
-       unsigned int *normalmap = (unsigned int*)background;
+       unsigned int *normalmap = (unsigned int *)background;
        normalmap += NORMALMAP_SCANLINE * backgroundW;
-       dst = (unsigned short*)normalmap;
-       displacementMap = (short*)dst;
+       dst = (unsigned short *)normalmap;
+       displacementMap = (short *)dst;
        dst2 = displacementMap;
 
        for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) {
-               scrollModTable[scanline] = (int) (backgroundW / scrollScaleTable[scanline] + 0.5f);
+               scrollModTable[scanline] = (int)(backgroundW / scrollScaleTable[scanline] + 0.5f);
                for (i = 0; i < backgroundW; i++) {
                        x = (int)(i * scrollScaleTable[scanline] + 0.5f);
                        if (x < backgroundW) {
                                *dst = (unsigned short)(normalmap[x] >> 8) & 0xFF;
-                               if ((short)*dst > maxDisplacement) maxDisplacement = (short)(*dst);
-                               if ((short)*dst < minDisplacement) minDisplacement = (short)(*dst);
+                               if ((short)*dst > maxDisplacement)
+                                       maxDisplacement = (short)(*dst);
+                               if ((short)*dst < minDisplacement)
+                                       minDisplacement = (short)(*dst);
                        } else {
                                *dst = 0;
                        }
@@ -282,9 +264,13 @@ static void processNormal() {
        /* Second pass - subtract half maximum displacement to displace in both directions */
        for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) {
                for (i = 0; i < backgroundW; i++) {
-                       /* Remember that MIN_SCROLL is the padding around the screen, so ti's the maximum displacement we can get (positive & negative) */
-                       *dst2 = 2 * MAX_DISPLACEMENT * (*dst2 - minDisplacement) / (maxDisplacement - minDisplacement) - MAX_DISPLACEMENT;
-                       *dst2 = (short)((float)*dst2 / scrollScaleTable[scanline] + 0.5f); /* Displacements must also scale with distance*/
+                       /* Remember that MIN_SCROLL is the padding around the screen, so ti's the
+                        * maximum displacement we can get (positive & negative) */
+                       *dst2 = 2 * MAX_DISPLACEMENT * (*dst2 - minDisplacement) /
+                                   (maxDisplacement - minDisplacement) -
+                               MAX_DISPLACEMENT;
+                       *dst2 = (short)((float)*dst2 / scrollScaleTable[scanline] +
+                                       0.5f); /* Displacements must also scale with distance*/
                        dst2++;
                }
        }
@@ -306,12 +292,11 @@ static void initScrollTables() {
        }
 }
 
-
 static void updateScrollTables(float dt) {
        int i = 0;
 
        nearScrollAmount += dt * NEAR_SCROLL_SPEED;
-       nearScrollAmount = (float) fmod(nearScrollAmount, 512.0f);
+       nearScrollAmount = (float)fmod(nearScrollAmount, 512.0f);
 
        for (i = 0; i < REFLECTION_HEIGHT; i++) {
                scrollTable[i] = nearScrollAmount / scrollScaleTable[i];
@@ -320,298 +305,9 @@ static void updateScrollTables(float dt) {
 }
 
 /* -------------------------------------------------------------------------------------------------
- *                                   RLE STUFF
+ *                                   PROPELLER STUFF
  * -------------------------------------------------------------------------------------------------
  */
-/* Limit streak count per scanline so we can directly jump to specific scanline */
-#define RLE_STREAKS_PER_SCANLINE 4
-/* Every streak is encoded by 2 bytes: offset and count of black pixels in the streak */
-#define RLE_BYTES_PER_SCANLINE RLE_STREAKS_PER_SCANLINE * 2
-#define RLE_FILL_COLOR 0
-#define RLE_FILL_COLOR_32 ((RLE_FILL_COLOR << 16) | RLE_FILL_COLOR)
-
-#define RLE_FIXED_BITS 16
-
-static int rleByteCount(int w, int h) {
-       return h * RLE_BYTES_PER_SCANLINE + w;
-}
-
-static RLEBitmap *rleCreate(unsigned int w, unsigned int h) {
-       RLEBitmap *ret = (RLEBitmap*)malloc(sizeof(RLEBitmap));
-       ret->w = w;
-       ret->h = h;
-
-       /* Add some padding at the end of the buffer, with the worst case for a scanline (w/2 streaks) */
-       ret->scans = (unsigned char*) calloc(rleByteCount(w, h), 1);
-
-       return ret;
-}
-
-static void rleDestroy(RLEBitmap *b) {
-       if (!b) return;
-       free(b->scans);
-       free(b);
-}
-
-static RLEBitmap *rleEncode(RLEBitmap *b, unsigned char *pixels, unsigned int w, unsigned int h) {
-       int scanline;
-       int i;
-       int penActive = 0;
-       int counter = 0;
-       int accum = 0;
-       unsigned char *output;
-
-       /* https://www.youtube.com/watch?v=RKMR02o1I88&feature=youtu.be&t=55 */
-       if (!b) b = rleCreate(w, h);
-       else memset(b->scans, 0, rleByteCount(b->w, b->h)); /* The following code assumes cleared array */
-
-       for (scanline = 0; scanline < h; scanline++) {
-               output = b->scans + scanline * RLE_BYTES_PER_SCANLINE;
-               accum = 0;
-               for (i = 0; i < w; i++) {
-                       if (*pixels++) {
-                               if (penActive) {
-                                       if (counter >= PIXEL_PADDING) {
-                                               *output++ = (unsigned char) counter;
-                                               counter = 0;
-                                               *output++ = (unsigned char)accum;
-                                       }
-                                       counter++;
-                                       accum++;
-                               } else {
-                                       *output++ = (unsigned char)accum;
-                                       counter = 1;
-                                       accum++;
-                                       penActive = 1;
-                               }
-                       } else {
-                               if (penActive) {
-                                       *output++ = (unsigned char)counter;
-                                       counter = 1;
-                                       accum++;
-                                       penActive = 0;
-                               } else {
-                                       counter++;
-                                       accum++;
-                               }
-                       }
-               }
-
-               if (penActive) {
-                       *output++ = (unsigned char)counter;
-               }
-               penActive = 0;
-               counter = 0;
-       }
-
-       return b;
-}
-
-static void rleDistributeStreaks(RLEBitmap *bitmap) {
-       int scanline, halfW = bitmap->w >> 1;
-       unsigned char *ptr, tmp;
-
-       ptr = bitmap->scans;
-       for (scanline = 0; scanline < bitmap->h; scanline++) {
-               if (ptr[0] >= halfW) {
-                       tmp = ptr[0];
-                       ptr[0] = ptr[6];
-                       ptr[6] = tmp;
-                       tmp = ptr[1];
-                       ptr[1] = ptr[7];
-                       ptr[7] = tmp;
-               }
-
-               ptr += 8;
-       }
-}
-
-static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride,
-       RLEBitmap *bitmap, int blitX, int blitY)
-{
-       int scanline = 0;
-       int streakPos = 0;
-       int streakLength = 0;
-       int streak = 0;
-       unsigned char *input = bitmap->scans;
-       unsigned short *output;
-       unsigned int *output32;
-
-       dst += blitX + blitY * dstStride;
-
-       for (scanline = blitY; scanline < blitY + bitmap->h; scanline++) {
-               if (scanline < 0 || scanline >= dstH) continue;
-               for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) {
-                       streakPos = *input++;
-                       streakLength = *input++;
-
-                       if ((streakPos + blitX) <= 0) continue;
-
-                       output = dst + streakPos;
-
-                       /* Check if we need to write the first pixel as 16bit */
-                       if (streakLength % 2) {
-                               *output++ = RLE_FILL_COLOR;
-                       }
-
-                       /* Then, write 2 pixels at a time */
-                       streakLength >>= 1;
-                       output32 = (unsigned int*) output;
-                       while (streakLength--) {
-                               *output32++ = RLE_FILL_COLOR_32;
-                       }
-               }
-
-               dst += dstStride;
-       }
-}
-
-static void interpolateScan(unsigned char *output, unsigned char *a, unsigned char *b, float t) {
-       static int div = 1 << 23;
-       int ti, i;
-
-       t += 1.0f;
-       ti = (*((unsigned int*)&t)) & 0x7FFFFF;
-
-       for (i = 0; i < RLE_BYTES_PER_SCANLINE; i++) {
-               if (*a == 0) {
-                       *output++ = *b++;
-                       a++;
-               } else {
-                       if (*b == 0) {
-                               *output++ = *a++;
-                               b++;
-                       } else {
-                               *output++ = ((*b++ * ti) + (*a++ * (div - ti))) >> 23;
-                       }
-               }
-       }
-}
-
-static void rleBlitScale(unsigned short *dst, int dstW, int dstH, int dstStride,
-       RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY)
-{
-       int scanline = 0;
-       int streakPos = 0;
-       int streakLength = 0;
-       int streak = 0;
-       unsigned short *output;
-       unsigned int *output32;
-       unsigned char *input;
-       int scanlineCounter = 0;
-       int scaleXFixed;
-       static unsigned char scan[512];
-
-       /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/
-       int blitH = (int)(bitmap->h * scaleY + 0.5f);
-
-       /* From this point on, scaleY will be inverted */
-       scaleY = 1.0f / scaleY;
-
-       scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f);
-
-       dst += blitX + blitY * dstStride;
-
-       for (scanline = blitY; scanline < blitY + blitH; scanline++) {
-               float normalScan = scanlineCounter * scaleY; /* ScaleY  is inverted */
-               unsigned char *scan0 = bitmap->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan;
-               unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE;
-               normalScan -= (int)normalScan;
-               interpolateScan(scan, scan0, scan1, normalScan);
-               input = scan;
-               scanlineCounter++;
-
-               if (scanline < 0 || scanline >= dstH) continue;
-               for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) {
-                       streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS;
-                       streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS;
-
-                       if ((streakPos + blitX) <= 0) continue;
-
-                       output = dst + streakPos;
-
-                       /* Check if we need to write the first pixel as 16bit */
-                       if (streakLength % 2) {
-                               *output++ = RLE_FILL_COLOR;
-                       }
-
-                       /* Then, write 2 pixels at a time */
-                       streakLength >>= 1;
-                       output32 = (unsigned int*)output;
-                       while (streakLength--) {
-                               *output32++ = RLE_FILL_COLOR_32;
-                       }
-               }
-
-               dst += dstStride;
-       }
-}
-
-
-
-static void rleBlitScaleInv(unsigned short *dst, int dstW, int dstH, int dstStride,
-       RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY)
-{
-       int scanline = 0;
-       int streakPos = 0;
-       int streakLength = 0;
-       int streak = 0;
-       unsigned short *output;
-       unsigned int *output32;
-       unsigned char *input;
-       int scanlineCounter = 0;
-       int scaleXFixed;
-       static unsigned char scan[512];
-
-       /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/
-       int blitH = (int)(bitmap->h * scaleY + 0.5f);
-
-       /* From this point on, scaleY will be inverted */
-       scaleY = 1.0f / scaleY;
-
-       scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f);
-
-       dst += blitX + blitY * dstStride;
-
-       for (scanline = blitY; scanline > blitY - blitH; scanline--) {
-               float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */
-               unsigned char *scan0 = bitmap->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan;
-               unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE;
-               normalScan -= (int)normalScan;
-               interpolateScan(scan, scan0, scan1, normalScan);
-               input = scan;
-               scanlineCounter++;
-
-               if (scanline < 0 || scanline >= dstH) continue;
-               for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) {
-                       streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS;
-                       streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS;
-
-                       if ((streakPos + blitX) <= 0) continue;
-
-                       output = dst + streakPos;
-
-                       /* Check if we need to write the first pixel as 16bit */
-                       if (streakLength % 2) {
-                               *output++ = RLE_FILL_COLOR;
-                       }
-
-                       /* Then, write 2 pixels at a time */
-                       streakLength >>= 1;
-                       output32 = (unsigned int*)output;
-                       while (streakLength--) {
-                               *output32++ = RLE_FILL_COLOR_32;
-                       }
-               }
-
-               dst -= dstStride;
-       }
-}
-
-/* -------------------------------------------------------------------------------------------------
-*                                   PROPELLER STUFF
-* -------------------------------------------------------------------------------------------------
-*/
 
 #define PROPELLER_CIRCLE_RADIUS 18
 #define PROPELLER_CIRCLE_RADIUS_SQ (PROPELLER_CIRCLE_RADIUS * PROPELLER_CIRCLE_RADIUS)
@@ -667,17 +363,20 @@ static void updatePropeller(float t) {
                        /* First circle */
                        cx = propellerState.circleX[0] - i;
                        cy = propellerState.circleY[0] - j;
-                       if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++;
+                       if (cx * cx + cy * cy < PROPELLER_CIRCLE_RADIUS_SQ)
+                               count++;
 
                        /* 2nd circle */
                        cx = propellerState.circleX[1] - i;
                        cy = propellerState.circleY[1] - j;
-                       if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++;
+                       if (cx * cx + cy * cy < PROPELLER_CIRCLE_RADIUS_SQ)
+                               count++;
 
                        /* 3rd circle */
                        cx = propellerState.circleX[2] - i;
                        cy = propellerState.circleY[2] - j;
-                       if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++;
+                       if (cx * cx + cy * cy < PROPELLER_CIRCLE_RADIUS_SQ)
+                               count++;
 
                        *dst++ = count >= 2;
                }
diff --git a/src/scr/minifx.c b/src/scr/minifx.c
new file mode 100644 (file)
index 0000000..84f9c38
--- /dev/null
@@ -0,0 +1,169 @@
+#include "demo.h"
+#include "imago2.h"
+#include "screen.h"
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "rlebmap.h"
+
+/* APPROX. 170 FPS Minimum */
+
+static int init(void);
+static void destroy(void);
+static void start(long trans_time);
+static void stop(long trans_time);
+static void draw(void);
+
+static void updatePropeller(float t, RleBitmap *rle);
+
+static unsigned short *backBuffer;
+
+static unsigned char miniFXBuffer[1024];
+
+static long lastFrameTime = 0;
+
+static struct screen scr = {"minifx", init, destroy, start, 0, draw};
+
+struct screen *minifx_screen(void) {
+       return &scr;
+}
+
+static int init(void) {
+       /* Allocate back buffer */
+       backBuffer = calloc(FB_WIDTH * FB_HEIGHT, sizeof(unsigned short));
+
+       return 0;
+}
+
+static void destroy(void) {
+       free(backBuffer);
+       backBuffer = 0;
+}
+
+static void start(long trans_time) { lastFrameTime = time_msec; }
+
+static void draw(void) {
+       long lastFrameDuration;
+       int i, stride;
+       RleBitmap *rle;
+       int clearColor;
+       unsigned short clearColor16;
+
+       lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f;
+       lastFrameTime = time_msec;
+
+       clearColor = 0x888888;
+       clearColor16 = ((clearColor << 8) & 0xF800)     /* R */
+                          | ((clearColor >> 5) & 0x07E0)   /* G */
+                          | ((clearColor >> 19) & 0x001F); /* B */
+
+       for (i=0; i<FB_WIDTH * FB_HEIGHT; i++) {
+               backBuffer[i] = clearColor16;
+       }
+
+       /* For now create / destroy in each frame. We will manage these later */
+       rle = rleCreate(32, 32);
+
+       updatePropeller(time_msec / 1000.0f, rle);
+       stride = FB_WIDTH;
+       /*
+       rleBlit(rle, backBuffer, FB_WIDTH, FB_HEIGHT, stride,
+                       100, 100);
+       */
+
+       rleBlitScale(rle, backBuffer, FB_WIDTH, FB_HEIGHT, stride, 50,
+                 50, 3.0, 3.0);
+
+       rleDestroy(rle);
+
+       /* Blit effect to framebuffer */
+       memcpy(fb_pixels, backBuffer, FB_WIDTH * FB_HEIGHT * sizeof(unsigned short));
+       swap_buffers(0);
+}
+
+
+#define PROPELLER_CIRCLE_RADIUS 18
+#define PROPELLER_CIRCLE_RADIUS_SQ (PROPELLER_CIRCLE_RADIUS * PROPELLER_CIRCLE_RADIUS)
+
+static struct {
+       int circleX[3];
+       int circleY[3];
+} propellerState;
+
+static void updatePropeller(float t, RleBitmap *rle) {
+
+       int i, j;
+       int cx, cy, count = 0;
+       unsigned char *dst;
+       float x = 0.0f;
+       float y = 18.0f;
+       float nx, ny;
+       float cost, sint;
+       static float sin120 = 0.86602540378f;
+       static float cos120 = -0.5f;
+
+       t *= 0.1; /* Slow-mo to see what happens */
+
+       /* Rotate */
+       sint = sin(t);
+       cost = cos(t);
+       nx = x * cost - y * sint;
+       ny = y * cost + x * sint;
+       x = nx;
+       y = ny;
+       propellerState.circleX[0] = (int)(x + 0.5f) + 16;
+       propellerState.circleY[0] = (int)(y + 0.5f) + 16;
+
+       /* Rotate by 120 degrees, for the second circle */
+       nx = x * cos120 - y * sin120;
+       ny = y * cos120 + x * sin120;
+       x = nx;
+       y = ny;
+       propellerState.circleX[1] = (int)(x + 0.5f) + 16;
+       propellerState.circleY[1] = (int)(y + 0.5f) + 16;
+
+       /* 3rd circle */
+       nx = x * cos120 - y * sin120;
+       ny = y * cos120 + x * sin120;
+       x = nx;
+       y = ny;
+       propellerState.circleX[2] = (int)(x + 0.5f) + 16;
+       propellerState.circleY[2] = (int)(y + 0.5f) + 16;
+
+       /* Write effect to the mini fx buffer*/
+       dst = miniFXBuffer;
+       for (j = 0; j < 32; j++) {
+               for (i = 0; i < 32; i++) {
+                       count = 0;
+
+                       /* First circle */
+                       cx = propellerState.circleX[0] - i;
+                       cy = propellerState.circleY[0] - j;
+                       if (cx * cx + cy * cy < PROPELLER_CIRCLE_RADIUS_SQ)
+                               count++;
+
+                       /* 2nd circle */
+                       cx = propellerState.circleX[1] - i;
+                       cy = propellerState.circleY[1] - j;
+                       if (cx * cx + cy * cy < PROPELLER_CIRCLE_RADIUS_SQ)
+                               count++;
+
+                       /* 3rd circle */
+                       cx = propellerState.circleX[2] - i;
+                       cy = propellerState.circleY[2] - j;
+                       if (cx * cx + cy * cy < PROPELLER_CIRCLE_RADIUS_SQ)
+                               count++;
+
+                       *dst++ = count >= 2;
+               }
+       }
+
+       /* Then, encode to rle */
+       rleEncode(rle, miniFXBuffer, 32, 32);
+
+       /* Distribute the produced streaks so that they don't produce garbage when interpolated */
+       rleDistributeStreaks(rle);
+}
diff --git a/src/scr/raytrace.c b/src/scr/raytrace.c
new file mode 100644 (file)
index 0000000..1593d9f
--- /dev/null
@@ -0,0 +1,239 @@
+#include <stdio.h>
+#include <math.h>
+#include "demo.h"
+#include "screen.h"
+#include "gfxutil.h"
+#include "util.h"
+#include "cgmath/cgmath.h"
+#include "rt.h"
+
+static int init(void);
+static void destroy(void);
+static void start(long trans_time);
+static void draw(void);
+
+static struct screen scr = {
+       "raytrace",
+       init,
+       destroy,
+       start,
+       0,
+       draw
+};
+
+struct tile {
+       int x, y;
+       uint16_t *fbptr;
+};
+
+#define TILESZ         16
+#define NUM_TILES      ((320 / TILESZ) * (240 / TILESZ))
+
+static cgm_vec3 raydir[240][320];
+static struct tile tiles[NUM_TILES];
+static struct rtscene scn;
+
+struct screen *raytrace_screen(void)
+{
+       return &scr;
+}
+
+static int init(void)
+{
+       int i, j, k;
+       float z = 1.0f / tan(cgm_deg_to_rad(25.0f));
+       struct tile *tptr = tiles;
+
+       for(i=0; i<240; i++) {
+               cgm_vec3 *vptr = raydir[i];
+               float y = 1.0f - (float)i / 120.0f;
+               for(j=0; j<320; j++) {
+                       vptr->x = ((float)j / 160.0f - 1.0f) * 1.333333f;
+                       vptr->y = y;
+                       vptr->z = z;
+                       vptr++;
+
+                       if(((j & (TILESZ-1)) | (i & (TILESZ-1))) == 0) {
+                               tptr->x = j;
+                               tptr->y = i;
+                               tptr->fbptr = fb_pixels + i * 320 + j;
+                               tptr++;
+                       }
+               }
+       }
+
+       rt_init(&scn);
+
+       rt_color(1, 0, 0);
+       rt_specular(0.8f, 0.8f, 0.8f);
+       rt_shininess(30.0f);
+       rt_add_sphere(&scn, 0, 0, 0, 1);        /* x,y,z, rad */
+
+       rt_color(0.4, 0.4, 0.4);
+       rt_specular(0, 0, 0);
+       rt_shininess(1);
+       rt_add_plane(&scn, 0, 1, 0, -1);                /* nx,ny,nz, dist */
+
+       rt_color(1, 1, 1);
+       rt_add_light(&scn, -8, 15, -10);
+       return 0;
+}
+
+static void destroy(void)
+{
+       rt_destroy(&scn);
+}
+
+static void start(long start_time)
+{
+}
+
+static uint16_t INLINE rend_pixel(int x, int y)
+{
+       int r, g, b;
+       cgm_ray ray;
+       cgm_vec3 col;
+
+       ray.dir = raydir[y][x];
+       cgm_vcons(&ray.origin, 0, 0, -5);
+
+       if(ray_trace(&ray, &scn, 0, &col)) {
+               r = cround64(col.x * 255.0f);
+               g = cround64(col.y * 255.0f);
+               b = cround64(col.z * 255.0f);
+               if(r > 255) r = 255;
+               if(g > 255) g = 255;
+               if(b > 255) b = 255;
+               return PACK_RGB16(r, g, b);
+       }
+       return 0;
+}
+
+#define CMPMASK                0xe79c
+static void rend_tile(uint16_t *fbptr, int x0, int y0, int tsz, int valid)
+{
+       uint16_t *cptr[4];
+       uint16_t cpix[4], tmp;
+       uint32_t pp0, pp1, pp2, pp3, *fb32;
+       int i, x1, y1, offs;
+
+       fb32 = (uint32_t*)fbptr;
+
+       if(tsz <= 2) {
+               switch(valid) {
+               case 0:
+                       fbptr[1] = fbptr[320] = fbptr[321] = *fbptr;
+                       break;
+               case 1:
+                       fbptr[0] = fbptr[320] = fbptr[321] = fbptr[1];
+                       break;
+               case 2:
+                       fbptr[0] = fbptr[1] = fbptr[321] = fbptr[320];
+                       break;
+               case 3:
+                       fbptr[0] = fbptr[1] = fbptr[320] = fbptr[321];
+                       break;
+               default:
+                       printf("valid = %d\n", valid);
+                       fbptr[0] = fbptr[1] = fbptr[320] = fbptr[321] = 0xff00;
+               }
+               return;
+       }
+
+       offs = tsz - 1;
+       x1 = x0 + offs;
+       y1 = y0 + offs;
+
+       cptr[0] = fbptr;
+       cptr[1] = fbptr + tsz - 1;
+       cptr[2] = fbptr + (offs << 8) + (offs << 6);
+       cptr[3] = cptr[2] + tsz - 1;
+
+       cpix[0] = valid == 0 ? *cptr[0] : rend_pixel(x0, y0);
+       cpix[1] = valid == 1 ? *cptr[1] : rend_pixel(x1, y0);
+       cpix[2] = valid == 2 ? *cptr[2] : rend_pixel(x0, y1);
+       cpix[3] = valid == 3 ? *cptr[3] : rend_pixel(x1, y1);
+
+       tmp = cpix[0] & CMPMASK;
+       if((cpix[1] & CMPMASK) != tmp) goto subdiv;
+       if((cpix[2] & CMPMASK) != tmp) goto subdiv;
+       if((cpix[3] & CMPMASK) != tmp) goto subdiv;
+
+       pp0 = cpix[0] | ((uint32_t)cpix[0] << 16);
+       pp1 = cpix[1] | ((uint32_t)cpix[1] << 16);
+       pp2 = cpix[2] | ((uint32_t)cpix[2] << 16);
+       pp3 = cpix[3] | ((uint32_t)cpix[3] << 16);
+
+       switch(tsz) {
+       case 2:
+#ifdef SUBDBG
+               pp0 = 0x18ff;
+#endif
+               fb32[0] = fb32[160] = pp0;
+               break;
+       case 4:
+#ifdef SUBDBG
+               pp0 = pp1 = pp2 = pp3 = 0x03800380;
+#endif
+               fb32[0] = fb32[160] = pp0;
+               fb32[1] = fb32[161] = pp1;
+               fb32[320] = fb32[480] = pp2;
+               fb32[321] = fb32[481] = pp3;
+               break;
+       case 8:
+#ifdef SUBDBG
+               pp1 = pp0 = pp2 = pp3 = 0xe00fe00f;
+#endif
+               fb32[0] = fb32[1] = pp0; fb32[2] = fb32[3] = pp1;
+               fb32[160] = fb32[161] = pp0; fb32[162] = fb32[163] = pp1;
+               fb32[320] = fb32[321] = pp0; fb32[322] = fb32[323] = pp1;
+               fb32[480] = fb32[481] = pp0; fb32[482] = fb32[483] = pp1;
+               fb32[640] = fb32[641] = pp2; fb32[642] = fb32[643] = pp3;
+               fb32[800] = fb32[801] = pp2; fb32[802] = fb32[803] = pp3;
+               fb32[960] = fb32[961] = pp2; fb32[962] = fb32[963] = pp3;
+               fb32[1120] = fb32[1121] = pp2; fb32[1122] = fb32[1123] = pp3;
+               break;
+
+       case 16:
+#ifdef SUBDBG
+               pp0 = 0xff00ff00;
+#endif
+               for(i=0; i<4; i++) {
+                       memset16(fbptr, pp0, 16); fbptr += 320;
+                       memset16(fbptr, pp0, 16); fbptr += 320;
+                       memset16(fbptr, pp0, 16); fbptr += 320;
+                       memset16(fbptr, pp0, 16); fbptr += 320;
+               }
+               break;
+       }
+       return;
+
+subdiv:
+       *cptr[0] = cpix[0];
+       *cptr[1] = cpix[1];
+       *cptr[2] = cpix[2];
+       *cptr[3] = cpix[3];
+
+       tsz >>= 1;
+       rend_tile(fbptr, x0, y0, tsz, 0);
+       rend_tile(fbptr + tsz, x0 + tsz, y0, tsz, 1);
+       fbptr += (tsz << 8) + (tsz << 6);
+       y0 += tsz;
+       rend_tile(fbptr, x0, y0, tsz, 2);
+       rend_tile(fbptr + tsz, x0 + tsz, y0, tsz, 3);
+}
+
+static void draw(void)
+{
+       int i, j, xbound, ybound;
+       uint16_t *fbptr;
+       struct tile *tile;
+
+       tile = tiles;
+       for(i=0; i<NUM_TILES; i++) {
+               rend_tile(tile->fbptr, tile->x, tile->y, TILESZ, -1);
+               tile++;
+       }
+
+       swap_buffers(0);
+}
diff --git a/src/scr/rt.c b/src/scr/rt.c
new file mode 100644 (file)
index 0000000..13f2dbe
--- /dev/null
@@ -0,0 +1,261 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <float.h>
+#include "rt.h"
+#include "util.h"
+#include "darray.h"
+
+static cgm_vec3 cur_col, cur_spec;
+static float cur_shin;
+static struct image *cur_tex;
+
+void rt_init(struct rtscene *scn)
+{
+       scn->obj = darr_alloc(0, sizeof *scn->obj);
+       scn->num_obj = 0;
+       scn->lt = darr_alloc(0, sizeof *scn->lt);
+       scn->num_lt = 0;
+
+       cgm_vcons(&cur_col, 1, 1, 1);
+       cgm_vcons(&cur_spec, 0, 0, 0);
+       cur_shin = 1;
+       cur_tex = 0;
+}
+
+void rt_destroy(struct rtscene *scn)
+{
+       darr_free(scn->obj);
+       darr_free(scn->lt);
+       memset(scn, 0, sizeof *scn);
+}
+
+
+void rt_color(float r, float g, float b)
+{
+       cgm_vcons(&cur_col, r, g, b);
+}
+
+void rt_specular(float r, float g, float b)
+{
+       cgm_vcons(&cur_spec, r, g, b);
+}
+
+void rt_shininess(float s)
+{
+       cur_shin = s;
+}
+
+static union rtobject *add_object(struct rtscene *scn, enum rt_obj_type type)
+{
+       union rtobject *obj;
+
+       obj = calloc_nf(1, sizeof *obj);
+       obj->type = type;
+
+       obj->x.mtl.kd = cur_col;
+       obj->x.mtl.ks = cur_spec;
+       obj->x.mtl.shin = cur_shin;
+       obj->x.mtl.tex = cur_tex;
+
+       darr_push(scn->obj, &obj);
+       scn->num_obj = darr_size(scn->obj);
+       return obj;
+}
+
+union rtobject *rt_add_sphere(struct rtscene *scn, float x, float y, float z, float r)
+{
+       union rtobject *obj = add_object(scn, RT_SPH);
+       cgm_vcons(&obj->s.p, x, y, z);
+       obj->s.r = r;
+       return obj;
+}
+
+union rtobject *rt_add_plane(struct rtscene *scn, float nx, float ny, float nz, float d)
+{
+       union rtobject *obj = add_object(scn, RT_PLANE);
+       cgm_vcons(&obj->p.n, nx, ny, nz);
+       obj->p.d = d;
+       return obj;
+}
+
+struct rtlight *rt_add_light(struct rtscene *scn, float x, float y, float z)
+{
+       struct rtlight *lt = calloc_nf(1, sizeof *lt);
+
+       cgm_vcons(&lt->p, x, y, z);
+       lt->color = cur_col;
+
+       darr_push(scn->lt, &lt);
+       scn->num_lt = darr_size(scn->lt);
+       return lt;
+}
+
+
+/* color is initialized to black */
+static void shade(struct rayhit *hit, struct rtscene *scn, int lvl, cgm_vec3 *color)
+{
+       int i;
+       float ndotl, vdotr, spec;
+       cgm_ray sray;
+       cgm_vec3 col, rdir;
+       struct rtlight *lt;
+       struct rtmaterial *mtl = &hit->obj->x.mtl;
+
+       sray.origin = hit->p;
+       cgm_vnormalize(&hit->n);
+       cgm_vnormalize(&hit->ray->dir);
+
+       for(i=0; i<scn->num_lt; i++) {
+               lt = scn->lt[i];
+               sray.dir = lt->p;
+               cgm_vsub(&sray.dir, &sray.origin);
+
+               if(ray_scene(&sray, scn, 1.0f, 0)) continue;
+
+               cgm_vnormalize(&sray.dir);
+               ndotl = cgm_vdot(&sray.dir, &hit->n);
+               if(ndotl < 0.0f) ndotl = 0.0f;
+
+               rdir = hit->ray->dir;
+               cgm_vreflect(&rdir, &hit->n);
+               vdotr = cgm_vdot(&sray.dir, &rdir);
+               if(vdotr < 0.0f) vdotr = 0.0f;
+               spec = pow(vdotr, mtl->shin);
+
+               color->x += (mtl->kd.x * ndotl + mtl->ks.x * spec) * lt->color.x;
+               color->y += (mtl->kd.y * ndotl + mtl->ks.y * spec) * lt->color.y;
+               color->z += (mtl->kd.z * ndotl + mtl->ks.z * spec) * lt->color.z;
+       }
+}
+
+int ray_trace(cgm_ray *ray, struct rtscene *scn, int lvl, cgm_vec3 *color)
+{
+       struct rayhit hit;
+
+       color->x = color->y = color->z = 0.0f;
+       if(!ray_scene(ray, scn, FLT_MAX, &hit)) {
+               return 0;
+       }
+       hit.ray = ray;
+       shade(&hit, scn, lvl, color);
+       return 1;
+}
+
+
+int ray_scene(cgm_ray *ray, struct rtscene *scn, float maxt, struct rayhit *hit)
+{
+       int i;
+
+       if(hit) {
+               struct rayhit hit0 = {FLT_MAX};
+
+               /* find nearest hit */
+               for(i=0; i<scn->num_obj; i++) {
+                       if(ray_object(ray, scn->obj[i], maxt, hit) && hit->t < hit0.t) {
+                               hit0 = *hit;
+                       }
+               }
+
+               if(hit0.obj) {
+                       *hit = hit0;
+                       return 1;
+               }
+       } else {
+               /* find any hit */
+               for(i=0; i<scn->num_obj; i++) {
+                       if(ray_object(ray, scn->obj[i], maxt, 0)) {
+                               return 1;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+int ray_object(cgm_ray *ray, union rtobject *obj, float maxt, struct rayhit *hit)
+{
+       switch(obj->type) {
+       case RT_SPH:
+               return ray_sphere(ray, &obj->s, maxt, hit);
+       case RT_PLANE:
+               return ray_plane(ray, &obj->p, maxt, hit);
+       default:
+               break;
+       }
+       return 0;
+}
+
+#define SQ(x)  ((x) * (x))
+int ray_sphere(cgm_ray *ray, struct rtsphere *sph, float maxt, struct rayhit *hit)
+{
+       float a, a2, b, c, d, sqrt_d, t1, t2;
+
+       a = SQ(ray->dir.x) + SQ(ray->dir.y) + SQ(ray->dir.z);
+       b = 2.0f * ray->dir.x * (ray->origin.x - sph->p.x) +
+               2.0f * ray->dir.y * (ray->origin.y - sph->p.y) +
+               2.0f * ray->dir.z * (ray->origin.z - sph->p.z);
+       c = SQ(sph->p.x) + SQ(sph->p.y) + SQ(sph->p.z) +
+               SQ(ray->origin.x) + SQ(ray->origin.y) + SQ(ray->origin.z) +
+               2.0f * (-sph->p.x * ray->origin.x - sph->p.y * ray->origin.y - sph->p.z * ray->origin.z) -
+               SQ(sph->r);
+
+       if((d = SQ(b) - 4.0f * a * c) < 0.0f) return 0;
+
+       sqrt_d = sqrt(d);
+       a2 = 2.0f * a;
+       t1 = (-b + sqrt_d) / a2;
+       t2 = (-b - sqrt_d) / a2;
+
+       if((t1 < 1e-5f && t2 < 1e-5f) || (t1 > maxt && t2 > maxt)) {
+               return 0;
+       }
+
+       if(hit) {
+               float t;
+               if(t1 < 1e-5f) {
+                       t = t2;
+               } else if(t2 < 1e-5f) {
+                       t = t1;
+               } else {
+                       t = t1 < t2 ? t1 : t2;
+               }
+
+               hit->t = t;
+               cgm_raypos(&hit->p, ray, t);
+
+               hit->n.x = hit->p.x - sph->p.x;
+               hit->n.y = hit->p.y - sph->p.y;
+               hit->n.z = hit->p.z - sph->p.z;
+
+               hit->obj = (union rtobject*)sph;
+       }
+       return 1;
+}
+
+int ray_plane(cgm_ray *ray, struct rtplane *plane, float maxt, struct rayhit *hit)
+{
+       cgm_vec3 vo;
+       float t, ndotdir;
+
+       ndotdir = cgm_vdot(&plane->n, &ray->dir);
+       if(fabs(ndotdir) < 1e-5) {
+               return 0;
+       }
+
+       vo.x = plane->n.x * plane->d - ray->origin.x;
+       vo.y = plane->n.y * plane->d - ray->origin.y;
+       vo.z = plane->n.z * plane->d - ray->origin.z;
+       t = cgm_vdot(&plane->n, &vo) / ndotdir;
+
+       if(t < 1e-5 || t > maxt) return 0;
+
+       if(hit) {
+               hit->t = t;
+               cgm_raypos(&hit->p, ray, t);
+               hit->n = plane->n;
+
+               hit->obj = (union rtobject*)plane;
+       }
+       return 1;
+}
diff --git a/src/scr/rt.h b/src/scr/rt.h
new file mode 100644 (file)
index 0000000..f619a88
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef RT_H_
+#define RT_H_
+
+#include "image.h"
+#include "cgmath/cgmath.h"
+
+struct rtmaterial {
+       cgm_vec3 kd, ks;
+       float shin;
+       struct image *tex;
+};
+
+enum rt_obj_type { RT_SPH, RT_PLANE };
+
+#define OBJ_COMMON     \
+       enum rt_obj_type type; \
+       struct rtmaterial mtl
+
+struct rtany {
+       OBJ_COMMON;
+};
+
+struct rtsphere {
+       OBJ_COMMON;
+       cgm_vec3 p;
+       float r;
+};
+
+struct rtplane {
+       OBJ_COMMON;
+       cgm_vec3 n;
+       float d;
+};
+
+union rtobject {
+       enum rt_obj_type type;
+       struct rtany x;
+       struct rtsphere s;
+       struct rtplane p;
+};
+
+struct rtlight {
+       cgm_vec3 p, color;
+};
+
+struct rayhit {
+       float t;
+       cgm_vec3 p, n;
+       float u, v;
+       cgm_ray *ray;
+       union rtobject *obj;
+};
+
+struct rtscene {
+       union rtobject **obj;
+       int num_obj;
+       struct rtlight **lt;
+       int num_lt;
+};
+
+/* scene management */
+void rt_init(struct rtscene *scn);
+void rt_destroy(struct rtscene *scn);
+
+void rt_color(float r, float g, float b);
+void rt_specular(float r, float g, float b);
+void rt_shininess(float s);
+
+union rtobject *rt_add_sphere(struct rtscene *scn, float x, float y, float z, float r);
+union rtobject *rt_add_plane(struct rtscene *scn, float nx, float ny, float nz, float d);
+struct rtlight *rt_add_light(struct rtscene *scn, float x, float y, float z);
+
+/* returns 0 for no hit */
+int ray_trace(cgm_ray *ray, struct rtscene *scn, int lvl, cgm_vec3 *color);
+
+int ray_object(cgm_ray *ray, union rtobject *obj, float maxt, struct rayhit *hit);
+int ray_scene(cgm_ray *ray, struct rtscene *scn, float maxt, struct rayhit *hit);
+int ray_sphere(cgm_ray *ray, struct rtsphere *sph, float maxt, struct rayhit *hit);
+int ray_plane(cgm_ray *ray, struct rtplane *plane, float maxt, struct rayhit *hit);
+
+#endif /* RT_H_ */
index 062eb57..3aa3b7e 100644 (file)
@@ -377,62 +377,62 @@ unsigned char fog(float z) {
        return (unsigned char)ret;
 }
 
-void sort(PointSprite *begin, PointSprite *end) {\r
-       PointSprite pivotValue;\r
-       size_t sz;\r
-       PointSprite *left, *right;\r
-       int leftCond, rightCond;\r
-       PointSprite tmp;\r
-\r
-       sz = end - begin;\r
-\r
-       if (sz < 2) return; /* already sorted */\r
-       if (sz == 2) {\r
-               /* trivial case */\r
-               if (begin[1] < begin[0]) {\r
-                       tmp = begin[0];\r
-                       begin[0] = begin[1];\r
-                       begin[1] = tmp;\r
-                       return;\r
-               }\r
-       }\r
-\r
-       /* minimum 3 elements from now on */\r
-\r
-       /* choose a pivot near the middle, since we frequently sort already sorted arrays */\r
-       pivotValue = begin[sz / 2];\r
-\r
-       left = begin;\r
-       right = end - 1;\r
-\r
-       while (right > left) {\r
-               /* check if left and right elements meet the conditions */\r
-               leftCond = pivotValue >= *left;\r
-               rightCond = pivotValue < *right;\r
-\r
-               if (!leftCond && !rightCond) {\r
-                       tmp = *left;\r
-                       *left = *right;\r
-                       *right = tmp;\r
-                       left++;\r
-                       right--;\r
-               }\r
-               else if (leftCond && rightCond) {\r
-                       left++;\r
-                       right--;\r
-               }\r
-               else if (leftCond) {\r
-                       left++;\r
-               }\r
-               else {\r
-                       right--;\r
-               }\r
-       }\r
-\r
-       /* recursion */\r
-       sort(begin, left);\r
-       sort(left, end);\r
-}\r
+void sort(PointSprite *begin, PointSprite *end) {
+       PointSprite pivotValue;
+       size_t sz;
+       PointSprite *left, *right;
+       int leftCond, rightCond;
+       PointSprite tmp;
+
+       sz = end - begin;
+
+       if (sz < 2) return; /* already sorted */
+       if (sz == 2) {
+               /* trivial case */
+               if (begin[1] < begin[0]) {
+                       tmp = begin[0];
+                       begin[0] = begin[1];
+                       begin[1] = tmp;
+                       return;
+               }
+       }
+
+       /* minimum 3 elements from now on */
+
+       /* choose a pivot near the middle, since we frequently sort already sorted arrays */
+       pivotValue = begin[sz / 2];
+
+       left = begin;
+       right = end - 1;
+
+       while (right > left) {
+               /* check if left and right elements meet the conditions */
+               leftCond = pivotValue >= *left;
+               rightCond = pivotValue < *right;
+
+               if (!leftCond && !rightCond) {
+                       tmp = *left;
+                       *left = *right;
+                       *right = tmp;
+                       left++;
+                       right--;
+               }
+               else if (leftCond && rightCond) {
+                       left++;
+                       right--;
+               }
+               else if (leftCond) {
+                       left++;
+               }
+               else {
+                       right--;
+               }
+       }
+
+       /* recursion */
+       sort(begin, left);
+       sort(left, end);
+}
 
 void sortPointSprites() {
        sort(pointSprites, pointSprites + pointSpriteCount);
index baf4ec2..190b19f 100644 (file)
@@ -25,6 +25,9 @@ struct screen *metaballs_screen(void);
 struct screen *greets_screen(void);
 struct screen *infcubes_screen(void);
 struct screen *hairball_screen(void);
+struct screen *cybersun_screen(void);
+struct screen *raytrace_screen(void);
+struct screen *minifx_screen(void);
 
 void start_loadscr(void);
 void end_loadscr(void);
@@ -79,6 +82,16 @@ int scr_init(void)
        if(!(scr[idx++] = hairball_screen())) {
                return -1;
        }
+       if(!(scr[idx++] = cybersun_screen())) {
+               return -1;
+       }
+       if(!(scr[idx++] = raytrace_screen())) {
+               return -1;
+       }
+    if (!(scr[idx++] = minifx_screen())) {
+               return -1;
+    }
+    
        num_screens = idx;
 
        assert(num_screens <= NUM_SCR);
@@ -187,7 +200,7 @@ int scr_change(struct screen *s, long trans_time)
 /* loading screen */
 extern uint16_t loading_pixels[];
 static long prev_load_msec;
-static long load_delay = 180;
+static long load_delay;
 
 void start_loadscr(void)
 {
@@ -198,7 +211,9 @@ void start_loadscr(void)
        }
 
        swap_buffers(loading_pixels);
-       sleep_msec(load_delay * 2);
+       if(load_delay) {
+               sleep_msec(load_delay * 2);
+       }
        prev_load_msec = get_msec();
 }
 
@@ -216,7 +231,9 @@ void end_loadscr(void)
        blitfb(loading_pixels + SPLAT_Y * 320 + SPLAT_X, loading_pixels + 320 * 240, 32, 72, 32);
        blit_key(loading_pixels + FING_Y * 320 + FING_LAST_X, 320, loading_pixels + 247 * 320 + 64, FING_W, FING_H, FING_W, 0);
        swap_buffers(loading_pixels);
-       sleep_msec(load_delay * 4);
+       if(load_delay) {
+               sleep_msec(load_delay * 3);
+       }
 }
 
 void loadscr(int n, int count)
index f2487cf..784b208 100644 (file)
@@ -9,6 +9,7 @@
 #include "cfgopt.h"
 #include "sball.h"
 #include "vmath.h"
+#include "cpuid.h"
 
 static void handle_event(SDL_Event *ev);
 static void toggle_fullscreen(void);
@@ -65,6 +66,10 @@ int main(int argc, char **argv)
        SDL_WM_SetCaption("dosdemo/SDL", 0);
        SDL_ShowCursor(0);
 
+       if(read_cpuid(&cpuid) == 0) {
+               print_cpuid(&cpuid);
+       }
+
        time_msec = 0;
        if(demo_init(argc, argv) == -1) {
                /*free(fb_pixels);*/
index 41102e6..269c965 100644 (file)
@@ -4,9 +4,10 @@
 #include "tinyfps.h"
 #include "demo.h"
 
-/* TinyFPS, just a minimal fraps like font to show FPS during the demo and not just after.
- * I'll be using it in my effects for my performance test purposes, just adding it here.
- * Maybe it would be nice if initFpsFonts would be called in demo.c once but I avoided touching that code.
+/* TinyFPS, just a minimal fraps like font to show FPS during the demo and not
+ * just after.  I'll be using it in my effects for my performance test
+ * purposes, just adding it here.  Maybe it would be nice if initFpsFonts would
+ * be called in demo.c once but I avoided touching that code.
  */
 
 /*
index 91adfec..69853c8 100644 (file)
@@ -4,7 +4,7 @@
 #include <errno.h>
 #include "treestor.h"
 
-#if defined(__WATCOMC__) || defined(_MSC_VER) || defined(__DJGPP__)
+#if defined(__WATCOMC__) || defined(WIN32) || defined(__DJGPP__)
 #include <malloc.h>
 #else
 #include <alloca.h>
index a91bb95..2a70ec8 100644 (file)
@@ -1,3 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
 #include "util.h"
+#include "demo.h"
 
 uint32_t perf_start_count, perf_interval_count;
+
+void *malloc_nf_impl(size_t sz, const char *file, int line)
+{
+       void *p;
+       if(!(p = malloc(sz))) {
+               fprintf(stderr, "%s:%d failed to allocate %lu bytes\n", file, line, (unsigned long)sz);
+               demo_abort();
+       }
+       return p;
+}
+
+void *calloc_nf_impl(size_t num, size_t sz, const char *file, int line)
+{
+       void *p;
+       if(!(p = calloc(num, sz))) {
+               fprintf(stderr, "%s:%d failed to allocate %lu bytes\n", file, line, (unsigned long)(num * sz));
+               demo_abort();
+       }
+       return p;
+}
+
+void *realloc_nf_impl(void *p, size_t sz, const char *file, int line)
+{
+       if(!(p = realloc(p, sz))) {
+               fprintf(stderr, "%s:%d failed to realloc %lu bytes\n", file, line, (unsigned long)sz);
+               demo_abort();
+       }
+       return p;
+}
index 8a46036..ec87a4d 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef UTIL_H_
 #define UTIL_H_
 
+#include <stdlib.h>
 #include "inttypes.h"
 
 #ifdef __GNUC__
@@ -110,21 +111,26 @@ void halt(void);
 
 #ifdef __GNUC__
 #if defined(__i386__) || defined(__x86_64__)
-#define memset16(dest, val, count) asm volatile ( \
-       "cld\n\t" \
-       "test $1, %2\n\t" \
-       "jz 0f\n\t" \
-       "rep stosw\n\t" \
-       "jmp 1f\n\t" \
-       "0:\n\t" \
-       "shr $1, %2\n\t" \
-       "push %%ax\n\t" \
-       "shl $16, %%eax\n\t" \
-       "pop %%ax\n\t" \
-       "rep stosl\n\t" \
-       "1:\n\t"\
-       :: "D"(dest), "a"((uint16_t)(val)), "c"(count) \
-       : "memory")
+#define memset16(dest, val, count) \
+       do { \
+               uint32_t dummy1, dummy2; \
+               asm volatile ( \
+                       "cld\n\t" \
+                       "test $1, %%ecx\n\t" \
+                       "jz 0f\n\t" \
+                       "rep stosw\n\t" \
+                       "jmp 1f\n\t" \
+                       "0:\n\t" \
+                       "shr $1, %%ecx\n\t" \
+                       "push %%ax\n\t" \
+                       "shl $16, %%eax\n\t" \
+                       "pop %%ax\n\t" \
+                       "rep stosl\n\t" \
+                       "1:\n\t"\
+                       : "=D"(dummy1), "=c"(dummy2) \
+                       : "0"(dest), "a"((uint16_t)(val)), "1"(count) \
+                       : "flags", "memory"); \
+       } while(0)
 #else
 static void INLINE memset16(void *dest, uint16_t val, int count)
 {
@@ -168,14 +174,14 @@ static void INLINE memset16(void *dest, uint16_t val, int count)
        : "%eax", "%ebx", "%ecx", "%edx")
 
 #define debug_break() \
-       asm volatile ("int $3")
+       asm volatile("int $3")
 
 #define halt() \
        asm volatile("hlt")
 #endif
 
 #ifdef _MSC_VER
-void __inline memset16(void *dest, uint16_t val, int count)
+static void __inline memset16(void *dest, uint16_t val, int count)
 {
        __asm {
                cld
@@ -221,6 +227,36 @@ void __inline memset16(void *dest, uint16_t val, int count)
        do { \
                __asm { int 3 } \
        } while(0)
+
+static unsigned int __inline get_cs(void)
+{
+       unsigned int res;
+       __asm {
+               xor eax, eax
+               mov ax, cs
+               mov [res], ax
+       }
+       return res;
+}
 #endif
 
+unsigned int get_cs(void);
+#define get_cpl()      ((int)(get_cs() & 3))
+
+void get_msr(uint32_t msr, uint32_t *low, uint32_t *high);
+void set_msr(uint32_t msr, uint32_t low, uint32_t high);
+
+
+/* Non-failing versions of malloc/calloc/realloc. They never return 0, they call
+ * demo_abort on failure. Use the macros, don't call the *_impl functions.
+ */
+#define malloc_nf(sz)  malloc_nf_impl(sz, __FILE__, __LINE__)
+void *malloc_nf_impl(size_t sz, const char *file, int line);
+#define calloc_nf(n, sz)       calloc_nf_impl(n, sz, __FILE__, __LINE__)
+void *calloc_nf_impl(size_t num, size_t sz, const char *file, int line);
+#define realloc_nf(p, sz)      realloc_nf_impl(p, sz, __FILE__, __LINE__)
+void *realloc_nf_impl(void *p, size_t sz, const char *file, int line);
+
+
+
 #endif /* UTIL_H_ */
diff --git a/src/util_s.asm b/src/util_s.asm
new file mode 100644 (file)
index 0000000..65198b5
--- /dev/null
@@ -0,0 +1,63 @@
+       section .text
+       bits 32
+; foo_ are watcom functions, _foo are djgpp functions
+
+       global get_cs
+       global _get_cs
+       global get_cs_
+get_cs:
+_get_cs:
+get_cs_:
+       xor eax, eax
+       mov ax, cs
+       ret
+
+       global get_msr
+       global _get_msr
+get_msr:
+_get_msr:
+       push ebp
+       mov ebp, esp
+       push ebx
+       mov ecx, [ebp + 8]
+       rdmsr
+       mov ebx, [ebp + 12]
+       mov [ebx], eax
+       mov ebx, [ebp + 16]
+       mov [ebx], edx
+       pop ebx
+       pop ebp
+       ret
+
+       global get_msr_
+get_msr_:
+       push ebx
+       push edx
+       mov ecx, eax
+       rdmsr
+       pop ebx
+       mov [ebx], eax
+       pop ebx
+       mov [ebx], edx
+       ret
+
+       global set_msr
+       global _set_msr
+set_msr:
+_set_msr:
+       mov ecx, [esp + 4]
+       mov eax, [esp + 8]
+       mov edx, [esp + 12]
+       rdmsr
+       ret
+
+       global set_msr_
+set_msr_:
+       mov ecx, eax
+       mov eax, edx
+       mov edx, ebx
+       wrmsr
+       ret
+
+
+; vi:ft=nasm:
index a59aa3e..c549b3e 100644 (file)
@@ -3,7 +3,11 @@
 #include <string.h>
 #include <stdint.h>
 #include <assert.h>
+#ifdef WIN32
+#include <malloc.h>
+#else
 #include <alloca.h>
+#endif
 #include "image.h"
 
 struct rect {
index b6e9f4e..0763597 100644 (file)
@@ -3,12 +3,18 @@ bin = img2bin
 
 root = ../..
 
-CFLAGS = -pedantic -Wall -g -I$(root)/libs/imago/src
-LDFLAGS = -L$(root)/libs/imago -limago -lm
+imagodir = $(root)/libs/imago
+libimago = $(imagodir)/libimago.a
 
-$(bin): $(obj)
+CFLAGS = -pedantic -Wall -g -I$(imagodir)/src
+LDFLAGS = -L$(imagodir) -limago -lm
+
+$(bin): $(obj) $(libimago)
        $(CC) -o $@ $(obj) $(LDFLAGS)
 
+$(libimago):
+       $(MAKE) -C $(imagodir)
+
 .PHONY: clean
 clean:
        rm -f $(obj) $(bin)
diff --git a/tools/scripts/fixmknam b/tools/scripts/fixmknam
new file mode 100755 (executable)
index 0000000..15c6118
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in `find . -name 'makefile*'`; do
+       name=`echo $i | sed 's/makefile/Makefile/'`
+       echo "$i -> $name"
+       mv $i $name
+done
index c0e8660..6687f82 100755 (executable)
@@ -1,10 +1,10 @@
 #!/bin/sh
 
 # NOTES:
-# assumes a PCem setup with a fat16 image mounted at /pcem_dos. fstab entry:
-#  /home/nuclear/.pcem/pentium_dos.img /pcem_dos msdos user,noauto,loop,fmask=0113,dmask=0002,gid=6,offset=32256 0 0
+# assumes a PCem setup with a fat16 image mounted at /pcem/pentium. fstab entry:
+#  /home/nuclear/.pcem/pentium_dos.img /pcem/pentium msdos user,noauto,loop,fmask=0113,dmask=0002,gid=6,offset=32256 0 0
 
-mntpt=/pcem_dos
+mntpt=/pcem/pentium
 do_umount=false
 
 if ! ( mount | grep pcem >/dev/null ); then