removed clang-format and clang_complete files from the repo
[dosdemo] / README.md
1 Unnamed Mindlapse DOS demo for Pentium-era PCs
2 ----------------------------------------------
3 The demo uses VBE 320x240 16bpp. Some VBE implementations do not expose
4 double-scan video modes (240 lines), but can be made to work with a third-party
5 VBE TSR like `univbe` or `s3vbe`. Linear framebuffer (VBE 2.0) support is
6 recommended, but not necessary. The demo will fallback to VBE 1.2 banked modes
7 if LFB modes are not available.
8
9 Source structure
10 ----------------
11  - src/          cross-platform demo framework and miscellaneous utility code
12  - src/scr/      demo screens (parts) and effects support code
13  - src/dos/      DOS platform code
14  - src/glut/     GLUT platform code (windows/UNIX version)
15  - src/sdl/      SDL 1.x platform code (windows/UNIX version)
16  - libs/cgmath/  math library, header-file only
17  - libs/imago/   image loading library (includes libpng, zlib, libjpeg)
18  - libs/anim/    keyframe animation library
19
20 Coding style conventions
21 ------------------------
22 Very few style issues are mandated:
23
24   - All filenames should be lowercase unless convention says otherwise
25     (`Makefile`, `README`, etc).
26   - All filenames under `src/` and of any tools necessary to build from MS-DOS
27     will have to use maximum 8.3 characters.
28   - Source code should be C89-compliant. Any compiler-specific features beyond
29     that will have to be ifdefed.
30   - Use tabs for indentation, where each tab is equivalent to 4 spaces.
31
32 Everything else is left to the discretion of each individual, but also if
33 you're editing an existing file, try to match the style of the surrounding code.
34
35 Some general style suggestions, which will not be enforced:
36
37   - Don't use overly long names, abbreviate wherever it makes sense.
38   - Don't cast the return value of malloc. `void*` are converted implicitly, and
39     the cast hides forgetting to include `stdlib.h`.
40   - Preferably use lowercase with underscores for everything.
41   - Preferably use the K&R brace style if possible.
42
43 This section will be expanded as necessary.
44
45 Building on DOS with Watcom
46 ---------------------------
47 Make sure you have Watcom or OpenWatcom installed, and the appropriate env-vars
48 set (the watcom installer automatically adds them to autoexec.bat by default).
49
50 Run wmake to build. Needs dos4gw.exe in current dir.
51
52 OpenWatcom cross-compilation on UNIX
53 ------------------------------------
54 source owdev script with contents (change WATCOM var as necessary):
55
56   export WATCOM=$HOME/devel/ow
57   export PATH=$WATCOM/binl:$PATH
58   export INCLUDE=$WATCOM/h:$INCLUDE
59
60 Run wmake to build. Needs dos4gw.exe and wstub.exe in current dir or PATH
61
62 Simply running ./demo.exe might invoke magic of the ancients to start wine,
63 which will in turn start dosbox, which will execute the DOS binary! If the gods
64 are slumbering in valhalla, just typing `dosbox demo.exe` should do the trick.
65
66 Building with DJGPP
67 -------------------
68 The DJGPP port of GCC is the recommended toolchain to use for building the demo,
69 either natively or cross-compiled on UNIX.
70
71 For native DOS builds add the DJGPP bin directory to the path (usually
72 `c:\djgpp\bin`) and set the DJGPP environment variable to point to the
73 `djgpp.env` file.
74
75 For cross-compiling on UNIX simply source the `setenv` file which comes with
76 DJGPP, which will set the `PATH` and `DJDIR` variables as necessary.
77
78 In both cases, run `make -f Makefile.dj` to build. To run the resulting
79 `demo.exe` you'll need to copy `cwsdpmi.exe` to the same directory. You can find
80 it here: ftp://ftp.fu-berlin.de/pc/languages/djgpp/current/v2misc/csdpmi7b.zip
81
82 When building natively on an old computer, and encounter a huge amount of disk
83 swapping, and corresponding ridiculously long compile times, make sure to
84 disable any memory managers and try again. `EMM386` may interfere with
85 `CWSDPMI`'s ability to use more than 32mb of RAM, and modern versions of GCC
86 need way more than that. Disable the memory manager with `emm386 off`, and
87 verify the amount of usable RAM with `go32-v2`.
88
89 Another problem is the MS-DOS version of `HIMEM.SYS` which only reports up to
90 64mb. To use more than that, which is necessary for modern versions of GCC, you
91 can either disable `HIMEM.SYS` completely, or use the `HIMEM.SYS` driver that
92 comes with Windows 9x (DOS >= 7). Here's a copy in case you need it:
93 http://mutantstargoat.com/~nuclear/tmp/d7himem.sys
94
95
96 Building and running with the SDL backend
97 -----------------------------------------
98 Run make to build (assuming make on your system is GNU make), or use the visual
99 studio 2013 project on Windows.
100
101 The SDL backend will scale the framebuffer up, by the factor specified in the
102 `FBSCALE` environment variable. So run the demo as: `FBSCALE=3 ./demo` for
103 a 3x scale factor, or just export the `FBSCALE` env var in the shell you are
104 going to use for running the demo. The default scale factor is 2x.
105
106 Datafiles
107 ---------
108 The demo datafiles are in their own subversion repo. To checkout the data files
109 run the following in the demo root directory:
110
111   svn co svn://mutantstargoat.com/datadirs/dosdemo data
112
113 Random optimization details about the Pentium1 (p54c)
114 -----------------------------------------------------
115 Use cround64 (util.h) for float -> integer conversions, instead of casts.
116
117 Performance measurement with RDTSC:
118     perf_start();
119     /* code under test */
120     perf_end(); /* result in perf_interval_count */
121
122 Cache organization (L1): 8kb data / 8kb instruction
123 128 sets of 2 cache lines, 32 bytes per cache line.
124
125 Addresses which are multiples of 4096 fall in the same set and can only have
126 two of them in cache at any time.
127
128 U/V pipe pairing rules:
129  - both instructions must be simple
130  - no read-after-write or write-after-write reg dependencies
131  - no displacement AND immediate in either instruction
132  - instr. with prefixes (except 0x0f) can only run on U pipe.
133  - prefixes are treated as separate 1-byte instructions (except 0x0f).
134  - branches can be paired if they are the second instr. of the pair only.
135
136 Simple instructions are:
137  - mov reg, reg/mem/imm
138  - mov mem, reg/imm
139  - alu reg, reg/mem/imm (alu: add/sub/cmp/and/or/xor)
140  - alu mem, reg/imm
141  - inc reg/mem
142  - dec reg/mem
143  - push reg/mem
144  - pop reg
145  - lea reg,mem
146  - jmp/call/jcc near
147  - nop
148  - test reg,reg/mem
149  - test acc,imm
150
151 U-only pairable instructions:
152  - adc, sbb
153  - shr, sar, shl, sal with immediate
154  - ror, rol, rcr, rcl with immediate=1
155
156 Notes about DJGPP & CWSDPMI
157 ---------------------------
158 Can't use the `hlt` instruction for waiting for interrupts, because we're
159 running in ring3 by default. I surrounded all the `hlt` instructions with a
160 `USE_HLT` conditional, which is undefined when building with DJGPP.
161
162 It's possible to arrange for our code to run on ring0 by changing the DPMI
163 provider from `cwsdpmi.exe` to `cwsdpr0.exe` by running:
164 `stubedit demo.exe dpmi=cwsdpr0.exe`, but I haven't tested under win9x to see if
165 it still works if we do that.
166
167 Our fucking segments don't start at 0 ... to access arbitrary parts of physical
168 memory we need to call `__djgpp_nearptr_enable()` and use the following macros I
169 defined in `cdpmi.h`:
170
171     #define virt_to_phys(v)     ((v) + __djgpp_base_address)
172     #define phys_to_virt(p)     ((p) - __djgpp_base_address)
173
174 Notes about moving code to/from a DOS computer
175 ----------------------------------------------
176 The easiest way to move code back and forth to a DOS computer, is to connect it
177 to the local network. For this you need a DOS packet driver for your NIC, which
178 thankfully most NIC vendors seem to provide, and a number of useful network
179 utilities which come with their own TCP/IP stack (mTCP and WATTCP). The
180 following are recommended:
181
182  - mTCP: http://www.brutman.com/mTCP
183  - WATTCP: http://www.watt-32.net
184  - ssh2dos: http://sshdos.sourceforge.net
185  - rsync: http://www.2net.co.uk/rsync.html
186
187 Here's an example batch file I'm using to set up the network:
188
189     @echo off
190     c:\net\rtspkt\rtspkt 0x61
191     set MTCPCFG=c:\net\mtcp\mtcp.cfg
192     set WATT_ROOT=c:\net\watt
193     set WATTCP.CFG=c:\net\watt\bin
194     set ETC=c:\net\watt\bin
195     set PATH=%PATH%;c:\net\mtcp;c:\net\watt\bin
196
197 The rtspkt program is the packet driver for my realtek NIC, and I'm instructing
198 it to use interrupt 61h. The rest are environment variables needed by mTCP and
199 WATTCP. If you run out of environment space you might need to increase it with
200 `SHELL=C:\DOS\COMMAND.COM /e:1024 /p` in `config.sys`, or just put all binaries
201 in a single place instead of adding multiple directories to the `PATH`.
202
203 ### mTCP configuration
204 The `mtcp.cfg` file configures the mTCP TCP/IP stack. Go through the file, which
205 comes with mTCP, and make any necessary changes. For instance I've set
206 `packetint 0x61` to match the packet driver interrupt, and I'm using static IP
207 assignments, so I've set it up like this:
208
209     ipaddr 192.168.0.21
210     netmask 255.255.0.0
211     gateway 192.168.1.1
212     nameserver 1.1.1.1
213
214 ### WATTCP configuration
215 The `wattcp.cfg` file is in the wattcp bin directory, and includes similar
216 configuration options:
217
218     my_ip = 192.168.0.21
219     hostname = "retrop1"
220     netmask = 255.255.0.0
221     nameserver = 1.1.1.1
222     gateway = 192.168.1.1
223     domain.suffix = localdomain
224     pkt.vector = 0x61
225     hosts = $(ETC)\hosts
226
227 ### Server-side configuration
228 The `pull.bat` file in the demo repo uses rsync to get the source code from the
229 git repo on my main GNU/Linux computer. To avoid having to type passwords all
230 the time, I've configures rsyncd to allow access to the demo directory in the
231 `/etc/rsyncd.conf` file:
232
233     [dosdemo]
234     path = /home/nuclear/code/demoscene/dosdemo
235     comment = DOS demo project
236
237 Since the DOS rsync utility is unfortunately read-only, the `push.bat` relies on
238 ssh2dos instead, which does require a password. The sshd on the server might
239 need to be configured to allow older encryption algorithms, depending on your
240 current setup.