commit 37d7e0fd43264d909e8a3f4836ff047267cc13c1 Author: archive Date: Fri Dec 12 00:00:00 2014 +0000 as released 2014-12-12 diff --git a/DATA/AMAZON.LBM b/DATA/AMAZON.LBM new file mode 100644 index 0000000..407cf97 Binary files /dev/null and b/DATA/AMAZON.LBM differ diff --git a/DATA/BACKDROP.LBM b/DATA/BACKDROP.LBM new file mode 100644 index 0000000..e673da4 Binary files /dev/null and b/DATA/BACKDROP.LBM differ diff --git a/DATA/BACKDROP.SCR b/DATA/BACKDROP.SCR new file mode 100644 index 0000000..3d99e52 --- /dev/null +++ b/DATA/BACKDROP.SCR @@ -0,0 +1,2 @@ +backdrop.dat lpic 0 0 320 99 +back2.dat lpic 0 100 320 199 diff --git a/DATA/BEAST.LBM b/DATA/BEAST.LBM new file mode 100644 index 0000000..138085c Binary files /dev/null and b/DATA/BEAST.LBM differ diff --git a/DATA/BEAST.SCR b/DATA/BEAST.SCR new file mode 100644 index 0000000..2a8f0bf --- /dev/null +++ b/DATA/BEAST.SCR @@ -0,0 +1,5 @@ +beast_1.dat DSPRITE 16 16 56 64 +beast_2.dat DSPRITE 80 16 56 64 +beast_3.dat DSPRITE 144 16 56 64 +beast_4.dat DSPRITE 208 16 56 64 + diff --git a/DATA/BLANKMAP.LBM b/DATA/BLANKMAP.LBM new file mode 100644 index 0000000..3cafa98 Binary files /dev/null and b/DATA/BLANKMAP.LBM differ diff --git a/DATA/CHACMOO2.LBM b/DATA/CHACMOO2.LBM new file mode 100644 index 0000000..bc9c508 Binary files /dev/null and b/DATA/CHACMOO2.LBM differ diff --git a/DATA/CHACMOOL.LBM b/DATA/CHACMOOL.LBM new file mode 100644 index 0000000..306d871 Binary files /dev/null and b/DATA/CHACMOOL.LBM differ diff --git a/DATA/DOORS1.LBM b/DATA/DOORS1.LBM new file mode 100644 index 0000000..c0ab9f3 Binary files /dev/null and b/DATA/DOORS1.LBM differ diff --git a/DATA/DOORS1.SCR b/DATA/DOORS1.SCR new file mode 100644 index 0000000..d361828 --- /dev/null +++ b/DATA/DOORS1.SCR @@ -0,0 +1,2 @@ +door1.dat WALL 2 2 8 +door2.dat WALL 11 2 8 diff --git a/DATA/DP_BPAL.$$$ b/DATA/DP_BPAL.$$$ new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/DATA/DP_BPAL.$$$ differ diff --git a/DATA/DP_CPAL.$$$ b/DATA/DP_CPAL.$$$ new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/DATA/DP_CPAL.$$$ differ diff --git a/DATA/DP_OPAL.$$$ b/DATA/DP_OPAL.$$$ new file mode 100644 index 0000000..17bc906 Binary files /dev/null and b/DATA/DP_OPAL.$$$ differ diff --git a/DATA/DP_PREFS b/DATA/DP_PREFS new file mode 100644 index 0000000..755a793 Binary files /dev/null and b/DATA/DP_PREFS differ diff --git a/DATA/DP_SPAL.$$$ b/DATA/DP_SPAL.$$$ new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/DATA/DP_SPAL.$$$ differ diff --git a/DATA/FIRE.LBM b/DATA/FIRE.LBM new file mode 100644 index 0000000..b49b648 Binary files /dev/null and b/DATA/FIRE.LBM differ diff --git a/DATA/FLATS1.LBM b/DATA/FLATS1.LBM new file mode 100644 index 0000000..db2b613 Binary files /dev/null and b/DATA/FLATS1.LBM differ diff --git a/DATA/FLATS1.SCR b/DATA/FLATS1.SCR new file mode 100644 index 0000000..f28958e --- /dev/null +++ b/DATA/FLATS1.SCR @@ -0,0 +1,8 @@ +f1_1.dat flat 2 2 +f1_2.dat flat 11 2 +f1_3.dat flat 20 2 +f1_4.dat flat 29 2 +f1_5.dat flat 2 11 +f1_6.dat flat 11 11 +f1_7.dat flat 20 11 +f1_8.dat flat 29 11 diff --git a/DATA/FLATS2.LBM b/DATA/FLATS2.LBM new file mode 100644 index 0000000..bf818e9 Binary files /dev/null and b/DATA/FLATS2.LBM differ diff --git a/DATA/FLATS2.SCR b/DATA/FLATS2.SCR new file mode 100644 index 0000000..de0be31 --- /dev/null +++ b/DATA/FLATS2.SCR @@ -0,0 +1,4 @@ +f2_1.dat flat 2 2 +f2_2.dat flat 11 2 +f2_3.dat flat 2 11 +f2_4.dat flat 11 11 diff --git a/DATA/FONT1.LBM b/DATA/FONT1.LBM new file mode 100644 index 0000000..2b01233 Binary files /dev/null and b/DATA/FONT1.LBM differ diff --git a/DATA/FONT1.SCR b/DATA/FONT1.SCR new file mode 100644 index 0000000..0899b8a --- /dev/null +++ b/DATA/FONT1.SCR @@ -0,0 +1,2 @@ +font1.dat font 32 126 + diff --git a/DATA/GETMAP.BAT b/DATA/GETMAP.BAT new file mode 100644 index 0000000..3f6f27c --- /dev/null +++ b/DATA/GETMAP.BAT @@ -0,0 +1,4 @@ +..\sgrab\sgrab map +..\idlink\idlink -b +copy todd3d.tod ..\source +cd ..\source diff --git a/DATA/GRABALL.BAT b/DATA/GRABALL.BAT new file mode 100644 index 0000000..fd9ff03 --- /dev/null +++ b/DATA/GRABALL.BAT @@ -0,0 +1,20 @@ +..\sgrab\sgrab doors1 +..\sgrab\sgrab walls1 +..\sgrab\sgrab walls2 +..\sgrab\sgrab walls3 +..\sgrab\sgrab walls4 +..\sgrab\sgrab walls5 +..\sgrab\sgrab walls6 +..\sgrab\sgrab sprite1 +..\sgrab\sgrab sprite2 +..\sgrab\sgrab sprite3 +..\sgrab\sgrab sprite4 +..\sgrab\sgrab sprite5 +..\sgrab\sgrab flats1 +..\sgrab\sgrab flats2 +..\sgrab\sgrab playscr +..\sgrab\sgrab weapons +..\sgrab\sgrab font1 +..\sgrab\sgrab map +..\lights\lights playscr.lbm 59 +..\idlink\idlink -b diff --git a/DATA/LINKFILE.ILN b/DATA/LINKFILE.ILN new file mode 100644 index 0000000..9524b47 --- /dev/null +++ b/DATA/LINKFILE.ILN @@ -0,0 +1,149 @@ +todd3d.tod + +palette.dat palette +lights.dat lights + +$OPENCOMP map +map1.dat map +map2.dat +map3.dat +map4.dat +map5.dat +map6.dat +map7.dat +map8.dat +map9.dat +map10.dat + +$OPENCOMP playscr +playscr.dat playscreen + +$OPENCOMP font1 +font1.dat font + +;=============== +; rendering data +;=============== + +; sprites +LABEL startsprites + +$OPENCOMP sprite1 +sp1_1.dat brazier +sp1_2.dat +sp1_3.dat +sp1_4.dat + +$OPENCOMP sprite2 +sp2_1.dat chacmool + +$OPENCOMP sprite3 +sp3_1.dat snake + +$OPENCOMP sprite4 +sp4_1.dat urn1 +sp4_2.dat urn2 +sp4_3.dat bowl +sp4_4.dat cup +sp4_5.dat jade1 +sp4_6.dat ankh + +$OPENCOMP sprite5 +sp5_1.dat atk1 +sp5_2.dat +sp5_3.dat +sp5_4.dat atk1_mx +sp5_5.dat exp1 +sp5_6.dat +sp5_7.dat exp1_mx + +LABEL endsprites + +$OPENCOMP weapons +weapons.dat weapons + + + +; flat floors / ceilings +LABEL startflats +$OPENCOMP flats1 +f1_1.dat ; Stone ceiling +f1_2.dat ; wood floor +f1_3.dat +f1_4.dat +f1_5.dat +f1_6.dat +f1_7.dat +f1_8.dat +$OPENCOMP flats2 +f2_1.dat +f2_2.dat +f2_3.dat +f2_4.dat +LABEL endflats + + +; walls +LABEL startwalls +$OPENCOMP walls1 +w1_1.dat +w1_2.dat +w1_3.dat +w1_4.dat +w1_5.dat +w1_6.dat +w1_7.dat +w1_8.dat +$OPENCOMP walls2 +w1_9.dat +w1_10.dat +w1_11.dat +w1_12.dat +w1_13.dat +w1_14.dat +w1_15.dat +w1_16.dat +$OPENCOMP walls3 +w1_17.dat +w1_18.dat +w1_19.dat +w1_20.dat +w1_21.dat +w1_22.dat +w1_23.dat +w1_24.dat +$OPENCOMP walls4 +w1_25.dat +w1_26.dat +w1_27.dat +w1_28.dat +w1_29.dat +w1_30.dat +w1_31.dat +w1_32.dat +$OPENCOMP walls5 +w1_33.dat +w1_34.dat +w1_35.dat +w1_36.dat +w1_37.dat +w1_38.dat +w1_39.dat +w1_40.dat +$OPENCOMP walls6 +w1_41.dat +w1_42.dat +w1_43.dat +w1_44.dat +w1_45.dat +w1_46.dat +w1_47.dat +w1_48.dat + + +; doors (doors are the same data as walls) +$OPENCOMP doors1 +door1.dat wolfdoor +door2.dat wooddoor + +LABEL endwalls diff --git a/DATA/MAP.LBM b/DATA/MAP.LBM new file mode 100644 index 0000000..67ca225 Binary files /dev/null and b/DATA/MAP.LBM differ diff --git a/DATA/MAP.SCR b/DATA/MAP.SCR new file mode 100644 index 0000000..a3b6c6c --- /dev/null +++ b/DATA/MAP.SCR @@ -0,0 +1,10 @@ +map1.dat raw 0 0 64 64 +map2.dat raw 64 0 64 64 +map3.dat raw 128 0 64 64 +map4.dat raw 192 0 64 64 +map5.dat raw 256 0 64 64 +map6.dat raw 0 64 64 64 +map7.dat raw 64 64 64 64 +map8.dat raw 128 64 64 64 +map9.dat raw 192 64 64 64 +map10.dat raw 0 64 64 64 diff --git a/DATA/MAP2.LBM b/DATA/MAP2.LBM new file mode 100644 index 0000000..8bfd4fa Binary files /dev/null and b/DATA/MAP2.LBM differ diff --git a/DATA/MENU.LBM b/DATA/MENU.LBM new file mode 100644 index 0000000..2302e20 Binary files /dev/null and b/DATA/MENU.LBM differ diff --git a/DATA/MENU.SCR b/DATA/MENU.SCR new file mode 100644 index 0000000..25290d6 --- /dev/null +++ b/DATA/MENU.SCR @@ -0,0 +1,2 @@ +menu.dat lpic 16 16 184 104 +binky.dat lpic 208 16 24 24 diff --git a/DATA/NAZI.LBM b/DATA/NAZI.LBM new file mode 100644 index 0000000..bb96935 Binary files /dev/null and b/DATA/NAZI.LBM differ diff --git a/DATA/NAZI.SCR b/DATA/NAZI.SCR new file mode 100644 index 0000000..d0a79f7 --- /dev/null +++ b/DATA/NAZI.SCR @@ -0,0 +1,9 @@ +nazi_1.dat DSPRITE 37 32 22 48 +nazi_2.dat DSPRITE 113 32 17 48 +nazi_3.dat DSPRITE 187 32 14 48 +nazi_4.dat DSPRITE 255 32 15 48 +nazi_5.dat DSPRITE 38 104 21 48 +nazi_6.dat DSPRITE 113 104 16 48 +nazi_7.dat DSPRITE 183 104 14 48 +nazi_8.dat DSPRITE 255 104 17 48 + diff --git a/DATA/PALETTE.PCX b/DATA/PALETTE.PCX new file mode 100644 index 0000000..6518119 Binary files /dev/null and b/DATA/PALETTE.PCX differ diff --git a/DATA/PLAYSCR.LBM b/DATA/PLAYSCR.LBM new file mode 100644 index 0000000..e31ff2a Binary files /dev/null and b/DATA/PLAYSCR.LBM differ diff --git a/DATA/PLAYSCR.SCR b/DATA/PLAYSCR.SCR new file mode 100644 index 0000000..fe7d74f --- /dev/null +++ b/DATA/PLAYSCR.SCR @@ -0,0 +1 @@ +playscr.dat lpic 0 0 320 200 diff --git a/DATA/RGRID8.LBM b/DATA/RGRID8.LBM new file mode 100644 index 0000000..b48569d Binary files /dev/null and b/DATA/RGRID8.LBM differ diff --git a/DATA/SHARK.SCR b/DATA/SHARK.SCR new file mode 100644 index 0000000..2e5e880 --- /dev/null +++ b/DATA/SHARK.SCR @@ -0,0 +1 @@ +ogre_1.dat DSPRITE 16 16 37 55 diff --git a/DATA/SOFT3D.ICN b/DATA/SOFT3D.ICN new file mode 100644 index 0000000..dc8d0e6 Binary files /dev/null and b/DATA/SOFT3D.ICN differ diff --git a/DATA/SPRITE1.LBM b/DATA/SPRITE1.LBM new file mode 100644 index 0000000..331ca48 Binary files /dev/null and b/DATA/SPRITE1.LBM differ diff --git a/DATA/SPRITE1.SCR b/DATA/SPRITE1.SCR new file mode 100644 index 0000000..e8c2c83 --- /dev/null +++ b/DATA/SPRITE1.SCR @@ -0,0 +1,5 @@ +sp1_1.dat DSPRITE 24 19 48 61 +sp1_2.dat DSPRITE 96 19 48 61 +sp1_3.dat DSPRITE 168 19 48 61 +sp1_4.dat DSPRITE 240 19 48 61 + diff --git a/DATA/SPRITE2.LBM b/DATA/SPRITE2.LBM new file mode 100644 index 0000000..9dfc6ce Binary files /dev/null and b/DATA/SPRITE2.LBM differ diff --git a/DATA/SPRITE2.SCR b/DATA/SPRITE2.SCR new file mode 100644 index 0000000..4ecbf3d --- /dev/null +++ b/DATA/SPRITE2.SCR @@ -0,0 +1,2 @@ +sp2_1.dat DSPRITE 19 16 58 64 + diff --git a/DATA/SPRITE3.LBM b/DATA/SPRITE3.LBM new file mode 100644 index 0000000..ee8e8a2 Binary files /dev/null and b/DATA/SPRITE3.LBM differ diff --git a/DATA/SPRITE3.SCR b/DATA/SPRITE3.SCR new file mode 100644 index 0000000..ac9ac59 --- /dev/null +++ b/DATA/SPRITE3.SCR @@ -0,0 +1,2 @@ +sp3_1.dat DSPRITE 16 16 64 64 + diff --git a/DATA/SPRITE4.LBM b/DATA/SPRITE4.LBM new file mode 100644 index 0000000..540332a Binary files /dev/null and b/DATA/SPRITE4.LBM differ diff --git a/DATA/SPRITE4.SCR b/DATA/SPRITE4.SCR new file mode 100644 index 0000000..7f32b1f --- /dev/null +++ b/DATA/SPRITE4.SCR @@ -0,0 +1,7 @@ +sp4_1.dat DSPRITE 29 36 34 44 +sp4_2.dat DSPRITE 105 36 34 44 +sp4_3.dat DSPRITE 175 56 37 18 +sp4_4.dat DSPRITE 254 53 17 19 +sp4_5.dat DSPRITE 25 108 47 44 +sp4_6.dat DSPRITE 111 101 23 49 + diff --git a/DATA/SPRITE5.LBM b/DATA/SPRITE5.LBM new file mode 100644 index 0000000..537cee4 Binary files /dev/null and b/DATA/SPRITE5.LBM differ diff --git a/DATA/SPRITE5.SCR b/DATA/SPRITE5.SCR new file mode 100644 index 0000000..903a3c4 --- /dev/null +++ b/DATA/SPRITE5.SCR @@ -0,0 +1,8 @@ +sp5_1.dat DSPRITE 16 16 28 28 +sp5_2.dat DSPRITE 52 16 28 28 +sp5_3.dat DSPRITE 16 52 28 28 +sp5_4.dat DSPRITE 52 52 28 28 +sp5_5.dat DSPRITE 88 16 36 36 +sp5_6.dat DSPRITE 160 16 48 48 +sp5_7.dat DSPRITE 232 16 48 48 + diff --git a/DATA/TEMP b/DATA/TEMP new file mode 100644 index 0000000..52440f8 --- /dev/null +++ b/DATA/TEMP @@ -0,0 +1,200 @@ +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 +atemp 00000000 btemp 0 ctemp 00000000 dtemp 0 diff --git a/DATA/TODD.ILN b/DATA/TODD.ILN new file mode 100644 index 0000000..cd325bf --- /dev/null +++ b/DATA/TODD.ILN @@ -0,0 +1,62 @@ + +soft3d.dat + +palette.dat palette +lights.dat lights + +$OPENCOMP map +map1.dat map +map2.dat +map3.dat +map4.dat +map5.dat +map6.dat +map7.dat +map8.dat +map9.dat + +$OPENCOMP playscr +toddscr.dat playscreen + +$OPENCOMP font1 +font1.dat font + +;=============== +; rendering data +;=============== + +; sprites +LABEL startsprites + +$OPENCOMP nazi +nazi_1.dat nazi +nazi_2.dat +nazi_3.dat +nazi_4.dat +nazi_5.dat +nazi_6.dat +nazi_7.dat +nazi_8.dat + +LABEL endsprites + + +; flat floors / ceilings +LABEL startflats +$OPENCOMP flats1 +f1_1.dat ; Stone ceiling +f1_2.dat ; wood floor +LABEL endflats + + +; walls +LABEL startwalls +$OPENCOMP walls1 +w1_1.dat ; green brick +w1_2.dat ; wood slats + +; doors (doors are the same data as walls) +$OPENCOMP doors1 +door1.dat wolfdoor + +LABEL endwalls diff --git a/DATA/TODD3D.ICN b/DATA/TODD3D.ICN new file mode 100644 index 0000000..f1fb9c1 Binary files /dev/null and b/DATA/TODD3D.ICN differ diff --git a/DATA/TORCHES b/DATA/TORCHES new file mode 100644 index 0000000..3f6a9b7 --- /dev/null +++ b/DATA/TORCHES @@ -0,0 +1,2 @@ +torch_1.dat DSPRITE 16 17 19 47 +torch_2.dat DSPRITE 48 17 19 47 diff --git a/DATA/TROLL.LBM b/DATA/TROLL.LBM new file mode 100644 index 0000000..21b0d04 Binary files /dev/null and b/DATA/TROLL.LBM differ diff --git a/DATA/TROLL.SCR b/DATA/TROLL.SCR new file mode 100644 index 0000000..729b3fb --- /dev/null +++ b/DATA/TROLL.SCR @@ -0,0 +1,6 @@ +troll_1.dat DSPRITE 26 16 24 64 +troll_2.dat DSPRITE 74 16 24 64 +troll_3.dat DSPRITE 122 16 24 64 +troll_4.dat DSPRITE 170 16 24 64 +troll_5.dat DSPRITE 208 16 48 64 + diff --git a/DATA/TROLL2.LBM b/DATA/TROLL2.LBM new file mode 100644 index 0000000..bbbec9d Binary files /dev/null and b/DATA/TROLL2.LBM differ diff --git a/DATA/TROLL2.SCR b/DATA/TROLL2.SCR new file mode 100644 index 0000000..6641971 --- /dev/null +++ b/DATA/TROLL2.SCR @@ -0,0 +1,4 @@ +troll_6.dat DSPRITE 16 16 56 64 +troll_7.dat DSPRITE 80 16 56 64 +troll_8.dat DSPRITE 144 16 56 64 + diff --git a/DATA/WALLS1.LBM b/DATA/WALLS1.LBM new file mode 100644 index 0000000..4f00a24 Binary files /dev/null and b/DATA/WALLS1.LBM differ diff --git a/DATA/WALLS1.SCR b/DATA/WALLS1.SCR new file mode 100644 index 0000000..881da58 --- /dev/null +++ b/DATA/WALLS1.SCR @@ -0,0 +1,8 @@ +w1_1.dat wall 2 2 8 +w1_2.dat wall 10 2 8 +w1_3.dat wall 18 2 8 +w1_4.dat wall 26 2 8 +w1_5.dat wall 2 10 8 +w1_6.dat wall 10 10 8 +w1_7.dat wall 18 10 8 +w1_8.dat wall 26 10 8 diff --git a/DATA/WALLS2.LBM b/DATA/WALLS2.LBM new file mode 100644 index 0000000..5bbdf83 Binary files /dev/null and b/DATA/WALLS2.LBM differ diff --git a/DATA/WALLS2.SCR b/DATA/WALLS2.SCR new file mode 100644 index 0000000..c2df4cf --- /dev/null +++ b/DATA/WALLS2.SCR @@ -0,0 +1,8 @@ +w1_9.dat wall 2 2 8 +w1_10.dat wall 10 2 8 +w1_11.dat wall 18 2 8 +w1_12.dat wall 26 2 8 +w1_13.dat wall 2 10 8 +w1_14.dat wall 10 10 8 +w1_15.dat wall 18 10 8 +w1_16.dat wall 26 10 8 diff --git a/DATA/WALLS3.LBM b/DATA/WALLS3.LBM new file mode 100644 index 0000000..a1e2710 Binary files /dev/null and b/DATA/WALLS3.LBM differ diff --git a/DATA/WALLS3.SCR b/DATA/WALLS3.SCR new file mode 100644 index 0000000..2eb0ffe --- /dev/null +++ b/DATA/WALLS3.SCR @@ -0,0 +1,8 @@ +w1_17.dat wall 2 2 8 +w1_18.dat wall 11 2 8 +w1_19.dat wall 20 2 8 +w1_20.dat wall 29 2 8 +w1_21.dat wall 2 11 8 +w1_22.dat wall 11 11 8 +w1_23.dat wall 20 11 8 +w1_24.dat wall 29 11 8 diff --git a/DATA/WALLS4.LBM b/DATA/WALLS4.LBM new file mode 100644 index 0000000..2bd67fa Binary files /dev/null and b/DATA/WALLS4.LBM differ diff --git a/DATA/WALLS4.SCR b/DATA/WALLS4.SCR new file mode 100644 index 0000000..c102d53 --- /dev/null +++ b/DATA/WALLS4.SCR @@ -0,0 +1,8 @@ +w1_25.dat wall 2 2 8 +w1_26.dat wall 11 2 8 +w1_27.dat wall 20 2 8 +w1_28.dat wall 29 2 8 +w1_29.dat wall 2 11 8 +w1_30.dat wall 11 11 8 +w1_31.dat wall 20 11 8 +w1_32.dat wall 29 11 8 diff --git a/DATA/WALLS5.LBM b/DATA/WALLS5.LBM new file mode 100644 index 0000000..ad25152 Binary files /dev/null and b/DATA/WALLS5.LBM differ diff --git a/DATA/WALLS5.SCR b/DATA/WALLS5.SCR new file mode 100644 index 0000000..88d6e1d --- /dev/null +++ b/DATA/WALLS5.SCR @@ -0,0 +1,8 @@ +w1_33.dat wall 2 2 8 +w1_34.dat wall 11 2 8 +w1_35.dat wall 20 2 8 +w1_36.dat wall 29 2 8 +w1_37.dat wall 2 11 8 +w1_38.dat wall 11 11 8 +w1_39.dat wall 20 11 8 +w1_40.dat wall 29 11 8 diff --git a/DATA/WALLS6.LBM b/DATA/WALLS6.LBM new file mode 100644 index 0000000..ec205ce Binary files /dev/null and b/DATA/WALLS6.LBM differ diff --git a/DATA/WALLS6.SCR b/DATA/WALLS6.SCR new file mode 100644 index 0000000..1f1e38b --- /dev/null +++ b/DATA/WALLS6.SCR @@ -0,0 +1,8 @@ +w1_41.dat wall 2 2 8 +w1_42.dat wall 11 2 8 +w1_43.dat wall 20 2 8 +w1_44.dat wall 29 2 8 +w1_45.dat wall 2 11 8 +w1_46.dat wall 11 11 8 +w1_47.dat wall 20 11 8 +w1_48.dat wall 29 11 8 diff --git a/DATA/WEAPON2.LBM b/DATA/WEAPON2.LBM new file mode 100644 index 0000000..7bf758e Binary files /dev/null and b/DATA/WEAPON2.LBM differ diff --git a/DATA/WEAPONS.LBM b/DATA/WEAPONS.LBM new file mode 100644 index 0000000..fc6eb1a Binary files /dev/null and b/DATA/WEAPONS.LBM differ diff --git a/DATA/WEAPONS.SCR b/DATA/WEAPONS.SCR new file mode 100644 index 0000000..2c02a8a --- /dev/null +++ b/DATA/WEAPONS.SCR @@ -0,0 +1 @@ +weapons.dat lpic 103 159 128 32 diff --git a/DATA/_BACKUP_.LBM b/DATA/_BACKUP_.LBM new file mode 100644 index 0000000..db2b613 Binary files /dev/null and b/DATA/_BACKUP_.LBM differ diff --git a/DP_PREFS b/DP_PREFS new file mode 100644 index 0000000..aec29b3 Binary files /dev/null and b/DP_PREFS differ diff --git a/IDLINK/BACKUP.BAT b/IDLINK/BACKUP.BAT new file mode 100644 index 0000000..c79617e --- /dev/null +++ b/IDLINK/BACKUP.BAT @@ -0,0 +1,5 @@ +copy *.c %1 +copy *.asm %1 +copy *.h %1 +copy *.equ %1 +copy *.inc %1 diff --git a/IDLINK/D.BAT b/IDLINK/D.BAT new file mode 100644 index 0000000..682aef0 --- /dev/null +++ b/IDLINK/D.BAT @@ -0,0 +1 @@ +td386 idlink diff --git a/IDLINK/IDLINK.C b/IDLINK/IDLINK.C new file mode 100644 index 0000000..0e30e40 --- /dev/null +++ b/IDLINK/IDLINK.C @@ -0,0 +1,928 @@ +#define VERSION "0.4" + +/* +============================================================================= + + IDLINK + + by John Carmack + +To do +----- +Allow .. in filenames +lump compression +allow block alignment for dynamic paging + +============================================================================= +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "\miscsrc\types.h" +#include "\miscsrc\minmisc.h" +#include "\miscsrc\script.h" + +#pragma hdrstop + + + + +typedef struct +{ + char id[4]; + int numlumps; + long headeroffset; + int headerlength; +} compprologue_t; + +typedef struct +{ + char name[14]; + int lumptype; // the command number used to produce the lump + long dataoffset; + long datalength; +} compheader_t; + + +typedef enum +{ + co_uncompressed, + co_rle, + co_rlew, + co_huffman, + co_carmacized +} compress_t; + + +typedef struct +{ + long filepos; // debug: make these three byte values? + long size; + unsigned nameofs; + compress_t compress; +} lumpinfo_t; + + +typedef struct +{ + int numlumps; + long infotableofs; + long infotablesize; +} fileinfo_t; + + +fileinfo_t fileinfo,oldfileinfo; +lumpinfo_t *lumpinfo,*oldlumpinfo; +int *contentbuffer,*oldcontent; +char *content_p; + +boolean incompfile; +int comphandle; +compprologue_t compprologue; +compheader_t *compheader,*compheader_p; + +char filename[MAXPATH]; +char filepath[MAXPATH]; +char sourcepath[MAXPATH]; +char destpath[MAXPATH]; +char scriptfilename[MAXPATH]; +char datafilename[MAXPATH]; +char contentfilename[MAXPATH]; +char compfilepath[MAXPATH]; +byte *lumpalloc; // for lumpinfo and the names +char *name_p; + +int datahandle; +int filescopied; + +boolean fullbuild; + +unsigned long oldtime; // time stamp of old file (bit fields) +unsigned long newtime; + + +/* + + +output filename + +; any line starting with a non alphanumeric char is a comment +filename [-compression] [lumpname] +LABEL [lumpname] + + +idlink [-b][-path FILENAME] scriptfile + +put in a SPARSE command + +*/ + + + +/* +============================================================================= + + GENERIC FUNCTIONS + +============================================================================= +*/ + +int SafeOpenWrite (char *filename) +{ + int handle; + + handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_TRUNC + , S_IREAD | S_IWRITE); + + if (handle == -1) + MS_Quit ("Error opening %s: %s\n",filename,strerror(errno)); + + return handle; +} + +int SafeOpenRead (char *filename) +{ + int handle; + + handle = open(filename,O_RDONLY | O_BINARY); + + if (handle == -1) + MS_Quit ("Error opening %s: %s\n",filename,strerror(errno)); + + return handle; +} + + +void SafeRead (int handle, void far *buffer, unsigned count) +{ + unsigned iocount; + + _dos_read (handle,buffer,count,&iocount); + if (iocount != count) + MS_Quit ("File read failure\n"); +} + + +void SafeWrite (int handle, void far *buffer, unsigned count) +{ + unsigned iocount; + + _dos_write (handle,buffer,count,&iocount); + if (iocount != count) + MS_Quit ("File write failure\n"); +} + + +void far *SafeMalloc (long size) +{ + void far *ptr; + + ptr = farmalloc (size); + + if (!ptr) + MS_Quit ("Malloc failure for %l bytes\n",size); + + return ptr; +} + + +/* +============================================================================= + + COPOSITE FILE STUFF + +============================================================================= +*/ + + +/* +================= += += OpenComposite += +================= +*/ + +void OpenComposite (void) +{ + char *str; + + if (incompfile) + { + close (comphandle); + free (compheader); + } + +// +// get and qualify composite data file name +// + GetToken (false); + + for (str = token ; *str ; str++) + if (*str == '.') + break; + + if (!*str) + strcat (str,".DAT"); + + if (token[0] == '\\') + strcpy (compfilepath,token); + else + { + strcpy (compfilepath,sourcepath); + strcat (compfilepath,token); + } + +// +// open it and read in header +// + comphandle = SafeOpenRead (compfilepath); + SafeRead (comphandle,&compprologue,sizeof(compprologue)); + + if (strncmp(compprologue.id,"SGRB",4)) + MS_Quit ("Composite file %s doesn't have SGRB id\n",compfilepath); + + compheader = SafeMalloc (compprologue.headerlength); + + lseek (comphandle,compprologue.headeroffset,SEEK_SET); + + SafeRead (comphandle,compheader,compprologue.headerlength); + + getftime(comphandle,(struct ftime *)&newtime); + + incompfile = true; +} + + +/* +================= += += CloseComposite += +================= +*/ + +void CloseComposite (void) +{ + if (!incompfile) + MS_Quit ("$CLOSECOMP issued without an open composite file\n"); + + close (comphandle); + free (compheader); + incompfile = false; +} + + +/* +============================================================================= + + IDLINK FUNCTIONS + +============================================================================= +*/ + +/* +=================== += += QualifyFilename += +=================== +*/ + +void QualifyFilename (void) +{ + if (incompfile) + { + if (filename[0] == '\\' || strlen(filename)>13) + MS_Quit ("Illegal comp file member name: %s\n",filename); + + strcpy (filepath,compfilepath); + strcat (filepath,":"); + strcat (filepath,filename); + return; + } + + if (filename[0] == '\\') + strcpy (filepath,filename); + else + { + strcpy (filepath,sourcepath); + strcat (filepath,filename); + } +} + + +/* +================= += += ReadOldFile += += Tries to read in info from old file. += If there is a problem, a full rebuild will be specified += +================= +*/ + +void ReadOldFile (void) +{ + int iocount,size; + int handle; + +// +// open and read data file +// + datahandle = open(datafilename,O_RDWR | O_BINARY); + if (datahandle == -1) + { + printf ("No current file to do a partial build from. Rebuilding.\n"); + fullbuild = true; + return; + } + + iocount = read (datahandle,&oldfileinfo,sizeof(oldfileinfo)); + if (iocount != sizeof(oldfileinfo)) + { + printf ("Couldn't read old fileinfo. Rebuilding.\n"); + close (datahandle); + fullbuild = true; + return; + } + + size = oldfileinfo.infotablesize; + + oldlumpinfo = malloc (size); + if (!oldlumpinfo) + { + printf ("Couldn't allocate %u bytes for oldinfotable. Rebuilding.\n" + ,size); + close (datahandle); + fullbuild = true; + return; + } + + lseek (datahandle,oldfileinfo.infotableofs,SEEK_SET); + iocount = read (datahandle , oldlumpinfo, size); + if (iocount != size) + { + printf ("Couldn't read old fileinfo. Rebuilding.\n"); + close (datahandle); + fullbuild = true; + return; + } + +// +// get timestamp +// + getftime(datahandle,(struct ftime *)&oldtime); + +// +// load in the content file +// + handle = open(contentfilename,O_RDWR | O_BINARY); + if (handle == -1) + { + printf ("No content file. Rebuilding.\n"); + close (datahandle); + fullbuild = true; + return; + } + + size = filelength (handle); + oldcontent = malloc (size); + if (!oldcontent) + { + printf ("Couldn't allocate %u bytes for oldcontent. Rebuilding.\n" + ,size); + close (handle); + close (datahandle); + fullbuild = true; + return; + } + + iocount = read (handle,oldcontent,size); + if (iocount != size) + { + printf ("Couldn't read old content file. Rebuilding.\n"); + close (handle); + close (datahandle); + fullbuild = true; + return; + } +} + + +/* +=================== += += ParseScript += +=================== +*/ + +void ParseScript (void) +{ + char *fname_p; + +// +// load the script file into memory +// + LoadScriptFile (scriptfilename); + incompfile = false; + +// +// get the output filename +// + GetToken (true); + strcpy (datafilename,destpath); + strcat (datafilename,token); + +// +// the content file holds a list of the pathnames used to build the +// data file. Used for future makes +// + strcpy (contentfilename,datafilename); + fname_p = contentfilename+strlen(contentfilename); + while ( *fname_p != '.' ) + if (--fname_p == datafilename) + { // filename didn't have an extension + fname_p = contentfilename+strlen(contentfilename); + break; + } + strcpy (fname_p,".ICN"); + + + printf ("Data file : %s\n",datafilename); + printf ("Content file : %s\n",contentfilename); + + if (!fullbuild) + ReadOldFile (); + + if (fullbuild) + { + unlink (datafilename); + datahandle = open(datafilename,O_RDWR | O_BINARY | O_CREAT, S_IREAD | S_IWRITE); + if (datahandle == -1) + MS_Quit ("Error opening data file: %s\n",strerror(errno)); + } + +// +// count the lumps in the script +// + fileinfo.numlumps = 0; + + do + { + while (TokenAvailable ()) // skip to the end of line + GetToken (false); + + GetToken (true); // get the next token + if (!endofscript && token[0] != '$') // don't count commands + fileinfo.numlumps++; + + } while (!endofscript); + + printf ("%i lumps in output file\n",fileinfo.numlumps); + +// +// allocate space for the lump directory and names +// + lumpalloc = malloc (0xfff0); + if (!lumpalloc) + MS_Quit ("Couldn't allocate lump directory!\n"); + + lumpinfo = (lumpinfo_t *) (lumpalloc + 16-FP_OFF(lumpalloc)); + name_p = (char *)(lumpinfo + fileinfo.numlumps); + +// +// allocate space for the content file +// + contentbuffer = malloc (0xfff0); + if (!contentbuffer) + MS_Quit ("Couldn't allocate lump directory!\n"); + content_p = (char *)(contentbuffer + fileinfo.numlumps); + *content_p++ = 0; // in case the first lump is a label + +// +// position the file pointer to begin writing data +// + if (fullbuild) + // leave space in the data file for the header + lseek (datahandle,sizeof(fileinfo),SEEK_SET); + else + // go to the end of the file + lseek (datahandle,filelength (datahandle),SEEK_SET); +} + + +/* +=================== += += CopyFiles += +=================== +*/ + +#define BUFFERSIZE 0xfff0 + +void CopyFiles (void) +{ + int i; + int lump,oldlump; + int inputhandle; + long size; + char *buffer,*oldname_p; + + filescopied = 0; + + script_p = scriptbuffer; + GetToken (true); // skip output name + + buffer = malloc (BUFFERSIZE); + + for (lump=0 ; lumpdataoffset,SEEK_SET); + size = compheader_p->datalength; + } + else + size = filelength (inputhandle); + + printf ("%4i = %s (%lu bytes)\n" + ,lump,filepath,size); + + lumpinfo[lump].filepos = tell(datahandle); + lumpinfo[lump].size = size; + lumpinfo[lump].compress = co_uncompressed; + + do + { + read (inputhandle,buffer,BUFFERSIZE); + if (size < BUFFERSIZE) + write (datahandle,buffer,size); + else + write (datahandle,buffer,BUFFERSIZE); + + size -= BUFFERSIZE; + + } while (size > 0); + + if (!incompfile) + close (inputhandle); + } + + free (buffer); + +} + + +/* +=================== += += WriteDirectory += +=================== +*/ + +void WriteDirectory (void) +{ +// +// write lumpinfo +// + fileinfo.infotableofs = tell(datahandle); + fileinfo.infotablesize = name_p - (char *)lumpinfo; + write (datahandle,lumpinfo,fileinfo.infotablesize); + +// +// write fileinfo +// + lseek (datahandle,0,SEEK_SET); + write (datahandle,&fileinfo,sizeof(fileinfo)); + + close (datahandle); +} + + + +/* +=================== += += WriteContentFile += +=================== +*/ + +void WriteContentFile (void) +{ + int handle,size,iocount; + + unlink (contentfilename); + handle = open(contentfilename,O_RDWR | O_BINARY | O_CREAT, S_IREAD | S_IWRITE); + if (handle == -1) + MS_Quit ("Error opening content file: %s\n",strerror(errno)); + + size = content_p - (char *)contentbuffer; + iocount = write (handle,contentbuffer,size); + if (iocount != size) + MS_Quit ("Write error on content file\n"); + + close (handle); +} + + +/* +=================== += += main += +=================== +*/ + +int main (void) +{ + int parmnum,parmsleft; + + printf ("\nIDLINK "VERSION" by John Carmack, copyright (c) 1992 Id Software\n"); + + parmsleft = _argc; + +// +// check for help +// + if (MS_CheckParm ("?")) + { + printf ( +"Usage: idlink [-b] [-source path] [-dest path] [-script scriptfile]\n\n" + +"-b Force a full rebuild of the file, rather than a file\n" +" bulking partial update\n" +"\n" +"-source path To place the source for the files in another directory\n" +"\n" +"-dest path To place the linked file in another directory\n" +"\n" +"-script file The script name defaults to LINKFILE.ILN if not specified\n" +); + exit (1); + } + + +// +// check for full or partial build +// + if (MS_CheckParm ("b")) + { + printf ("Full rebuild\n"); + fullbuild = true; + parmsleft--; + } + else + { + printf ("Partial make (file size may increase, use -b to rebuild)\n"); + fullbuild = false; + } + + +// +// get source directory for data files +// + parmnum = MS_CheckParm ("source"); + + if (parmnum) + { + strcpy (sourcepath,_argv[parmnum+1]); + parmsleft -= 2; + } + else + { + strcpy(sourcepath, "X:\\"); + sourcepath[0] = 'A' + getdisk(); + getcurdir(0, sourcepath+3); + } + if (sourcepath[strlen(sourcepath)-1] != '\\') + strcat (sourcepath,"\\"); + + printf ("Source directory : %s\n",sourcepath); + +// +// get destination directory for link file +// + parmnum = MS_CheckParm ("dest"); + + if (parmnum) + { + strcpy (destpath,_argv[parmnum+1]); + parmsleft -= 2; + } + else + { + strcpy(destpath, "X:\\"); + destpath[0] = 'A' + getdisk(); + getcurdir(0, destpath+3); + } + if (destpath[strlen(destpath)-1] != '\\') + strcat (destpath,"\\"); + + printf ("Destination directory : %s\n",destpath); + +// +// get script file +// + parmnum = MS_CheckParm ("script"); + + if (parmnum) + { + strcpy (scriptfilename,_argv[parmnum+1]); + parmsleft -= 2; + } + else + { + strcpy(scriptfilename, "X:\\"); + scriptfilename[0] = 'A' + getdisk(); + getcurdir(0, scriptfilename+3); + strcat (scriptfilename,"\\LINKFILE.ILN"); + } + + printf ("Script file : %s\n",scriptfilename); + + if (parmsleft != 1) + MS_Quit ("Improper parameters. IDLINK -? for help.\n"); + +// +// start doing stuff +// + ParseScript (); + CopyFiles (); + + if (filescopied) + { + WriteDirectory (); + WriteContentFile (); + } + else + { + close (datahandle); + } + + printf ("\n%u files copied.\n",filescopied); + return 0; +} diff --git a/IDLINK/IDLINK.DSK b/IDLINK/IDLINK.DSK new file mode 100644 index 0000000..9e1cc7b Binary files /dev/null and b/IDLINK/IDLINK.DSK differ diff --git a/IDLINK/IDLINK.EXE b/IDLINK/IDLINK.EXE new file mode 100644 index 0000000..48437c3 Binary files /dev/null and b/IDLINK/IDLINK.EXE differ diff --git a/IDLINK/IDLINK.PRJ b/IDLINK/IDLINK.PRJ new file mode 100644 index 0000000..9c688ad Binary files /dev/null and b/IDLINK/IDLINK.PRJ differ diff --git a/IDLINK/IDLINK.TXT b/IDLINK/IDLINK.TXT new file mode 100644 index 0000000..ebf588f --- /dev/null +++ b/IDLINK/IDLINK.TXT @@ -0,0 +1,41 @@ + +IDLINK DOCUMENTATION +-------------------- + +idlink [-b] [-source path] [-dest path] [-script scriptfile] + +-b Force a full rebuild of the file, rather than a file + bulking partial update + +-source path To place the source for the files in another directory + +-dest path To place the linked file in another directory + +-script file The script name defaults to LINKFILE.ILN if not specified + + + +Script file format: + +; Comments can be uses at the beginning of a line, or after a command's parms +; whitespace can be introduced anywhere, but a command cannot cross lines +outputfilename ; must be the first token of the file + +filename [labelname] ; adds filename to the data file, possibly with label +$OPENCOMP filename ; opens a composite data file. Filenames after this + ; are assumed to be in the composit file +$CLOSECOMP ; Closes the open composite file. Files after this + ; are assumed to be seperate files. You can issue + ; multiple $OPENCOMPs without $CLOSECOMP +LABEL labelname ; inserts a label on an empty lump + + +Idlink generates the output linked file, and a file with the same base and +a content file with a .ICN (Id CoNtent file) extension. This file holds the +pathnames and composite files for each of the lumps. This allows the partial +linking to find the correct data even if you rearrange the link script. You +can delete this file whenever you want, it will just force a full rebuild. + +During a partial link, if a lump has grown it will be added on to the end of +the file, leaving wasted space behind. You should periodically use the -B +option to force a rebuild from scratch. diff --git a/IDLINK/WALLS1.SCR b/IDLINK/WALLS1.SCR new file mode 100644 index 0000000..936187d --- /dev/null +++ b/IDLINK/WALLS1.SCR @@ -0,0 +1,6 @@ +COMPOSITE + +w1_1.dat wall 2 2 10 +w1_2.dat wall 11 2 6 +w1_3.dat wall 20 2 8 +w1_4.dat wall 29 2 12 diff --git a/LIGHTS/LIGHTS.C b/LIGHTS/LIGHTS.C new file mode 100644 index 0000000..cebf62e --- /dev/null +++ b/LIGHTS/LIGHTS.C @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +typedef unsigned char byte; +unsigned NUMLIGHTS; + +byte palette[768]; +byte far lightpalette[254][256]; + + +/* +===================== += += RF_BuildLights += += 0 is full palette += NUMLIGHTS and NUMLIGHTS+1 are all black += +===================== +*/ + +void RF_BuildLights (void) +{ + int i,l,c,test,table; + int red,green,blue; + int dist,bestdist,rdist,gdist,bdist,bestcolor; + byte *palptr, *palsrc; + byte far *screen; + + screen = MK_FP(0xa000,0); + + for (l=0;l added 11-12-94 + // Allows last 16 palette entries to be unafected + // by shading and thus available for lighted tiles + // such as flames, lamps, etc. + + if (c < 248) + { + palptr = palette; + bestdist = 32000; + for (test=0;test<256;test++) + { + rdist = (int)*palptr++ - red; + gdist = (int)*palptr++ - green; + bdist = (int)*palptr++ - blue; + dist = rdist*rdist + gdist*gdist + bdist*bdist; + if (dist +#include +#include +#include +#include +#include + +#define SC_index 0x3c4 +#define SC_mapmask 2 + +/* +** FUNCTION PROTOTYPES +*/ + +void GetChunkID(char huge *buffer,char *tempstr); +int NextChunkID(char huge *buffer); +void huge *Decompress(char huge *buffer,char *unpacked,int bpwidth,char planes); +void huge *SetupLBM(char *filename); +void Do_CGA_Screen(char huge *buffer,char compress,char planes,int width,int height); +void Do_EGA_Screen(char huge *buffer,char compress,char planes,int width,int height,int scrwidth); +void Do_MCGA_Screen(char huge *buffer,char compress,int width,int height); +void EGA_MoveBitplane(char huge *from,char far *to,int bpwidth); + +char typestr[5],huge *startbuff; + +// EGA loader NOTE: the "scrwidth" var should be 0=320 mode,1=640 mode + +void LoadLBM(char *filename,int scrwidth,int graphflag) +{ + + char huge *buffer,huge *cmap; + char planes, + tempstr[5], + compress; + int handle, + width, + height; + + if((buffer = SetupLBM(filename))==NULL) exit(1); + + /* + ** Need to get BMHD info, like: + ** - screen width, height + ** - # of bitplanes + ** - compression flag (YES/NO) + */ + + CurrentLBM.width=width = (*(buffer+9)&0xFF)+(*(buffer+8)*256); + CurrentLBM.height=height = (*(buffer+11)&0xFF)+(*(buffer+10)*256); + CurrentLBM.planes=planes = *(buffer+16); + compress = *(buffer+18); + + /* + if ((strcmp(typestr,"PBM ")!=0)&&(planes==8)) + { + printf("This VGA screen is not in PBM format, but ILBM, which I\ncannot decode at this time.\n"); + exit(1); + }*/ + + /* + ** Find the CMAP chunk so I can remap the registers... + */ + + movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4); + tempstr[4]=0; + while (strcmp(tempstr,"CMAP")!=0) + { + buffer += NextChunkID(buffer); + movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4); + } + + cmap = buffer+8; + + /* + ** Now, find the BODY chunk... + */ + + movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4); + while (strcmp(tempstr,"BODY")!=0) + { + buffer += NextChunkID(buffer); + movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4); + } + + /* + ** Found the BODY chunk! Here we go! + */ + + buffer += 8; /* point to actual data */ + + /* Turn graphics mode on, if desired */ + + if (graphflag==1) + { + switch (planes) + { + case 2: { _AX=4; geninterrupt(0x10); break; } + case 4: { + _AX=0x0d; + geninterrupt(0x10); + scrwidth=0; + break; + } + case 8: { _AX=0x13; geninterrupt(0x10); break; } + } + } + + switch (planes) + { + case 2: Do_CGA_Screen(buffer,compress,planes,width,height); + break; + case 4: Do_EGA_Screen(buffer,compress,planes,width,height,scrwidth); + break; + case 8: { + unsigned int i; + + for (i=0;i<0x300;i++) (unsigned char)*cmap++ >>= 2; + + cmap -= 0x300; // reset to beginning again + + _BX = 0; + _CX = 0x100; + _ES = FP_SEG(cmap); + _DX = FP_OFF(cmap); + _AX = 0x1012; + geninterrupt(0x10); + + Do_MCGA_Screen(buffer,compress,width,height); + + break; + } + + default: { + printf("This screen has %d bitplanes. I don't understand that sort of stuff.\n",planes); + exit(); + } + } + farfree((void far *)startbuff); +} + + + +//============================================== +//= +//= Load a *LARGE* file into a FAR buffer! +//= by John Romero (C) 1990 PCRcade +//= +//============================================== + +unsigned long LoadFile(char *filename,char huge *buffer) +{ + unsigned int handle,flength1,flength2,buf1,buf2,foff1,foff2; + + buf1=FP_OFF(buffer); + buf2=FP_SEG(buffer); + +asm mov WORD PTR foff1,0 // file offset = 0 (start) +asm mov WORD PTR foff2,0 + +asm mov dx,filename +asm mov ax,3d00h // OPEN w/handle (read only) +asm int 21h +asm jc out + +asm mov handle,ax +asm mov bx,ax +asm xor cx,cx +asm xor dx,dx +asm mov ax,4202h +asm int 21h // SEEK (find file length) +asm jc out + +asm mov flength1,ax +asm mov flength2,dx + +asm mov cx,flength2 +asm inc cx // <- at least once! + +L_1: + +asm push cx + +asm mov cx,foff2 +asm mov dx,foff1 +asm mov ax,4200h +asm int 21h // SEEK from start + +asm push ds +asm mov bx,handle +asm mov cx,-1 +asm mov dx,buf1 +asm mov ax,buf2 +asm mov ds,ax +asm mov ah,3fh // READ w/handle +asm int 21h +asm pop ds + +asm pop cx +asm jc out +asm cmp ax,-1 +asm jne out + +asm push cx // need to read the last byte +asm push ds // into the segment! IMPORTANT! +asm mov bx,handle +asm mov cx,1 +asm mov dx,buf1 +asm add dx,-1 +asm mov ax,buf2 +asm mov ds,ax +asm mov ah,3fh +asm int 21h +asm pop ds +asm pop cx + +asm add buf2,1000h +asm inc WORD PTR foff2 +asm loop L_1 + +out: + +asm mov bx,handle // CLOSE w/handle +asm mov ah,3eh +asm int 21h + +return (flength2*0x10000+flength1); + +} + + + +void huge *SetupLBM(char *filename) +{ + int handle; + char huge *buffer; + char tempstr[64]; + + + buffer = startbuff = (char huge *)farmalloc(0xf000); + if (buffer==NULL) return(NULL); + + strupr(filename); + if (strstr(filename,".")==NULL) + strcat(filename,".LBM"); + + + LoadFile(filename,buffer); + + GetChunkID(buffer,tempstr); + if (strcmp(tempstr,"FORM")!=0) + { + printf("This isn't in ILBM FORM format file!\n"); + return(NULL); + } + + /* + ** point past the FORM chunk + ** and see if this really IS + ** and ILBM file + */ + + buffer += 8; + GetChunkID(buffer,tempstr); + strcpy(typestr,tempstr); // save file type + if ((strcmp(tempstr,"ILBM")!=0) && (strcmp(tempstr,"PBM ")!=0) ) + { + printf("This isn't an ILBM format file!\n"); + return(NULL); + } + + /* + ** point to BMHD chunk, the first NORMAL chunk! + */ + + buffer += 4; + GetChunkID(buffer,tempstr); + if (strcmp(tempstr,"BMHD")!=0) + { + printf("What kind of ILBM is this? There's no BMHD chunk!\n"); + return(NULL); + } + return(buffer); +} + + + +void GetChunkID(char huge *buffer,char *tempstr) +{ + movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4); + tempstr[4]=0; +} + + + +int NextChunkID(char huge *buffer) +{ + unsigned int newoffset; + + newoffset = (*(buffer+7)&0xFF) + (*(buffer+6)*256); + if ((newoffset & 1)==1) newoffset += 1; + return(newoffset+8); /* +8 because chunk + offset = 8 bytes! */ +} + + + +/* +** CGA loader +*/ + +void Do_CGA_Screen(char huge *buffer,char compress,char planes,int width,int height) +{ + unsigned int bpwidth, + loopY, + loopX, + loopB, + offset, + data; + char far *screen, + b1, + b2, + unpacked[80]; + + + bpwidth = width/8; + + for (loopY=0;loopY>= 2; + b1 >>= 1; + b2 >>= 1; + } + */ + + *screen = data >> 8; + *(screen+1) = data; + screen += 2; + } + + if (compress==0) + buffer += bpwidth*planes; + } +} + + + +/* +** EGA loader (NOTE: the "scrwidth" var should be 0=320 mode,1=640 mode +*/ + +void Do_EGA_Screen(char huge *buffer,char compress,char planes,int width,int height,int scrwidth) +{ + unsigned int bpwidth, + loopY, + loopX, + loopB, + offset, + data; + char far *screen = (char far *)0xa0000000, + b1, + b2, + unpacked[160]; + + + bpwidth = width/8; + + for (loopY=0;loopY>tloop2); + } + movedata(_DS,(unsigned)unpacked1,FP_SEG(screen),FP_OFF(screen),width); + } + else movedata(_DS,(unsigned)unpacked,FP_SEG(screen),FP_OFF(screen),width); + } + else + { + movedata(FP_SEG(buffer),FP_OFF(buffer),FP_SEG(screen),FP_OFF(screen),width); + buffer += width; + } + screen = MK_FP(0xa000,FP_OFF(screen)+320); + } +} + + + + +/* +** ILBM's RLE decompressor. Merely pass the address of the compressed +** ILBM bitplane data, where to unpack it, the # of bytes each bitplane +** takes up, and the # of bit planes to unpack. +*/ + +void huge *Decompress(char huge *buffer,char *unpacked,int bpwidth,char planes) +{ + int count, + offset, + loopP; + unsigned char byte, + rept; + + for (loopP=0;loopP 0x80) + { + rept = (rept^0xff)+2; + byte = *(buffer+1); + buffer+=2; + + memset(unpacked,byte,rept); + } + else if (rept < 0x80) + { + rept++; + movedata(FP_SEG(buffer),FP_OFF(buffer)+1,_DS,(unsigned) unpacked,rept); + buffer += rept+1; + } + count += rept; + unpacked += rept; + + } while (count +#include +#include +#include +#include +#include +#include +#include "xlib_all.h" + +#define PROGRAM_GRAPHIX "GRAPHIX.LBM" +#define INTERFACE_SCREEN "INTRFACE.LBM" +#define DATA_FILE "TODD3D.TOD" + +#define UP_KEY 72 + 256 +#define DOWN_KEY 80 + 256 +#define LEFT_KEY 75 + 256 +#define RIGHT_KEY 77 + 256 + +#define GRID_MARK_COLOR 80 + +#define MAP_VIEW_SIZE 16 +#define MAP_SIZE 64 +#define MAX_TILES 40 +#define MAP_LAYERS 5 +#define TILE_SIZE 12 + +#define WEST_LAYER 0 +#define NORTH_LAYER 1 +#define FLOOR_LAYER 2 +#define CEILING_LAYER 3 +#define SPRITE_LAYER 4 + +#define PIC_BASEX 227 +#define PIC_BASEY 133 +# + +#define AA_BASEX 4 +#define AA_BASEY 4 +#define AA_MAXX 195 +#define AA_MAXY 195 + +#define MC_BASEX 254 +#define MC_BASEY 100 +#define MC_MAXX 303 +#define MC_MAXY 108 +#define MC_BGCOLOR 101 +#define MC_FGCOLOR 0 + +#define DM_BASEX 214 +#define DM_BASEY 10 +#define DM_MAXX 304 +#define DM_MAXY 18 +#define DM_BGCOLOR 101 +#define DM_FGCOLOR 0 + +#define IN_BASEX 214 +#define IN_BASEY 120 +#define IN_MAXX 304 +#define IN_MAXY 128 +#define IN_BGCOLOR 101 +#define IN_FGCOLOR 0 + +#define LEFT_MOUSE_CLICK 1 +#define RIGHT_MOUSE_CLICK 2 + +#define DM_NONE 0 +#define DM_WESTWALL 1 +#define DM_NORTHWALL 2 +#define DM_FLOOR 3 +#define DM_CEILING 4 +#define DM_SPRITE 5 + +#define TT_WESTWALL 0 +#define TT_NORTHWALL 1 +#define TT_FLAT 2 +#define TT_ACTOR 3 + +#define CC_NONE 0 +#define CC_WESTWALL 1 +#define CC_NORTHWALL 2 +#define CC_FLAT 3 +#define CC_FILL 4 +#define CC_DOOR 5 +#define CC_ACTOR 6 +#define CC_PLAYER 7 + +#define DLG_OKAY 0 +#define DLG_CANCEL 1 +#define DLG_YES 2 +#define DLG_NO 3 + +#define ID_OK 1 +#define ID_CANCEL 2 +#define ID_YES 4 +#define ID_NO 8 +#define ID_NOBUTTONS 16 +#define ID_NOTITLE 32 +#define ID_DEFAULT 1 +#define ID_OKAYCANCEL 3 +#define ID_YESNO 12 + +#define FILL_BUTTON 0 +#define NEW_BUTTON 1 +#define LOAD_BUTTON 2 +#define SAVE_BUTTON 3 +#define EXIT_BUTTON 4 +#define EXTRA_BUTTON 5 +#define PIC_LEFT_BUTTON 6 +#define PIC_RIGHT_BUTTON 7 + +#define WALL_BUTTON 8 +#define FLOOR_BUTTON 9 +#define CEILING_BUTTON 10 +#define TT4_BUTTON 11 +#define TT5_BUTTON 12 +#define PLAYER_BUTTON 13 +#define TT7_BUTTON 14 +#define SPRITE_BUTTON 15 +#define TT9_BUTTON 16 +#define TT10_BUTTON 17 + +#define OKAY_BUTTON 18 +#define CANCEL_BUTTON 19 +#define YES_BUTTON 20 +#define NO_BUTTON 21 + +#define END_OF_BUTTONS 22 +#define END_OF_MAIN_BUT 17 +#define END_OF_DLG_BUT 22 + +#define START_MAIN_BUT 0 +#define START_DLG_BUT 18 + + +extern void showLBM(int,int,char*,long); + +void load_user_fonts(void); +void exitfunc(void); + +void setUpInterface(void); +void drawLoop(void); +void handleUserActions(void); +char MouseOnButton(char); +void handleButton(char); +void pushButton(char); +void handleKeystroke(int); + +char MessageBox(int, int, long, char *, char *, int); +void deactivateMainButtons(void); +void activateMainButtons(void); +void deactivateDlgButtons(void); +void activateDlgButtons(void); + +void showDrawMode(void); +void showItemName(void); +void showCurrentPic(void); +void showMouseCoords(int, int); + +void handleMouseCursor(void); +void DrawGridTile(char xpos, char ypos); +void RedrawMap(); +void RedrawRow(char whichRow); +void RedrawCol(char whichCol); + +int SaveMapToTOD(void); +int LoadMapFromTOD(void); +int SaveMapToFile(char *); +int LoadMapFromFile(char *); + +void ScaleTiles(); + +void FillAnArea(char, char, char, char); + +typedef struct picStruct +{ + char *pbm; +} picType; + + +typedef struct scriptStruct +{ + char picFile[30]; + char picName[20]; + char Xoffset; + char Yoffset; +} scriptType; + +scriptStruct scripts[37] = +{ + "WALLS1.LBM", + "W1_1", + 2, + 2, + "WALLS1.LBM", + "W1_2", + 10, + 2, + "WALLS1.LBM", + "W1_3", + 18, + 2, + "WALLS1.LBM", + "W1_4", + 26, + 2, + "WALLS1.LBM", + "W1_5", + 2, + 10, + "WALLS1.LBM", + "W1_6", + 10, + 10, + "WALLS1.LBM", + "W1_7", + 18, + 10, + "WALLS1.LBM", + "W1_8", + 26, + 10, + "WALLS2.LBM", + "W2_1", + 2, + 2, + "WALLS2.LBM", + "W2_2", + 10, + 2, + "WALLS2.LBM", + "W2_3", + 18, + 2, + "WALLS2.LBM", + "W2_4", + 26, + 2, + "WALLS2.LBM", + "W2_5", + 2, + 10, + "WALLS2.LBM", + "W2_6", + 10, + 10, + "WALLS2.LBM", + "W2_7", + 18, + 10, + "WALLS2.LBM", + "W2_8", + 26, + 10, + "WALLS3.LBM", + "W3_1", + 2, + 2, + "WALLS3.LBM", + "W3_2", + 11, + 2, + "WALLS3.LBM", + "W3_3", + 20, + 2, + "WALLS3.LBM", + "W3_4", + 29, + 2, + "WALLS3.LBM", + "W3_5", + 2, + 11, + "WALLS3.LBM", + "W3_6", + 11, + 11, + "WALLS3.LBM", + "W3_7", + 20, + 11, + "WALLS3.LBM", + "W3_8", + 29, + 11, + "FLATS1.LBM", + "F1_1", + 2, + 2, + "FLATS1.LBM", + "F1_2", + 11, + 2, + "FLATS1.LBM", + "F1_3", + 20, + 2, + "FLATS1.LBM", + "F1_4", + 29, + 2, + "FLATS1.LBM", + "F1_5", + 2, + 11, + "FLATS1.LBM", + "F1_6", + 11, + 11, + "FLATS1.LBM", + "F1_7", + 20, + 11, + "FLATS1.LBM", + "F1_8", + 29, + 11, + "ACTORS1.LBM", + "A1_1", + 2, + 2, + "ACTORS1.LBM", + "A1_2", + 11, + 2, + "ACTORS1.LBM", + "P1_1", + 20, + 2, + "ACTORS1.LBM", + "W1_1", + 29, + 2, + "ACTORS1.LBM", + "A1_3", + 11, + 11 +}; + +char far *FillCursor[] = +{ "THISISATEST!!!"}; + +char far *userfnt1; +char *FillPic = NULL; + +char IN_ACTIVE_AREA = 0; +char DONE_DRAWING = 0; +char FILL_ACTIVE = 0; +char UPDATE_PIC_LBM = 1; +char DRAW_FROM_PIC = 1; +char GRAPHIC_CURSOR = 0; +char CurrentDrawMode = DM_WESTWALL; +char CurrentCursor = CC_WESTWALL; +char OldCursor = CurrentCursor; +char CurrentPic = 0; +char MinPic = 0; +char StartWallPic = 0; +char MaxWallPic = 23; +char MaxPic = MaxWallPic; +char StartFlatPic = 24; +char MaxFlatPic = 31; +char MaxScriptPic = 36; +char StartActorPic = 32; +char MaxActorPic = 36; + +int OldMouseX; +int OldMouseY; +int NewMouseX; +int NewMouseY; +char GRIDX; +char GRIDY; +char FillStartX; +char FillStartY; +char GridBaseX = 0; +char GridBaseY = 0; + +int buttons[] = +{ + 214, 73, 241, 81, 1, + 214, 85, 241, 93, 1, + 246, 73, 273, 81, 1, + 246, 85, 273, 93, 1, + 278, 73, 305, 81, 1, + 278, 85, 305, 93, 1, + 212, 133, 223, 144, 1, + 294, 133, 305, 144, 1, + + 215, 32, 230, 47, 1, + 233, 32, 248, 47, 1, + 251, 32, 266, 47, 1, + 269, 32, 284, 47, 1, + 287, 32, 302, 47, 1, + 215, 50, 230, 65, 1, + 233, 50, 248, 65, 1, + 251, 50, 266, 65, 1, + 269, 50, 284, 65, 1, + 287, 50, 302, 65, 1, + + 0, 0, 27, 8, 0, // DIALOG BUTTONS + 0, 9, 27, 17, 0, // Start out at grab position in graphix file + 0, 18, 27, 26, 0, // Are filled in on the fly leter based on where + 0, 27, 27, 35, 0, // dialog is to be shown + + 0, 0, 0, 0, 0 +}; + +char *DrawModes[] = +{ + "DRAW INACTIVE", + "WEST WALL", + "NORTH WALL", + "FLOOR", + "CEILING", + "SPRITE PLACEMENT", + "", +}; + +char DialogButtons[4][300]; +char DrawCursors[7][146]; +char DrawBuffer[TILE_SIZE*TILE_SIZE+2]; +//char Pics[4][MAX_TILES][TILE_SIZE*TILE_SIZE+2]; +picStruct Pics[4][MAX_TILES]; + +char map[MAP_LAYERS][MAP_SIZE*MAP_SIZE]; + +void main(void) +{ + int i; + int j; + + userfnt1 = (char far *) farmalloc(256*16+4); + + x_text_mode(); + x_set_mode(X_MODE_320x200,340); + x_text_init(); + NonVisual_Offs += ScrnLogicalByteWidth * 14; // Fixes mouse droppings prob. + x_mouse_init(); + MouseColor=103; + atexit(exitfunc); + load_user_fonts(); + x_set_doublebuffer(200); + + for (i=0; i < 4; i++) + for (j=0; j < MAX_TILES; j++) + Pics[i][j].pbm = (char *) malloc (TILE_SIZE*TILE_SIZE+2); + + setUpInterface(); + + drawLoop(); + + for (i=0; i < 4; i++) + for (j=0; j < MAX_TILES; j++) + free(Pics[i][j].pbm); + +} // main + +void drawLoop(void) +{ + x_mouse_window(0, 0, 319, 199); + + x_show_mouse(); + + while (!DONE_DRAWING) + { + handleUserActions(); + handleMouseCursor(); + } // while + + x_hide_mouse(); +} // drawLoop + +void handleUserActions(void) +{ + char BUTTON_FOUND = 0; + char currentButton; + int currentKey; + + if (MouseButtonStatus & LEFT_MOUSE_CLICK) + { + currentButton = 0; + while ((!BUTTON_FOUND) && (currentButton != END_OF_BUTTONS)) + { + if ((MouseOnButton(currentButton)) && + (buttons[currentButton*5+4])) + { + handleButton(currentButton); + BUTTON_FOUND = 1; + } // if + + currentButton++; + } // while + } // if + else if (bioskey(1)) + { + currentKey = bioskey(0); + if (!(currentKey & 0xFF)) + currentKey = (currentKey >> 8) + 256; + else + currentKey = currentKey & 0xFF; + + handleKeystroke(currentKey); + } // else +} // handleUserActions + +void handleKeystroke(int whichKey) +{ + switch (whichKey) + { + case UP_KEY : + if (GridBaseY > 0) + { + if (IN_ACTIVE_AREA) + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + else + x_hide_mouse(); + + x_shift_rect(AA_BASEX, AA_BASEY, + AA_MAXX-3, AA_MAXY-TILE_SIZE, + AA_BASEX, AA_BASEY+TILE_SIZE, Page0_Offs); + GridBaseY--; + RedrawRow(0); + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[0]); + + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + else + x_show_mouse(); + + showMouseCoords((OldMouseX-4)/TILE_SIZE,(OldMouseY-4)/TILE_SIZE); + } // if + break; + + case DOWN_KEY : + if (GridBaseY + MAP_VIEW_SIZE -1 < MAP_SIZE-1) + { + if (IN_ACTIVE_AREA) + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + else + x_hide_mouse(); + + x_shift_rect(AA_BASEX, AA_BASEY+TILE_SIZE, + AA_MAXX-3, AA_MAXY, + AA_BASEX, AA_BASEY, Page0_Offs); + GridBaseY++; + RedrawRow(MAP_VIEW_SIZE-1); + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[0]); + + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + else + x_show_mouse(); + + showMouseCoords((OldMouseX-4)/TILE_SIZE,(OldMouseY-4)/TILE_SIZE); + } // if + break; + + case LEFT_KEY : + + if (GridBaseX > 0) + { + if (IN_ACTIVE_AREA) + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + else + x_hide_mouse(); + x_shift_rect(AA_BASEX, AA_BASEY, AA_MAXX-TILE_SIZE-3, + AA_MAXY, AA_BASEX+TILE_SIZE, AA_BASEY, Page0_Offs); + GridBaseX--; + RedrawCol(0); + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[0]); + + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + else + x_show_mouse(); + + showMouseCoords((OldMouseX-4)/TILE_SIZE,(OldMouseY-4)/TILE_SIZE); + } // if + break; + + case RIGHT_KEY : + + if (GridBaseX + MAP_VIEW_SIZE - 1 < MAP_SIZE-1) + { + if (IN_ACTIVE_AREA) + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + else + x_hide_mouse(); + x_shift_rect(AA_BASEX+TILE_SIZE, AA_BASEY, AA_MAXX-3, + AA_MAXY, AA_BASEX, AA_BASEY, Page0_Offs); + GridBaseX++; + RedrawCol(MAP_VIEW_SIZE-1); + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[0]); + + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + else + x_show_mouse(); + + showMouseCoords((OldMouseX-4)/TILE_SIZE,(OldMouseY-4)/TILE_SIZE); + } // if + +// break; + } // switch +} // handleKeyStroke + +void handleButton(char whichButton) +{ + pushButton(whichButton); + + if (!MouseOnButton(whichButton)) // check if still modal to button + return; + + switch (whichButton) + { + case EXIT_BUTTON : + + if (MessageBox(160, 100, Page0_Offs, "Are you sure you want to exit?", + "Last Chance", ID_YESNO) == ID_YES) + DONE_DRAWING = 1; + + break; + + case SAVE_BUTTON : + if (MessageBox(160, 100, Page0_Offs, + "Do you want to save?", + "", ID_YESNO | ID_NOTITLE) == ID_YES) + { + if (MessageBox(160, 100, Page0_Offs, + "Do you want to insert\ninto .TOD file?", + "", ID_YESNO | ID_NOTITLE) == ID_YES) + SaveMapToTOD(); + else + SaveMapToFile("TODD.MAP"); + } // if + break; + + case LOAD_BUTTON : + if (MessageBox(160, 100, Page0_Offs, + "Do you want to load?", + "", ID_YESNO | ID_NOTITLE) == ID_YES) + { + if (MessageBox(160, 100, Page0_Offs, + "Do you want to extract\nfrom .TOD file?", + "", ID_YESNO | ID_NOTITLE) == ID_YES) + LoadMapFromTOD(); + else + LoadMapFromFile("TODD.MAP"); + + RedrawMap(); + } // if + break; + + case EXTRA_BUTTON : + + MessageBox(160, 100, Page0_Offs, + "This button has no\nmeaning as of yet.", "", ID_OK | ID_NOTITLE); + + break; + + case FILL_BUTTON : + + if (CurrentCursor == CC_FILL) + CurrentCursor = OldCursor; + else + { + OldCursor = CurrentCursor; + CurrentCursor = CC_FILL; + } // else + + if (IN_ACTIVE_AREA) + { + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs,DrawCursors[0]); + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + } // if + + break; + + case NEW_BUTTON : + + if (MessageBox(160, 100, Page0_Offs, + "Do you wish to start a\nnew map from scratch?", + "Last Chance", ID_YESNO) == ID_YES) + { + memset(map, 0, MAP_LAYERS*MAP_SIZE*MAP_SIZE); + RedrawMap(); + } // if + + break; + + case WALL_BUTTON : + if ((CurrentDrawMode != DM_WESTWALL) && + (CurrentDrawMode != DM_NORTHWALL)) + { + MinPic = StartWallPic; + CurrentPic = StartWallPic; + MaxPic = MaxWallPic; + + UPDATE_PIC_LBM = 1; + + showCurrentPic(); + showItemName(); + } // if + + if (CurrentDrawMode == DM_WESTWALL) + { + CurrentDrawMode = DM_NORTHWALL; + CurrentCursor = CC_NORTHWALL; + } // if + else + { + CurrentDrawMode = DM_WESTWALL; + CurrentCursor = CC_WESTWALL; + } // else + showDrawMode(); + + break; + + case FLOOR_BUTTON : + CurrentDrawMode = DM_FLOOR; + CurrentCursor = CC_FLAT; + showDrawMode(); + + MinPic = StartFlatPic; + CurrentPic = StartFlatPic; + MaxPic = MaxFlatPic; + + UPDATE_PIC_LBM = 1; + + showCurrentPic(); + showItemName(); + + break; + + case CEILING_BUTTON : + CurrentDrawMode = DM_CEILING; + CurrentCursor = CC_FLAT; + showDrawMode(); + + MinPic = StartFlatPic; + CurrentPic = StartFlatPic; + MaxPic = MaxFlatPic; + + UPDATE_PIC_LBM = 1; + + showCurrentPic(); + showItemName(); + break; + + case SPRITE_BUTTON : + CurrentDrawMode = DM_SPRITE; + CurrentCursor = CC_ACTOR; + showDrawMode(); + + MinPic = StartActorPic; + CurrentPic = StartActorPic; + MaxPic = MaxActorPic; + + UPDATE_PIC_LBM = 1; + + showCurrentPic(); + showItemName(); + break; + + case TT4_BUTTON : + case TT5_BUTTON : + case TT7_BUTTON : + case TT9_BUTTON : + case TT10_BUTTON : + + break; + + case PIC_LEFT_BUTTON : + if (CurrentPic > MinPic) + { + if (stricmp(scripts[CurrentPic].picFile,scripts[CurrentPic-1].picFile)) + UPDATE_PIC_LBM = 1; + CurrentPic--; + showCurrentPic(); + showItemName(); + } // if + break; + + case PIC_RIGHT_BUTTON : + if (CurrentPic < MaxPic) + { + if (stricmp(scripts[CurrentPic].picFile,scripts[CurrentPic+1].picFile)) + UPDATE_PIC_LBM = 1; + CurrentPic++; + showCurrentPic(); + showItemName(); + } // if + break; + + } // switch +} // handleButton + +void pushButton(char whichButton) +{ + char buttonBuffer[1000]; + char BUTTON_DOWN = 1; + + x_hide_mouse(); + + x_get_pbm(buttons[whichButton*5], buttons[whichButton*5+1], + (buttons[whichButton*5+2] - buttons[whichButton*5] + 1) / 4, + buttons[whichButton*5+3] - buttons[whichButton*5+1] + 1, + Page0_Offs, buttonBuffer); + x_rect_fill(buttons[whichButton*5] - 1, buttons[whichButton*5+1] - 1, + buttons[whichButton*5+2] + 2, buttons[whichButton*5+3] + 2, + Page0_Offs, 0); + x_put_pbm(buttons[whichButton*5] + 1, buttons[whichButton*5+1] + 1, + Page0_Offs, buttonBuffer); + + x_show_mouse(); + + while (MouseButtonStatus & LEFT_MOUSE_CLICK) + { + if (BUTTON_DOWN) + { + if (!MouseOnButton(whichButton)) + { + x_hide_mouse(); + x_rect_fill(buttons[whichButton*5] - 1, buttons[whichButton*5+1] - 1, + buttons[whichButton*5+2] + 2, buttons[whichButton*5+3] + 2, + Page0_Offs, 0); + x_put_pbm(buttons[whichButton*5], buttons[whichButton*5+1], + Page0_Offs, buttonBuffer); + x_show_mouse(); + + BUTTON_DOWN = 0; + } // if + } // if + else + { + if (MouseOnButton(whichButton)) + { + x_hide_mouse(); + x_rect_fill(buttons[whichButton*5] - 1, buttons[whichButton*5+1] - 1, + buttons[whichButton*5+2] + 2, buttons[whichButton*5+3] + 2, + Page0_Offs, 0); + x_put_pbm(buttons[whichButton*5] + 1, buttons[whichButton*5+1] + 1, + Page0_Offs, buttonBuffer); + x_show_mouse(); + + BUTTON_DOWN = 1; + } // if + } // else + }; + + x_hide_mouse(); + + x_rect_fill(buttons[whichButton*5] - 1, buttons[whichButton*5+1] - 1, + buttons[whichButton*5+2] + 2, buttons[whichButton*5+3] + 2, + Page0_Offs, 0); + x_put_pbm(buttons[whichButton*5], buttons[whichButton*5+1], + Page0_Offs, buttonBuffer); + + x_show_mouse(); +} // pushButton + +char MouseOnButton(char whichButton) +{ + if ((MouseX >= buttons[whichButton*5]) && + (MouseX <= buttons[whichButton*5+2]) && + (MouseY >= buttons[whichButton*5+1]) && + (MouseY <= buttons[whichButton*5+3])) + return 1; + + return 0; +} // MouseOnButton + +void handleOptionButtons(void) +{ +} // handleOptionButtons + +void setUpInterface(void) +{ + memset(map, 0, MAP_LAYERS*MAP_SIZE*MAP_SIZE); + memset(Pics, 0, 4*MAX_TILES); + + x_set_font(2); + + x_page_flip(0, 0); + + x_rect_fill(110, 80, 210, 120, Page1_Offs, 1); + x_printf(115, 95, Page1_Offs, 10, "Initializing MAZER..."); + + showLBM(0, 0, PROGRAM_GRAPHIX, Page0_Offs); + x_get_pbm(buttons[OKAY_BUTTON*5], buttons[OKAY_BUTTON*5+1], + (buttons[OKAY_BUTTON*5+2] - buttons[OKAY_BUTTON*5] + 1) / 4, + buttons[OKAY_BUTTON*5+3] - buttons[OKAY_BUTTON*5+1] + 1, + Page0_Offs, DialogButtons[DLG_OKAY]); + x_get_pbm(buttons[CANCEL_BUTTON*5], buttons[CANCEL_BUTTON*5+1], + (buttons[CANCEL_BUTTON*5+2] - buttons[CANCEL_BUTTON*5] + 1) / 4, + buttons[CANCEL_BUTTON*5+3] - buttons[CANCEL_BUTTON*5+1] + 1, + Page0_Offs, DialogButtons[DLG_CANCEL]); + x_get_pbm(buttons[YES_BUTTON*5], buttons[YES_BUTTON*5+1], + (buttons[YES_BUTTON*5+2] - buttons[YES_BUTTON*5] + 1) / 4, + buttons[YES_BUTTON*5+3] - buttons[YES_BUTTON*5+1] + 1, + Page0_Offs, DialogButtons[DLG_YES]); + x_get_pbm(buttons[NO_BUTTON*5], buttons[NO_BUTTON*5+1], + (buttons[NO_BUTTON*5+2] - buttons[NO_BUTTON*5] + 1) / 4, + buttons[NO_BUTTON*5+3] - buttons[NO_BUTTON*5+1] + 1, + Page0_Offs, DialogButtons[DLG_NO]); + x_get_pbm(0,45,TILE_SIZE/4,TILE_SIZE,Page0_Offs, DrawCursors[1]); + x_get_pbm(13,45,TILE_SIZE/4,TILE_SIZE,Page0_Offs, DrawCursors[2]); + x_get_pbm(26,45,TILE_SIZE/4,TILE_SIZE,Page0_Offs, DrawCursors[3]); + x_get_pbm(39,45,TILE_SIZE/4,TILE_SIZE,Page0_Offs, DrawCursors[4]); + x_get_pbm(52,45,TILE_SIZE/4,TILE_SIZE,Page0_Offs, DrawCursors[5]); + x_get_pbm(65,45, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[6]); + + ScaleTiles(); + + showLBM(0, 0, INTERFACE_SCREEN, Page0_Offs); + + showDrawMode(); + showItemName(); + + x_page_flip(0, 0); + + showCurrentPic(); +} // setUpInterface + +void load_user_fonts(void) +{ + FILE *f; + f=fopen("smalthin.fnt","rb"); + /* read char by char as fread wont read to far pointers in small model */ + { int i; char c; + for (i=0;i<256*8+4;i++){ + fread(&c,1,1,f); + *(userfnt1+i)=c; + } + } + + fclose(f); + + x_register_userfont(userfnt1); +} + +void exitfunc(void){ + x_mouse_remove(); + x_text_mode(); + printf("Ta-da\n"); +} + +char MessageBox(int baseX, int baseY, + long pageOffset, char * textMsg, char * titleMsg, + int buttonFlag) +{ + char Xoffset = 5; + char Yoffset = 5; + char TitleHeight = 10; + char TitleYoffset = 8; + char TextYoffset = 10; + char ButtonHeight = 9; + char ButtonWidth = 28; + int ButtonStart = 0; + int width = 100; + int height = 50; + char showButtons; + char ActiveButton = 0; + char AlterButton = 0; + + char *boxBG = NULL; + + int defaultColors[] = + { + 139, // basic color + 154, // hilite color + 144, // lolite color + 79, // title bar color + 255, // text color + 103 // title text color + }; + + int stringWidth; + int stringHeight; + + char numButtons = 0; + char currentButton = 0; + char BUTTON_FOUND = 0; + char return_value = 0; + + + if ((x_strlen(textMsg) > x_strlen(titleMsg)) || + (buttonFlag & ID_NOTITLE)) + width = x_strlen(textMsg) + Xoffset * 2; + else + width = x_strlen(titleMsg) + Xoffset * 4; + + height = x_strheight(textMsg) + Yoffset * 2; + if (!(buttonFlag & ID_NOTITLE)) + height += TitleHeight + TextYoffset + Yoffset; + + if (!(buttonFlag & ID_NOBUTTONS)) + height += ButtonHeight + Yoffset; + + if (buttonFlag & ID_OK) + { + buttons[OKAY_BUTTON*5+4] = 1; + numButtons++; + } + if (buttonFlag & ID_CANCEL) + { + buttons[CANCEL_BUTTON*5+4] = 1; + numButtons++; + } + if (buttonFlag & ID_YES) + { + buttons[YES_BUTTON*5+4] = 1; + numButtons++; + } + if (buttonFlag & ID_NO) + { + buttons[NO_BUTTON*5+4] = 1; + numButtons++; + } + + if ((numButtons * (ButtonWidth+2)) + ((numButtons-1) * Xoffset) + + (Xoffset * 2) > width) + width = (numButtons * ButtonWidth) + ((numButtons-1) * Xoffset) + + (Xoffset * 2); + + // to account for 4 pixel byte boundary + width += 4 - (width % 4); + + baseX -= width / 2; + baseY -= height / 2; + + deactivateMainButtons(); + + x_hide_mouse(); + + boxBG = (char *) malloc(width*height+2); + x_get_pbm(baseX, baseY, width/4, height, pageOffset, boxBG); + + x_rect_fill(baseX, baseY, baseX+width-1, baseY+height-1, + pageOffset, defaultColors[0]); + x_line(baseX, baseY, baseX+width-1, baseY, + defaultColors[1], pageOffset); + x_line(baseX, baseY, baseX, baseY+height-1, + defaultColors[1], pageOffset); + x_line(baseX, baseY+height-1, baseX+width-1, baseY+height-1, + defaultColors[2], pageOffset); + x_line(baseX+width-1, baseY, baseX+width-1, baseY+height-1, + defaultColors[2], pageOffset); + + if (!(buttonFlag & ID_NOTITLE)) + { + x_rect_fill(baseX+Xoffset, baseY+Yoffset, + baseX+width-1-Xoffset, baseY+Yoffset+TitleHeight, + pageOffset, defaultColors[3]); + x_line(baseX+Xoffset, baseY+Yoffset, + baseX+width-1-Xoffset, baseY+Yoffset, + defaultColors[2], pageOffset); + x_line(baseX+Xoffset, baseY+Yoffset, + baseX+Xoffset, baseY+Yoffset+TitleHeight, + defaultColors[2], pageOffset); + x_line(baseX+Xoffset, baseY+Yoffset+TitleHeight, + baseX+width-1-Xoffset, baseY+Yoffset+TitleHeight, + defaultColors[1], pageOffset); + x_line(baseX+width-1-Xoffset, baseY+Yoffset, + baseX+width-1-Xoffset, baseY+Yoffset+TitleHeight, + defaultColors[1], pageOffset); + + stringWidth = x_strlen(titleMsg); + x_printf(baseX+(width/2)-(stringWidth/2), baseY+TitleYoffset, + pageOffset, defaultColors[5], titleMsg); + } // if + else + { + TitleHeight = 0; + TextYoffset = 0; + } // else + + stringWidth = x_strlen(textMsg); + x_printf(baseX+(width/2)-(stringWidth/2), + baseY+Yoffset+TitleHeight+TextYoffset, + pageOffset, defaultColors[4], textMsg); + + if (!(buttonFlag & ID_NOBUTTONS)) + { + ButtonStart = baseX + (width / 2) - + ((numButtons * (ButtonWidth+2) + + (numButtons-1) * Xoffset) / 2); + for (showButtons = 0; showButtons < numButtons; showButtons++) + { + switch (showButtons) + { + case 0: + if (buttonFlag & ID_OK) + { + ActiveButton = DLG_OKAY; + AlterButton = OKAY_BUTTON; + } // if + else if (buttonFlag & ID_YES) + { + ActiveButton = DLG_YES; + AlterButton = YES_BUTTON; + } // else + break; + case 1: + if (buttonFlag & ID_CANCEL) + { + ActiveButton = DLG_CANCEL; + AlterButton = CANCEL_BUTTON; + } // if + else if (buttonFlag & ID_NO) + { + ActiveButton = DLG_NO; + AlterButton = NO_BUTTON; + } // else + break; + } // switch + + buttons[AlterButton*5] = ButtonStart+1; + buttons[AlterButton*5+1] = baseY+height-1-Yoffset-ButtonHeight+1; + buttons[AlterButton*5+2] = buttons[AlterButton*5] + ButtonWidth - 1; + buttons[AlterButton*5+3] = buttons[AlterButton*5+1] + ButtonHeight - 1; + + x_rect_fill(ButtonStart, baseY+height-1-Yoffset-ButtonHeight, + ButtonStart+ButtonWidth-1+3, + baseY+height-1-Yoffset-1+3,pageOffset,0); + x_put_pbm(ButtonStart+1, baseY+height-1-Yoffset-ButtonHeight+1, + pageOffset, DialogButtons[ActiveButton]); + + ButtonStart += ButtonWidth + 2 + Xoffset; + + } // for + } // if + + x_show_mouse(); + + + BUTTON_FOUND = 0; + + while (!return_value) + { + if (MouseButtonStatus & LEFT_MOUSE_CLICK) + { + if (buttonFlag & ID_NOBUTTONS) + return_value = ID_OK; + + currentButton = 0; + while ((!BUTTON_FOUND) && (currentButton != END_OF_BUTTONS)) + { + if ((MouseOnButton(currentButton)) && + (buttons[currentButton*5+4])) + { + + pushButton(currentButton); + + if (MouseOnButton(currentButton)) // check if still modal to button + { + + switch (currentButton) + { + case OKAY_BUTTON: + return_value = ID_OK; + BUTTON_FOUND = 1; + break; + + case CANCEL_BUTTON: + return_value = ID_CANCEL; + BUTTON_FOUND = 1; + break; + + case YES_BUTTON: + return_value = ID_YES; + BUTTON_FOUND = 1; + break; + + case NO_BUTTON: + return_value = ID_NO; + BUTTON_FOUND = 1; + break; + } // switch + } // if + } // if + + currentButton++; + } // while + } // if + } // while + + x_hide_mouse(); + + x_put_pbm(baseX, baseY, pageOffset, boxBG); + + x_show_mouse(); + + deactivateDlgButtons(); + activateMainButtons(); + + if (boxBG) + free(boxBG); + + return return_value; +} // char + +void deactivateMainButtons(void) +{ + char runButtons = START_MAIN_BUT; + + while ((runButtons < END_OF_MAIN_BUT) && + (runButtons < END_OF_BUTTONS)) + { + buttons[runButtons*5+4] = 0; + + runButtons++; + } // while +} // deactivateMainButtons + +void activateMainButtons(void) +{ + char runButtons = START_MAIN_BUT; + + while ((runButtons < END_OF_MAIN_BUT) && + (runButtons < END_OF_BUTTONS)) + { + buttons[runButtons*5+4] = 1; + + runButtons++; + } // while +} // activateMainButtons + +void deactivateDlgButtons(void) +{ + char runButtons = START_DLG_BUT; + + while ((runButtons < END_OF_DLG_BUT) && + (runButtons < END_OF_BUTTONS)) + { + buttons[runButtons*5+4] = 0; + + runButtons++; + } // while +} // deactivateDlgButtons + +void activateDlgButtons(void) +{ + char runButtons = START_DLG_BUT; + + while ((runButtons < END_OF_DLG_BUT) && + (runButtons < END_OF_BUTTONS)) + { + buttons[runButtons*5+4] = 1; + + runButtons++; + } // while +} // activateDlgButtons + +void showDrawMode(void) +{ + x_rect_fill(DM_BASEX, DM_BASEY, DM_MAXX, DM_MAXY, Page0_Offs, DM_BGCOLOR); + x_printf(DM_BASEX+((DM_MAXX-DM_BASEX)/2)- + (x_strlen(DrawModes[CurrentDrawMode])/2), + DM_BASEY + 2, + Page0_Offs, DM_FGCOLOR, DrawModes[CurrentDrawMode]); +} // showDrawMode + +void showItemName(void) +{ + x_rect_fill(IN_BASEX, IN_BASEY, IN_MAXX, IN_MAXY, Page0_Offs, IN_BGCOLOR); + x_printf(IN_BASEX+((IN_MAXX-IN_BASEX)/2)- + (x_strlen(scripts[CurrentPic].picName)/2), + IN_BASEY + 2, + Page0_Offs, IN_FGCOLOR, scripts[CurrentPic].picName); +} // showItemName + +void showMouseCoords(int posX, int posY) +{ + char buffer[20]; + + sprintf(buffer, "%d, %d", GridBaseX+posX, GridBaseY+posY); + + if (!IN_ACTIVE_AREA) + x_hide_mouse(); + + x_rect_fill(MC_BASEX, MC_BASEY, MC_MAXX, MC_MAXY, Page0_Offs, MC_BGCOLOR); + x_printf(MC_BASEX+2, + MC_BASEY + 2, + Page0_Offs, MC_FGCOLOR, buffer); + + if (!IN_ACTIVE_AREA) + x_show_mouse(); + +} // showMouseCoords + +void showCurrentPic(void) +{ + char picBuf[4100]; + + x_hide_mouse(); + + if (UPDATE_PIC_LBM) + { + showLBM(0, 0, scripts[CurrentPic].picFile, Page1_Offs); + UPDATE_PIC_LBM = 0; + } // if + + x_get_pbm(scripts[CurrentPic].Xoffset*8, + scripts[CurrentPic].Yoffset*8, 16, 64, Page1_Offs, picBuf); + x_put_pbm(PIC_BASEX, PIC_BASEY, Page0_Offs, picBuf); + + x_show_mouse(); +} // showCurrentPic + +void handleMouseCursor(void) +{ + NewMouseX = MouseX; + NewMouseY = MouseY; + + + if ((FILL_ACTIVE) && + (!(MouseButtonStatus & LEFT_MOUSE_CLICK))) + { + + FillAnArea(FillStartX, FillStartY, + (OldMouseX - 4)/TILE_SIZE, + (OldMouseY - 4)/TILE_SIZE); + RedrawMap(); + FILL_ACTIVE = 0; +// CurrentCursor = OldCursor; + + if ((NewMouseX < AA_BASEX) || (NewMouseX > AA_MAXX) || + (NewMouseY < AA_BASEY) || (NewMouseY > AA_MAXY)) + x_hide_mouse(); + else + { + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, + Page0_Offs, DrawCursors[0]); + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + } // else + + if ((NewMouseX < AA_BASEX) || (NewMouseX > AA_MAXX) || + (NewMouseY < AA_BASEY) || (NewMouseY > AA_MAXY)) + x_show_mouse(); + + return; + } // if + + + if ((NewMouseX >= AA_BASEX) && (NewMouseX <= AA_MAXX) && + (NewMouseY >= AA_BASEY) && (NewMouseY <= AA_MAXY)) + { + if (!IN_ACTIVE_AREA) + { + x_hide_mouse(); + OldMouseX = 4 + ((NewMouseX-4)/TILE_SIZE)*TILE_SIZE; + OldMouseY = 4 + ((NewMouseY-4)/TILE_SIZE)*TILE_SIZE; + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, + Page0_Offs, DrawCursors[0]); + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + + IN_ACTIVE_AREA = 1; + } // if + } // if + else + { + if (IN_ACTIVE_AREA) + { + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + + x_show_mouse(); + IN_ACTIVE_AREA = 0; + } // if + } // else + + if (IN_ACTIVE_AREA) + { + NewMouseX = 4 + ((NewMouseX-4)/TILE_SIZE)*TILE_SIZE; + NewMouseY = 4 + ((NewMouseY-4)/TILE_SIZE)*TILE_SIZE; + + if ((NewMouseX != OldMouseX) || (NewMouseY != OldMouseY) || + (MouseButtonStatus & LEFT_MOUSE_CLICK) || + (MouseButtonStatus & RIGHT_MOUSE_CLICK)) + { + if (!(MouseButtonStatus & LEFT_MOUSE_CLICK) && + !(MouseButtonStatus & RIGHT_MOUSE_CLICK)) + showMouseCoords((NewMouseX-4)/TILE_SIZE,(NewMouseY-4)/TILE_SIZE); + + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + OldMouseX = NewMouseX; + OldMouseY = NewMouseY; + + GRIDX = (OldMouseX - 4)/TILE_SIZE; + GRIDY = (OldMouseY - 4)/TILE_SIZE; + + if (MouseButtonStatus & LEFT_MOUSE_CLICK) + { + if (CurrentCursor == CC_FILL) + { + if (FILL_ACTIVE) + { + RedrawMap(); + //x_put_pbm(4, 4, Page0_Offs, FillPic); + if ((FillStartX <= GRIDX) && (FillStartY <= GRIDY)) + { + x_line(4+FillStartX*TILE_SIZE, 4+FillStartY*TILE_SIZE, + 4+GRIDX*TILE_SIZE+TILE_SIZE-1, 4+FillStartY*TILE_SIZE, + 255, Page0_Offs); + x_line(4+FillStartX*TILE_SIZE, 4+GRIDY*TILE_SIZE+TILE_SIZE-1, + 4+GRIDX*TILE_SIZE+TILE_SIZE-1, 4+GRIDY*TILE_SIZE+TILE_SIZE-1, + 255, Page0_Offs); + x_line(4+FillStartX*TILE_SIZE, 4+FillStartY*TILE_SIZE, + 4+FillStartX*TILE_SIZE, 4+GRIDY*TILE_SIZE+TILE_SIZE-1, + 255, Page0_Offs); + x_line(4+GRIDX*TILE_SIZE+TILE_SIZE-1, 4+FillStartY*TILE_SIZE, + 4+GRIDX*TILE_SIZE+TILE_SIZE-1, 4+GRIDY*TILE_SIZE+TILE_SIZE-1, + 255, Page0_Offs); + } // if + + } // if + else + { + FILL_ACTIVE = 1; + FillStartX = GRIDX; + FillStartY = GRIDY; + //FillPic = (char *) malloc(MAP_VIEW_SIZE*TILE_SIZE*TILE_SIZE); + //x_get_pbm(4, 4, (MAP_VIEW_SIZE*TILE_SIZE)/4, + // MAP_VIEW_SIZE*TILE_SIZE, Page0_Offs, FillPic); + } // else + } // if + else + { + switch (CurrentCursor) + { + case CC_WESTWALL : + map[WEST_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = CurrentPic-MinPic+1; + + if (DRAW_FROM_PIC) + { + x_get_pbm(PIC_BASEX, PIC_BASEY, TILE_SIZE/4, TILE_SIZE, + Page0_Offs, DrawBuffer); + x_rect_fill(0, 0, TILE_SIZE, TILE_SIZE, Page1_Offs, 0); + x_put_pbm(0, 0, Page1_Offs, DrawBuffer); + x_line(0, 0, TILE_SIZE, 0, 0, Page0_Offs); + x_line(0, TILE_SIZE-1, TILE_SIZE, TILE_SIZE-1, 0, Page1_Offs); + x_line(0, 0, 0, TILE_SIZE, 0, Page1_Offs); + x_line(3, 0, 3, TILE_SIZE, 0, Page1_Offs); + + if (!Pics[TT_WESTWALL][CurrentPic-MinPic][0]) + { + x_get_pbm(0, 0, 1, TILE_SIZE, + Page1_Offs, Pics[TT_WESTWALL][CurrentPic-MinPic]); + } // if + + DrawGridTile(GRIDX, GRIDY); + } // if + else + x_line(OldMouseX-1, OldMouseY, OldMouseX, OldMouseY + TILE_SIZE-1, + 103, Page0_Offs); + break; + + case CC_NORTHWALL : + map[NORTH_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = CurrentPic-MinPic+1; + + if (DRAW_FROM_PIC) + { + x_get_pbm(PIC_BASEX, PIC_BASEY, TILE_SIZE/4, 4, + Page0_Offs, DrawBuffer); + x_rect_fill(0, 0, TILE_SIZE, TILE_SIZE, Page1_Offs, 0); + x_put_pbm(0, 0, Page1_Offs, DrawBuffer); + x_line(0, 0, TILE_SIZE, 0, 0, Page1_Offs); + x_line(0, 3, TILE_SIZE, 3, 0, Page1_Offs); + x_line(0, 0, 0, TILE_SIZE, 0, Page1_Offs); + x_line(TILE_SIZE-1, 0, TILE_SIZE-1, TILE_SIZE, 0, Page1_Offs); + + if (!Pics[TT_NORTHWALL][CurrentPic-MinPic][0]) + { + x_get_pbm(0, 0, TILE_SIZE/4, 4, + Page1_Offs, Pics[TT_NORTHWALL][CurrentPic-MinPic]); + } // if + + DrawGridTile(GRIDX, GRIDY); + } // if + else + x_line(OldMouseX + 1, OldMouseY, OldMouseX + 5, OldMouseY, + 103, Page0_Offs); + break; + + case CC_FLAT : + if (CurrentDrawMode == DM_FLOOR) + map[FLOOR_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = CurrentPic-MinPic+1; + else + map[CEILING_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = CurrentPic-MinPic+1; + + if (DRAW_FROM_PIC) + { + // if (!Pics[TT_FLAT][CurrentPic-MinPic][0]) + // { + // x_get_pbm(0, 0, TILE_SIZE/4, TILE_SIZE, + // Page0_Offs, Pics[TT_FLAT][CurrentPic-MinPic]); + // } // if + + DrawGridTile(GRIDX, GRIDY); + } // if + else + x_rect_fill(OldMouseX + 2, OldMouseY + 2, + OldMouseX + 5, OldMouseY + 5, + Page0_Offs, 103); + break; + + case CC_ACTOR : + map[SPRITE_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = CurrentPic-MinPic+1; + + if (DRAW_FROM_PIC) + { + DrawGridTile(GRIDX, GRIDY); + } // if + + break; + } // if + } // else + } // if + else if (MouseButtonStatus & RIGHT_MOUSE_CLICK) + { + switch (CurrentCursor) + { + case CC_WESTWALL : + map[WEST_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = 0; + + DrawGridTile(GRIDX, GRIDY); + break; + + case CC_NORTHWALL : + map[NORTH_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = 0; + + DrawGridTile(GRIDX, GRIDY); + break; + + case CC_FLAT : + if (CurrentDrawMode == DM_FLOOR) + map[FLOOR_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = 0; + else + map[CEILING_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = 0; + + DrawGridTile(GRIDX, GRIDY); + break; + + case CC_ACTOR : + map[SPRITE_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = 0; + + if (DRAW_FROM_PIC) + { + DrawGridTile(GRIDX, GRIDY); + } // if + + break; + } // if + } // if + else + { + if (FILL_ACTIVE) + { + //x_put_pbm(4, 4, Page0_Offs, FillPic); + //free(FillPic); + //FillPic = NULL; + //RedrawMap(); + //FILL_ACTIVE = 0; + //CurrentCursor = OldCursor; + } // if + } // else + + + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[0]); + + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + } // if + } // if +} // handleMouseCursor + +void DrawGridTile(char xpos, char ypos) +{ + char TileBuffer[146]; + + x_rect_fill(0, 0, TILE_SIZE, TILE_SIZE, Page1_Offs, 0); + x_put_pix(0, 0, Page1_Offs, GRID_MARK_COLOR); + + if (map[FLOOR_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]) + { + x_put_pbm(0, 0, Page1_Offs, + Pics[TT_FLAT][map[FLOOR_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]-1]); + } // if + if (map[WEST_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]) + { + x_put_pbm(0, 0, Page1_Offs, + Pics[TT_WESTWALL][map[WEST_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]-1]); + } // if + if (map[NORTH_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]) + { + x_put_pbm(0, 0, Page1_Offs, + Pics[TT_NORTHWALL][map[NORTH_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]-1]); + } // if + if (map[SPRITE_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]) + { + x_put_masked_pbm(0, 0, Page1_Offs, + Pics[TT_ACTOR][map[SPRITE_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]-1]); + } // if + + x_get_pbm(0, 0, TILE_SIZE/4, TILE_SIZE, Page1_Offs, TileBuffer); + + x_put_pbm(4+xpos*TILE_SIZE, 4+ypos*TILE_SIZE, Page0_Offs, TileBuffer); + +} // DrawGridTile + +void RedrawMap(void) +{ + char row; + char col; + + + if (CurrentCursor != CC_FILL) + { + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs,DrawCursors[0]); + else + x_hide_mouse(); + } // if + + for (row = 0; row < MAP_VIEW_SIZE; row++) + { + for (col = 0; col < MAP_VIEW_SIZE; col++) + { + DrawGridTile(col, row); + } // for + } // for + + if (CurrentCursor != CC_FILL) + { + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + else + x_show_mouse(); + } // if +} // RedrawMap + +void RedrawCol(char whichCol) +{ + char row; + + for (row = 0; row < MAP_VIEW_SIZE; row++) + { + DrawGridTile(whichCol, row); + } // for +} // RedrawRow + +void RedrawRow(char whichRow) +{ + char col; + + for (col = 0; col < MAP_VIEW_SIZE; col++) + { + DrawGridTile(col, whichRow); + } // for +} // RedrawRow + +int SaveMapToFile(char *filename) +{ + int MapFile; + + if ((MapFile = f_open(filename, F_RDWR)) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[FLOOR_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[CEILING_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[NORTH_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[WEST_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[SPRITE_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_close(MapFile) == FILE_ERR) + return 0; + + MessageBox(160, 100, Page0_Offs, "New saved okay.", "", ID_OK | ID_NOTITLE); + + return 1; +} // SaveMapToFile + +int SaveMapToTOD(void) +{ + int MapFile; + + if ((MapFile = f_open(DATA_FILE, F_RDWR)) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x3E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[FLOOR_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x4E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[CEILING_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x5E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[NORTH_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x6E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[WEST_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0xCE0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[SPRITE_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_close(MapFile) == FILE_ERR) + return 0; + + MessageBox(160, 100, Page0_Offs, "New map inserted okay.", "", ID_OK | ID_NOTITLE); + + return 1; +} // SaveMapToTOD + +int LoadMapFromFile(char *filename) +{ + int MapFile; + long numRead; + + if ((MapFile = f_open(filename, F_RDWR)) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[FLOOR_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[CEILING_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[NORTH_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[WEST_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[SPRITE_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_close(MapFile) == FILE_ERR) + return 0; + + MessageBox(160, 100, Page0_Offs, "Old map loaded okay.", "", ID_OK | ID_NOTITLE); + + return 1; +} // LoadMapFromFile + +int LoadMapFromTOD(void) +{ + int MapFile; + long numRead; + + if ((MapFile = f_open(DATA_FILE, F_RDWR)) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x3E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[FLOOR_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x4E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[CEILING_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x5E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[NORTH_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x6E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[WEST_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0xCE0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[SPRITE_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_close(MapFile) == FILE_ERR) + return 0; + + MessageBox(160, 100, Page0_Offs, "Old map extracted okay.", "", ID_OK | ID_NOTITLE); + + return 1; +} // LoadMapFromTOD + +void ScaleTiles() +{ + char i; + char j; + WORD color; + char scaleX = TILE_SIZE; + char scaleY = TILE_SIZE; + char picToScale = 0; + + + + scaleX = 4; + scaleY = TILE_SIZE; + + picToScale = StartWallPic; + + while (picToScale <= MaxWallPic) + { + if ((picToScale == StartWallPic) || + (strcmpi(scripts[picToScale].picFile, scripts[picToScale-1].picFile))) + showLBM(0, 0, scripts[picToScale].picFile, Page0_Offs); + + x_rect_fill(0, 0, TILE_SIZE, TILE_SIZE, Page0_Offs, 0); + + for (i=0; i +#include +#include +#include +#include +#include "xlib_all.h" + +void load_user_fonts(void); +void exitfunc(void); + +char far *userfnt1; + +void main(void) +{ + int i; + int j; + + userfnt1 = (char far *) farmalloc(256*16+4); + + x_text_mode(); + x_set_mode(X_MODE_320x200,320); + x_text_init(); + x_mouse_init(); + MouseColor=15; + atexit(exitfunc); + load_user_fonts(); + + + getch(); +} // main + +void load_user_fonts(void) +{ + FILE *f; + f=fopen("tiny4.fnt","rb"); + /* read char by char as fread wont read to far pointers in small model */ + { int i; char c; + for (i=0;i<256*8+4;i++){ + fread(&c,1,1,f); + *(userfnt1+i)=c; + } + } + + fclose(f); + + x_register_userfont(userfnt1); +} + +void exitfunc(void){ + x_mouse_remove(); + x_text_mode(); + printf("Ta-da\n"); +} \ No newline at end of file diff --git a/MYMAP/MAZER.CPP b/MYMAP/MAZER.CPP new file mode 100644 index 0000000..4e1b521 --- /dev/null +++ b/MYMAP/MAZER.CPP @@ -0,0 +1,2157 @@ +#include +#include +#include +#include +#include +#include +#include +#include "xlib_all.h" + +#define PROGRAM_GRAPHIX "GRAPHIX.LBM" +#define INTERFACE_SCREEN "INTRFACE.LBM" +#define DATA_FILE "TODD3D.TOD" + +#define UP_KEY 72 + 256 +#define DOWN_KEY 80 + 256 +#define LEFT_KEY 75 + 256 +#define RIGHT_KEY 77 + 256 + +#define GRID_MARK_COLOR 80 + +#define MAP_VIEW_SIZE 16 +#define MAP_SIZE 64 +#define MAX_TILES 64 +#define MAP_LAYERS 5 +#define TILE_SIZE 12 + +#define WEST_LAYER 0 +#define NORTH_LAYER 1 +#define FLOOR_LAYER 2 +#define CEILING_LAYER 3 +#define SPRITE_LAYER 4 + +#define PIC_BASEX 227 +#define PIC_BASEY 133 + +#define AA_BASEX 4 +#define AA_BASEY 4 +#define AA_MAXX 195 +#define AA_MAXY 195 + +#define MC_BASEX 254 +#define MC_BASEY 100 +#define MC_MAXX 303 +#define MC_MAXY 108 +#define MC_BGCOLOR 101 +#define MC_FGCOLOR 0 + +#define DM_BASEX 214 +#define DM_BASEY 10 +#define DM_MAXX 304 +#define DM_MAXY 18 +#define DM_BGCOLOR 101 +#define DM_FGCOLOR 0 + +#define IN_BASEX 214 +#define IN_BASEY 120 +#define IN_MAXX 304 +#define IN_MAXY 128 +#define IN_BGCOLOR 101 +#define IN_FGCOLOR 0 + +#define LEFT_MOUSE_CLICK 1 +#define RIGHT_MOUSE_CLICK 2 + +#define DM_NONE 0 +#define DM_WESTWALL 1 +#define DM_NORTHWALL 2 +#define DM_FLOOR 3 +#define DM_CEILING 4 +#define DM_SPRITE 5 +#define DM_DOOR 6 + +#define TT_WESTWALL 0 +#define TT_NORTHWALL 1 +#define TT_FLAT 2 +#define TT_ACTOR 3 + +#define CC_NONE 0 +#define CC_WESTWALL 1 +#define CC_NORTHWALL 2 +#define CC_FLAT 3 +#define CC_FILL 4 +#define CC_DOOR 5 +#define CC_ACTOR 6 +#define CC_PLAYER 7 + +#define DLG_OKAY 0 +#define DLG_CANCEL 1 +#define DLG_YES 2 +#define DLG_NO 3 + +#define ID_OK 1 +#define ID_CANCEL 2 +#define ID_YES 4 +#define ID_NO 8 +#define ID_NOBUTTONS 16 +#define ID_NOTITLE 32 +#define ID_DEFAULT 1 +#define ID_OKAYCANCEL 3 +#define ID_YESNO 12 + +#define FILL_BUTTON 0 +#define NEW_BUTTON 1 +#define LOAD_BUTTON 2 +#define SAVE_BUTTON 3 +#define EXIT_BUTTON 4 +#define EXTRA_BUTTON 5 +#define PIC_LEFT_BUTTON 6 +#define PIC_RIGHT_BUTTON 7 + +#define WALL_BUTTON 8 +#define FLOOR_BUTTON 9 +#define CEILING_BUTTON 10 +#define TT4_BUTTON 11 +#define TT5_BUTTON 12 +#define PLAYER_BUTTON 13 +#define TT7_BUTTON 14 +#define SPRITE_BUTTON 15 +#define TT9_BUTTON 16 +#define TT10_BUTTON 17 + +#define OKAY_BUTTON 18 +#define CANCEL_BUTTON 19 +#define YES_BUTTON 20 +#define NO_BUTTON 21 + +#define END_OF_BUTTONS 22 +#define END_OF_MAIN_BUT 17 +#define END_OF_DLG_BUT 22 + +#define START_MAIN_BUT 0 +#define START_DLG_BUT 18 + + +extern void showLBM(int,int,char*,long); + +void load_user_fonts(void); +void exitfunc(void); + +void setUpInterface(void); +void drawLoop(void); +void handleUserActions(void); +char MouseOnButton(char); +void handleButton(char); +void pushButton(char); +void handleKeystroke(int); + +char MessageBox(int, int, long, char *, char *, int); +void deactivateMainButtons(void); +void activateMainButtons(void); +void deactivateDlgButtons(void); +void activateDlgButtons(void); + +void showDrawMode(void); +void showItemName(void); +void showCurrentPic(void); +void showMouseCoords(int, int); + +void handleMouseCursor(void); +void DrawGridTile(char xpos, char ypos); +void RedrawMap(); +void RedrawRow(char whichRow); +void RedrawCol(char whichCol); + +int SaveMapToTOD(void); +int LoadMapFromTOD(void); +int SaveMapToFile(char *); +int LoadMapFromFile(char *); + +void ScaleTiles(); + +void FillAnArea(char, char, char, char); + +typedef struct picStruct +{ + char *pbm; +} picType; + +typedef struct mapStruct +{ + char *layer; +} mapType; + +typedef struct scriptStruct +{ + char picFile[30]; + char picName[20]; + char Xoffset; + char Yoffset; +} scriptType; + +scriptStruct scripts[75] = +{ + "WALLS1.LBM", + "W1_1", + 2, + 2, + "WALLS1.LBM", + "W1_2", + 10, + 2, + "WALLS1.LBM", + "W1_3", + 18, + 2, + "WALLS1.LBM", + "W1_4", + 26, + 2, + "WALLS1.LBM", + "W1_5", + 2, + 10, + "WALLS1.LBM", + "W1_6", + 10, + 10, + "WALLS1.LBM", + "W1_7", + 18, + 10, + "WALLS1.LBM", + "W1_8", + 26, + 10, + "WALLS2.LBM", + "W2_1", + 2, + 2, + "WALLS2.LBM", + "W2_2", + 10, + 2, + "WALLS2.LBM", + "W2_3", + 18, + 2, + "WALLS2.LBM", + "W2_4", + 26, + 2, + "WALLS2.LBM", + "W2_5", + 2, + 10, + "WALLS2.LBM", + "W2_6", + 10, + 10, + "WALLS2.LBM", + "W2_7", + 18, + 10, + "WALLS2.LBM", + "W2_8", + 26, + 10, + "WALLS3.LBM", + "W3_1", + 2, + 2, + "WALLS3.LBM", + "W3_2", + 11, + 2, + "WALLS3.LBM", + "W3_3", + 20, + 2, + "WALLS3.LBM", + "W3_4", + 29, + 2, + "WALLS3.LBM", + "W3_5", + 2, + 11, + "WALLS3.LBM", + "W3_6", + 11, + 11, + "WALLS3.LBM", + "W3_7", + 20, + 11, + "WALLS3.LBM", + "W3_8", + 29, + 11, + "WALLS4.LBM", + "W4_1", + 2, + 2, + "WALLS4.LBM", + "W4_2", + 11, + 2, + "WALLS4.LBM", + "W4_3", + 20, + 2, + "WALLS4.LBM", + "W4_4", + 29, + 2, + "WALLS4.LBM", + "W4_5", + 2, + 11, + "WALLS4.LBM", + "W4_6", + 11, + 11, + "WALLS4.LBM", + "W4_7", + 20, + 11, + "WALLS4.LBM", + "W4_8", + 29, + 11, + "WALLS5.LBM", + "W5_1", + 2, + 2, + "WALLS5.LBM", + "W5_2", + 11, + 2, + "WALLS5.LBM", + "W5_3", + 20, + 2, + "WALLS5.LBM", + "W5_4", + 29, + 2, + "WALLS5.LBM", + "W5_5", + 2, + 11, + "WALLS5.LBM", + "W5_6", + 11, + 11, + "WALLS5.LBM", + "W5_7", + 20, + 11, + "WALLS5.LBM", + "W5_8", + 29, + 11, + "WALLS6.LBM", + "W6_1", + 2, + 2, + "WALLS6.LBM", + "W5_2", + 11, + 2, + "WALLS6.LBM", + "W5_3", + 20, + 2, + "WALLS6.LBM", + "W5_4", + 29, + 2, + "WALLS6.LBM", + "W5_5", + 2, + 11, + "WALLS6.LBM", + "W5_6", + 11, + 11, + "WALLS6.LBM", + "W5_7", + 20, + 11, + "WALLS6.LBM", + "W5_8", + 29, + 11, + "FLATS1.LBM", + "F1_1", + 2, + 2, + "FLATS1.LBM", + "F1_2", + 11, + 2, + "FLATS1.LBM", + "F1_3", + 20, + 2, + "FLATS1.LBM", + "F1_4", + 29, + 2, + "FLATS1.LBM", + "F1_5", + 2, + 11, + "FLATS1.LBM", + "F1_6", + 11, + 11, + "FLATS1.LBM", + "F1_7", + 20, + 11, + "FLATS1.LBM", + "F1_8", + 29, + 11, + "FLATS2.LBM", + "F2_1", + 2, + 2, + "FLATS2.LBM", + "F2_2", + 11, + 2, + "FLATS2.LBM", + "F2_3", + 2, + 11, + "FLATS2.LBM", + "F2_4", + 11, + 11, + "ACTORS1.LBM", + "A1_1", + 2, + 2, + "ACTORS1.LBM", + "A1_2", + 11, + 2, + "ACTORS1.LBM", + "P1_1", + 20, + 2, + "ACTORS1.LBM", + "W1_1", + 29, + 2, + "ACTORS1.LBM", + "A1_3", + 11, + 11, + "ACTORS1.LBM", + "W1_1", + 2, + 11, + "ACTORS1.LBM", + "W1_1", + 20, + 11, + "ACTORS1.LBM", + "W1_1", + 29, + 11, + "ACTORS2.LBM", + "U1_1", + 2, + 2, + "ACTORS2.LBM", + "U1_1", + 11, + 2, + "ACTORS2.LBM", + "B1_1", + 20, + 2, + "ACTORS2.LBM", + "C1_1", + 29, + 2, + "ACTORS2.LBM", + "J1_1", + 2, + 11, + "ACTORS1.LBM", + "VERTICAL DOOR", + 29, + 2, + "ACTORS2.LBM", + "A1_1", + 11, + 11, +}; + +char far *FillCursor[] = +{ "THISISATEST!!!"}; + +char far *userfnt1; +char *FillPic = NULL; + +char IN_ACTIVE_AREA = 0; +char DONE_DRAWING = 0; +char FILL_ACTIVE = 0; +char UPDATE_PIC_LBM = 1; +char DRAW_FROM_PIC = 1; +char GRAPHIC_CURSOR = 0; +char CurrentDrawMode = DM_WESTWALL; +char CurrentCursor = CC_WESTWALL; +char OldCursor = CurrentCursor; +char CurrentPic = 0; +char MinPic = 0; +char StartWallPic = 0; +char MaxWallPic = 47; +char MaxPic = MaxWallPic; +char StartFlatPic = MaxWallPic + 1; +char MaxFlatPic = StartFlatPic + 11; +char StartActorPic = MaxFlatPic + 1; +char MaxActorPic = StartActorPic + 14; +char MaxScriptPic = MaxActorPic; + +int OldMouseX; +int OldMouseY; +int NewMouseX; +int NewMouseY; +char GRIDX; +char GRIDY; +char FillStartX; +char FillStartY; +char GridBaseX = 0; +char GridBaseY = 0; + +int buttons[] = +{ + 214, 73, 241, 81, 1, + 214, 85, 241, 93, 1, + 246, 73, 273, 81, 1, + 246, 85, 273, 93, 1, + 278, 73, 305, 81, 1, + 278, 85, 305, 93, 1, + 212, 133, 223, 144, 1, + 294, 133, 305, 144, 1, + + 215, 32, 230, 47, 1, + 233, 32, 248, 47, 1, + 251, 32, 266, 47, 1, + 269, 32, 284, 47, 1, + 287, 32, 302, 47, 1, + 215, 50, 230, 65, 1, + 233, 50, 248, 65, 1, + 251, 50, 266, 65, 1, + 269, 50, 284, 65, 1, + 287, 50, 302, 65, 1, + + 0, 0, 27, 8, 0, // DIALOG BUTTONS + 0, 9, 27, 17, 0, // Start out at grab position in graphix file + 0, 18, 27, 26, 0, // Are filled in on the fly leter based on where + 0, 27, 27, 35, 0, // dialog is to be shown + + 0, 0, 0, 0, 0 +}; + +char *DrawModes[] = +{ + "DRAW INACTIVE", + "WEST WALL", + "NORTH WALL", + "FLOOR", + "CEILING", + "SPRITE PLACEMENT", + "", +}; + +char DialogButtons[4][300]; +char DrawCursors[7][146]; +char DrawBuffer[TILE_SIZE*TILE_SIZE+2]; +//char Pics[4][MAX_TILES][TILE_SIZE*TILE_SIZE+2]; +picStruct Pics[4][MAX_TILES]; + +char map[MAP_LAYERS][MAP_SIZE*MAP_SIZE]; + +void main(void) +{ + int i; + int j; + + userfnt1 = (char far *) farmalloc(256*16+4); + + x_text_mode(); + x_set_mode(X_MODE_320x200,340); + x_text_init(); + NonVisual_Offs += ScrnLogicalByteWidth * 14; // Fixes mouse droppings prob. + x_mouse_init(); + MouseColor=103; + atexit(exitfunc); + load_user_fonts(); + x_set_doublebuffer(200); + + for (i=0; i < 4; i++) + for (j=0; j < MAX_TILES; j++) + Pics[i][j].pbm = (char *) malloc (TILE_SIZE*TILE_SIZE+2); + + setUpInterface(); + + drawLoop(); + + for (i=0; i < 4; i++) + for (j=0; j < MAX_TILES; j++) + free(Pics[i][j].pbm); + +} // main + +void drawLoop(void) +{ + x_mouse_window(0, 0, 319, 199); + + x_show_mouse(); + + while (!DONE_DRAWING) + { + handleUserActions(); + handleMouseCursor(); + } // while + + x_hide_mouse(); +} // drawLoop + +void handleUserActions(void) +{ + char BUTTON_FOUND = 0; + char currentButton; + int currentKey; + + if (MouseButtonStatus & LEFT_MOUSE_CLICK) + { + currentButton = 0; + while ((!BUTTON_FOUND) && (currentButton != END_OF_BUTTONS)) + { + if ((MouseOnButton(currentButton)) && + (buttons[currentButton*5+4])) + { + handleButton(currentButton); + BUTTON_FOUND = 1; + } // if + + currentButton++; + } // while + } // if + else if (bioskey(1)) + { + currentKey = bioskey(0); + if (!(currentKey & 0xFF)) + currentKey = (currentKey >> 8) + 256; + else + currentKey = currentKey & 0xFF; + + handleKeystroke(currentKey); + } // else +} // handleUserActions + +void handleKeystroke(int whichKey) +{ + switch (whichKey) + { + case UP_KEY : + if (GridBaseY > 0) + { + if (IN_ACTIVE_AREA) + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + else + x_hide_mouse(); + + x_shift_rect(AA_BASEX, AA_BASEY, + AA_MAXX-3, AA_MAXY-TILE_SIZE, + AA_BASEX, AA_BASEY+TILE_SIZE, Page0_Offs); + GridBaseY--; + RedrawRow(0); + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[0]); + + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + else + x_show_mouse(); + + showMouseCoords((OldMouseX-4)/TILE_SIZE,(OldMouseY-4)/TILE_SIZE); + } // if + break; + + case DOWN_KEY : + if (GridBaseY + MAP_VIEW_SIZE -1 < MAP_SIZE-1) + { + if (IN_ACTIVE_AREA) + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + else + x_hide_mouse(); + + x_shift_rect(AA_BASEX, AA_BASEY+TILE_SIZE, + AA_MAXX-3, AA_MAXY, + AA_BASEX, AA_BASEY, Page0_Offs); + GridBaseY++; + RedrawRow(MAP_VIEW_SIZE-1); + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[0]); + + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + else + x_show_mouse(); + + showMouseCoords((OldMouseX-4)/TILE_SIZE,(OldMouseY-4)/TILE_SIZE); + } // if + break; + + case LEFT_KEY : + + if (GridBaseX > 0) + { + if (IN_ACTIVE_AREA) + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + else + x_hide_mouse(); + x_shift_rect(AA_BASEX, AA_BASEY, AA_MAXX-TILE_SIZE-3, + AA_MAXY, AA_BASEX+TILE_SIZE, AA_BASEY, Page0_Offs); + GridBaseX--; + RedrawCol(0); + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[0]); + + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + else + x_show_mouse(); + + showMouseCoords((OldMouseX-4)/TILE_SIZE,(OldMouseY-4)/TILE_SIZE); + } // if + break; + + case RIGHT_KEY : + + if (GridBaseX + MAP_VIEW_SIZE - 1 < MAP_SIZE-1) + { + if (IN_ACTIVE_AREA) + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + else + x_hide_mouse(); + x_shift_rect(AA_BASEX+TILE_SIZE, AA_BASEY, AA_MAXX-3, + AA_MAXY, AA_BASEX, AA_BASEY, Page0_Offs); + GridBaseX++; + RedrawCol(MAP_VIEW_SIZE-1); + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[0]); + + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + else + x_show_mouse(); + + showMouseCoords((OldMouseX-4)/TILE_SIZE,(OldMouseY-4)/TILE_SIZE); + } // if + +// break; + } // switch +} // handleKeyStroke + +void handleButton(char whichButton) +{ + pushButton(whichButton); + + if (!MouseOnButton(whichButton)) // check if still modal to button + return; + + switch (whichButton) + { + case EXIT_BUTTON : + + if (MessageBox(160, 100, Page0_Offs, "Are you sure you want to exit?", + "Last Chance", ID_YESNO) == ID_YES) + DONE_DRAWING = 1; + + break; + + case SAVE_BUTTON : + if (MessageBox(160, 100, Page0_Offs, + "Do you want to save?", + "", ID_YESNO | ID_NOTITLE) == ID_YES) + { + if (MessageBox(160, 100, Page0_Offs, + "Do you want to insert\ninto .TOD file?", + "", ID_YESNO | ID_NOTITLE) == ID_YES) + SaveMapToTOD(); + else + SaveMapToFile("TODD.MAP"); + } // if + break; + + case LOAD_BUTTON : + if (MessageBox(160, 100, Page0_Offs, + "Do you want to load?", + "", ID_YESNO | ID_NOTITLE) == ID_YES) + { + if (MessageBox(160, 100, Page0_Offs, + "Do you want to extract\nfrom .TOD file?", + "", ID_YESNO | ID_NOTITLE) == ID_YES) + LoadMapFromTOD(); + else + LoadMapFromFile("TODD.MAP"); + + RedrawMap(); + } // if + break; + + case EXTRA_BUTTON : + + MessageBox(160, 100, Page0_Offs, + "This button has no\nmeaning as of yet.", "", ID_OK | ID_NOTITLE); + + break; + + case FILL_BUTTON : + + if (CurrentCursor == CC_FILL) + CurrentCursor = OldCursor; + else + { + OldCursor = CurrentCursor; + CurrentCursor = CC_FILL; + } // else + + if (IN_ACTIVE_AREA) + { + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs,DrawCursors[0]); + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + } // if + + break; + + case NEW_BUTTON : + + if (MessageBox(160, 100, Page0_Offs, + "Do you wish to start a\nnew map from scratch?", + "Last Chance", ID_YESNO) == ID_YES) + { + memset(map, 0, MAP_LAYERS*MAP_SIZE*MAP_SIZE); + RedrawMap(); + } // if + + break; + + case WALL_BUTTON : + if ((CurrentDrawMode != DM_WESTWALL) && + (CurrentDrawMode != DM_NORTHWALL)) + { + MinPic = StartWallPic; + CurrentPic = StartWallPic; + MaxPic = MaxWallPic; + + UPDATE_PIC_LBM = 1; + + showCurrentPic(); + showItemName(); + } // if + + if (CurrentDrawMode == DM_WESTWALL) + { + CurrentDrawMode = DM_NORTHWALL; + CurrentCursor = CC_NORTHWALL; + } // if + else + { + CurrentDrawMode = DM_WESTWALL; + CurrentCursor = CC_WESTWALL; + } // else + showDrawMode(); + + break; + + case FLOOR_BUTTON : + CurrentDrawMode = DM_FLOOR; + CurrentCursor = CC_FLAT; + showDrawMode(); + + MinPic = StartFlatPic; + CurrentPic = StartFlatPic; + MaxPic = MaxFlatPic; + + UPDATE_PIC_LBM = 1; + + showCurrentPic(); + showItemName(); + + break; + + case CEILING_BUTTON : + CurrentDrawMode = DM_CEILING; + CurrentCursor = CC_FLAT; + showDrawMode(); + + MinPic = StartFlatPic; + CurrentPic = StartFlatPic; + MaxPic = MaxFlatPic; + + UPDATE_PIC_LBM = 1; + + showCurrentPic(); + showItemName(); + break; + + case SPRITE_BUTTON : + CurrentDrawMode = DM_SPRITE; + CurrentCursor = CC_ACTOR; + showDrawMode(); + + MinPic = StartActorPic; + CurrentPic = StartActorPic; + MaxPic = MaxActorPic; + + UPDATE_PIC_LBM = 1; + + showCurrentPic(); + showItemName(); + break; + + case TT4_BUTTON : + case TT5_BUTTON : + case TT7_BUTTON : + case TT9_BUTTON : + case TT10_BUTTON : + + break; + + case PIC_LEFT_BUTTON : + if (CurrentPic > MinPic) + { + if (stricmp(scripts[CurrentPic].picFile,scripts[CurrentPic-1].picFile)) + UPDATE_PIC_LBM = 1; + CurrentPic--; + showCurrentPic(); + showItemName(); + } // if + break; + + case PIC_RIGHT_BUTTON : + if (CurrentPic < MaxPic) + { + if (stricmp(scripts[CurrentPic].picFile,scripts[CurrentPic+1].picFile)) + UPDATE_PIC_LBM = 1; + CurrentPic++; + showCurrentPic(); + showItemName(); + } // if + break; + + } // switch +} // handleButton + +void pushButton(char whichButton) +{ + char buttonBuffer[1000]; + char BUTTON_DOWN = 1; + + x_hide_mouse(); + + x_get_pbm(buttons[whichButton*5], buttons[whichButton*5+1], + (buttons[whichButton*5+2] - buttons[whichButton*5] + 1) / 4, + buttons[whichButton*5+3] - buttons[whichButton*5+1] + 1, + Page0_Offs, buttonBuffer); + x_rect_fill(buttons[whichButton*5] - 1, buttons[whichButton*5+1] - 1, + buttons[whichButton*5+2] + 2, buttons[whichButton*5+3] + 2, + Page0_Offs, 0); + x_put_pbm(buttons[whichButton*5] + 1, buttons[whichButton*5+1] + 1, + Page0_Offs, buttonBuffer); + + x_show_mouse(); + + while (MouseButtonStatus & LEFT_MOUSE_CLICK) + { + if (BUTTON_DOWN) + { + if (!MouseOnButton(whichButton)) + { + x_hide_mouse(); + x_rect_fill(buttons[whichButton*5] - 1, buttons[whichButton*5+1] - 1, + buttons[whichButton*5+2] + 2, buttons[whichButton*5+3] + 2, + Page0_Offs, 0); + x_put_pbm(buttons[whichButton*5], buttons[whichButton*5+1], + Page0_Offs, buttonBuffer); + x_show_mouse(); + + BUTTON_DOWN = 0; + } // if + } // if + else + { + if (MouseOnButton(whichButton)) + { + x_hide_mouse(); + x_rect_fill(buttons[whichButton*5] - 1, buttons[whichButton*5+1] - 1, + buttons[whichButton*5+2] + 2, buttons[whichButton*5+3] + 2, + Page0_Offs, 0); + x_put_pbm(buttons[whichButton*5] + 1, buttons[whichButton*5+1] + 1, + Page0_Offs, buttonBuffer); + x_show_mouse(); + + BUTTON_DOWN = 1; + } // if + } // else + }; + + x_hide_mouse(); + + x_rect_fill(buttons[whichButton*5] - 1, buttons[whichButton*5+1] - 1, + buttons[whichButton*5+2] + 2, buttons[whichButton*5+3] + 2, + Page0_Offs, 0); + x_put_pbm(buttons[whichButton*5], buttons[whichButton*5+1], + Page0_Offs, buttonBuffer); + + x_show_mouse(); +} // pushButton + +char MouseOnButton(char whichButton) +{ + if ((MouseX >= buttons[whichButton*5]) && + (MouseX <= buttons[whichButton*5+2]) && + (MouseY >= buttons[whichButton*5+1]) && + (MouseY <= buttons[whichButton*5+3])) + return 1; + + return 0; +} // MouseOnButton + +void handleOptionButtons(void) +{ +} // handleOptionButtons + +void setUpInterface(void) +{ + memset(map, 0, MAP_LAYERS*MAP_SIZE*MAP_SIZE); +// memset(Pics, 0, 4*MAX_TILES); + + x_set_font(2); + + x_page_flip(0, 0); + + x_rect_fill(110, 80, 210, 120, Page1_Offs, 1); + x_printf(115, 95, Page1_Offs, 10, "Initializing MAZER..."); + + showLBM(0, 0, PROGRAM_GRAPHIX, Page0_Offs); + x_get_pbm(buttons[OKAY_BUTTON*5], buttons[OKAY_BUTTON*5+1], + (buttons[OKAY_BUTTON*5+2] - buttons[OKAY_BUTTON*5] + 1) / 4, + buttons[OKAY_BUTTON*5+3] - buttons[OKAY_BUTTON*5+1] + 1, + Page0_Offs, DialogButtons[DLG_OKAY]); + x_get_pbm(buttons[CANCEL_BUTTON*5], buttons[CANCEL_BUTTON*5+1], + (buttons[CANCEL_BUTTON*5+2] - buttons[CANCEL_BUTTON*5] + 1) / 4, + buttons[CANCEL_BUTTON*5+3] - buttons[CANCEL_BUTTON*5+1] + 1, + Page0_Offs, DialogButtons[DLG_CANCEL]); + x_get_pbm(buttons[YES_BUTTON*5], buttons[YES_BUTTON*5+1], + (buttons[YES_BUTTON*5+2] - buttons[YES_BUTTON*5] + 1) / 4, + buttons[YES_BUTTON*5+3] - buttons[YES_BUTTON*5+1] + 1, + Page0_Offs, DialogButtons[DLG_YES]); + x_get_pbm(buttons[NO_BUTTON*5], buttons[NO_BUTTON*5+1], + (buttons[NO_BUTTON*5+2] - buttons[NO_BUTTON*5] + 1) / 4, + buttons[NO_BUTTON*5+3] - buttons[NO_BUTTON*5+1] + 1, + Page0_Offs, DialogButtons[DLG_NO]); + x_get_pbm(0,45,TILE_SIZE/4,TILE_SIZE,Page0_Offs, DrawCursors[1]); + x_get_pbm(13,45,TILE_SIZE/4,TILE_SIZE,Page0_Offs, DrawCursors[2]); + x_get_pbm(26,45,TILE_SIZE/4,TILE_SIZE,Page0_Offs, DrawCursors[3]); + x_get_pbm(39,45,TILE_SIZE/4,TILE_SIZE,Page0_Offs, DrawCursors[4]); + x_get_pbm(52,45,TILE_SIZE/4,TILE_SIZE,Page0_Offs, DrawCursors[5]); + x_get_pbm(65,45, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[6]); + + ScaleTiles(); + + showLBM(0, 0, INTERFACE_SCREEN, Page0_Offs); + + showDrawMode(); + showItemName(); + + x_page_flip(0, 0); + + showCurrentPic(); +} // setUpInterface + +void load_user_fonts(void) +{ + FILE *f; + f=fopen("smalthin.fnt","rb"); + /* read char by char as fread wont read to far pointers in small model */ + { int i; char c; + for (i=0;i<256*8+4;i++){ + fread(&c,1,1,f); + *(userfnt1+i)=c; + } + } + + fclose(f); + + x_register_userfont(userfnt1); +} + +void exitfunc(void){ + x_mouse_remove(); + x_text_mode(); + printf("Ta-da\n"); +} + +char MessageBox(int baseX, int baseY, + long pageOffset, char * textMsg, char * titleMsg, + int buttonFlag) +{ + char Xoffset = 5; + char Yoffset = 5; + char TitleHeight = 10; + char TitleYoffset = 8; + char TextYoffset = 10; + char ButtonHeight = 9; + char ButtonWidth = 28; + int ButtonStart = 0; + int width = 100; + int height = 50; + char showButtons; + char ActiveButton = 0; + char AlterButton = 0; + + char *boxBG = NULL; + + int defaultColors[] = + { + 139, // basic color + 154, // hilite color + 144, // lolite color + 79, // title bar color + 255, // text color + 103 // title text color + }; + + int stringWidth; + int stringHeight; + + char numButtons = 0; + char currentButton = 0; + char BUTTON_FOUND = 0; + char return_value = 0; + + + if ((x_strlen(textMsg) > x_strlen(titleMsg)) || + (buttonFlag & ID_NOTITLE)) + width = x_strlen(textMsg) + Xoffset * 2; + else + width = x_strlen(titleMsg) + Xoffset * 4; + + height = x_strheight(textMsg) + Yoffset * 2; + if (!(buttonFlag & ID_NOTITLE)) + height += TitleHeight + TextYoffset + Yoffset; + + if (!(buttonFlag & ID_NOBUTTONS)) + height += ButtonHeight + Yoffset; + + if (buttonFlag & ID_OK) + { + buttons[OKAY_BUTTON*5+4] = 1; + numButtons++; + } + if (buttonFlag & ID_CANCEL) + { + buttons[CANCEL_BUTTON*5+4] = 1; + numButtons++; + } + if (buttonFlag & ID_YES) + { + buttons[YES_BUTTON*5+4] = 1; + numButtons++; + } + if (buttonFlag & ID_NO) + { + buttons[NO_BUTTON*5+4] = 1; + numButtons++; + } + + if ((numButtons * (ButtonWidth+2)) + ((numButtons-1) * Xoffset) + + (Xoffset * 2) > width) + width = (numButtons * ButtonWidth) + ((numButtons-1) * Xoffset) + + (Xoffset * 2); + + // to account for 4 pixel byte boundary + width += 4 - (width % 4); + + baseX -= width / 2; + baseY -= height / 2; + + deactivateMainButtons(); + + x_hide_mouse(); + + boxBG = (char *) malloc(width*height+2); + x_get_pbm(baseX, baseY, width/4, height, pageOffset, boxBG); + + x_rect_fill(baseX, baseY, baseX+width-1, baseY+height-1, + pageOffset, defaultColors[0]); + x_line(baseX, baseY, baseX+width-1, baseY, + defaultColors[1], pageOffset); + x_line(baseX, baseY, baseX, baseY+height-1, + defaultColors[1], pageOffset); + x_line(baseX, baseY+height-1, baseX+width-1, baseY+height-1, + defaultColors[2], pageOffset); + x_line(baseX+width-1, baseY, baseX+width-1, baseY+height-1, + defaultColors[2], pageOffset); + + if (!(buttonFlag & ID_NOTITLE)) + { + x_rect_fill(baseX+Xoffset, baseY+Yoffset, + baseX+width-1-Xoffset, baseY+Yoffset+TitleHeight, + pageOffset, defaultColors[3]); + x_line(baseX+Xoffset, baseY+Yoffset, + baseX+width-1-Xoffset, baseY+Yoffset, + defaultColors[2], pageOffset); + x_line(baseX+Xoffset, baseY+Yoffset, + baseX+Xoffset, baseY+Yoffset+TitleHeight, + defaultColors[2], pageOffset); + x_line(baseX+Xoffset, baseY+Yoffset+TitleHeight, + baseX+width-1-Xoffset, baseY+Yoffset+TitleHeight, + defaultColors[1], pageOffset); + x_line(baseX+width-1-Xoffset, baseY+Yoffset, + baseX+width-1-Xoffset, baseY+Yoffset+TitleHeight, + defaultColors[1], pageOffset); + + stringWidth = x_strlen(titleMsg); + x_printf(baseX+(width/2)-(stringWidth/2), baseY+TitleYoffset, + pageOffset, defaultColors[5], titleMsg); + } // if + else + { + TitleHeight = 0; + TextYoffset = 0; + } // else + + stringWidth = x_strlen(textMsg); + x_printf(baseX+(width/2)-(stringWidth/2), + baseY+Yoffset+TitleHeight+TextYoffset, + pageOffset, defaultColors[4], textMsg); + + if (!(buttonFlag & ID_NOBUTTONS)) + { + ButtonStart = baseX + (width / 2) - + ((numButtons * (ButtonWidth+2) + + (numButtons-1) * Xoffset) / 2); + for (showButtons = 0; showButtons < numButtons; showButtons++) + { + switch (showButtons) + { + case 0: + if (buttonFlag & ID_OK) + { + ActiveButton = DLG_OKAY; + AlterButton = OKAY_BUTTON; + } // if + else if (buttonFlag & ID_YES) + { + ActiveButton = DLG_YES; + AlterButton = YES_BUTTON; + } // else + break; + case 1: + if (buttonFlag & ID_CANCEL) + { + ActiveButton = DLG_CANCEL; + AlterButton = CANCEL_BUTTON; + } // if + else if (buttonFlag & ID_NO) + { + ActiveButton = DLG_NO; + AlterButton = NO_BUTTON; + } // else + break; + } // switch + + buttons[AlterButton*5] = ButtonStart+1; + buttons[AlterButton*5+1] = baseY+height-1-Yoffset-ButtonHeight+1; + buttons[AlterButton*5+2] = buttons[AlterButton*5] + ButtonWidth - 1; + buttons[AlterButton*5+3] = buttons[AlterButton*5+1] + ButtonHeight - 1; + + x_rect_fill(ButtonStart, baseY+height-1-Yoffset-ButtonHeight, + ButtonStart+ButtonWidth-1+3, + baseY+height-1-Yoffset-1+3,pageOffset,0); + x_put_pbm(ButtonStart+1, baseY+height-1-Yoffset-ButtonHeight+1, + pageOffset, DialogButtons[ActiveButton]); + + ButtonStart += ButtonWidth + 2 + Xoffset; + + } // for + } // if + + x_show_mouse(); + + + BUTTON_FOUND = 0; + + while (!return_value) + { + if (MouseButtonStatus & LEFT_MOUSE_CLICK) + { + if (buttonFlag & ID_NOBUTTONS) + return_value = ID_OK; + + currentButton = 0; + while ((!BUTTON_FOUND) && (currentButton != END_OF_BUTTONS)) + { + if ((MouseOnButton(currentButton)) && + (buttons[currentButton*5+4])) + { + + pushButton(currentButton); + + if (MouseOnButton(currentButton)) // check if still modal to button + { + + switch (currentButton) + { + case OKAY_BUTTON: + return_value = ID_OK; + BUTTON_FOUND = 1; + break; + + case CANCEL_BUTTON: + return_value = ID_CANCEL; + BUTTON_FOUND = 1; + break; + + case YES_BUTTON: + return_value = ID_YES; + BUTTON_FOUND = 1; + break; + + case NO_BUTTON: + return_value = ID_NO; + BUTTON_FOUND = 1; + break; + } // switch + } // if + } // if + + currentButton++; + } // while + } // if + } // while + + x_hide_mouse(); + + x_put_pbm(baseX, baseY, pageOffset, boxBG); + + x_show_mouse(); + + deactivateDlgButtons(); + activateMainButtons(); + + if (boxBG) + free(boxBG); + + return return_value; +} // char + +void deactivateMainButtons(void) +{ + char runButtons = START_MAIN_BUT; + + while ((runButtons < END_OF_MAIN_BUT) && + (runButtons < END_OF_BUTTONS)) + { + buttons[runButtons*5+4] = 0; + + runButtons++; + } // while +} // deactivateMainButtons + +void activateMainButtons(void) +{ + char runButtons = START_MAIN_BUT; + + while ((runButtons < END_OF_MAIN_BUT) && + (runButtons < END_OF_BUTTONS)) + { + buttons[runButtons*5+4] = 1; + + runButtons++; + } // while +} // activateMainButtons + +void deactivateDlgButtons(void) +{ + char runButtons = START_DLG_BUT; + + while ((runButtons < END_OF_DLG_BUT) && + (runButtons < END_OF_BUTTONS)) + { + buttons[runButtons*5+4] = 0; + + runButtons++; + } // while +} // deactivateDlgButtons + +void activateDlgButtons(void) +{ + char runButtons = START_DLG_BUT; + + while ((runButtons < END_OF_DLG_BUT) && + (runButtons < END_OF_BUTTONS)) + { + buttons[runButtons*5+4] = 1; + + runButtons++; + } // while +} // activateDlgButtons + +void showDrawMode(void) +{ + x_rect_fill(DM_BASEX, DM_BASEY, DM_MAXX, DM_MAXY, Page0_Offs, DM_BGCOLOR); + x_printf(DM_BASEX+((DM_MAXX-DM_BASEX)/2)- + (x_strlen(DrawModes[CurrentDrawMode])/2), + DM_BASEY + 2, + Page0_Offs, DM_FGCOLOR, DrawModes[CurrentDrawMode]); +} // showDrawMode + +void showItemName(void) +{ + x_rect_fill(IN_BASEX, IN_BASEY, IN_MAXX, IN_MAXY, Page0_Offs, IN_BGCOLOR); + x_printf(IN_BASEX+((IN_MAXX-IN_BASEX)/2)- + (x_strlen(scripts[CurrentPic].picName)/2), + IN_BASEY + 2, + Page0_Offs, IN_FGCOLOR, scripts[CurrentPic].picName); +} // showItemName + +void showMouseCoords(int posX, int posY) +{ + char buffer[20]; + + sprintf(buffer, "%d, %d", GridBaseX+posX, GridBaseY+posY); + + if (!IN_ACTIVE_AREA) + x_hide_mouse(); + + x_rect_fill(MC_BASEX, MC_BASEY, MC_MAXX, MC_MAXY, Page0_Offs, MC_BGCOLOR); + x_printf(MC_BASEX+2, + MC_BASEY + 2, + Page0_Offs, MC_FGCOLOR, buffer); + + if (!IN_ACTIVE_AREA) + x_show_mouse(); + +} // showMouseCoords + +void showCurrentPic(void) +{ + char picBuf[4100]; + + x_hide_mouse(); + + if (UPDATE_PIC_LBM) + { + showLBM(0, 0, scripts[CurrentPic].picFile, Page1_Offs); + UPDATE_PIC_LBM = 0; + } // if + + x_get_pbm(scripts[CurrentPic].Xoffset*8, + scripts[CurrentPic].Yoffset*8, 16, 64, Page1_Offs, picBuf); + x_put_pbm(PIC_BASEX, PIC_BASEY, Page0_Offs, picBuf); + + x_show_mouse(); +} // showCurrentPic + +void handleMouseCursor(void) +{ + NewMouseX = MouseX; + NewMouseY = MouseY; + + + if ((FILL_ACTIVE) && + (!(MouseButtonStatus & LEFT_MOUSE_CLICK))) + { + + FillAnArea(FillStartX, FillStartY, + (OldMouseX - 4)/TILE_SIZE, + (OldMouseY - 4)/TILE_SIZE); + RedrawMap(); + FILL_ACTIVE = 0; +// CurrentCursor = OldCursor; + + if ((NewMouseX < AA_BASEX) || (NewMouseX > AA_MAXX) || + (NewMouseY < AA_BASEY) || (NewMouseY > AA_MAXY)) + x_hide_mouse(); + else + { + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, + Page0_Offs, DrawCursors[0]); + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + } // else + + if ((NewMouseX < AA_BASEX) || (NewMouseX > AA_MAXX) || + (NewMouseY < AA_BASEY) || (NewMouseY > AA_MAXY)) + x_show_mouse(); + + return; + } // if + + + if ((NewMouseX >= AA_BASEX) && (NewMouseX <= AA_MAXX) && + (NewMouseY >= AA_BASEY) && (NewMouseY <= AA_MAXY)) + { + if (!IN_ACTIVE_AREA) + { + x_hide_mouse(); + OldMouseX = 4 + ((NewMouseX-4)/TILE_SIZE)*TILE_SIZE; + OldMouseY = 4 + ((NewMouseY-4)/TILE_SIZE)*TILE_SIZE; + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, + Page0_Offs, DrawCursors[0]); + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + + IN_ACTIVE_AREA = 1; + } // if + } // if + else + { + if (IN_ACTIVE_AREA) + { + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + + x_show_mouse(); + IN_ACTIVE_AREA = 0; + } // if + } // else + + if (IN_ACTIVE_AREA) + { + NewMouseX = 4 + ((NewMouseX-4)/TILE_SIZE)*TILE_SIZE; + NewMouseY = 4 + ((NewMouseY-4)/TILE_SIZE)*TILE_SIZE; + + if ((NewMouseX != OldMouseX) || (NewMouseY != OldMouseY) || + (MouseButtonStatus & LEFT_MOUSE_CLICK) || + (MouseButtonStatus & RIGHT_MOUSE_CLICK)) + { + if (!(MouseButtonStatus & LEFT_MOUSE_CLICK) && + !(MouseButtonStatus & RIGHT_MOUSE_CLICK)) + showMouseCoords((NewMouseX-4)/TILE_SIZE,(NewMouseY-4)/TILE_SIZE); + + x_put_pbm(OldMouseX, OldMouseY, Page0_Offs, DrawCursors[0]); + OldMouseX = NewMouseX; + OldMouseY = NewMouseY; + + GRIDX = (OldMouseX - 4)/TILE_SIZE; + GRIDY = (OldMouseY - 4)/TILE_SIZE; + + if (MouseButtonStatus & LEFT_MOUSE_CLICK) + { + if (CurrentCursor == CC_FILL) + { + if (FILL_ACTIVE) + { + RedrawMap(); + //x_put_pbm(4, 4, Page0_Offs, FillPic); + if ((FillStartX <= GRIDX) && (FillStartY <= GRIDY)) + { + x_line(4+FillStartX*TILE_SIZE, 4+FillStartY*TILE_SIZE, + 4+GRIDX*TILE_SIZE+TILE_SIZE-1, 4+FillStartY*TILE_SIZE, + 255, Page0_Offs); + x_line(4+FillStartX*TILE_SIZE, 4+GRIDY*TILE_SIZE+TILE_SIZE-1, + 4+GRIDX*TILE_SIZE+TILE_SIZE-1, 4+GRIDY*TILE_SIZE+TILE_SIZE-1, + 255, Page0_Offs); + x_line(4+FillStartX*TILE_SIZE, 4+FillStartY*TILE_SIZE, + 4+FillStartX*TILE_SIZE, 4+GRIDY*TILE_SIZE+TILE_SIZE-1, + 255, Page0_Offs); + x_line(4+GRIDX*TILE_SIZE+TILE_SIZE-1, 4+FillStartY*TILE_SIZE, + 4+GRIDX*TILE_SIZE+TILE_SIZE-1, 4+GRIDY*TILE_SIZE+TILE_SIZE-1, + 255, Page0_Offs); + } // if + + } // if + else + { + FILL_ACTIVE = 1; + FillStartX = GRIDX; + FillStartY = GRIDY; + //FillPic = (char *) malloc(MAP_VIEW_SIZE*TILE_SIZE*TILE_SIZE); + //x_get_pbm(4, 4, (MAP_VIEW_SIZE*TILE_SIZE)/4, + // MAP_VIEW_SIZE*TILE_SIZE, Page0_Offs, FillPic); + } // else + } // if + else + { + switch (CurrentCursor) + { + case CC_WESTWALL : + map[WEST_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = CurrentPic-MinPic+1; + + if (DRAW_FROM_PIC) + { + x_get_pbm(PIC_BASEX, PIC_BASEY, TILE_SIZE/4, TILE_SIZE, + Page0_Offs, DrawBuffer); + x_rect_fill(0, 0, TILE_SIZE, TILE_SIZE, Page1_Offs, 0); + x_put_pbm(0, 0, Page1_Offs, DrawBuffer); + x_line(0, 0, TILE_SIZE, 0, 0, Page0_Offs); + x_line(0, TILE_SIZE-1, TILE_SIZE, TILE_SIZE-1, 0, Page1_Offs); + x_line(0, 0, 0, TILE_SIZE, 0, Page1_Offs); + x_line(3, 0, 3, TILE_SIZE, 0, Page1_Offs); + + if (!Pics[TT_WESTWALL][CurrentPic-MinPic].pbm) + { + x_get_pbm(0, 0, 1, TILE_SIZE, + Page1_Offs, Pics[TT_WESTWALL][CurrentPic-MinPic].pbm); + } // if + + DrawGridTile(GRIDX, GRIDY); + } // if + else + x_line(OldMouseX-1, OldMouseY, OldMouseX, OldMouseY + TILE_SIZE-1, + 103, Page0_Offs); + break; + + case CC_NORTHWALL : + map[NORTH_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = CurrentPic-MinPic+1; + + if (DRAW_FROM_PIC) + { + x_get_pbm(PIC_BASEX, PIC_BASEY, TILE_SIZE/4, 4, + Page0_Offs, DrawBuffer); + x_rect_fill(0, 0, TILE_SIZE, TILE_SIZE, Page1_Offs, 0); + x_put_pbm(0, 0, Page1_Offs, DrawBuffer); + x_line(0, 0, TILE_SIZE, 0, 0, Page1_Offs); + x_line(0, 3, TILE_SIZE, 3, 0, Page1_Offs); + x_line(0, 0, 0, TILE_SIZE, 0, Page1_Offs); + x_line(TILE_SIZE-1, 0, TILE_SIZE-1, TILE_SIZE, 0, Page1_Offs); + + if (!Pics[TT_NORTHWALL][CurrentPic-MinPic].pbm) + { + x_get_pbm(0, 0, TILE_SIZE/4, 4, + Page1_Offs, Pics[TT_NORTHWALL][CurrentPic-MinPic].pbm); + } // if + + DrawGridTile(GRIDX, GRIDY); + } // if + else + x_line(OldMouseX + 1, OldMouseY, OldMouseX + 5, OldMouseY, + 103, Page0_Offs); + break; + + case CC_FLAT : + if (CurrentDrawMode == DM_FLOOR) + map[FLOOR_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = CurrentPic-MinPic+1; + else + map[CEILING_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = CurrentPic-MinPic+1; + + if (DRAW_FROM_PIC) + { + // if (!Pics[TT_FLAT][CurrentPic-MinPic][0]) + // { + // x_get_pbm(0, 0, TILE_SIZE/4, TILE_SIZE, + // Page0_Offs, Pics[TT_FLAT][CurrentPic-MinPic]); + // } // if + + DrawGridTile(GRIDX, GRIDY); + } // if + else + x_rect_fill(OldMouseX + 2, OldMouseY + 2, + OldMouseX + 5, OldMouseY + 5, + Page0_Offs, 103); + break; + + case CC_ACTOR : + map[SPRITE_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = CurrentPic-MinPic+1; + + if (DRAW_FROM_PIC) + { + DrawGridTile(GRIDX, GRIDY); + } // if + + break; + } // if + } // else + } // if + else if (MouseButtonStatus & RIGHT_MOUSE_CLICK) + { + switch (CurrentCursor) + { + case CC_WESTWALL : + map[WEST_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = 0; + + DrawGridTile(GRIDX, GRIDY); + break; + + case CC_NORTHWALL : + map[NORTH_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = 0; + + DrawGridTile(GRIDX, GRIDY); + break; + + case CC_FLAT : + if (CurrentDrawMode == DM_FLOOR) + map[FLOOR_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = 0; + else + map[CEILING_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = 0; + + DrawGridTile(GRIDX, GRIDY); + break; + + case CC_ACTOR : + map[SPRITE_LAYER][(GridBaseY+GRIDY)*MAP_SIZE + (GridBaseX+GRIDX)] = 0; + + if (DRAW_FROM_PIC) + { + DrawGridTile(GRIDX, GRIDY); + } // if + + break; + } // if + } // if + else + { + if (FILL_ACTIVE) + { + //x_put_pbm(4, 4, Page0_Offs, FillPic); + //free(FillPic); + //FillPic = NULL; + //RedrawMap(); + //FILL_ACTIVE = 0; + //CurrentCursor = OldCursor; + } // if + } // else + + + x_get_pbm(OldMouseX, OldMouseY, TILE_SIZE/4, TILE_SIZE, Page0_Offs, DrawCursors[0]); + + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + } // if + } // if +} // handleMouseCursor + +void DrawGridTile(char xpos, char ypos) +{ + char TileBuffer[146]; + + x_rect_fill(0, 0, TILE_SIZE, TILE_SIZE, Page1_Offs, 0); + x_put_pix(0, 0, Page1_Offs, GRID_MARK_COLOR); + + if (map[FLOOR_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]) + { + x_put_pbm(0, 0, Page1_Offs, + Pics[TT_FLAT][map[FLOOR_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]-1].pbm); + } // if + if (map[WEST_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]) + { + x_put_pbm(0, 0, Page1_Offs, + Pics[TT_WESTWALL][map[WEST_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]-1].pbm); + } // if + if (map[NORTH_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]) + { + x_put_pbm(0, 0, Page1_Offs, + Pics[TT_NORTHWALL][map[NORTH_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]-1].pbm); + } // if + if (map[SPRITE_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]) + { + x_put_masked_pbm(0, 0, Page1_Offs, + Pics[TT_ACTOR][map[SPRITE_LAYER][(GridBaseY+ypos)*MAP_SIZE+(GridBaseX+xpos)]-1].pbm); + } // if + + x_get_pbm(0, 0, TILE_SIZE/4, TILE_SIZE, Page1_Offs, TileBuffer); + + x_put_pbm(4+xpos*TILE_SIZE, 4+ypos*TILE_SIZE, Page0_Offs, TileBuffer); + +} // DrawGridTile + +void RedrawMap(void) +{ + char row; + char col; + + + if (CurrentCursor != CC_FILL) + { + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs,DrawCursors[0]); + else + x_hide_mouse(); + } // if + + for (row = 0; row < MAP_VIEW_SIZE; row++) + { + for (col = 0; col < MAP_VIEW_SIZE; col++) + { + DrawGridTile(col, row); + } // for + } // for + + if (CurrentCursor != CC_FILL) + { + if (IN_ACTIVE_AREA) + x_put_masked_pbm(OldMouseX, OldMouseY, Page0_Offs, + DrawCursors[CurrentCursor]); + else + x_show_mouse(); + } // if +} // RedrawMap + +void RedrawCol(char whichCol) +{ + char row; + + for (row = 0; row < MAP_VIEW_SIZE; row++) + { + DrawGridTile(whichCol, row); + } // for +} // RedrawRow + +void RedrawRow(char whichRow) +{ + char col; + + for (col = 0; col < MAP_VIEW_SIZE; col++) + { + DrawGridTile(col, whichRow); + } // for +} // RedrawRow + +int SaveMapToFile(char *filename) +{ + int MapFile; + + if ((MapFile = f_open(filename, F_RDWR)) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[FLOOR_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[CEILING_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[NORTH_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[WEST_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[SPRITE_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_close(MapFile) == FILE_ERR) + return 0; + + MessageBox(160, 100, Page0_Offs, "New saved okay.", "", ID_OK | ID_NOTITLE); + + return 1; +} // SaveMapToFile + +int SaveMapToTOD(void) +{ + int MapFile; + + if ((MapFile = f_open(DATA_FILE, F_RDWR)) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x3E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[FLOOR_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x4E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[CEILING_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x5E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[NORTH_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x6E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[WEST_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0xCE0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_write(MapFile, map[SPRITE_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_close(MapFile) == FILE_ERR) + return 0; + + MessageBox(160, 100, Page0_Offs, "New map inserted okay.", "", ID_OK | ID_NOTITLE); + + return 1; +} // SaveMapToTOD + +int LoadMapFromFile(char *filename) +{ + int MapFile; + long numRead; + + if ((MapFile = f_open(filename, F_RDWR)) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[FLOOR_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[CEILING_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[NORTH_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[WEST_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[SPRITE_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_close(MapFile) == FILE_ERR) + return 0; + + MessageBox(160, 100, Page0_Offs, "Old map loaded okay.", "", ID_OK | ID_NOTITLE); + + return 1; +} // LoadMapFromFile + +int LoadMapFromTOD(void) +{ + int MapFile; + long numRead; + + if ((MapFile = f_open(DATA_FILE, F_RDWR)) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x3E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[FLOOR_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x4E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[CEILING_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x5E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[NORTH_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0x6E0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[WEST_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_seek(MapFile, 0xCE0A, SEEK_START) == FILE_ERR) + return 0; + + if (f_read(MapFile, map[SPRITE_LAYER], MAP_SIZE*MAP_SIZE) == FILE_ERR) + return 0; + + if (f_close(MapFile) == FILE_ERR) + return 0; + + MessageBox(160, 100, Page0_Offs, "Old map extracted okay.", "", ID_OK | ID_NOTITLE); + + return 1; +} // LoadMapFromTOD + +void ScaleTiles() +{ + char i; + char j; + WORD color; + char scaleX = TILE_SIZE; + char scaleY = TILE_SIZE; + char picToScale = 0; + + + + scaleX = 4; + scaleY = TILE_SIZE; + + picToScale = StartWallPic; + + while (picToScale <= MaxWallPic) + { + if ((picToScale == StartWallPic) || + (strcmpi(scripts[picToScale].picFile, scripts[picToScale-1].picFile))) + showLBM(0, 0, scripts[picToScale].picFile, Page0_Offs); + + x_rect_fill(0, 0, TILE_SIZE, TILE_SIZE, Page0_Offs, 0); + + for (i=0; i +#include +#include +//#include +#include "xlib_all.h" + +/*-------------------------------------------------------------------------*/ +/* ILBM320 by Mark E. Kern. The following source code may be used, */ +/* modified, copied and shared with no obligation to the author */ +/* whatsoever, as long as this notice accompanies the source. */ +/* Please direct any questions to GEnie:MKERN1 or CS:70670,3120. */ +/* Code written in Borland C++ in ANSI C mode. Sept 9,1991 */ +/* ------------------------------------------------------------------------*/ + + +/***************************************************************************\ +** ** +* SHOWLBM by Todd Michael Lewis * +* * +* August 27, 1994 * +* * +* Using Mark E. Kern's code for the display of ILBMs, this routine was * +* developed to show ILBMs using the XLIB graphic display library with a * +* call to showLBM(x, y, LBM_FILE). * +* * +** ** +\***************************************************************************/ + +char testPBM[14] = +{ + 3, 1, + 1,1,1, + 1,1,1, + 1,1,0, + 1,0,0, +}; + +/* This defines the key information header contained in the ILBM format */ +struct headform{ + long flen; + char msg2[8]; + long hlen; + int width; + int length; + int xoff; + int yoff; + char planes; + char masking; + char compression; + char padbyte; + int transparent; + char x_aspect; + char y_aspect; + int screenWidth; + int screenHeight; +}; + +/* Structure used to store RGB values as they are read from the file */ +struct RGBColor { + char red; + char green; + char blue; +}; + +char RGBpalette[768]; + +int ReadHeader(FILE *picFile, struct headform *header); +int ReadCMap(FILE *picFile, struct headform *header); +int DumpToScreen(FILE *picFile, struct headform *header, long page); +void drawline(int *yoffset,unsigned char Vbuff[322], + int *scanline,long page,int maxLines); +long ReverseLong(long num); +int ReverseWord(int num); +int expo(int x,int y); +void setDAC(struct RGBColor pallete[256]); + +/* expo calculates x^y and returns it as an integer value. */ +int expo(int x,int y){ + int answer=x; + + while(y > 1){ + answer = answer * x; + --y; + } + return(answer); +} + +/* This code reverses the byte order in the long values read in from the + file. This is to satisfy Intel's byte ordering scheme. */ +long ReverseLong(long num){ + long actualnum; + + actualnum = ((num >> 24) & 0x000000ff) | + ((num >> 8) & 0x0000ff00) | + ((num << 8) & 0x00ff0000) | + ((num << 24) & 0xff000000); + return(actualnum); +} + +/* This code reverses the byte order in the word values read in from the + file. This is to satisfy Intel's byte ordering scheme. */ +int ReverseWord(int num){ + int actualnum; + + actualnum = ((num >> 8) & 0x00ff) | + ((num << 8) & 0xff00); + return(actualnum); +} + +/* main asks for the ILBM file to diplay, opens the file, and then proceeds + to: 1)Init the graphics. + 2)Read in the major header information. + 3)Read in the color map and set the DAC registers. + 4)Dump the image line by line from the file to the screen. + 5)Wait for a keypress before closing up the file and shutting down. */ + +void showLBM(int startX, int startY, char *filename, long page) +{ + FILE *picFile; + struct headform header; + + picFile = fopen(filename,"rb"); + ReadHeader(picFile,&header); + ReadCMap(picFile,&header); + DumpToScreen(picFile,&header, page); + fclose(picFile); +} + +/* ReadHeader takes a file pointer and starts to read in values into the + header structure previously defined. It first checks to see if the + file is an ILBM file by looking for the word "FORM", which should be + in the beginning of the file. */ +int ReadHeader(FILE *picFile, struct headform *header){ + int err; + char form[5]; + + fread(form,4,1,picFile); + form[4]='\0'; + if(strcmp("FORM",form) != 0) + return(1); + fread(&header->flen,sizeof(header->flen),1,picFile); + fread(&header->msg2,8,1,picFile); + fread(&header->hlen,4,1,picFile); + fread(&header->width,sizeof(header->width),1,picFile); + fread(&header->length,sizeof(header->length),1,picFile); + fread(&header->xoff,sizeof(header->xoff),1,picFile); + fread(&header->yoff,sizeof(header->yoff),1,picFile); + fread(&header->planes,sizeof(header->planes),1,picFile); + fread(&header->masking,sizeof(header->masking),1,picFile); + fread(&header->compression,sizeof(header->compression),1,picFile); + fread(&header->padbyte,sizeof(header->padbyte),1,picFile); + fread(&header->transparent,sizeof(header->transparent),1,picFile); + fread(&header->x_aspect,sizeof(header->x_aspect),1,picFile); + fread(&header->y_aspect,sizeof(header->y_aspect),1,picFile); + fread(&header->screenWidth,sizeof(header->screenWidth),1,picFile); + fread(&header->screenHeight,sizeof(header->screenHeight),1,picFile); + + /* Finished loading in the header, now reverse the values to make + them Intel compatible. */ + header->flen = ReverseLong(header->flen); + header->hlen = ReverseLong(header->hlen); + header->width = ReverseWord(header->width); + header->length = ReverseWord(header->length); + header->xoff = ReverseWord(header->xoff); + header->yoff = ReverseWord(header->yoff); + header->transparent = ReverseWord(header->transparent); + header->screenWidth = ReverseWord(header->screenWidth); + header->screenHeight = ReverseWord(header->screenHeight); + + return(0); +} + +/* ReadCMap first looks for the CMAP text in the file which denotes the + beginning of the color information. Once it finds the CMAP header, it + checks to see if the number of colors(x 3 for numbytes) matches the + length of the CMAP, which is read in after the header. If everything + is ok, it then loads up the array pallete with the rgb values contained + in the CMAP section of the file. ReadCMap then calls setDAC to load + the video DAC registers with the appropriate values. */ +int ReadCMap(FILE *picFile, struct headform *header){ + char form[5]; + long CMAPsize; + struct palettetype pal; + unsigned char rgbTuple[3]; + int x; + int numColors; + struct RGBColor pallete[256]; + + fread(form,4,1,picFile); + form[4]='\0'; + if(strcmp("CMAP",form) != 0) + return(1); + fread(&CMAPsize,sizeof(CMAPsize),1,picFile); + CMAPsize=ReverseLong(CMAPsize); + numColors=expo(2,header->planes); + if(CMAPsize != (numColors*3)) + return(1); + for(x=0;x>2; + pallete[x].green = rgbTuple[1]>>2; + pallete[x].blue = rgbTuple[2]>>2; + RGBpalette[x*3] = rgbTuple[0]>>2; + RGBpalette[x*3+1] = rgbTuple[1]>>2; + RGBpalette[x*3+2] = rgbTuple[2]>>2; + } + setDAC(pallete); + return(0); +} + +/* setDAC uses some pretty sophisticated funtions of Borland C. We first + set up a bunch of variables to hold CPU register values in type REGS. + Once we have done this, we can make some low level calls to the video + BIOS to set up the colors we want in the picture. We enter a loop that + sets each register to a RGB color combination and calls the BIOS routine + to set the specific DAC register we are interesed in. */ +void setDAC(struct RGBColor pallete[256]) +{ + union REGS regs; + int i; + + /* This sets up each of the 16 pallete entries to enable the proper + DAC register when the pallete value is combined with the pixel + value. */ +/* for(i=0;i<16;++i){ + regs.h.ah = 0x10; + regs.h.al = 0x00; + regs.h.bh = i; + regs.h.bl = i; + int86(0x10,®s,®s); + } + + regs.h.bl = 0x00; + for (i=0;i<256;++i){ + regs.h.ah = 0x10; /* set specific DAC rgb register value */ +// regs.h.al = 0x10; /* subfunction number, set register */ +// regs.h.ch = pallete[i].green; /* CH contains the green value */ +// regs.h.cl = pallete[i].blue; /* CL contains the blue value */ +// regs.h.dh = pallete[i].red; /* DH contains the red value */ +// int86(0x10, ®s, ®s); /* int 10h */ +// ++regs.h.bl; +// }*/ + x_put_pal_raw(RGBpalette, 256, 0); + +} + +/* DumpToScreen unpacks the graphics information contained in the file. It + first searches for the BODY header which precedes the actual graphics + data. If we don't find the BODY header, the program will just crash, since + I don't look out for the end of the file here. Once it finds the header, + it reads in the next value, which is the length of the body. We use this + value to read in the the next n number of bytes as specified by the body + length. ILBM seems to use a run length encoding scheme to pack the data. + The function looks at the first byte read. If the first byte read in is + between -1 and -127, then this means we are to read in the next byte + value, and repeat this value 1 to 127 times depending on the first byte + value we read. I.E. if the first value we read was -1, we read the next + value and repeat this value in the scanline 2 times (1-(-1)). If the + header value was -128, we would do nothing, as this is the no-operation + code. If the header value, call this n,is between 0 and 128, we interpret + this to mean the next n bytes are to be read in normally and stuffed + into the scanline without any sort of expansion or processing. Once this + function has read enough bytes to make up a scanline (320 bytes in VGA + mode 13h), we call a routine that dumps the scanline we just built to + the screen. We keep doing this until we run out of bytes to read. Note + that it is possible for an image to have more than 200 scanlines of data, + but our scanline dump routine ignores lines past 200. */ +int DumpToScreen(FILE *picFile, struct headform *header, long page){ + int yoffset=0; /* the y coord of the scanline */ + int index=0; /* index into the scanline array */ + int pixelsToGo=0; /* number of pixels to go to form a line*/ + int i; /* loop counter */ + int maxLines = header->length; + unsigned char Vbuff[322]; /* buffer to hold the scanline. It + is 4 bytes longer than the regular + length so it can hold hsize and + vsize data for the putimage call */ + int repeat; /* how many times to repeat the byte*/ + char repeatValue; /* raw byte value from file */ + char bufValue; /* raw buffer value read from file*/ + long size; /* size of the BODY segment */ + long bytesToGo; /* bytes to go till end of BODY */ + char form[5]; /* holds header */ + fread(form,4,1,picFile); + form[4]='\0'; + while(strcmp("BODY",form) != 0){ /* find the BODY */ + form[0]=form[1]; + form[1]=form[2]; + form[2]=form[3]; + form[3]=fgetc(picFile); + } + fread(&size,sizeof(size),1,picFile); + bytesToGo = ReverseLong(size); + +// Vbuff[0]=(320-1) & 0xff; + /* set up height and width of + our scanline. Since we use + putimage to dump our scanline, + we have to tell it how big + the 'shape' we are drawing + to the screen is. In our case + the shape is 320x1 in size.*/ +// Vbuff[1]=(320-1) >> 8; +// Vbuff[2]=1; +// Vbuff[3]=0; + + Vbuff[0] = 160; + Vbuff[1] = 1; + + index = index+2; + +// index = index+4; /* update the index into the scanline */ + + /* Check to see if the compression is of the proper type, which in + our case is 1. If it is uncompressed, or if we don't know the + compression type, we exit the program. */ + if(header->compression != 1) + return(1); + while(bytesToGo > 0) + { + fread(&repeatValue,1,1,picFile); + if(ferror(picFile)) + { + } + --bytesToGo; + repeat = repeatValue; + + if (repeat == -128); + else if((repeat <= -1) && (repeat >= -127)) + { + fread(&bufValue,1,1,picFile); + if(ferror(picFile)) + { + } + --bytesToGo; + for (i=0;i<(1-repeat);++i) + { + Vbuff[pixelsToGo+4-index] = bufValue; + ++pixelsToGo; + if(pixelsToGo == 320) + drawline(&yoffset,Vbuff,&pixelsToGo,page, + maxLines); + } + } + + else if((repeat >= 0) && (repeat <= 127)) + { + for(i=0;i<=repeat;++i) + { + fread(&(Vbuff[pixelsToGo+4-index]),1,1,picFile); + if(ferror(picFile)) + { + } + --bytesToGo; + ++pixelsToGo; + if(pixelsToGo == 320) + drawline(&yoffset,Vbuff,&pixelsToGo,page,maxLines); + } + } /*end if*/ + }/*end while bodysize*/ + return(0); +} + + +/* drawline takes an array containing the scanline data we have just + read in, and dumps it to the screen using the putimage call in the + Borland BGI. The function then increments the yvalue to point to + the next scanline, then resets the pixels to go value (scanline) to + 0 again. If we are currently working on a scanline greater than can + fit on the screen (i.e. greater than 200), we just ignore it and don't + draw it to the screen. */ +void drawline(int *yoffset,unsigned char Vbuff[322], + int *scanline,long page, int maxLines) +{ + + // must split image because CHAR cannot hold a length of 320 + + unsigned char PBMbuff[162]; + char *imagePtr; + + if(*yoffset <= maxLines) +// putimage(0,*yoffset,Vbuff,COPY_PUT); + imagePtr = Vbuff; + x_bm_to_pbm(imagePtr, PBMbuff); + x_put_pbm(0,*yoffset,page,PBMbuff); + Vbuff[160] = 160; + Vbuff[161] = 1; + imagePtr+=160; + x_bm_to_pbm(imagePtr, PBMbuff); + x_put_pbm(160,*yoffset,page,PBMbuff); + ++*yoffset; + *scanline=0; +} + + diff --git a/MYMAP/SHOWLBM.CPP b/MYMAP/SHOWLBM.CPP new file mode 100644 index 0000000..391d569 --- /dev/null +++ b/MYMAP/SHOWLBM.CPP @@ -0,0 +1,395 @@ +#include +#include +#include +//#include +#include "xlib_all.h" + +/*-------------------------------------------------------------------------*/ +/* ILBM320 by Mark E. Kern. The following source code may be used, */ +/* modified, copied and shared with no obligation to the author */ +/* whatsoever, as long as this notice accompanies the source. */ +/* Please direct any questions to GEnie:MKERN1 or CS:70670,3120. */ +/* Code written in Borland C++ in ANSI C mode. Sept 9,1991 */ +/* ------------------------------------------------------------------------*/ + + +/***************************************************************************\ +** ** +* SHOWLBM by Todd Michael Lewis * +* * +* August 27, 1994 * +* * +* Using Mark E. Kern's code for the display of ILBMs, this routine was * +* developed to show ILBMs using the XLIB graphic display library with a * +* call to showLBM(x, y, LBM_FILE). * +* * +** ** +\***************************************************************************/ + +char testPBM[14] = +{ + 3, 1, + 1,1,1, + 1,1,1, + 1,1,0, + 1,0,0, +}; + +/* This defines the key information header contained in the ILBM format */ +struct headform{ + long flen; + char msg2[8]; + long hlen; + int width; + int length; + int xoff; + int yoff; + char planes; + char masking; + char compression; + char padbyte; + int transparent; + char x_aspect; + char y_aspect; + int screenWidth; + int screenHeight; +}; + +/* Structure used to store RGB values as they are read from the file */ +struct RGBColor { + char red; + char green; + char blue; +}; + +char RGBpalette[768]; + +int ReadHeader(FILE *picFile, struct headform *header); +int ReadCMap(FILE *picFile, struct headform *header); +int DumpToScreen(FILE *picFile, struct headform *header, long page); +void drawline(int *yoffset,unsigned char Vbuff[322], + int *scanline,long page,int maxLines); +long ReverseLong(long num); +int ReverseWord(int num); +int expo(int x,int y); +void setDAC(struct RGBColor pallete[256]); + +/* expo calculates x^y and returns it as an integer value. */ +int expo(int x,int y){ + int answer=x; + + while(y > 1){ + answer = answer * x; + --y; + } + return(answer); +} + +/* This code reverses the byte order in the long values read in from the + file. This is to satisfy Intel's byte ordering scheme. */ +long ReverseLong(long num){ + long actualnum; + + actualnum = ((num >> 24) & 0x000000ff) | + ((num >> 8) & 0x0000ff00) | + ((num << 8) & 0x00ff0000) | + ((num << 24) & 0xff000000); + return(actualnum); +} + +/* This code reverses the byte order in the word values read in from the + file. This is to satisfy Intel's byte ordering scheme. */ +int ReverseWord(int num){ + int actualnum; + + actualnum = ((num >> 8) & 0x00ff) | + ((num << 8) & 0xff00); + return(actualnum); +} + +/* main asks for the ILBM file to diplay, opens the file, and then proceeds + to: 1)Init the graphics. + 2)Read in the major header information. + 3)Read in the color map and set the DAC registers. + 4)Dump the image line by line from the file to the screen. + 5)Wait for a keypress before closing up the file and shutting down. */ + +void showLBM(int startX, int startY, char *filename, long page) +{ + FILE *picFile; + struct headform header; + + picFile = fopen(filename,"rb"); + ReadHeader(picFile,&header); + ReadCMap(picFile,&header); + DumpToScreen(picFile,&header, page); + fclose(picFile); +} + +/* ReadHeader takes a file pointer and starts to read in values into the + header structure previously defined. It first checks to see if the + file is an ILBM file by looking for the word "FORM", which should be + in the beginning of the file. */ +int ReadHeader(FILE *picFile, struct headform *header){ + int err; + char form[5]; + + fread(form,4,1,picFile); + form[4]='\0'; + if(strcmp("FORM",form) != 0) + return(1); + fread(&header->flen,sizeof(header->flen),1,picFile); + fread(&header->msg2,8,1,picFile); + fread(&header->hlen,4,1,picFile); + fread(&header->width,sizeof(header->width),1,picFile); + fread(&header->length,sizeof(header->length),1,picFile); + fread(&header->xoff,sizeof(header->xoff),1,picFile); + fread(&header->yoff,sizeof(header->yoff),1,picFile); + fread(&header->planes,sizeof(header->planes),1,picFile); + fread(&header->masking,sizeof(header->masking),1,picFile); + fread(&header->compression,sizeof(header->compression),1,picFile); + fread(&header->padbyte,sizeof(header->padbyte),1,picFile); + fread(&header->transparent,sizeof(header->transparent),1,picFile); + fread(&header->x_aspect,sizeof(header->x_aspect),1,picFile); + fread(&header->y_aspect,sizeof(header->y_aspect),1,picFile); + fread(&header->screenWidth,sizeof(header->screenWidth),1,picFile); + fread(&header->screenHeight,sizeof(header->screenHeight),1,picFile); + + /* Finished loading in the header, now reverse the values to make + them Intel compatible. */ + header->flen = ReverseLong(header->flen); + header->hlen = ReverseLong(header->hlen); + header->width = ReverseWord(header->width); + header->length = ReverseWord(header->length); + header->xoff = ReverseWord(header->xoff); + header->yoff = ReverseWord(header->yoff); + header->transparent = ReverseWord(header->transparent); + header->screenWidth = ReverseWord(header->screenWidth); + header->screenHeight = ReverseWord(header->screenHeight); + + return(0); +} + +/* ReadCMap first looks for the CMAP text in the file which denotes the + beginning of the color information. Once it finds the CMAP header, it + checks to see if the number of colors(x 3 for numbytes) matches the + length of the CMAP, which is read in after the header. If everything + is ok, it then loads up the array pallete with the rgb values contained + in the CMAP section of the file. ReadCMap then calls setDAC to load + the video DAC registers with the appropriate values. */ +int ReadCMap(FILE *picFile, struct headform *header){ + char form[5]; + long CMAPsize; + struct palettetype pal; + unsigned char rgbTuple[3]; + int x; + int numColors; + struct RGBColor pallete[256]; + + fread(form,4,1,picFile); + form[4]='\0'; + if(strcmp("CMAP",form) != 0) + return(1); + fread(&CMAPsize,sizeof(CMAPsize),1,picFile); + CMAPsize=ReverseLong(CMAPsize); + numColors=expo(2,header->planes); + if(CMAPsize != (numColors*3)) + return(1); + for(x=0;x>2; + pallete[x].green = rgbTuple[1]>>2; + pallete[x].blue = rgbTuple[2]>>2; + RGBpalette[x*3] = rgbTuple[0]>>2; + RGBpalette[x*3+1] = rgbTuple[1]>>2; + RGBpalette[x*3+2] = rgbTuple[2]>>2; + } + setDAC(pallete); + return(0); +} + +/* setDAC uses some pretty sophisticated funtions of Borland C. We first + set up a bunch of variables to hold CPU register values in type REGS. + Once we have done this, we can make some low level calls to the video + BIOS to set up the colors we want in the picture. We enter a loop that + sets each register to a RGB color combination and calls the BIOS routine + to set the specific DAC register we are interesed in. */ +void setDAC(struct RGBColor pallete[256]) +{ + union REGS regs; + int i; + + /* This sets up each of the 16 pallete entries to enable the proper + DAC register when the pallete value is combined with the pixel + value. */ +/* for(i=0;i<16;++i){ + regs.h.ah = 0x10; + regs.h.al = 0x00; + regs.h.bh = i; + regs.h.bl = i; + int86(0x10,®s,®s); + } + + regs.h.bl = 0x00; + for (i=0;i<256;++i){ + regs.h.ah = 0x10; /* set specific DAC rgb register value */ +// regs.h.al = 0x10; /* subfunction number, set register */ +// regs.h.ch = pallete[i].green; /* CH contains the green value */ +// regs.h.cl = pallete[i].blue; /* CL contains the blue value */ +// regs.h.dh = pallete[i].red; /* DH contains the red value */ +// int86(0x10, ®s, ®s); /* int 10h */ +// ++regs.h.bl; +// }*/ + x_put_pal_raw(RGBpalette, 256, 0); + +} + +/* DumpToScreen unpacks the graphics information contained in the file. It + first searches for the BODY header which precedes the actual graphics + data. If we don't find the BODY header, the program will just crash, since + I don't look out for the end of the file here. Once it finds the header, + it reads in the next value, which is the length of the body. We use this + value to read in the the next n number of bytes as specified by the body + length. ILBM seems to use a run length encoding scheme to pack the data. + The function looks at the first byte read. If the first byte read in is + between -1 and -127, then this means we are to read in the next byte + value, and repeat this value 1 to 127 times depending on the first byte + value we read. I.E. if the first value we read was -1, we read the next + value and repeat this value in the scanline 2 times (1-(-1)). If the + header value was -128, we would do nothing, as this is the no-operation + code. If the header value, call this n,is between 0 and 128, we interpret + this to mean the next n bytes are to be read in normally and stuffed + into the scanline without any sort of expansion or processing. Once this + function has read enough bytes to make up a scanline (320 bytes in VGA + mode 13h), we call a routine that dumps the scanline we just built to + the screen. We keep doing this until we run out of bytes to read. Note + that it is possible for an image to have more than 200 scanlines of data, + but our scanline dump routine ignores lines past 200. */ +int DumpToScreen(FILE *picFile, struct headform *header, long page){ + int yoffset=0; /* the y coord of the scanline */ + int index=0; /* index into the scanline array */ + int pixelsToGo=0; /* number of pixels to go to form a line*/ + int i; /* loop counter */ + int maxLines = header->length; + unsigned char Vbuff[322]; /* buffer to hold the scanline. It + is 4 bytes longer than the regular + length so it can hold hsize and + vsize data for the putimage call */ + int repeat; /* how many times to repeat the byte*/ + char repeatValue; /* raw byte value from file */ + char bufValue; /* raw buffer value read from file*/ + long size; /* size of the BODY segment */ + long bytesToGo; /* bytes to go till end of BODY */ + char form[5]; /* holds header */ + fread(form,4,1,picFile); + form[4]='\0'; + while(strcmp("BODY",form) != 0){ /* find the BODY */ + form[0]=form[1]; + form[1]=form[2]; + form[2]=form[3]; + form[3]=fgetc(picFile); + } + fread(&size,sizeof(size),1,picFile); + bytesToGo = ReverseLong(size); + +// Vbuff[0]=(320-1) & 0xff; + /* set up height and width of + our scanline. Since we use + putimage to dump our scanline, + we have to tell it how big + the 'shape' we are drawing + to the screen is. In our case + the shape is 320x1 in size.*/ +// Vbuff[1]=(320-1) >> 8; +// Vbuff[2]=1; +// Vbuff[3]=0; + + Vbuff[0] = 160; + Vbuff[1] = 1; + + index = index+2; + +// index = index+4; /* update the index into the scanline */ + + /* Check to see if the compression is of the proper type, which in + our case is 1. If it is uncompressed, or if we don't know the + compression type, we exit the program. */ + if(header->compression != 1) + return(1); + while(bytesToGo > 0) + { + fread(&repeatValue,1,1,picFile); + if(ferror(picFile)) + { + } + --bytesToGo; + repeat = repeatValue; + + if (repeat == -128); + else if((repeat <= -1) && (repeat >= -127)) + { + fread(&bufValue,1,1,picFile); + if(ferror(picFile)) + { + } + --bytesToGo; + for (i=0;i<(1-repeat);++i) + { + Vbuff[pixelsToGo+4-index] = bufValue; + ++pixelsToGo; + if(pixelsToGo == 320) + drawline(&yoffset,Vbuff,&pixelsToGo,page, + maxLines); + } + } + + else if((repeat >= 0) && (repeat <= 127)) + { + for(i=0;i<=repeat;++i) + { + fread(&(Vbuff[pixelsToGo+4-index]),1,1,picFile); + if(ferror(picFile)) + { + } + --bytesToGo; + ++pixelsToGo; + if(pixelsToGo == 320) + drawline(&yoffset,Vbuff,&pixelsToGo,page,maxLines); + } + } /*end if*/ + }/*end while bodysize*/ + return(0); +} + + +/* drawline takes an array containing the scanline data we have just + read in, and dumps it to the screen using the putimage call in the + Borland BGI. The function then increments the yvalue to point to + the next scanline, then resets the pixels to go value (scanline) to + 0 again. If we are currently working on a scanline greater than can + fit on the screen (i.e. greater than 200), we just ignore it and don't + draw it to the screen. */ +void drawline(int *yoffset,unsigned char Vbuff[322], + int *scanline,long page, int maxLines) +{ + + // must split image because CHAR cannot hold a length of 320 + + unsigned char PBMbuff[162]; + char *imagePtr; + + if(*yoffset <= maxLines) +// putimage(0,*yoffset,Vbuff,COPY_PUT); + imagePtr = Vbuff; + x_bm_to_pbm(imagePtr, PBMbuff); + x_put_pbm(0,*yoffset,page,PBMbuff); + Vbuff[160] = 160; + Vbuff[161] = 1; + imagePtr+=160; + x_bm_to_pbm(imagePtr, PBMbuff); + x_put_pbm(160,*yoffset,page,PBMbuff); + ++*yoffset; + *scanline=0; +} + + diff --git a/MYMAP/SHOWLBM.OBJ b/MYMAP/SHOWLBM.OBJ new file mode 100644 index 0000000..f0b6ac8 Binary files /dev/null and b/MYMAP/SHOWLBM.OBJ differ diff --git a/MYMAP/SM.BAT b/MYMAP/SM.BAT new file mode 100644 index 0000000..0deba04 --- /dev/null +++ b/MYMAP/SM.BAT @@ -0,0 +1 @@ +copy todd3d.tod c:\raven\source diff --git a/MYMAP/SMALTHIN.FNT b/MYMAP/SMALTHIN.FNT new file mode 100644 index 0000000..63c07f4 Binary files /dev/null and b/MYMAP/SMALTHIN.FNT differ diff --git a/MYMAP/SOUND.OBJ b/MYMAP/SOUND.OBJ new file mode 100644 index 0000000..60d34d5 Binary files /dev/null and b/MYMAP/SOUND.OBJ differ diff --git a/MYMAP/SPRITE4.LBM b/MYMAP/SPRITE4.LBM new file mode 100644 index 0000000..4f809a3 Binary files /dev/null and b/MYMAP/SPRITE4.LBM differ diff --git a/MYMAP/SV.EXE b/MYMAP/SV.EXE new file mode 100644 index 0000000..dd0f1a2 Binary files /dev/null and b/MYMAP/SV.EXE differ diff --git a/MYMAP/TDCONFIG.TD b/MYMAP/TDCONFIG.TD new file mode 100644 index 0000000..fa8e3bd Binary files /dev/null and b/MYMAP/TDCONFIG.TD differ diff --git a/MYMAP/TIMPANI.FNT b/MYMAP/TIMPANI.FNT new file mode 100644 index 0000000..8907f0a Binary files /dev/null and b/MYMAP/TIMPANI.FNT differ diff --git a/MYMAP/TINY4.FNT b/MYMAP/TINY4.FNT new file mode 100644 index 0000000..d213c3d Binary files /dev/null and b/MYMAP/TINY4.FNT differ diff --git a/MYMAP/TODD.MAP b/MYMAP/TODD.MAP new file mode 100644 index 0000000..2b0c709 Binary files /dev/null and b/MYMAP/TODD.MAP differ diff --git a/MYMAP/VAR6X8.FNT b/MYMAP/VAR6X8.FNT new file mode 100644 index 0000000..6cd3b0d Binary files /dev/null and b/MYMAP/VAR6X8.FNT differ diff --git a/MYMAP/VARSWISB.FNT b/MYMAP/VARSWISB.FNT new file mode 100644 index 0000000..a4a357b Binary files /dev/null and b/MYMAP/VARSWISB.FNT differ diff --git a/MYMAP/VARSWISL.FNT b/MYMAP/VARSWISL.FNT new file mode 100644 index 0000000..d1b2e56 Binary files /dev/null and b/MYMAP/VARSWISL.FNT differ diff --git a/MYMAP/WALLS1.LBM b/MYMAP/WALLS1.LBM new file mode 100644 index 0000000..4f00a24 Binary files /dev/null and b/MYMAP/WALLS1.LBM differ diff --git a/MYMAP/WALLS2.LBM b/MYMAP/WALLS2.LBM new file mode 100644 index 0000000..391fe61 Binary files /dev/null and b/MYMAP/WALLS2.LBM differ diff --git a/MYMAP/WALLS3.LBM b/MYMAP/WALLS3.LBM new file mode 100644 index 0000000..a1e2710 Binary files /dev/null and b/MYMAP/WALLS3.LBM differ diff --git a/MYMAP/WALLS4.LBM b/MYMAP/WALLS4.LBM new file mode 100644 index 0000000..e41cccb Binary files /dev/null and b/MYMAP/WALLS4.LBM differ diff --git a/MYMAP/WALLS5.LBM b/MYMAP/WALLS5.LBM new file mode 100644 index 0000000..ad25152 Binary files /dev/null and b/MYMAP/WALLS5.LBM differ diff --git a/MYMAP/WALLS6.LBM b/MYMAP/WALLS6.LBM new file mode 100644 index 0000000..ec205ce Binary files /dev/null and b/MYMAP/WALLS6.LBM differ diff --git a/MYMAP/_BACKUP_.LBM b/MYMAP/_BACKUP_.LBM new file mode 100644 index 0000000..eaf8ff1 Binary files /dev/null and b/MYMAP/_BACKUP_.LBM differ diff --git a/README b/README new file mode 100644 index 0000000..6a3a2fb --- /dev/null +++ b/README @@ -0,0 +1,43 @@ +This file is provided for a quick reference to some of the functionality and +future functionality of this 3D engine. + +Keyboard Commands +================= + + ESC - exit the demo + CURSOR UP - move forwards + CURSOR DOWN - move backwards + CURSOR LEFT - turn counter-clockwise + CURSOR RIGHT - turn clockwise + INSERT - increase size of screen + DELETE - decrease size of screen + PGUP - move up y-axis + PGDN - move down y-axis + +Right now, the engine supports a bi-quadrilateral projection scheme (ala +Wolfenstien) but with some noteable exceptions: + + First, the engine supports lighting in the form of distance shading + (i.e. it get darker the farther away one goes in the z direction) for + an added effect of depth. In the future, we will add localize lighting + so that certain rooms can be darker than others and a torch can light up + the surrounding areas (ala Doom). + + Second, we have the ability to move along the y-axis and can create the + effect of bobbing up and down as we walk, jumping, falling down, etc. + + Third, our floors and ceilings are texture-mapped adding even more to the + visual detail. We will probably put in some detail options including + shutting off floor and ceiling texturing to support slower machines. We + can even shut off the ceiling and provide and scrolling skyline. + + Fourth, the engine suppors 8 rotation views for any object or sprite + (ala Doom). + + Lastly, (not shown in demo) our ceiling and floor tile suppor morphing for + realistic contours. In simpler terms, we can make some ceilings higher + than others and the adjacent tiles will stretch and morph to make a smooth + transitional surface. We can thus create cavernous rooms with huge + monsters. + + diff --git a/SGRAB/D.BAT b/SGRAB/D.BAT new file mode 100644 index 0000000..0c8c38f --- /dev/null +++ b/SGRAB/D.BAT @@ -0,0 +1 @@ +td386 sgrab sprite1 diff --git a/SGRAB/DOOMGRB.C b/SGRAB/DOOMGRB.C new file mode 100644 index 0000000..e6c3189 --- /dev/null +++ b/SGRAB/DOOMGRB.C @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include + +#include "sgrab.h" +#pragma hdrstop + +#define TRANSCOLOR 0 + + +typedef struct +{ + short leftoffset; // source pixels to the left of midpoint + short width; // last row used - first row + 1 + short collumnofs[256]; // only [width] used, [0] is &collumnofs[width] + // 0 collumnofs means empty row + // the data is : top, bottom, pixels... +} dsprite_t; + + + +/* +============== += += GrabDSprite += += filename dsprite x y width height += +============== +*/ + +void GrabDSprite (void) +{ + int x,y,xl,yl,w,h; + byte far *screen_p; + int linedelta; + dsprite_t far *header; + int first,last; + + GetToken (false); + xl = atoi (token); + GetToken (false); + yl = atoi (token); + GetToken (false); + w = atoi (token); + GetToken (false); + h = atoi (token); + + +// +// find first and last collumn +// + screen_p = MK_FP(0xa000,yl*SCREENWIDTH+xl); + for (first=0 ; first=0 ; last--) + { + for (y=0 ; yleftoffset = w/2 - first; + header->width = w; + +// +// start grabbing rows +// + lump_p = (byte far *)&header->collumnofs[header->width]; + + screen_p = MK_FP(0xa000,yl*SCREENWIDTH+xl+first); + for (x=0 ; x< w ; x++,screen_p++) + { + // find first good pixel + for (first=0 ; firstcollumnofs[x] = 0; // nothing in this collumn + continue; + } + // find last good pixel + for (last=h-1 ; last>=0 ; last--) + { + if ( *(screen_p+last*SCREENWIDTH) != TRANSCOLOR ) + break; + *(screen_p+last*SCREENWIDTH) ^= 0xff; + } + + // grab that segment + header->collumnofs[x] = lump_p - (byte far *)header; + *lump_p++ = h - 1 - first; + *lump_p++ = h - 1 - last; + for (y=first ; y<=last ; y++) + { + *lump_p++ = *(screen_p+y*SCREENWIDTH); + *(screen_p+y*SCREENWIDTH) = 0xff; + } + } +} + + diff --git a/SGRAB/DOOMGRB.OBJ b/SGRAB/DOOMGRB.OBJ new file mode 100644 index 0000000..043fa2e Binary files /dev/null and b/SGRAB/DOOMGRB.OBJ differ diff --git a/SGRAB/DP_BPAL.$$$ b/SGRAB/DP_BPAL.$$$ new file mode 100644 index 0000000..17bc906 Binary files /dev/null and b/SGRAB/DP_BPAL.$$$ differ diff --git a/SGRAB/DP_CPAL.$$$ b/SGRAB/DP_CPAL.$$$ new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/SGRAB/DP_CPAL.$$$ differ diff --git a/SGRAB/DP_OPAL.$$$ b/SGRAB/DP_OPAL.$$$ new file mode 100644 index 0000000..17bc906 Binary files /dev/null and b/SGRAB/DP_OPAL.$$$ differ diff --git a/SGRAB/DP_PREFS b/SGRAB/DP_PREFS new file mode 100644 index 0000000..8b6c3bc Binary files /dev/null and b/SGRAB/DP_PREFS differ diff --git a/SGRAB/DP_SPAL.$$$ b/SGRAB/DP_SPAL.$$$ new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/SGRAB/DP_SPAL.$$$ differ diff --git a/SGRAB/GENGRAB.C b/SGRAB/GENGRAB.C new file mode 100644 index 0000000..2a34113 --- /dev/null +++ b/SGRAB/GENGRAB.C @@ -0,0 +1,447 @@ +#include +#include +#include +#include +#include + +#include "sgrab.h" +#pragma hdrstop + + + +typedef struct +{ + unsigned width,height; + unsigned planeofs[4]; + int orgx,orgy; // from here on out is optional + int hitxl,hityl,hitxh,hityh; +} pic_t; + +typedef struct +{ + short width,height; + short orgx,orgy; + byte data; +} lpic_t; + +typedef struct +{ + unsigned height; + char width[256]; + unsigned charofs[256]; +} font_t; + + + + +/* +============== += += GrabRaw += += filename RAW x y width height += +============== +*/ + +void GrabRaw (void) +{ + int x,y,xl,yl,xh,yh,w,h; + byte far *screen_p; + int linedelta; + + GetToken (false); + xl = atoi (token); + GetToken (false); + yl = atoi (token); + GetToken (false); + w = atoi (token); + GetToken (false); + h = atoi (token); + + xh = xl+w; + yh = yl+h; + + screen_p = MK_FP(0xa000,yl*SCREENWIDTH+xl); + linedelta = SCREENWIDTH - w; + + for (y=yl ; ywidth = w; + header->height = h; + + lump_p = (byte far *)&header->orgx; + +// +// optional origin offset +// + if (TokenAvailable()) + { + GetToken (false); + header->orgx = atoi (token); + GetToken (false); + header->orgy = atoi (token); + lump_p = (byte far *)&header->hitxl; + // + // optional hit rectangle + // + if (TokenAvailable()) + { + GetToken (false); + header->hitxl = atoi (token); + GetToken (false); + header->hitxh = atoi (token); + GetToken (false); + header->hityl = atoi (token); + GetToken (false); + header->hityh = atoi (token); + lump_p = ((byte far *)&header->hityh)+1; + } + } + + +// +// grab in munged format +// + for (p=0 ; p<4 ; p++) + { + header->planeofs[p] = lump_p - lumpbuffer; + + for (y=0 ; y=clipplane) + *lump_p++ = 0; // pad with transparent + else + { + *lump_p++ = *screen_p; + *screen_p = 0; + } + screen_p += 4; + } + } + } + +} + + +/* +============== += += GrabLinearPic += += filename LPIC x y width height [orgx orgy] += +============== +*/ + +void GrabLinearPic (void) +{ + int x,y,xl,yl,xh,yh,w,h,p; + int clipplane; + lpic_t far *header; + byte far *screen_p; + + GetToken (false); + xl = atoi (token); + GetToken (false); + yl = atoi (token); + GetToken (false); + w = atoi (token); + GetToken (false); + h = atoi (token); + + header = (lpic_t far *)lump_p; + header->width = w; + header->height = h; + + +// +// optional origin offset +// + if (TokenAvailable()) + { + GetToken (false); + header->orgx = atoi (token); + GetToken (false); + header->orgy = atoi (token); + } + else + header->orgx = header->orgy = 0; + + lump_p = (byte far *)&header->data; + + +// +// grab it +// + for (y=0 ; yheight, and += advances sx,sy += +=================== +*/ + +int GrabChar (void) +{ + int y; + byte far *screen_p,b; + int count; + +// +// look for a vertical line with a source pixel +// + + do + { + screen_p = MK_FP(0xa000,sy*SCREENWIDTH+sx); + for (y=0 ; yheight ; y++) + if (screen_p[y*SCREENWIDTH]) + goto startgrabing; + if (++sx == SCREENWIDTH) + { + sx=0; + sy += font->height+1; + if (sy+font->height > SCREENHEIGHT) + { + printf ("Ran out of characters at char %i\n",ch); + exit (1); + } + } + + } while (1); + +startgrabing: +// +// grab the character +// + font->width[ch] = 0; + font->charofs[ch] = lump_p - (byte far *)font; + + do + { + font->width[ch]++; + + screen_p = MK_FP(0xa000,sy*SCREENWIDTH+sx); + count = 0; + + for (y=0 ; yheight ; y++) + { + b = *screen_p; + if (b) + count++; + if (b==254) // 254 is a grabbable 0 + b = 0; + *lump_p++ = b; + screen_p += SCREENWIDTH; + } + + if (count) // color the grabbed collumn + for (y=0 ; yheight ; y++) + { + screen_p -= SCREENWIDTH; + *screen_p = 1; + } + + if (++sx == SCREENWIDTH) + { + sx=0; + sy += font->height+1; + return; + } + + if (!count) // hit a blank row? + { + lump_p -= font->height; + font->width[ch]--; + return; + } + + } while (1); +} + + +/* +=================== += += GrabFont += += filename FONT startchar endchar [startchar endchar [...]] += +=================== +*/ + +void GrabFont (void) +{ + int c; + int x,y; + byte far *screen_p; + int top,bottom; + int startchar,endchar; + + font = (font_t far *)lump_p; + _fmemset (font,0,sizeof(*font)); + +// +// find the height of the font by scanning for quide lines (color 255) +// + screen_p = MK_FP(0xa000,0); + + top = -1; + for (y=0;y<10;y++) + if (screen_p[y*SCREENWIDTH] == 255) + { + top = y; + break; + } + + if (top == -1) + MS_Quit ("No color 255 top guideline found!\n"); + + bottom = -1; + for ( y++ ; y<100 ; y++) + if (screen_p[y*SCREENWIDTH] == 255) + { + bottom = y; + break; + } + + if (bottom == -1) + MS_Quit ("No color 255 bottom guideline found!\n"); + + font->height = bottom-top-1; + lump_p = &(byte)font->charofs[256]; + + sx = 0; + sy = top+1; + +// +// grab ranges of characters +// + do + { + GetToken (false); + startchar = atoi (token); + GetToken (false); + endchar = atoi (token); + + for (ch=startchar ; ch<=endchar ; ch++) + GrabChar (); + + } while (TokenAvailable ()); +} + + diff --git a/SGRAB/GENGRAB.OBJ b/SGRAB/GENGRAB.OBJ new file mode 100644 index 0000000..4642333 Binary files /dev/null and b/SGRAB/GENGRAB.OBJ differ diff --git a/SGRAB/LNXGRAB.C b/SGRAB/LNXGRAB.C new file mode 100644 index 0000000..e5ec394 --- /dev/null +++ b/SGRAB/LNXGRAB.C @@ -0,0 +1,241 @@ +#include +#include +#include +#include +#include + +#include "sgrab.h" +#pragma hdrstop + +#define TILEBOXWIDTH 24 +#define TILEBOXHEIGHT 32 +#define TILESPERLINE 12 + +#define TILEWIDTH 16 +#define TILEHEIGHT 30 + +#define MASKCOLOR 255 + +/* +============== += += GrabLynxWalls += += filename LYNXWALLS numtiles += +============== +*/ + +void GrabLynxWalls (void) +{ + int x,y,xl,yl,w,h; + int t,tiles; + byte far *screen_p; + + GetToken (false); + tiles = atoi (token); + + for (t=0 ; t=0;lastline--) + { + for (x=0;x=0;lastx--) + if (quadrant[y][lastx] != MASKCOLOR) + break; + + // leave space for line length in bytes + length_p = lump_p; + lump_p++; + + // grab the line, packing pixels if 3 in a row + databyte = bit = 0; + + for (x=0 ; x<=lastx ; x++) + { + pixel = quadrant[y][x]; + if (pixel==MASKCOLOR) + pixel = 0; + pixel <<= bit; + databyte |= pixel; + bit += 4; + if (bit>=8) + { + *lump_p++ = (byte)databyte; + bit-=8; + databyte>>=8; + } +#if 0 + // check for a run of pixels + for (rle=0 ; x+rle<=lastx ; rle++) + if (quadrant[y][x+rle+1] != pixel) + break; +#endif + + } + if (bit || *(lump_p-1)&1 || lump_p == length_p+1) + // if bits left, lynx bug, or nothing on line, write a final byte out + *lump_p++ = (byte)databyte; + + // write out the length + *length_p = lump_p-length_p; + } + +} + + +/* +============== += += GrabLynxScale += += filename LYNXSCALE spot += +============== +*/ + +void GrabLynxScale (void) +{ + int spot,x,y,xl,yl,xh,yh; + byte far *screen_p,pixel; + int linedelta; + + GetToken (false); + spot = atoi (token); + + xl = spot%5*64+1; + yl = spot/5*62+1; + +// +// grab the source block +// + xh = xl+63; + yh = yl+60; + + screen_p = MK_FP(0xa000,yl*SCREENWIDTH+xl); + linedelta = SCREENWIDTH - 63; + + memset (counts,0,sizeof(counts)); + + for (y=yl ; y +#include +#include +#include +#include +#include + +#include "sgrab.h" +#pragma hdrstop + + + +typedef struct +{ + unsigned height; // in blocks*2 + unsigned collumnofs[64]; +} wall_t; + + +typedef struct +{ + unsigned postofs[4096]; +} holo_t; +// post data: numruns [skipvalue(*2) runlen [data]] + +typedef struct +{ + unsigned width; + unsigned top,bottom; + unsigned postofs[]; +} scaleshape_t; + + + +/* +============== += += GrabWall += += filename WALL xblock yblock blockheight += +============== +*/ + +void GrabWall (void) +{ + int x,y,xl,yl,xh,yh,w,h; + byte far *screen_p; + int linedelta; + wall_t far *header; + + GetToken (false); + xl = atoi (token)*8; + GetToken (false); + yl = atoi (token)*8; + GetToken (false); + h = atoi (token)*8; + w = 64; + + xh = xl+w; + yh = yl+h; + + header = (wall_t far *)lump_p; + header->height = h/4; // block height*2 + + for (x=0;x<64;x++) + header->collumnofs[x] = 65*2+x*h - (96-h); // adjusted for entry + + lump_p = (byte far *)&header->collumnofs[64]; + + screen_p = MK_FP(0xa000,yl*SCREENWIDTH+xl); + + for (x=xl;xwidth = w; + lump_p = (byte far *)&header->postofs[w]; +// +// copy the lines to post[], then let SparsePost () write the data +// + header->top = WORLDHEIGHT; + header->bottom = 0; + + for (x=0 ; xpostofs[x] = lump_p - (byte far *)header; + + for (y=0 ; ytop) + header->top = adj; + if (adj > header->bottom) + header->bottom = adj; + } + + *(screen_p+y*SCREENWIDTH) = 0; + } + SparsePost (); + screen_p++; + } +} + +/* +============================================================================= + + HOLOGRAM + +============================================================================= +*/ + + +/* +============== += += GrabHolo += += filename HOLO += +============== +*/ + +#define HOLOSIZE 64 + +void GrabHolo (void) +{ + int x,y,z,shift; + int runcount,runs,count,lastz; + byte far *screen_p,pixel; + byte far *runs_p, far *count_p; + holo_t far *header; + byte far *plane[HOLOSIZE]; + boolean inrun; + +// +// initialize a blank hologram +// A plane is an X/Y horizontal slice through the hologram +// + for (z=0;z=0;y--) + if (*(plane[z]+y*HOLOSIZE+x)) + { + if (y==HOLOSIZE-1 || !*(plane[z]+(y+1)*HOLOSIZE+x)) + *(plane[z]+y*HOLOSIZE+x) = pixel; + } + *screen_p = pixel; + } + +// +// color the west plane +// + for (z=0;z=0;x--) + if (*(plane[z]+y*HOLOSIZE+x)) + { + if (x==HOLOSIZE-1 || !*(plane[z]+y*HOLOSIZE+x+1)) + *(plane[z]+y*HOLOSIZE+x) = pixel; + } + *screen_p = pixel; + } + + +// +// color the top plane +// + for (y=0;y=0;z--) + if (*(plane[z]+y*HOLOSIZE+x)) + { + if (z==HOLOSIZE-1 || !*(plane[z+1]+y*HOLOSIZE+x)) + *(plane[z]+y*HOLOSIZE+x) = pixel; + } + *screen_p = pixel; + } + + +// +// draw an orthographic representation +// + screen_p = MK_FP(0xa000,0); + for (y=0;ypostofs[4096]; + + for (y=0;ypostofs[y*HOLOSIZE+x] = lump_p - (byte far *)header; + runs_p = lump_p++; + + runs = 0; + lastz = 0; + inrun = false; + + for (z=0;zpostofs[y*HOLOSIZE+x] = 0; + *screen_p = 255; + lump_p--; + continue; + } + *runs_p = runs; + + *screen_p = pixel; + } + + + for (z=0;z +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sgrab.h" +#pragma hdrstop + + +boolean pause; +byte *lumpbuffer,*lump_p; + + +/* +============================================================================ + + LBM STUFF + +============================================================================ +*/ + +#define PEL_WRITE_ADR 0x3c8 +#define PEL_READ_ADR 0x3c7 +#define PEL_DATA 0x3c9 + + +#define FORMID ('F'+('O'<<8)+((long)'R'<<16)+((long)'M'<<24)) +#define ILBMID ('I'+('L'<<8)+((long)'B'<<16)+((long)'M'<<24)) +#define PBMID ('P'+('B'<<8)+((long)'M'<<16)+((long)' '<<24)) +#define BMHDID ('B'+('M'<<8)+((long)'H'<<16)+((long)'D'<<24)) +#define BODYID ('B'+('O'<<8)+((long)'D'<<16)+((long)'Y'<<24)) +#define CMAPID ('C'+('M'<<8)+((long)'A'<<16)+((long)'P'<<24)) + +typedef unsigned char UBYTE; +typedef short WORD; +typedef unsigned short UWORD; +typedef long LONG; + +typedef enum +{ + ms_none, + ms_mask, + ms_transcolor, + ms_lasso +} mask_t; + +typedef enum +{ + cm_none, + cm_rle1 +} compress_t; + +typedef struct +{ + UWORD w,h; + WORD x,y; + UBYTE nPlanes; + UBYTE masking; + UBYTE compression; + UBYTE pad1; + UWORD transparentColor; + UBYTE xAspect,yAspect; + WORD pageWidth,pageHeight; +} bmhd_t; + +bmhd_t bmhd; + +unsigned ShortSwap (unsigned l) +{ + byte b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; +} + +long LongSwap (long l) +{ + byte b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((long)b1<<24) + ((long)b2<<16) + ((long)b3<<8) + b4; +} + +long Align (long l) +{ + if (l&1) + return l+1; + return l; +} + + + +/* +================ += += LBMRLEdecompress += += Source must be evenly aligned! += +================ +*/ + +byte huge *LBMRLEDecompress (byte far *source,byte far *unpacked + ,int bpwidth) +{ + int count,plane; + byte b,rept; + + count = 0; + + do + { + rept = *source++; + + if (rept > 0x80) + { + rept = (rept^0xff)+2; + b = *source++; + _fmemset(unpacked,b,rept); + unpacked += rept; + } + else if (rept < 0x80) + { + rept++; + _fmemcpy(unpacked,source,rept); + unpacked += rept; + source += rept; + } + else + rept = 0; // rept of 0x80 is NOP + + count += rept; + + } while (countbpwidth) + MS_Quit ("Decompression exceeded width!\n"); + + + return source; +} + + +#define BPLANESIZE 128 +byte bitplanes[9][BPLANESIZE]; // max size 1024 by 9 bit planes + + +/* +================= += += MungeBitPlanes8 += += This destroys the bit plane data! += +================= +*/ + +void MungeBitPlanes8 (int width, byte far *dest) +{ +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm shl [BYTE PTR bitplanes + BPLANESIZE*7 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*6 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*5 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*4 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*3 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*2 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +} + + +void MungeBitPlanes4 (int width, byte far *dest) +{ +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm xor al,al +asm shl [BYTE PTR bitplanes + BPLANESIZE*3 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*2 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +} + + +void MungeBitPlanes2 (int width, byte far *dest) +{ +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm xor al,al +asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +} + + +void MungeBitPlanes1 (int width, byte far *dest) +{ +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm xor al,al +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +} + + +/* +================= += += LoadLBM += +================= +*/ + +void LoadLBM (char *filename) +{ + int handle; + int i,y,p,planes; + long size,remaining; + unsigned readsize,iocount; + byte far *LBMbuffer; + byte huge *LBM_P, huge *LBMEND_P; + byte far *pic_p; + byte huge *body_p; + unsigned linesize,rowsize; + + long formtype,formlength; + long chunktype,chunklength; + void (*mungecall) (int, byte far *); + +// +// load the LBM +// + handle = _open (filename,O_RDONLY); + if ( handle == -1) + MS_Quit ("Cannot open %s\n",filename); + + size = filelength (handle); + LBMbuffer = farmalloc (size); + if (!LBMbuffer) + MS_Quit ("Cannot allocate %lu byte\n",size); + + remaining = size; + LBM_P = LBMbuffer; + + while (remaining) + { + readsize = remaining < 0xf000 ? remaining : 0xf000; + _dos_read (handle,LBM_P,readsize,&iocount); + if (iocount != readsize) + MS_Quit ("Read failure on %s\n",filename); + remaining -= readsize; + LBM_P += readsize; + } + + close (handle); + +// +// parse the LBM header +// + LBM_P = LBMbuffer; + if ( *(long far *)LBMbuffer != FORMID ) + MS_Quit ("No FORM ID at start of file!\n"); + + LBM_P += 4; + formlength = LongSwap( *(long far *)LBM_P ); + LBM_P += 4; + LBMEND_P = LBM_P + Align(formlength); + + formtype = *(long far *)LBM_P; + + if (formtype != ILBMID && formtype != PBMID) + MS_Quit ("Unrecognized form type: %c%c%c%c\n", formtype&0xff + ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff); + + LBM_P += 4; + +// +// parse chunks +// + asm mov ax,0x13 // go into VGA mode + asm int 0x10 + + + while (LBM_P < LBMEND_P) + { + chunktype = *(long far *)LBM_P; + LBM_P += 4; + chunklength = LongSwap(*(long far *)LBM_P); + LBM_P += 4; + + switch (chunktype) + { + case BMHDID: + _fmemcpy (&bmhd,LBM_P,sizeof(bmhd)); + bmhd.w = ShortSwap(bmhd.w); + bmhd.h = ShortSwap(bmhd.h); + bmhd.x = ShortSwap(bmhd.x); + bmhd.y = ShortSwap(bmhd.y); + bmhd.pageWidth = ShortSwap(bmhd.pageWidth); + bmhd.pageHeight = ShortSwap(bmhd.pageHeight); + break; + + case CMAPID: + outportb (PEL_WRITE_ADR,0); + for (i=0;i> 2); + break; + + case BODYID: + body_p = LBM_P; + + if (formtype == PBMID) + { + // + // unpack PBM + // + for (y=0 ; y MAXLUMP) + MS_Quit ("Lump size exceeded %l, memory corrupted!\n",MAXLUMP); + + if (!composite) + { + // open a seperate file for the lump + + if ( (handle = open(filename, O_BINARY | O_WRONLY | O_CREAT | + O_TRUNC,S_IREAD | S_IWRITE) ) == -1) + MS_Quit ("Cannot open %s\n",filename); + } + else + { + // record directory info for the lump in the composte header + + if (grabbed == MAXLUMPS) + MS_Quit ("Too many lumps grabbed for composite file!\n"); + + if (strlen(filename) > 13) + MS_Quit ("Filename %s is too long for composite name!\n",filename); + + strcpy (header_p->name,filename); + header_p->lumptype = cmd; + header_p->dataoffset = tell (handle); + header_p->datalength = size; + + header_p++; + } + + _dos_write (handle,lumpbuffer , size , &iocount); + if (iocount != size) + MS_Quit ("Write error on %s\n",filename); + + if (!composite) + close(handle); + + } while (script_p < scriptend_p); + +// +// if a composite grab, write the header out +// + if (composite) + { + offset = tell (handle); + size = grabbed*sizeof(compheader_t); + _dos_write (handle,header , size, &iocount); + if (iocount != size) + MS_Quit ("Write error on %s\n",filename); + + lseek (handle,0,SEEK_SET); + strncpy (compprologue.id,"SGRB",4); + compprologue.numlumps = grabbed; + compprologue.headeroffset = offset; + compprologue.headerlength = size; + + _dos_write (handle,&compprologue , sizeof(compprologue), &iocount); + + close (handle); + } + + +// +// all done +// +asm mov ax,0x3 // go into text mode +asm int 0x10 + + if (composite) + printf ("%i lumps grabbed in a composite file\n",grabbed); + else + printf ("%i lumps grabbed\n",grabbed); + + exit (0); +} + + diff --git a/SGRAB/SGRAB.DSK b/SGRAB/SGRAB.DSK new file mode 100644 index 0000000..62b7aa5 Binary files /dev/null and b/SGRAB/SGRAB.DSK differ diff --git a/SGRAB/SGRAB.EXE b/SGRAB/SGRAB.EXE new file mode 100644 index 0000000..79e0d93 Binary files /dev/null and b/SGRAB/SGRAB.EXE differ diff --git a/SGRAB/SGRAB.H b/SGRAB/SGRAB.H new file mode 100644 index 0000000..c0f109d --- /dev/null +++ b/SGRAB/SGRAB.H @@ -0,0 +1,14 @@ +#include "\miscsrc\types.h" +#include "\miscsrc\minmisc.h" +#include "\miscsrc\script.h" + +#define SCREENWIDTH 320 +#define SCREENHEIGHT 200 + +#define PEL_WRITE_ADR 0x3c8 +#define PEL_READ_ADR 0x3c7 +#define PEL_DATA 0x3c9 + + +extern boolean pause; +extern byte *lumpbuffer,*lump_p; diff --git a/SGRAB/SGRAB.OBJ b/SGRAB/SGRAB.OBJ new file mode 100644 index 0000000..00de4cf Binary files /dev/null and b/SGRAB/SGRAB.OBJ differ diff --git a/SGRAB/SGRAB.PRJ b/SGRAB/SGRAB.PRJ new file mode 100644 index 0000000..2d565d3 Binary files /dev/null and b/SGRAB/SGRAB.PRJ differ diff --git a/SGRAB/SGRAB.SYM b/SGRAB/SGRAB.SYM new file mode 100644 index 0000000..a8e4da0 Binary files /dev/null and b/SGRAB/SGRAB.SYM differ diff --git a/SGRAB/SGRAB.TXT b/SGRAB/SGRAB.TXT new file mode 100644 index 0000000..2269f4c --- /dev/null +++ b/SGRAB/SGRAB.TXT @@ -0,0 +1,70 @@ +SGRAB DOCUMENTATION +------------------- + +SGRAB [-s | -c] [-p] filename + -s force seperate files + -c force a composite .DAT file (default) + -p wait for a keypress after each grab command + + +Filename should be the root (no extension) of the picture (.LBM) to be +grabbed. The script file (.SCR) is read in and parsed, causing lumps to be +grabbed off the screen and saved into an output data (.DAT) file. + +If the -s option is used, or the first command in the script file is +$SEPERATE, the lumps are each saved to a seperate file, rather than being +combined into a composite file. + + +The script file format is as follows: + +[$SEPERATE] +lumpname grabcommand [parameters] +; Comments can be uses at the beginning of a line, or after a command's parms +; whitespace can be introduced anywhere, but a command cannot cross lines + + + +If the lumps are being saved individually, lumpname can be any valid pathname, +but for composite files it must be a filename[.ext] size. + + +Current grab commands: + +GENERAL + +filename RAW x y width height + An unadorned raw block of pixels + +filename PIC x y width height [orgx orgy [hitxl hityl hitxh hityh]] + A structured pic, with optional origin offsets and hit rectangles + +filename LPIC x y width height [orgx orgy [hitxl hityl hitxh hityh]] + A linear VGA pic, with optional origin offsets + +filename FONT startchar endchar [startchar endchar [...]] + A proportional font, possible skipping ranges of characters + +filename PALETTE [startcolor endcolor] + The VGA palette, all 256 by default + +RAVEN ENGINE + +filename WALL xblock yblock blockheight + Blocks are multiples of 8 pixels, implicit 8 block height + +filename FLAT xblock yblock + Flat floors or ceilings, implicit 8 by 8 block size + +filename DSCALE x y width height + Values in pixels, not blocks. + +LYNX + +filename LYNXWALLS numtiles + Grabs numtiles 16*30 walls off the template screen + +filename LYNXSCALE spot + Grabs a 64*60 lynx sprite from position spot (0-14) on the template screen + + diff --git a/SGRAB/SPRITE1.DAT b/SGRAB/SPRITE1.DAT new file mode 100644 index 0000000..67ec1cf Binary files /dev/null and b/SGRAB/SPRITE1.DAT differ diff --git a/SGRAB/SPRITE1.LBM b/SGRAB/SPRITE1.LBM new file mode 100644 index 0000000..facdc29 Binary files /dev/null and b/SGRAB/SPRITE1.LBM differ diff --git a/SGRAB/SPRITE1.SCR b/SGRAB/SPRITE1.SCR new file mode 100644 index 0000000..f0ba4d8 --- /dev/null +++ b/SGRAB/SPRITE1.SCR @@ -0,0 +1 @@ +spr1 dsprite 2 2 6 8 diff --git a/SGRAB/_BACKUP_.LBM b/SGRAB/_BACKUP_.LBM new file mode 100644 index 0000000..278ef8e Binary files /dev/null and b/SGRAB/_BACKUP_.LBM differ diff --git a/SOURCE/3DNOTES.DOC b/SOURCE/3DNOTES.DOC new file mode 100644 index 0000000..d1ec2da --- /dev/null +++ b/SOURCE/3DNOTES.DOC @@ -0,0 +1,56 @@ +Steps to producing a picture on the screen from all the values in soft3d + +FRACUNIT => a constant that is 1.0 in fixed point + + +Player starts out at: + playerx = (3 * 64 + 32) * FRACUNIT; + playery = (3 * 64 + 32) * FRACUNIT; + playerz = 32 * FRACUNIT; + playerangle = 0; + + +The interrupt does the reading of controls and controlling movement. +The play loop itself does nothing but Render the view and shoot the rendered +drawing to the screen. + +Movement: + Pg/Up & Dn change playerz by FRACUNIT + Home sets playerz to 32.0 + + For translation movement: + Up and Down - + Checks to see if the move can be made then increments the players position + by a set amount. + + playerx and playery are updated depending upon angle of movement and + if the operation succeeds. In this case if you did not run into a wall. + + Left and Right - + Changes the playerangle by PLAYERTURNSPEED; in this case 1 degree(?) + + + +View Rendering : + +This is done with a call to RF_RenderView int R_PUBLIC.C sending player +position and angle. + +This sets the global varibles viewx, viewy, viewz by stripping off most +of the lowest nibbles of the fixed point numbers. viewangle is set to +playerangle. + +SetupFrame is then called: +View buffer is cleared +wallz array is set to MAXZ + 1 ((6 shl 22) + 1) +mapcache_height contents are set to 0xF0 +numspans is set to 0 +frameon is incremented(?) +viewtilex and viewtiley are set to the respective x and y values shifted +by 22(?) + +viewfineangle is set by shifting viewangle by 5 +Initializes backvertex; + + + \ No newline at end of file diff --git a/SOURCE/BLITBUF.ASM b/SOURCE/BLITBUF.ASM new file mode 100644 index 0000000..4ee0021 --- /dev/null +++ b/SOURCE/BLITBUF.ASM @@ -0,0 +1,169 @@ + .386 + .MODEL small + +SKIPPRIMITIVES = 0 ; set to 1 to skip unwound drawing + +INCLUDE viewsize.inc +INCLUDE macros.inc + + +SCREEN = 0a0000h +SCREENWIDTH = 320 + +PEL_WRITE_ADR = 03c8h +PEL_DATA = 03c9h + + .DATA + +EXTRN viewbuffer:WORD +EXTRN viewLocation:DWORD +EXTRN windowWidth:DWORD +EXTRN windowHeight:DWORD + + .CODE + +;========================================================================= +;= VI_DrawMaskedPicToBuffer = +;= = +;= C prototype: = +;= void VI_DrawMaskedPicToBuffer (int x, int y, pic_t *pic) = +;========================================================================= + + @Proc VI_DrawMaskedPicToBuffer, , <,,> + + + mov edi,OFFSET viewbuffer + mov esi,[pic] ; si -> pic + +;----- Set up y and height + + xor ecx,ecx + mov cx,[esi+2] ; get height (row count) of image + mov eax,[y] ; get row location + sub ax,[esi+6] ; subtract orgy + +;----- Adjust for y < 0 + + or eax,eax ; is y < 0 ? + jnl short @@findheight ; if not, go to height adjust + add ecx,eax ; if so, add y to height (h -= (-y)) + xor eax,eax ; y = 0 + +;----- Check for bitmap going off the bottom edge + +@@findheight: + push eax ; save y + add eax,ecx ; bottom row of image + cmp eax,windowHeight + pop eax ; restore y + jle short @@heightok ; if not, get on with it + mov ecx,windowHeight + sub ecx,eax ; h = bottom - y + +@@heightok: + +;;;; set es:edi to di+(eax*MAX_VIEW_WIDTH) + + mov ebx,windowWidth + mul ebx ; oh no, not a mul! + add edi,eax ; move down Viewbuffer to proper row + +;----- Set up x and width + + mov edx,[x] ; get column location + sub dx,[esi+4] ; subtract orgx + mov bx,[esi] ; get width (col count) of image + +;----- Set up esi to pic->data + + add esi,8 + +;----- Adjust for x < 0 + + or edx,edx ; is x < 0: + jnl short @@findwidth ; if not, go to width adjust + add ebx,edx ; if so, add x to width (w -= (-x)) + +;----- Check for bitmap going off the right edge + +@@findwidth: + push edx ; save x + add edx,ebx ; rightmost col of image + cmp edx,windowWidth ; is (w+x) > right ? + pop edx ; restore x + jle short @@widthok ; if not, get on with it + mov ebx,windowWidth ; if so, + sub ebx,edx ; w = right - x + +@@widthok: + +;----- Set up edi to point to Veiwbuffer[x,y] + + add edi,edx + + mov edx,windowWidth ; set eax to pixels in viewbuffer + sub edx,ebx ; to right of our image + +@@rowloop: + + push ecx ; save height (row count) + +;------ Copy this row (masked) to Viewbuffer + + mov ecx,ebx ; get width (col count) of image + shr ecx,2 + +@@colloop: ; for each pixel in row +; lodsb ; get the pixel +; test al,al ; check for zero (mask) +; jnz short @@putit ; if not zero, put it in Viewbuffer +; inc di ; otherwise, increment Viewbuffer ptr + + lodsd + test eax,eax + jnz short @@try1 + add edi,4 + loop @@colloop + jmp short @@rowdone + +@@try1: + test al,al + jz short @@try2 + mov [es:edi],al +@@try2: + inc edi + shr eax,8 + test al,al + jz short @@try3 + mov [es:edi],al +@@try3: + inc edi + shr eax,8 + test al,al + jz short @@try4 + mov [es:edi],al +@@try4: + inc edi + shr eax,8 + test al,al + jz short @@next4 + mov [es:edi],al +@@next4: + inc edi + loop @@colloop ; and go to next pixel +; jmp short @@rowdone ; we must be done with this row +;@@putit: ; put the pixel in Viewbuffer +; stosb ; go ahead, put it there +; loop @@colloop ; go to the next pixel +@@rowdone: ; this row is finished + +;------ + + pop ecx ; restore height (row count) + + add edi,edx ; increment Viewbuffer to next row + loop @@rowloop ; go to the next row + + @exitp + ENDP +END diff --git a/SOURCE/DP_PREFS b/SOURCE/DP_PREFS new file mode 100644 index 0000000..c276c77 Binary files /dev/null and b/SOURCE/DP_PREFS differ diff --git a/SOURCE/DRAWBKUP.ASM b/SOURCE/DRAWBKUP.ASM new file mode 100644 index 0000000..e2e27e0 --- /dev/null +++ b/SOURCE/DRAWBKUP.ASM @@ -0,0 +1,474 @@ + .386 + .MODEL small + +SKIPPRIMITIVES = 0 ; set to 1 to skip unwound drawing + +INCLUDE viewsize.inc +INCLUDE macros.inc + + +SCREEN = 0a0000h +SCREENWIDTH = 320 + +PEL_WRITE_ADR = 03c8h +PEL_DATA = 03c9h + + .DATA + +EXTRN viewbuffer:WORD +EXTRN viewLocation:DWORD +EXTRN windowWidth:DWORD +EXTRN windowHeight:DWORD + + .CODE + +;============================================================================ +; +; Fixed point math +; +;============================================================================ + +@Proc FIXEDMUL, <>, <,> + mov eax,op1 + imul [op2] + shrd eax,edx,16 + @exitp <> +ENDP + +@Proc FIXEDDIV, <>, <,> + mov eax,op1 + cdq + shld edx,eax,16 + sal eax,16 + idiv [op2] +@exitp <> + +ENDP + + + +;============================================================================ +; +; RF_BlitView +; +;============================================================================ + +@Proc RF_BlitView, + + mov esi,OFFSET viewbuffer + mov edi,[viewLocation] + mov ebx,[windowHeight] + mov eax,SCREENWIDTH + sub eax,[windowWidth] + mov edx,eax + mov eax,[windowWidth] + shr eax,2 + +ALIGN 4 +@@blitloop1: + mov ecx,eax + rep movsd + add edi,edx + dec ebx + jnz @@blitloop1 + + @exitp +ENDP + + +;============================================================================ +; +; Merge +; +; merge two parts of the unsorted array to the sorted array +; +;============================================================================ + +.DATA + +EXTRN src1:DWORD +EXTRN src2:DWORD +EXTRN dest:DWORD +EXTRN size1:DWORD +EXTRN size2:DWORD + +PUBLIC mergefrom1 +PUBLIC finishfrom1 +PUBLIC mergefrom2 +PUBLIC finishfrom2 +PUBLIC mergedone + +.CODE + + @Proc Merge, + + mov ebx,[src1] + mov esi,[src2] + mov edi,[dest] + mov ecx,[size1] + mov edx,[size2] + + mov eax,[ebx] + cmp eax,[esi] + jb SHORT mergefrom2 ; if (*src1 < *src2) goto mergefrom2; + +mergefrom1: + stosd + add ebx,4 ; *dest++ = *src1++; + mov eax,[ebx] + dec ecx + jz finishfrom2 ; if (!--size1) goto finishfrom2; + cmp eax,[esi] + ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1; + +mergefrom2: + movsd ; *dest++ = *src2++; + dec edx + jz finishfrom1 ; if (!--size2) goto finishfrom1; + cmp eax,[esi] + ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1; + jmp SHORT mergefrom2 + + ALIGN 4 +finishfrom2: + movsd ; *dest++ = *src2++; + dec edx ; while (size2--) + jnz SHORT finishfrom2 + jmp SHORT mergedone + + ALIGN 4 +finishfrom1: + stosd + add ebx,4 ; *dest++ = *src1++; + mov eax,[ebx] + loop SHORT finishfrom1 ; while (size1--) + +mergedone: + mov [dest],edi + @exitp + ENDP + + +;============================================================================ +; +; unwound vertical scaling code +; +; eax light table pointer, 0 lowbyte overwritten +; ebx all 0, low byte overwritten +; ecx fractional step value +; edx fractional scale value +; esi start of source pixels +; edi bottom pixel in screenbuffer to blit into +; +; ebx should be set to 0 0 0 dh to feed the pipeline +;============================================================================ + +SCALELABEL MACRO number +vscale&number: +ENDM + +LINE = MAXWINDOWHEIGHT +REPT MAXWINDOWHEIGHT-1 + SCALELABEL %LINE + mov al,[esi+ebx] ; get source pixel + add edx,ecx ; calculate next location + mov al,[eax] ; translate the color + xor ebx,ebx + shld ebx,edx,16 ; get address of next location + mov [edi-(LINE-1)*MAXWINDOWWIDTH],al ; draw a pixel to the buffer +LINE = LINE-1 +ENDM +vscale1: + mov al,[esi+ebx] + add edx,ecx + mov al,[eax] + mov [edi],al +vscale0: + ret + + +.DATA + +SCALEDEFINE MACRO number + dd vscale&number +ENDM + + ALIGN 4 +scalecalls LABEL +LINE = 0 +REPT MAXWINDOWHEIGHT+1 + SCALEDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC scalecalls + +;================================================= + +; +; parameters for RN_ScalePost +; +sp_dest dd 0 +sp_count dd 0 +sp_fracstep dd 0 +sp_frac dd 0 +sp_source dd 0 +sp_colormap dd 0 + +PUBLIC sp_dest, sp_count, sp_fracstep, sp_frac, sp_source, sp_colormap + +.CODE + + +;================ +; +; ScalePost +; +;================ + + @Proc ScalePost, + +IFE SKIPPRIMITIVES + + mov edx,[sp_frac] + mov ecx,[sp_fracstep] + mov esi,[sp_source] + mov eax,[sp_colormap] + mov edi,[sp_dest] + xor ebx,ebx + shld ebx,edx,16 ; get address of first location + mov ebp,[sp_count] + call [scalecalls+ebp*4] + +ENDIF + + @exitp + ENDP + + +;============================================================================ +; +; unwound masked vertical scaling code +; +; eax light table pointer, 0 lowbyte overwritten +; ebx all 0, low byte overwritten +; ecx all 0, low byte overwritten +; edx fractional scale value +; esi start of source pixels +; edi bottom pixel in screenbuffer to blit into +; ebp fractional step value +; +; ebx should be set to 0 0 0 dh to feed the pipeline +;============================================================================ + +ALIGN 4 +MSCALELABEL MACRO number +mvscale&number: +ENDM + +LINE = MAXWINDOWHEIGHT +REPT MAXWINDOWHEIGHT-1 + MSCALELABEL %LINE + mov al,[esi+ebx] ; get source pixel + add edx,ebp ; calculate next location + mov cl,al ; save original color for jcxz + mov al,[eax] ; translate the color + xor ebx,ebx + shld ebx,edx,16 ; get address of next location + jcxz $+9 + mov [edi-(LINE-1)*MAXWINDOWWIDTH],al ; draw a pixel to the buffer +LINE = LINE-1 +ENDM +mvscale1: + mov al,[esi+ebx] + add edx,ecx + mov al,[eax] + test al,0 + jz mvscale0 + mov [edi],al +mvscale0: + ret + + +.DATA + +MSCALEDEFINE MACRO number + dd mvscale&number +ENDM + + ALIGN 4 +mscalecalls LABEL +LINE = 0 +REPT MAXWINDOWHEIGHT+1 + MSCALEDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC mscalecalls + +mscalecall dd 0 + +.CODE + + +;================ +; +; ScaleMaskedPost +; +; Same parameters as ScalePost, but 0 pixels are not drawn +; +;================ + + @Proc ScaleMaskedPost, + +IFE SKIPPRIMITIVES + + mov ebp,[sp_count] + mov eax,[mscalecalls+ebp*4] + mov [mscalecall],eax + + mov edx,[sp_frac] + mov ebp,[sp_fracstep] + mov esi,[sp_source] + mov eax,[sp_colormap] + mov edi,[sp_dest] + xor ebx,ebx + xor ecx,ecx + shld ebx,edx,16 ; get address of first location + call [mscalecall] + +ENDIF + + @exitp + ENDP + + +;============================================================================ +; +; unwound horizontal texture mapping code +; +; eax lighttable +; ebx xtotal 6 bits units 26 bits frac +; ecx ytotal 6 bits units 26 bits frac +; edx xstep +; esi start of block +; edi dest +; ebp scratch offset +; +; [ystep] +; +; ebp should by preset from ebx / ecx before calling +;============================================================================ + +MAPLABEL MACRO number +hmap&number: +ENDM + +LINE = MAXWINDOWWIDTH +REPT MAXWINDOWWIDTH + MAPLABEL %LINE + mov al,[esi+ebp] ; get source pixel + add ebx,edx ; xtotal += xstep + add ecx,[ystep] ; ytotal += ystep + xor ebp,ebp + mov al,[eax] ; translate color + shld ebp,ecx,6 ; shift in new y/x position + shld ebp,ebx,6 + mov [edi-(LINE-1)],al ; write pixel +LINE = LINE-1 +ENDM +hmap0: + ret + + +.DATA + +ystep dd 0 + +MAPDEFINE MACRO number + dd hmap&number +ENDM + + ALIGN 4 +mapcalls LABEL +LINE = 0 +REPT MAXWINDOWWIDTH+1 + MAPDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC mapcalls + + + +mapcall dd 0 + +; +; parameters for RN_MapLine +; +mr_dest dd 0 ; pointer to first pixel in view buffer +mr_count dd 0 +mr_picture dd 0 ; pointer to 4096 pixel block +mr_colormap dd 0 ; page aligned light table +mr_xfrac dd 0 ; 16 frac bits +mr_yfrac dd 0 ; 16 frac bits +mr_xstep dd 0 +mr_ystep dd 0 + +PUBLIC mr_dest,mr_picture,mr_colormap,mr_xfrac,mr_yfrac,mr_xstep,mr_ystep,mr_count + +.CODE + + +;================ +; +; MapRow +; +; Horizontal texture mapping +; +;================ + + +@Proc MapRow, + +IFE SKIPPRIMITIVES + + mov eax,[mr_count] + mov ebx,[mapcalls+eax*4] + mov [mapcall],ebx ; spot to jump into unwound + + mov edi,[mr_dest] + add edi,[mr_count] + dec edi + + mov eax,[mr_ystep] + shl eax,10 + mov [ystep],eax + + mov eax,[mr_colormap] + mov ebx,[mr_xfrac] + shl ebx,10 + mov ecx,[mr_yfrac] + shl ecx,10 + mov edx,[mr_xstep] + shl edx,10 + mov esi,[mr_picture] + + + xor ebp,ebp + shld ebp,ecx,6 + shld ebp,ebx,6 ; do first step for pipeline + + call [mapcall] + + shr ebx,10 + mov [mr_xfrac],ebx + shr ecx,10 + mov [mr_yfrac],ecx + +ENDIF + + @exitp +ENDP + +END diff --git a/SOURCE/D_DISK.C b/SOURCE/D_DISK.C new file mode 100644 index 0000000..83f3f2e --- /dev/null +++ b/SOURCE/D_DISK.C @@ -0,0 +1,332 @@ +// D_DISK.C + +#include +#include +#include +#include +#include + +#include "d_global.h" +#include "d_disk.h" +#include "d_misc.h" + +/* +============================================================================= + + GLOBALS + +============================================================================= +*/ + +fileinfo_t fileinfo; // the file header +lumpinfo_t *infotable; // pointers into the cache file +void **lumpmain; // pointers to the lumps in main memory + +int cachehandle; // handle of current file + +FILE *debugstream; // misc io stream + +/* +============================================================================ + + LOW LEVEL ROUTINES + +============================================================================ +*/ + + +/* +====================== += += CA_ReadFile += +====================== +*/ + +void CA_ReadFile (char *name, void *buffer, unsigned length) +{ + int handle; + + if ((handle = open(name,O_RDONLY | O_BINARY)) == -1) + MS_Error ("CA_ReadFile: Open failed!"); + + if (!read(handle,buffer,length)) + { + close (handle); + MS_Error ("CA_LoadFile: Read failed!"); + } + + close (handle); +} + + +/* +====================== += += CA_LoadFile += +====================== +*/ + +void *CA_LoadFile (char *name) +{ + int handle; + unsigned length; + void *buffer; + + if ((handle = open(name,O_RDONLY | O_BINARY)) == -1) + MS_Error ("CA_LoadFile: Open failed!"); + + length = filelength (handle); + + if (!(buffer = malloc(length)) ) + MS_Error ("CA_LoadFile: Malloc failed!"); + + if (!read(handle,buffer,length)) + { + close (handle); + MS_Error ("CA_LoadFile: Read failed!"); + } + + close (handle); + + return buffer; +} + + +/* +============================================================================ + + IDLINK STUFF + +============================================================================ +*/ + + +/* +==================== += += CA_InitFile += +==================== +*/ + +void CA_InitFile (char *filename) +{ + unsigned size,i; + +// +// if a file is allready open, shut it down +// + if (cachehandle) + { + close (cachehandle); + free (infotable); + for (i=0 ; i < fileinfo.numlumps ; i++) + if (lumpmain[i]) + free (lumpmain[i]); + free (lumpmain); + } + +// +// load the header +// + if ((cachehandle = open(filename, + O_RDONLY | O_BINARY, S_IREAD)) == -1) + MS_Error ("Can't open %s!",filename); + + read(cachehandle, (void *)&fileinfo, sizeof(fileinfo)); + +// +// load the info list +// + size = fileinfo.infotablesize; + infotable = malloc(size); + lseek (cachehandle,fileinfo.infotableofs,SEEK_SET); + read (cachehandle, (void *)infotable, size); + + size = fileinfo.numlumps*sizeof(int); + lumpmain = malloc(size); + memset (lumpmain,0,size); +} + + +/* +==================== += += CA_CheckNamedNum += += Returns -1 if name not found += +==================== +*/ + +int CA_CheckNamedNum (char *name) +{ + int i,ofs; + + for (i=0 ; i=fileinfo.numlumps) + MS_Error ("CA_LumpPointer: %i > numlumps!",lump); +#endif + if (!lumpmain[lump]) { + // + // load the lump off disk + // + if (! (lumpmain[lump] = malloc(infotable[lump].size)) ) + MS_Error ("CA_LumpPointer: malloc failure of lump %d, with size %d", + lump,infotable[lump].size); + lseek (cachehandle, infotable[lump].filepos, SEEK_SET); + read (cachehandle,lumpmain[lump],infotable[lump].size); + } + + return lumpmain[lump]; +} + + +/* +==================== += += CA_ReadLump += += Reads a lump into an allready allocated buffer += Does NOT consider it to be cached there, so it is ok to change it += +==================== +*/ + +void CA_ReadLump (int lump, void *dest) +{ +#ifdef PARMCHECK + if (lump>=fileinfo.numlumps) + MS_Error ("CA_ReadLump: %i > numlumps!",lump); +#endif + lseek (cachehandle, infotable[lump].filepos, SEEK_SET); + read (cachehandle,dest,infotable[lump].size); +} + + + +/* +==================== += += CA_FreeLump += += Frees the memory associated with a lump += +==================== +*/ + +void CA_FreeLump (unsigned lump) +{ +#ifdef PARMCHECK + if (lump>=fileinfo.numlumps) + MS_Error ("CA_FreeLump: %i > numlumps!",lump); +#endif + free (lumpmain[lump]); + lumpmain[lump] = NULL; +} + + +/* +==================== += += CA_WriteLump += += Writes a lump back out to disk. It must be currently cached in. += No size change is possible += +==================== +*/ + +void CA_WriteLump (unsigned lump) +{ +#ifdef PARMCHECK + if (lump>=fileinfo.numlumps) + MS_Error ("CA_WriteLump: %i > numlumps!",lump); + if (!lumpmain[lump]) + MS_Error ("CA_WriteLump: %i not cached in!",lump); +#endif + + lseek (cachehandle,infotable[lump].filepos, SEEK_SET); + write (cachehandle,lumpmain[lump],infotable[lump].size); +} + + +/* +====================== += += CA_OpenDebug += +====================== +*/ + +void CA_OpenDebug (void) +{ + debugstream = fopen("DEBUG.TXT","w"); +} + + +/* +====================== += += CA_CloseDebug += +====================== +*/ + +void CA_CloseDebug (void) +{ + fclose (debugstream); +} + diff --git a/SOURCE/D_DISK.H b/SOURCE/D_DISK.H new file mode 100644 index 0000000..0c19d79 --- /dev/null +++ b/SOURCE/D_DISK.H @@ -0,0 +1,50 @@ +// D_DISK.H + +#ifndef __DISK__ +#define __DISK__ + +#include + +#pragma noalign (fileinfo_s) + +typedef struct fileinfo_s // must be noaligned, or the first +{ // short will be padded to 4 bytes + short numlumps; + int infotableofs; + int infotablesize; +} fileinfo_t; + + +typedef struct +{ + int filepos; + unsigned size; + short nameofs; + short compress; +} lumpinfo_t; + + + +extern fileinfo_t fileinfo; // the file header +extern lumpinfo_t *infotable; // pointers into the cache file +extern void **lumpmain; // pointers to the lumps in main memory + +extern int cachehandle; // handle of current file + +extern FILE *debugstream; // misc io stream + + +void CA_ReadFile (char *name, void *buffer, unsigned length); +void *CA_LoadFile (char *name); + +void CA_InitFile (char *filename); +int CA_CheckNamedNum (char *name); +int CA_GetNamedNum (char *name); +void *CA_CacheLump (int lump); +void CA_ReadLump (int lump, void *dest); +void CA_FreeLump (unsigned lump); +void CA_WriteLump (unsigned lump); +void CA_OpenDebug (void); +void CA_CloseDebug (void); + +#endif diff --git a/SOURCE/D_FONT.C b/SOURCE/D_FONT.C new file mode 100644 index 0000000..9ecc9b1 --- /dev/null +++ b/SOURCE/D_FONT.C @@ -0,0 +1,285 @@ +// d_font.c + +#include +#include +#include + +#include "d_global.h" +#include "d_video.h" +#include "d_misc.h" +#include "d_font.h" + + +font_t *font; +int fontbasecolor = 0; +int fontspacing = 1; + +char str[MAXPRINTF]; // general purpose string buffer + +int printx = 0,printy = 0; // the printing position (top left corner) + +int windowx = 0; // window size for text positioning +int windowy = 0; +int windoww = 320; +int windowh = 200; + + +/* +======================== += += FN_RawPrint += += Draws a string of characters to the screen += +======================== +*/ + +void FN_RawPrint (char *str) +{ + byte b; + byte *dest, *source; + int width,height; + char ch; + int x,y; + int oldpx; + + oldpx = printx; + + dest = ylookup[printy]+printx; + + height = font->height; + + while ( (ch=*str++) != 0) + { + width = font->width[ch]; + source = ((byte *)font) + font->charofs[ch]; + + while (width--) + { + for (y=0;yheight); +} + + +/* +======================== += += FN_RawWidth += += Returns the width of a string += Does NOT handle newlines += +======================== +*/ + +int FN_RawWidth (char *str) +{ + int width; + + width = 0; + + while (*str) + { + width += font->width[*str++]; + width += fontspacing; + } + + return width; +} + + +/* +======================== += += FN_Print += += Prints a string in the current window, with newlines += going down a line and back to windowx += +======================== +*/ + +void FN_Print(char *s) +{ + char c, *se; + unsigned h; + + h = font->height; + + while (*s) + { + se = s; + + c = *se; + while (c && c != '\n') + c= *++se; + + *se = '\0'; + + FN_RawPrint (s); + + s = se; + if (c) + { + *se = c; + s++; + + printx = windowx; + printy += h; + } + } +} + + +/* +===================== += += FN_PrintCentered += += Prints a multi line string with each line centered += +===================== +*/ + +void FN_PrintCentered (char *s) +{ + char c, *se; + unsigned w,h; + + h = font->height; + + while (*s) + { + se = s; + + c = *se; + while (c && c != '\n') + c= *++se; + + *se = '\0'; + + w = FN_RawWidth (s); + printx = windowx + (windoww-w)/2; + FN_RawPrint (s); + + s = se; + if (c) + { + *se = c; + s++; + + printx = windowx; + printy += h; + } + } +} + + +/* +===================== += += FN_Printf += += Prints a printf style formatted string at the current print position += using the current print routines += +===================== +*/ + +void FN_Printf (char *fmt, ...) +{ + va_list argptr; + int cnt; + + va_start (argptr,fmt); + cnt = vsprintf (str,fmt,argptr); + va_end (argptr); + + if (cnt>=MAXPRINTF) + MS_Error ("FN_Printf: String too long: %s",fmt); + + FN_Print (str); +} + + +/* +===================== += += FN_CenterPrintf += += As FN_Printf, but centers each line of text in the window bounds += +===================== +*/ + +void FN_CenterPrintf (char *fmt, ...) +{ + va_list argptr; + int cnt; + + va_start (argptr,fmt); + cnt = vsprintf (str,fmt,argptr); + va_end (argptr); + + if (cnt>=MAXPRINTF) + MS_Error ("FN_CPrintf: String too long: %s",fmt); + + FN_PrintCentered (str); +} + + +/* +===================== += += FN_BlockCenterPrintf += += As FN_CenterPrintf, but also enters the entire set of lines vertically in += the window bounds += +===================== +*/ + +void FN_BlockCenterPrintf (char *fmt, ...) +{ + va_list argptr; + int cnt; + char *s; + int height; + + va_start (argptr,fmt); + cnt = vsprintf (str,fmt,argptr); + va_end (argptr); + + if (cnt>=MAXPRINTF) + MS_Error ("FN_CCPrintf: String too long: %s",fmt); + + height = 1; + s = str; + + while (*s) + { + if (*s++=='\n') + height++; + } + + height *= font->height; + + printy = windowy + (windowh-height)/2; + FN_PrintCentered (str); +} + + diff --git a/SOURCE/D_FONT.H b/SOURCE/D_FONT.H new file mode 100644 index 0000000..9d6c3f2 --- /dev/null +++ b/SOURCE/D_FONT.H @@ -0,0 +1,31 @@ +// d_font.h + +#ifndef __FONT__ +#define __FONT__ + +#define MAXPRINTF 256 + +typedef struct +{ + short height; + char width[256]; + short charofs[256]; +} font_t; + + +extern font_t *font; +extern int fontbasecolor; +extern int fontspacing; + +extern int printx,printy; +extern int windowx,windowy,windoww,windowh; + + +int FN_RawWidth (char *str); + +void FN_Printf (char *fmt, ...); +void FN_CenterPrintf (char *fmt, ...); +void FN_BlockCenterPrintf (char *fmt, ...); + + +#endif diff --git a/SOURCE/D_GLOBAL.H b/SOURCE/D_GLOBAL.H new file mode 100644 index 0000000..808b327 --- /dev/null +++ b/SOURCE/D_GLOBAL.H @@ -0,0 +1,7 @@ +// d_global.h + +#define PARMCHECK + +typedef unsigned char byte; +typedef unsigned short word; +typedef enum {false,true} boolean; diff --git a/SOURCE/D_INTS.C b/SOURCE/D_INTS.C new file mode 100644 index 0000000..d3ca930 --- /dev/null +++ b/SOURCE/D_INTS.C @@ -0,0 +1,563 @@ +// d_ints.c + +#include +#include +#include +#include + +#include "d_global.h" +#include "d_video.h" +#include "d_ints.h" +#include "d_misc.h" + +#define TIMERINT 8 +#define KEYBOARDINT 9 + +#define ISRCOLOR 190 +#define FRAMEHOOKCOLOR 200 +#define TIMERHOOKCOLOR 210 + +#define VBLCOUNTER 16000 // this could be a bit higher, but + // i'm givving it some latency elbow room + +void (*oldkeyboardisr)() = 0; +void (*oldtimerisr)() = 0; + +//=================================== + +void (*framehook)() = 0; // called every frame (cursor) +void (*timerhook)() = 0; // called every other frame (player) + +boolean timeractive = false; + +int timerspeed; // 16 bit hardware counter value +int colorborder = 0; // if true, ISRs will color border +int timecount; + +int framesperhook,framecounter; +int intsperframe,intcounter; +int oldbordercolor; +byte *pendingscreen; + +//=================================== + +boolean keyboard[NUMCODES]; +boolean paused,capslock; +char lastascii; +byte lastscan; + +byte ASCIINames[] = // Unshifted ASCII for scan codes + { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0 + 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1 + 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2 + 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4 + '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 + }, + ShiftNames[] = // Shifted ASCII for scan codes + { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0 + 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1 + 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2 + 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4 + '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 + }, + SpecialNames[] = // ASCII for 0xe0 prefixed codes + { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2 + 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 + 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 + }; + + +int scanbuttons[NUMBUTTONS] = +{ + SC_UPARROW, // bt_north + SC_RIGHTARROW, // bt_east + SC_DOWNARROW, // bt_south + SC_LEFTARROW, // bt_west + SC_CONTROL, // bt_a + SC_ALT, // bt_b + SC_SPACE, // bt_c + SC_RSHIFT // bt_d +}; + + +int in_button[NUMBUTTONS]; // frames the button has been down + + + +//=========================================================================== + + + +/* +================ += += INT_KeyboardISR += +================ +*/ + +#pragma interrupt(INT_KeyboardISR) +void INT_KeyboardISR () +{ +static boolean special; + byte k,c; + unsigned short temp; + _XSTACK *ptr; /* ptr to the stack frame */ + +// Get the scan code + + k = _inbyte((unsigned short)0x60); + +// acknowledge the interrupt + + _outbyte((unsigned short)0x20,(unsigned char)0x20); + if (k == 0xe0) // Special key prefix + special = true; + else if (k == 0xe1) // Handle Pause key + paused = true; + else + { + if (k & 0x80) // Break code + { + k &= 0x7f; + keyboard[k] = false; + } + else // Make code + { + lastscan = k; + keyboard[k] = true; + + if (special) + c = SpecialNames[k]; + else + { + if (k == SC_CAPSLOCK) + { + capslock ^= true; + // DEBUG - make caps lock light work + } + + if (keyboard[SC_LSHIFT] || keyboard[SC_RSHIFT]) // If shifted + { + c = ShiftNames[k]; + if ((c >= 'A') && (c <= 'Z') && capslock) + c += 'a' - 'A'; + } + else + { + c = ASCIINames[k]; + if ((c >= 'a') && (c <= 'z') && capslock) + c -= 'a' - 'A'; + } + } + if (c) + lastascii = c; + + *(short *)0x41c = *(short *)0x41a; // clear bios key buffer + } + + special = false; + } + +} + +//=========================================================================== + +/* +================ += += INT_TimerISR += +================ +*/ + +#pragma interrupt(INT_TimerISR) +void INT_TimerISR () +{ + _XSTACK *ptr; // ptr to the stack frame + +// don't chain this to the dos isr + + ptr = (_XSTACK *)_get_stk_frame(); // get ptr to the V86 _XSTACK frame + ptr->opts |= _STK_NOINT; // set _STK_NOINT to prevent V86 call + + _outbyte(0x20,0x20); // Ack the interrupt + CLI; // don't let any more ints hit + + if (colorborder) + VI_ColorBorder(ISRCOLOR); + + if (--intcounter <= 0) + { + intcounter = intsperframe; + // + // increment timing variables + // + timecount++; + + if (framehook) + { + if (colorborder) + VI_ColorBorder(FRAMEHOOKCOLOR); + framehook (); + } + + // + // call the user hook if needed + // + if (timerhook && --framecounter <= 0) + { + framecounter = framesperhook; + + if (colorborder) + VI_ColorBorder(TIMERHOOKCOLOR); + timerhook (); + } + } + + if (colorborder) + VI_ColorBorder(oldbordercolor); +} + +//=========================================================================== + +/* +===================== += += INT_SetTimer0 += += Sets system timer 0 to the specified speed += +===================== +*/ + +void INT_SetTimer0(int speed) +{ +#ifdef PARMCHECK + if (speed > 0 && speed < 150) + MS_Error ("SD_SetTimer0: %i is a bad value",speed); +#endif + + timerspeed = speed; + + _outbyte(0x43,0x36); // Change timer 0 + _outbyte(0x40,timerspeed); + _outbyte(0x40,timerspeed >> 8); +} + +/* +===================== += += INT_SetIntsPerFrame += += Determines the number of interrupts that will occur each += raster scan. (VGA 70 fps) += +===================== +*/ + +void INT_SetIntsPerFrame (int ints) +{ + intsperframe = intcounter = ints; + INT_SetTimer0(VBLCOUNTER/ints); +} + + + +/* +================ += += INT_TimerHook += +================ +*/ + +void INT_TimerHook(void (* hook)(void), int tics) +{ + framecounter = framesperhook = tics; + timerhook = hook; +} + + +/* +================ += += INT_FrameHook += +================ +*/ + +void INT_FrameHook(void (* hook)(void) ) +{ + framehook = hook; +} + + +/* +===================== += += IN_ClearKeysDown += += Clears the keyboard array += +===================== +*/ + +void IN_ClearKeysDown(void) +{ + lastscan = SC_NONE; + lastascii = KEY_NONE; + memset (keyboard,0,sizeof(keyboard)); +} + + +/* +=================== += += IN_ReadControls += +=================== +*/ + +void IN_ReadControls (void) +{ + int i; + boolean buttonstate[NUMBUTTONS]; + + memset (buttonstate,0,sizeof(buttonstate)); +// +// get keyboard +// + for (i=0;i>=1) + if (buttons&1) + btnstate[i] = true; + if (mouseb1) + btnstate[0] = true; + if (mouseb2) + btnstate[1] = true; +#endif +} + + +/* +===================== += += IN_CheckAck += +===================== +*/ + +boolean IN_CheckAck (void) +{ + unsigned i,buttons; + +// +// see if something has been pressed +// + if (lastscan) + return true; + +#if 0 +// DBDOOM + buttons = IN_JoyButtons () << 4; + if (mousepresent) + buttons |= IN_MouseButtons (); + + for (i=0;i<8;i++,buttons>>=1) + if ( buttons&1 ) + { + if (!btnstate[i]) + return true; + } + else + btnstate[i]=false; + if ( mouseb1 ) + { + if (!btnstate[0]) + return true; + } + else + btnstate[0]=false; + + if ( mouseb2 ) + { + if (!btnstate[1]) + return true; + } + else + btnstate[1]=false; +#endif + + return false; +} + + +/* +===================== += += IN_Ack += +===================== +*/ + +void IN_Ack (void) +{ + IN_StartAck (); + + while (!IN_CheckAck ()) + ; +} + + +/* +===================== += += IN_AckTics += += Wait a certain number of tics or aborts out if any += button is pressed += +===================== +*/ + +boolean IN_AckTics(int delay) +{ + int lasttime; + + lasttime = timecount; + IN_StartAck (); + do + { + if (IN_CheckAck()) + return true; + } while (timecount - lasttime < delay); + + return false; +} + + + +//========================================================================== + + +/* +================ += += INT_Setup += +================ +*/ + +void INT_Setup (void) +{ + oldkeyboardisr = _dos_getvect(KEYBOARDINT); + _dpmi_lockregion (INT_KeyboardISR,4096); + _dos_setvect (KEYBOARDINT, INT_KeyboardISR); + + oldtimerisr = _dos_getvect(TIMERINT); + _dpmi_lockregion (INT_TimerISR,4096); + _dos_setvect (TIMERINT, INT_TimerISR); + timeractive = true; + + INT_SetFPS(70); +} + + +/* +================ += += INT_Shutdown += +================ +*/ + +void INT_Shutdown (void) +{ + if (oldkeyboardisr) + _dos_setvect (KEYBOARDINT, oldkeyboardisr); + + if (oldtimerisr) + _dos_setvect (TIMERINT, oldtimerisr); + + INT_SetTimer0 (0); // back to 18.4 ips +} + +void INT_SetFPS(int fps) +{ + INT_SetTimer0(1193180/fps); +} diff --git a/SOURCE/D_INTS.H b/SOURCE/D_INTS.H new file mode 100644 index 0000000..2762b92 --- /dev/null +++ b/SOURCE/D_INTS.H @@ -0,0 +1,131 @@ +// d_ints.h + +// +// keyboard scan codes +// +#define NUMCODES 128 + + +#define SC_NONE 0 +#define SC_BAD 0xff +#define SC_ENTER 0X1c +#define SC_ESCAPE 0x01 +#define SC_SPACE 0x39 +#define SC_BACKSPACE 0x0e +#define SC_TAB 0x0f +#define SC_ALT 0x38 +#define SC_CONTROL 0x1d +#define SC_CAPSLOCK 0x3a +#define SC_LSHIFT 0x2a +#define SC_RSHIFT 0x36 +#define SC_UPARROW 0x48 +#define SC_DOWNARROW 0x50 +#define SC_LEFTARROW 0x4b +#define SC_RIGHTARROW 0x4d +#define SC_INSERT 0x52 +#define SC_DELETE 0x53 +#define SC_HOME 0x47 +#define SC_END 0x4f +#define SC_PGUP 0x49 +#define SC_PGDN 0x51 +#define SC_F1 0x3b +#define SC_F2 0x3c +#define SC_F3 0x3d +#define SC_F4 0x3e +#define SC_F5 0x3f +#define SC_F6 0x40 +#define SC_F7 0x41 +#define SC_F8 0x42 +#define SC_F9 0x43 +#define SC_F10 0x44 +#define SC_F11 0x57 +#define SC_F12 0x59 + +#define SC_1 0x02 +#define SC_2 0x03 +#define SC_3 0x04 +#define SC_4 0x05 +#define SC_5 0x06 +#define SC_6 0x07 +#define SC_7 0x08 +#define SC_8 0x09 +#define SC_9 0x0a +#define SC_0 0x0b + +#define SC_A 0x1e +#define SC_B 0x30 +#define SC_C 0x2e +#define SC_D 0x20 +#define SC_E 0x12 +#define SC_F 0x21 +#define SC_G 0x22 +#define SC_H 0x23 +#define SC_I 0x17 +#define SC_J 0x24 +#define SC_K 0x25 +#define SC_L 0x26 +#define SC_M 0x32 +#define SC_N 0x31 +#define SC_O 0x18 +#define SC_P 0x19 +#define SC_Q 0x10 +#define SC_R 0x13 +#define SC_S 0x1f +#define SC_T 0x14 +#define SC_U 0x16 +#define SC_V 0x2f +#define SC_W 0x11 +#define SC_X 0x2d +#define SC_Y 0x15 +#define SC_Z 0x2c + +#define KEY_NONE 0 +#define KEY_RETURN 0x0d +#define KEY_ENTER 0X0d +#define KEY_ESCAPE 0x1b +#define KEY_SPACE 0x20 +#define KEY_BACKSPACE 0x08 +#define KEY_TAB 0x09 +#define KEY_DELETE 0x7f + + +extern byte *pendingscreen; + +#define NUMBUTTONS 9 + +enum { + bt_nobutton = -1, + bt_north = 0, + bt_east, + bt_south, + bt_west, + bt_a, + bt_b, + bt_c, + bt_d +}; + + +extern boolean keyboard[NUMCODES]; +extern boolean paused,capslock; +extern char lastascii; +extern byte lastscan; + +extern boolean timeractive; + +extern int timecount; + +extern int scanbuttons[NUMBUTTONS]; +extern int in_button[NUMBUTTONS]; // frames the button has been down + + +void INT_Setup (void); +void INT_Shutdown (void); + +void INT_FrameHook(void (* hook)(void)); +void INT_TimerHook(void (* hook)(void), int tics); + +void IN_ClearKeysDown (void); +void IN_Ack (void); +void IN_ReadControls (void); +void INT_SetFPS(int fps); diff --git a/SOURCE/D_MISC.C b/SOURCE/D_MISC.C new file mode 100644 index 0000000..f5b632d --- /dev/null +++ b/SOURCE/D_MISC.C @@ -0,0 +1,147 @@ +// P_MISC.C + +#include +#include +#include +#include +#include + +#include "d_global.h" +#include "d_ints.h" +#include "d_video.h" +#include "d_misc.h" + +int my_argc; +char ** my_argv; + +/* +============================================================================= + + ODD FUNCTIONS + +============================================================================= +*/ + + +/* +================= += += MS_CheckParm += += Checks for the given parameter in the program's command line arguments += += Returns the argument number (1 to argc-1) or 0 if not present += +================= +*/ + +int MS_CheckParm (char *check) +{ + int i; + char *parm; + + for (i = 1;i +#include +#include +#include +#include + +#include "d_global.h" +#include "d_ints.h" +#include "d_video.h" +#include "d_misc.h" +// added to allow drawing directly to buffer where frame is built +// TML 9-20-94 +#include "r_public.h" + +#define CRTCOFF (_inbyte(STATUS_REGISTER_1)&1) + +void VI_CopyUpdate (void); +void VI_BlitMaskedPic (byte *source,byte *dest,int width,int height,int mask); + +/* +============================================================================= + + GLOBALS + +============================================================================= +*/ + +byte *screen = (byte *)SCREEN; + +byte *ylookup[SCREENHEIGHT]; // into video screen + +/* +============================================================================= + + VGA REGISTER MANAGEMENT ROUTINES + +============================================================================= +*/ + + +/* +================= += += VI_SetTextMode += +================= +*/ + +void VI_SetTextMode (void) +{ + union REGS r; + + r.x.ax = 3; + int86 (0x10,(const union REGS *)&r,&r); +} + + +//========================================================================= + +/* +================= += += VI_SetVGAMode += +================= +*/ + +void VI_SetVGAMode (void) +{ + union REGS r; + + r.x.ax = 0x13; + int86 (0x10,(const union REGS *)&r,&r); +} + + +//========================================================================= + +/* +================= += += VI_WaitVBL += +================= +*/ + +void VI_WaitVBL (int vbls) +{ + int old; + int i,stat; + + while (vbls--) + { + // wait for display enabled, so we know it isn't just after vsync + waitdisplay: + CLI; + while (CRTCOFF) + ; + + // wait for display just turned off + waitbottom: + STI; + i--; // time for an interrupt + CLI; + + for (i=0;i<10;i++) + { + stat = _inbyte(STATUS_REGISTER_1); + if (stat & 8) + goto waitdisplay; // vsync... + if (!(stat&1)) + goto waitbottom; + } + STI; + } +} + + +/* +============================================================================= + + PALETTE OPS + +============================================================================= +*/ + + +/* +================= += += VI_FillPalette += +================= +*/ + +void VI_FillPalette (int red, int green, int blue) +{ + int i; + + _outbyte (PEL_WRITE_ADR,0); + for (i=0;i<256;i++) + { + _outbyte (PEL_DATA,red); + _outbyte (PEL_DATA,green); + _outbyte (PEL_DATA,blue); + } +} + +//=========================================================================== + +/* +================= += += VI_SetColor += +================= +*/ + +void VI_SetColor (int color, int red, int green, int blue) +{ + _outbyte (PEL_WRITE_ADR,color); + _outbyte (PEL_DATA,red); + _outbyte (PEL_DATA,green); + _outbyte (PEL_DATA,blue); +} + +//=========================================================================== + +/* +================= += += VI_GetColor += +================= +*/ + +void VI_GetColor (int color, int *red, int *green, int *blue) +{ + _outbyte (PEL_READ_ADR,color); + *red = _inbyte (PEL_DATA); + *green = _inbyte (PEL_DATA); + *blue = _inbyte (PEL_DATA); +} + +//=========================================================================== + +/* +================= += += VI_SetPalette += +================= +*/ + +void VI_SetPalette (byte *palette) +{ + int i; + + _outbyte (PEL_WRITE_ADR,0); + for (i=0;i<768;i++) + _outbyte(PEL_DATA,*palette++); +} + + +//=========================================================================== + +/* +================= += += VI_GetPalette += +================= +*/ + +void VI_GetPalette (byte *palette) +{ + int i; + + _outbyte (PEL_READ_ADR,0); + for (i=0;i<768;i++) + *palette++ = _inbyte(PEL_DATA); +} + + +//=========================================================================== + +/* +================= += += VI_FadeOut += += Fades the current palette to the given color in the given number of steps += +================= +*/ + +void VI_FadeOut (int start, int end, int red, int green, int blue, int steps) +{ + byte basep[256][3],work[256][3]; + int i,j,delta; + + VI_GetPalette (&basep[0][0]); + +// +// fade through intermediate frames +// + for (i=0;iwidth; + height = pic->height; + source = &pic->data; + + dest = ylookup[y]+x; + while (height--) { + memcpy (dest,source,(size_t)width); + source += width; + dest += SCREENWIDTH; + } +} + + + +/* +================= += += VI_DrawMaskedPic += += Masks a block of main memory to the screen. += Uses orgx,orgy to offset the block += If the hot spot is inside the block shape, the offsets are positive += +================= +*/ + +void VI_DrawMaskedPic (int x, int y, pic_t *pic) +{ + byte *dest, *source; + int width,height,xcor,col; + + x -= pic->orgx; + y -= pic->orgy; + height = pic->height; + source = &pic->data; + while (y<0) { + source += pic->width; + height--; + } + while (height--) { + if (y<200) { + dest = ylookup[y]+x; + xcor = x; + width = pic->width; + while (width--) { + if ((xcor>=0)&&(xcor<=319)) { + if (*source) *dest = *source; + } + xcor++; + source++; + dest++; + } + } + y++; + } +} + +/* +================= += += VI_DrawMaskedPicToBuffer += += Masks a block of main memory to the offscreen buffer where frame is built += Uses orgx,orgy to offset the block += If the hot spot is inside the block shape, the offsets are positive += +================= +*/ + +// TML - Added 9-20-94 (allows image transfer to viewbuffer) + +void VI_DrawMaskedPicToBuffer2 (int x, int y, pic_t *pic) +{ + byte *dest,*source; + int width,height,xcor,col; + + x -= pic->orgx; + y -= pic->orgy; + height = pic->height; + source = &pic->data; + while (y<0) { + source += pic->width; + height--; + } + while (height--) { + if (y<200) { +// dest = ylookup[y]+x; // for blitting to video mem. + dest = viewbuffer+(y*MAX_VIEW_WIDTH+x); + xcor = x; + width = pic->width; + while (width--) { + if ((xcor>=0)&&(xcor<=319)) { + if (*source) *dest = *source; + } + xcor++; + source++; + dest++; + } + } + y++; + } +} + +void VI_Init (void) +{ + int y; + + for (y=0;y],[<[,]...>] +;* +;* Defines a C-callable PUBLIC procedure. Performs the following functions: +;* +;* a) Makes the name PUBLIC. +;* b) Delares a NEAR PROC. +;* c) Saves EBP. +;* d) Establishes stack frame base (EBP <- ESP). +;* e) Saves registers (if given). +;* f) Defines arguments (if given) as [ebp+?]. +;* +;* (Ex:) @Proc MyFunc, , <, > +;* @Proc MyFunc,, <> +;* +;*-------------------------------------------------------------------------- +;* @ExitP [] +;* +;* Leaves a routine previously defined using the '@Proc' macro. +;* +;* a) Cleans up local variables from stack. +;* b) Restores registers. +;* c) Restores EBP. +;* d) Returns ("ret"). +;* +;* (Ex:) @ExitP +;* +;*************************************************************************** +;* Notes: +;* +;* Every procedure defined using "@Proc" must end with "@ExitP". Do not +;* include a "ret" statement in the procedure; jump to a label just before +;* the "@ExitP" macro. +;* +;* The register list given with "@ExitP" must match EXACTLY with the list +;* given with the matching "@Proc" macro. The registers MUST ALWAYS specify +;* 32-bit registers. +;* +;* The variable "typ" may be BYTE, WORD, DWORD, or PTR. +;*************************************************************************** +@Proc MACRO name, regs, args + PUBLIC name + name PROC NEAR + @arg = 8 + @reg = 0 + @loc = 0 + push ebp + mov ebp,esp + ifnb + @Push regs + endif + + irp x, + ifnb + @DefArg x, %(@arg) + endif + endm + ENDM + + +@ExitP MACRO regs + @ClnStk %@loc + ifnb + @Pop regs + endif + pop ebp + ret + ENDM + + +;******************************************************************************* +;* @Local <[,]...> +;* +;* Used within a C-callable procedure declared using "@Proc" to define local +;* (stack) variables. +;* +;* a) Defines local variables as EQUates to [ebp - ?]. +;* +;* (Ex:) @Local <, > +;* @Local < +;* @EndLoc +;*-------------------------------------------------------------------------- +;* @EndLoc +;* +;* Must be used after the final "@Local" statement within a procedure. +;* +;* a) Reserves storage for the previously defined "@Local" variables. +;* +;******************************************************************************* +;* Notes: +;* +;* You can only use "@Local" in a procedure defined with "@Proc" and "@ExitP". +;* ("@ExitP" deallocates the stack storage reserved by "@EndLoc".) +;* +;* The variable "typ" may be BYTE, WORD, DWORD, or PTR. However, all local +;* variables reserve space as if they were DWORDs, to keep the stack DWORD- +;* aligned. +;******************************************************************************* +@Local MACRO local_list + irp x, + ifnb + @loc = @loc + 4 + @DefLoc x, %(@reg+@loc) + endif + endm + ENDM + +@EndLoc MACRO + @LocStk %@loc + ENDM + +@LocStk MACRO num_bytes + sub esp,num_bytes + ENDM + + +;****************************************************************************** +;* @Invoke name, [p1[, p2]...] +;* +;* Calls a C-callable routine with the parameters specified, if any. +;* +;* a) Repeat for all parameters given: +;* 1. Push p? (where p? is one of p10,p9..p1). +;* b) Call the function. +;* c) Clean up the stack. +;* +;* (Ex:) @Invoke Myfunc, MyParm1, MyParm2 +;* +;****************************************************************************** +;* Notes: +;* +;* All parameters are pushed as DWORD PTRs to keep the stack DWORD-aligned. +;****************************************************************************** +@ClnStk MACRO num_bytes + add esp,num_bytes + ENDM + +@Invoke MACRO name,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10 + @prm = 0 + irp x, + ifnb + @prm = @prm + 4 + push DWORD PTR x + endif + endm + call name + @ClnStk %@prm + ENDM + + +;****************************************************************************** +;* @Push +;* +;* Used by the "@Proc" macro to save the register list given. May be used if +;* desired as a shorthand for multiple DWORD push statements. +;* +;* a) Repeat for all elements given: +;* 1. Update register displacement counter (@reg). +;* 2. Push r? (where r? is one of the r1,r2..r14). +;* +;* (Ex:) @Push ebx, esi, edi +;* +;*-------------------------------------------------------------------------- +;* @Pop +;* +;* Counterpart of the above "@Push" macro. +;* +;* a) Repeat for all elements given: +;* 1. Pop r? (where r? is one of the r14,r13..r1). +;* +;* (Ex:) @Pop ebx, esi, edi +;****************************************************************************** +@Push MACRO r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14 + irp x, + ifnb + @reg = @reg + 4 + push x + endif + endm + ENDM + +@Pop MACRO r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14 + irp x, + ifnb + pop x + endif + endm + ENDM + + +;****************************************************************************** +;* @DefArg +;* +;* Used by the "@Proc" macro to setup EQUates to a procedure's arguments. Has +;* no "standalone" use. +;* +;* a) Defines variable as [ebp+?]. +;* b) Updates argument displacement counter (@arg). +;* +;* (Ex:) @DefArg MyArg1, DWORD +;****************************************************************************** +@DefArg MACRO name, typ, displ + + @val_typ = @False + ifidni , ;;Byte + @val_typ = @True + name EQU BYTE PTR [ebp + displ] + @arg = @arg + 4 + endif + + ifidni , ;;Word + @val_typ = @True + name EQU WORD PTR [ebp + displ] + @arg = @arg + 4 + endif + + ifidni , ;;DWord + @val_typ = @True + name EQU DWORD PTR [ebp + displ] + @arg = @arg + 4 + endif + + ifidni , ;;pointer + @val_typ = @True + name EQU DWORD PTR [ebp + displ] + @arg = @arg + 4 + endif + + ife @val_typ + %OUT Unknown type typ. + .ERR + endif + ENDM + + +;****************************************************************************** +;* @DefLoc name, typ +;* +;* Used by the "@Local" macro to setup EQUates to the local variables. Has +;* no "standalone" use. +;* +;* a) Update local variable displacement counter (@loc). +;* b) Define variable as [ebp-?]. +;* +;* (Ex:) @LocArg MyLoc1, DWORD +;****************************************************************************** +@DefLoc MACRO name, typ, displ + @val_typ = @False + ifidni , ;;Byte + @val_typ = @True + name EQU BYTE PTR [ebp - displ] + endif + + ifidni , ;;Word + @val_typ = @True + name EQU WORD PTR [ebp - displ] + endif + + ifidni , ;;DWord + @val_typ = @True + name EQU DWORD PTR [ebp - displ] + endif + + ifidni , ;;pointer + @val_typ = @True + name EQU DWORD PTR [ebp - displ] + endif + + ife @val_typ + %OUT Unknown type typ. + .ERR + endif + ENDM + diff --git a/SOURCE/MAKEDISK.BAT b/SOURCE/MAKEDISK.BAT new file mode 100644 index 0000000..c7002d4 --- /dev/null +++ b/SOURCE/MAKEDISK.BAT @@ -0,0 +1,3 @@ +copy todd3d.exe %1 +copy todd3d.tod %1 +copy readme. %1 diff --git a/SOURCE/MAKEFILE b/SOURCE/MAKEFILE new file mode 100644 index 0000000..bef187f --- /dev/null +++ b/SOURCE/MAKEFILE @@ -0,0 +1,29 @@ +EXE = todd3d + +AFLAGS = /mx +CFLAGS = /g /t /d2 /O3 /znoansi +LFLAGS = /g /t + +OBJS = todd3d.obj \ + r_public.obj \ + r_spans.obj \ + r_conten.obj \ + r_plane.obj \ + r_render.obj \ + r_walls.obj \ + ra_draw.obj \ + blitbuf.obj \ + d_disk.obj \ + d_ints.obj \ + d_misc.obj \ + d_video.obj + + +$(EXE): $(OBJS) + $(CC) $(LFLAGS) /m /e $(EXE) *.obj mouse.lib + +.c.obj: + $(CC) /c $(CFLAGS) /o $(.TARGET) $(.NEWER) + +.asm.obj: + tasm $(AFLAGS) $(.NEWER),$(.TARGET) diff --git a/SOURCE/MAKEIT.BAT b/SOURCE/MAKEIT.BAT new file mode 100644 index 0000000..63a59e3 --- /dev/null +++ b/SOURCE/MAKEIT.BAT @@ -0,0 +1 @@ +c:\codebldr\bin\make diff --git a/SOURCE/NEWMAKE.BAT b/SOURCE/NEWMAKE.BAT new file mode 100644 index 0000000..d3f5a12 --- /dev/null +++ b/SOURCE/NEWMAKE.BAT @@ -0,0 +1 @@ + diff --git a/SOURCE/NEW_DRAW.ASM b/SOURCE/NEW_DRAW.ASM new file mode 100644 index 0000000..e2e27e0 --- /dev/null +++ b/SOURCE/NEW_DRAW.ASM @@ -0,0 +1,474 @@ + .386 + .MODEL small + +SKIPPRIMITIVES = 0 ; set to 1 to skip unwound drawing + +INCLUDE viewsize.inc +INCLUDE macros.inc + + +SCREEN = 0a0000h +SCREENWIDTH = 320 + +PEL_WRITE_ADR = 03c8h +PEL_DATA = 03c9h + + .DATA + +EXTRN viewbuffer:WORD +EXTRN viewLocation:DWORD +EXTRN windowWidth:DWORD +EXTRN windowHeight:DWORD + + .CODE + +;============================================================================ +; +; Fixed point math +; +;============================================================================ + +@Proc FIXEDMUL, <>, <,> + mov eax,op1 + imul [op2] + shrd eax,edx,16 + @exitp <> +ENDP + +@Proc FIXEDDIV, <>, <,> + mov eax,op1 + cdq + shld edx,eax,16 + sal eax,16 + idiv [op2] +@exitp <> + +ENDP + + + +;============================================================================ +; +; RF_BlitView +; +;============================================================================ + +@Proc RF_BlitView, + + mov esi,OFFSET viewbuffer + mov edi,[viewLocation] + mov ebx,[windowHeight] + mov eax,SCREENWIDTH + sub eax,[windowWidth] + mov edx,eax + mov eax,[windowWidth] + shr eax,2 + +ALIGN 4 +@@blitloop1: + mov ecx,eax + rep movsd + add edi,edx + dec ebx + jnz @@blitloop1 + + @exitp +ENDP + + +;============================================================================ +; +; Merge +; +; merge two parts of the unsorted array to the sorted array +; +;============================================================================ + +.DATA + +EXTRN src1:DWORD +EXTRN src2:DWORD +EXTRN dest:DWORD +EXTRN size1:DWORD +EXTRN size2:DWORD + +PUBLIC mergefrom1 +PUBLIC finishfrom1 +PUBLIC mergefrom2 +PUBLIC finishfrom2 +PUBLIC mergedone + +.CODE + + @Proc Merge, + + mov ebx,[src1] + mov esi,[src2] + mov edi,[dest] + mov ecx,[size1] + mov edx,[size2] + + mov eax,[ebx] + cmp eax,[esi] + jb SHORT mergefrom2 ; if (*src1 < *src2) goto mergefrom2; + +mergefrom1: + stosd + add ebx,4 ; *dest++ = *src1++; + mov eax,[ebx] + dec ecx + jz finishfrom2 ; if (!--size1) goto finishfrom2; + cmp eax,[esi] + ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1; + +mergefrom2: + movsd ; *dest++ = *src2++; + dec edx + jz finishfrom1 ; if (!--size2) goto finishfrom1; + cmp eax,[esi] + ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1; + jmp SHORT mergefrom2 + + ALIGN 4 +finishfrom2: + movsd ; *dest++ = *src2++; + dec edx ; while (size2--) + jnz SHORT finishfrom2 + jmp SHORT mergedone + + ALIGN 4 +finishfrom1: + stosd + add ebx,4 ; *dest++ = *src1++; + mov eax,[ebx] + loop SHORT finishfrom1 ; while (size1--) + +mergedone: + mov [dest],edi + @exitp + ENDP + + +;============================================================================ +; +; unwound vertical scaling code +; +; eax light table pointer, 0 lowbyte overwritten +; ebx all 0, low byte overwritten +; ecx fractional step value +; edx fractional scale value +; esi start of source pixels +; edi bottom pixel in screenbuffer to blit into +; +; ebx should be set to 0 0 0 dh to feed the pipeline +;============================================================================ + +SCALELABEL MACRO number +vscale&number: +ENDM + +LINE = MAXWINDOWHEIGHT +REPT MAXWINDOWHEIGHT-1 + SCALELABEL %LINE + mov al,[esi+ebx] ; get source pixel + add edx,ecx ; calculate next location + mov al,[eax] ; translate the color + xor ebx,ebx + shld ebx,edx,16 ; get address of next location + mov [edi-(LINE-1)*MAXWINDOWWIDTH],al ; draw a pixel to the buffer +LINE = LINE-1 +ENDM +vscale1: + mov al,[esi+ebx] + add edx,ecx + mov al,[eax] + mov [edi],al +vscale0: + ret + + +.DATA + +SCALEDEFINE MACRO number + dd vscale&number +ENDM + + ALIGN 4 +scalecalls LABEL +LINE = 0 +REPT MAXWINDOWHEIGHT+1 + SCALEDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC scalecalls + +;================================================= + +; +; parameters for RN_ScalePost +; +sp_dest dd 0 +sp_count dd 0 +sp_fracstep dd 0 +sp_frac dd 0 +sp_source dd 0 +sp_colormap dd 0 + +PUBLIC sp_dest, sp_count, sp_fracstep, sp_frac, sp_source, sp_colormap + +.CODE + + +;================ +; +; ScalePost +; +;================ + + @Proc ScalePost, + +IFE SKIPPRIMITIVES + + mov edx,[sp_frac] + mov ecx,[sp_fracstep] + mov esi,[sp_source] + mov eax,[sp_colormap] + mov edi,[sp_dest] + xor ebx,ebx + shld ebx,edx,16 ; get address of first location + mov ebp,[sp_count] + call [scalecalls+ebp*4] + +ENDIF + + @exitp + ENDP + + +;============================================================================ +; +; unwound masked vertical scaling code +; +; eax light table pointer, 0 lowbyte overwritten +; ebx all 0, low byte overwritten +; ecx all 0, low byte overwritten +; edx fractional scale value +; esi start of source pixels +; edi bottom pixel in screenbuffer to blit into +; ebp fractional step value +; +; ebx should be set to 0 0 0 dh to feed the pipeline +;============================================================================ + +ALIGN 4 +MSCALELABEL MACRO number +mvscale&number: +ENDM + +LINE = MAXWINDOWHEIGHT +REPT MAXWINDOWHEIGHT-1 + MSCALELABEL %LINE + mov al,[esi+ebx] ; get source pixel + add edx,ebp ; calculate next location + mov cl,al ; save original color for jcxz + mov al,[eax] ; translate the color + xor ebx,ebx + shld ebx,edx,16 ; get address of next location + jcxz $+9 + mov [edi-(LINE-1)*MAXWINDOWWIDTH],al ; draw a pixel to the buffer +LINE = LINE-1 +ENDM +mvscale1: + mov al,[esi+ebx] + add edx,ecx + mov al,[eax] + test al,0 + jz mvscale0 + mov [edi],al +mvscale0: + ret + + +.DATA + +MSCALEDEFINE MACRO number + dd mvscale&number +ENDM + + ALIGN 4 +mscalecalls LABEL +LINE = 0 +REPT MAXWINDOWHEIGHT+1 + MSCALEDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC mscalecalls + +mscalecall dd 0 + +.CODE + + +;================ +; +; ScaleMaskedPost +; +; Same parameters as ScalePost, but 0 pixels are not drawn +; +;================ + + @Proc ScaleMaskedPost, + +IFE SKIPPRIMITIVES + + mov ebp,[sp_count] + mov eax,[mscalecalls+ebp*4] + mov [mscalecall],eax + + mov edx,[sp_frac] + mov ebp,[sp_fracstep] + mov esi,[sp_source] + mov eax,[sp_colormap] + mov edi,[sp_dest] + xor ebx,ebx + xor ecx,ecx + shld ebx,edx,16 ; get address of first location + call [mscalecall] + +ENDIF + + @exitp + ENDP + + +;============================================================================ +; +; unwound horizontal texture mapping code +; +; eax lighttable +; ebx xtotal 6 bits units 26 bits frac +; ecx ytotal 6 bits units 26 bits frac +; edx xstep +; esi start of block +; edi dest +; ebp scratch offset +; +; [ystep] +; +; ebp should by preset from ebx / ecx before calling +;============================================================================ + +MAPLABEL MACRO number +hmap&number: +ENDM + +LINE = MAXWINDOWWIDTH +REPT MAXWINDOWWIDTH + MAPLABEL %LINE + mov al,[esi+ebp] ; get source pixel + add ebx,edx ; xtotal += xstep + add ecx,[ystep] ; ytotal += ystep + xor ebp,ebp + mov al,[eax] ; translate color + shld ebp,ecx,6 ; shift in new y/x position + shld ebp,ebx,6 + mov [edi-(LINE-1)],al ; write pixel +LINE = LINE-1 +ENDM +hmap0: + ret + + +.DATA + +ystep dd 0 + +MAPDEFINE MACRO number + dd hmap&number +ENDM + + ALIGN 4 +mapcalls LABEL +LINE = 0 +REPT MAXWINDOWWIDTH+1 + MAPDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC mapcalls + + + +mapcall dd 0 + +; +; parameters for RN_MapLine +; +mr_dest dd 0 ; pointer to first pixel in view buffer +mr_count dd 0 +mr_picture dd 0 ; pointer to 4096 pixel block +mr_colormap dd 0 ; page aligned light table +mr_xfrac dd 0 ; 16 frac bits +mr_yfrac dd 0 ; 16 frac bits +mr_xstep dd 0 +mr_ystep dd 0 + +PUBLIC mr_dest,mr_picture,mr_colormap,mr_xfrac,mr_yfrac,mr_xstep,mr_ystep,mr_count + +.CODE + + +;================ +; +; MapRow +; +; Horizontal texture mapping +; +;================ + + +@Proc MapRow, + +IFE SKIPPRIMITIVES + + mov eax,[mr_count] + mov ebx,[mapcalls+eax*4] + mov [mapcall],ebx ; spot to jump into unwound + + mov edi,[mr_dest] + add edi,[mr_count] + dec edi + + mov eax,[mr_ystep] + shl eax,10 + mov [ystep],eax + + mov eax,[mr_colormap] + mov ebx,[mr_xfrac] + shl ebx,10 + mov ecx,[mr_yfrac] + shl ecx,10 + mov edx,[mr_xstep] + shl edx,10 + mov esi,[mr_picture] + + + xor ebp,ebp + shld ebp,ecx,6 + shld ebp,ebx,6 ; do first step for pipeline + + call [mapcall] + + shr ebx,10 + mov [mr_xfrac],ebx + shr ecx,10 + mov [mr_yfrac],ecx + +ENDIF + + @exitp +ENDP + +END diff --git a/SOURCE/Q.BAT b/SOURCE/Q.BAT new file mode 100644 index 0000000..655fa04 --- /dev/null +++ b/SOURCE/Q.BAT @@ -0,0 +1 @@ +c:\qedit\q %1 %2 %3 %4 %5 diff --git a/SOURCE/R.BAT b/SOURCE/R.BAT new file mode 100644 index 0000000..1461b56 --- /dev/null +++ b/SOURCE/R.BAT @@ -0,0 +1 @@ +todd3d diff --git a/SOURCE/RA_DRAW.ASM b/SOURCE/RA_DRAW.ASM new file mode 100644 index 0000000..84f68e9 --- /dev/null +++ b/SOURCE/RA_DRAW.ASM @@ -0,0 +1,577 @@ + .386 + .MODEL small + +SKIPPRIMITIVES = 0 ; set to 1 to skip unwound drawing + +INCLUDE viewsize.inc +INCLUDE macros.inc + + +SCREEN = 0a0000h +SCREENWIDTH = 320 + +PEL_WRITE_ADR = 03c8h +PEL_DATA = 03c9h + + .DATA + +EXTRN viewbuffer:WORD +EXTRN viewLocation:DWORD +EXTRN viewylookup;DWORD +EXTRN windowWidth:DWORD +EXTRN windowHeight:DWORD + + + .CODE + +;============================================================================ +; +; Fixed point math +; +;============================================================================ + +@Proc FIXEDMUL, <>, <,> + mov eax,op1 + imul [op2] + shrd eax,edx,16 + @exitp <> +ENDP + +@Proc FIXEDDIV, <>, <,> + mov eax,op1 + cdq + shld edx,eax,16 + sal eax,16 + idiv [op2] + endz: +@exitp <> + +ENDP + + + +;============================================================================ +; +; RF_BlitView +; +;============================================================================ + +@Proc RF_BlitView, + + mov esi,OFFSET viewbuffer + mov edi,[viewLocation] + mov ebx,[windowHeight] + mov eax,SCREENWIDTH + sub eax,[windowWidth] + mov edx,eax ; x modulos + mov eax,[windowWidth] + shr eax,2 + +ALIGN 4 +@@blitloop1: + mov ecx,eax + rep movsd + add edi,edx + dec ebx + jnz @@blitloop1 + + @exitp +ENDP + +;============================================================================ +; +; ClearViewBuffer +; +;============================================================================ + +@Proc ClearViewBuffer, + + mov ebx,[windowHeight] + mov esi,[windowWidth] + mov edx,esi + shr esi,2 + xor eax,eax + +ALIGN 4 +@@clearloop: + dec ebx + mov ecx,esi + mov edi,OFFSET viewylookup + mov edi,[edi+ebx*4] + rep stosd + add edi,edx + cmp ebx,0 + jnz @@clearloop + + @exitp +ENDP + +;============================================================================ +; +; Merge +; +; merge two parts of the unsorted array to the sorted array +; +;============================================================================ + +.DATA + +EXTRN src1:DWORD +EXTRN src2:DWORD +EXTRN dest:DWORD +EXTRN size1:DWORD +EXTRN size2:DWORD + +PUBLIC mergefrom1 +PUBLIC finishfrom1 +PUBLIC mergefrom2 +PUBLIC finishfrom2 +PUBLIC mergedone + +.CODE + + @Proc Merge, + + mov ebx,[src1] + mov esi,[src2] + mov edi,[dest] + mov ecx,[size1] + mov edx,[size2] + + mov eax,[ebx] + cmp eax,[esi] + jb SHORT mergefrom2 ; if (*src1 < *src2) goto mergefrom2; + +mergefrom1: + stosd + add ebx,4 ; *dest++ = *src1++; + mov eax,[ebx] + dec ecx + jz finishfrom2 ; if (!--size1) goto finishfrom2; + cmp eax,[esi] + ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1; + +mergefrom2: + movsd ; *dest++ = *src2++; + dec edx + jz finishfrom1 ; if (!--size2) goto finishfrom1; + cmp eax,[esi] + ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1; + jmp SHORT mergefrom2 + + ALIGN 4 +finishfrom2: + movsd ; *dest++ = *src2++; + dec edx ; while (size2--) + jnz SHORT finishfrom2 + jmp SHORT mergedone + + ALIGN 4 +finishfrom1: + stosd + add ebx,4 ; *dest++ = *src1++; + mov eax,[ebx] + loop SHORT finishfrom1 ; while (size1--) + +mergedone: + mov [dest],edi + @exitp + ENDP + + +;============================================================================ +; +; unwound vertical scaling code +; +; eax light table pointer, 0 lowbyte overwritten +; ebx all 0, low byte overwritten +; ecx fractional step value +; edx fractional scale value +; esistart of source pixels +; edi bottom pixel in screenbuffer to blit into +; +; ebx should be set to 0 0 0 dh to feed the pipeline +;============================================================================ + +; the assembler creates vscale: numbers of the following +; code segement. LINE is used as the arg to SCALELABEL. there exists +; vscale:. the value of LINE ranges from 0 to +; MAXWINDOWWIDTH. scalecalls is made visible to the other modules with the +; PUBLIC directive. + + +SCALEDEFINE MACRO number + dd vscale&number +ENDM + +ALIGN 4 +scalecalls LABEL UNKNOWN +LINE = 0 +REPT MAXWINDOWHEIGHT + 1 + SCALEDEFINE %LINE +LINE = LINE + 1 +ENDM + +scalecall dd 0 + +PUBLIC scalecalls + +;================================================= + +; +; parameters for RN_ScalePost +; +sp_dest dd 0 +sp_count dd 0 +sp_fracstep dd 0 +sp_frac dd 0 +sp_source dd 0 +sp_colormap dd 0 + +PUBLIC sp_dest, sp_count, sp_fracstep, sp_frac, sp_source, sp_colormap + +.CODE + + +;================ +; +; ScalePost +; +;================ + + @Proc ScalePost, + +IFE SKIPPRIMITIVES + + mov edx,[sp_frac] + mov ecx,[sp_fracstep] + mov esi,[sp_source] + mov eax,[sp_colormap] + mov edi,[sp_dest] + xor ebx,ebx + shld ebx,edx,16 ; get address of first location + mov ebp,[sp_count] + call [scalecalls+ebp*4] + +ENDIF + + @exitp + ENDP + +;============================================================================ + + @Proc GetScaleRoutines + + mov eax,OFFSET vscale200 + + @exitp + ENDP + +; +;============================================================================ +; +; unwound masked vertical scaling code +; +; eax light table pointer, 0 lowbyte overwritten +; ebx all 0, low byte overwritten +; ecx all 0, low byte overwritten +; edx fractional scale value +; esi start of source pixels +; edi bottom pixel in screenbuffer to blit into +; ebp fractional step value +; +; ebx should be set to 0 0 0 dh to feed the pipeline +;============================================================================ + +; the assembler creates mvscale: numbers of the following +; code segement. all sections of the code are ALINGN'ed on a 32 bit +; boundary. LINE is used as the arg to MSCALELABEL. there exists +; mvscale + +IFE SKIPPRIMITIVES + + mov ebp,[sp_count] + mov eax,[mscalecalls+ebp*4] + mov [mscalecall],eax + + mov edx,[sp_frac] + mov ebp,[sp_fracstep] + mov esi,[sp_source] + mov eax,[sp_colormap] + mov edi,[sp_dest] + xor ebx,ebx + xor ecx,ecx + shld ebx,edx,16 ; get address of first location + call [mscalecall] + +ENDIF + @exitp + ENDP + +;============================================================================ + + @Proc GetMScaleRoutines + + mov eax,OFFSET mvscale200 + + @exitp + ENDP + +;============================================================================ +; +; unwound horizontal texture mapping code +; +; eax lighttable +; ebx xtotal 6 bits units 26 bits frac +; ecx ytotal 6 bits units 26 bits frac +; edx xstep +; esi start of block +; edi dest +; ebp scratch offset +; +; [ystep] +; +; ebp should by preset from ebx / ecx before calling +;============================================================================ + +; the assembler creates hmap: numbers of the following +; code segement. all sections of the code are not ALINGN'ed on a 32 bit +; boundary. LINE is used as the arg to MAPLABEL. there exists +; hmapMAXWINDOWWIDTH: to hmap0: units of code. map0 is used as the exit +; point. + +MAPLABEL MACRO number +hmap&number: +ENDM + +LINE = MAXWINDOWWIDTH +REPT MAXWINDOWWIDTH + MAPLABEL %LINE + mov al,[esi+ebp] ; get source pixel + add ebx,edx ; xtotal += xstep + add ecx,[ystep] ; ytotal += ystep + xor ebp,ebp + mov al,[eax] ; translate color + shld ebp,ecx,6 ; shift in new y/x position + shld ebp,ebx,6 + mov [edi-(LINE-1)],al ; write pixel +LINE = LINE - 1 +ENDM +hmap0: + ret + + +.DATA + +ystep dd 0 +mapcall dd 0 + +; the following 2 macros allocate a block of dd or 4 byte locations that are +; ALIGN'ed on a 4 byte or 32 bit boundary. the starting 4 bytes may be +; referred to as mapcalls. the others may not because in the macro MAPDEFINE +; they are not given a name. the label mapcalls refers to a position in the +; code which happens to be the start of the allocated block. there are +; MAXWINDOWWIDTH + 1 4 byte word's are allocated and each word is initialized +; with the address of hmap:. the value of LINE ranges from 0 to +; MAXWINDOWWIDTH. mapcalls is made visible to the other modules with the +; PUBLIC directive. + +MAPDEFINE MACRO number + dd hmap&number +ENDM + +ALIGN 4 +mapcalls LABEL UNKNOWN +LINE = 0 +REPT MAXWINDOWWIDTH + 1 + MAPDEFINE %LINE +LINE = LINE + 1 +ENDM + +PUBLIC mapcalls + + + + +; +; parameters for RN_MapLine +; +mr_dest dd 0 ; pointer to first pixel in view buffer +mr_count dd 0 +mr_picture dd 0 ; pointer to 4096 pixel block +mr_colormap dd 0 ; page aligned light table +mr_xfrac dd 0 ; 16 frac bits +mr_yfrac dd 0 ; 16 frac bits +mr_xstep dd 0 +mr_ystep dd 0 + +PUBLIC mr_dest, mr_picture, mr_colormap, mr_xfrac +PUBLIC mr_yfrac, mr_xstep, mr_ystep, mr_count + +.CODE + + +;================ +; +; MapRow +; +; Horizontal texture mapping +; +;================ + + +@Proc MapRow, + +IFE SKIPPRIMITIVES + + mov eax,[mr_count] + mov ebx,[mapcalls+eax*4] + mov [mapcall],ebx ; spot to jump into unwound + + mov edi,[mr_dest] + add edi,[mr_count] + dec edi + + mov eax,[mr_ystep] + shl eax,10 + mov [ystep],eax + + mov eax,[mr_colormap] + mov ebx,[mr_xfrac] + shl ebx,10 + mov ecx,[mr_yfrac] + shl ecx,10 + mov edx,[mr_xstep] + shl edx,10 + mov esi,[mr_picture] + + xor ebp,ebp + shld ebp,ecx,6 + shld ebp,ebx,6 ; do first step for pipeline + + call [mapcall] + + shr ebx,10 + mov [mr_xfrac],ebx + shr ecx,10 + mov [mr_yfrac],ecx + +ENDIF + + @exitp +ENDP + +END diff --git a/SOURCE/RA_DRAW.BKP b/SOURCE/RA_DRAW.BKP new file mode 100644 index 0000000..e2e27e0 --- /dev/null +++ b/SOURCE/RA_DRAW.BKP @@ -0,0 +1,474 @@ + .386 + .MODEL small + +SKIPPRIMITIVES = 0 ; set to 1 to skip unwound drawing + +INCLUDE viewsize.inc +INCLUDE macros.inc + + +SCREEN = 0a0000h +SCREENWIDTH = 320 + +PEL_WRITE_ADR = 03c8h +PEL_DATA = 03c9h + + .DATA + +EXTRN viewbuffer:WORD +EXTRN viewLocation:DWORD +EXTRN windowWidth:DWORD +EXTRN windowHeight:DWORD + + .CODE + +;============================================================================ +; +; Fixed point math +; +;============================================================================ + +@Proc FIXEDMUL, <>, <,> + mov eax,op1 + imul [op2] + shrd eax,edx,16 + @exitp <> +ENDP + +@Proc FIXEDDIV, <>, <,> + mov eax,op1 + cdq + shld edx,eax,16 + sal eax,16 + idiv [op2] +@exitp <> + +ENDP + + + +;============================================================================ +; +; RF_BlitView +; +;============================================================================ + +@Proc RF_BlitView, + + mov esi,OFFSET viewbuffer + mov edi,[viewLocation] + mov ebx,[windowHeight] + mov eax,SCREENWIDTH + sub eax,[windowWidth] + mov edx,eax + mov eax,[windowWidth] + shr eax,2 + +ALIGN 4 +@@blitloop1: + mov ecx,eax + rep movsd + add edi,edx + dec ebx + jnz @@blitloop1 + + @exitp +ENDP + + +;============================================================================ +; +; Merge +; +; merge two parts of the unsorted array to the sorted array +; +;============================================================================ + +.DATA + +EXTRN src1:DWORD +EXTRN src2:DWORD +EXTRN dest:DWORD +EXTRN size1:DWORD +EXTRN size2:DWORD + +PUBLIC mergefrom1 +PUBLIC finishfrom1 +PUBLIC mergefrom2 +PUBLIC finishfrom2 +PUBLIC mergedone + +.CODE + + @Proc Merge, + + mov ebx,[src1] + mov esi,[src2] + mov edi,[dest] + mov ecx,[size1] + mov edx,[size2] + + mov eax,[ebx] + cmp eax,[esi] + jb SHORT mergefrom2 ; if (*src1 < *src2) goto mergefrom2; + +mergefrom1: + stosd + add ebx,4 ; *dest++ = *src1++; + mov eax,[ebx] + dec ecx + jz finishfrom2 ; if (!--size1) goto finishfrom2; + cmp eax,[esi] + ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1; + +mergefrom2: + movsd ; *dest++ = *src2++; + dec edx + jz finishfrom1 ; if (!--size2) goto finishfrom1; + cmp eax,[esi] + ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1; + jmp SHORT mergefrom2 + + ALIGN 4 +finishfrom2: + movsd ; *dest++ = *src2++; + dec edx ; while (size2--) + jnz SHORT finishfrom2 + jmp SHORT mergedone + + ALIGN 4 +finishfrom1: + stosd + add ebx,4 ; *dest++ = *src1++; + mov eax,[ebx] + loop SHORT finishfrom1 ; while (size1--) + +mergedone: + mov [dest],edi + @exitp + ENDP + + +;============================================================================ +; +; unwound vertical scaling code +; +; eax light table pointer, 0 lowbyte overwritten +; ebx all 0, low byte overwritten +; ecx fractional step value +; edx fractional scale value +; esi start of source pixels +; edi bottom pixel in screenbuffer to blit into +; +; ebx should be set to 0 0 0 dh to feed the pipeline +;============================================================================ + +SCALELABEL MACRO number +vscale&number: +ENDM + +LINE = MAXWINDOWHEIGHT +REPT MAXWINDOWHEIGHT-1 + SCALELABEL %LINE + mov al,[esi+ebx] ; get source pixel + add edx,ecx ; calculate next location + mov al,[eax] ; translate the color + xor ebx,ebx + shld ebx,edx,16 ; get address of next location + mov [edi-(LINE-1)*MAXWINDOWWIDTH],al ; draw a pixel to the buffer +LINE = LINE-1 +ENDM +vscale1: + mov al,[esi+ebx] + add edx,ecx + mov al,[eax] + mov [edi],al +vscale0: + ret + + +.DATA + +SCALEDEFINE MACRO number + dd vscale&number +ENDM + + ALIGN 4 +scalecalls LABEL +LINE = 0 +REPT MAXWINDOWHEIGHT+1 + SCALEDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC scalecalls + +;================================================= + +; +; parameters for RN_ScalePost +; +sp_dest dd 0 +sp_count dd 0 +sp_fracstep dd 0 +sp_frac dd 0 +sp_source dd 0 +sp_colormap dd 0 + +PUBLIC sp_dest, sp_count, sp_fracstep, sp_frac, sp_source, sp_colormap + +.CODE + + +;================ +; +; ScalePost +; +;================ + + @Proc ScalePost, + +IFE SKIPPRIMITIVES + + mov edx,[sp_frac] + mov ecx,[sp_fracstep] + mov esi,[sp_source] + mov eax,[sp_colormap] + mov edi,[sp_dest] + xor ebx,ebx + shld ebx,edx,16 ; get address of first location + mov ebp,[sp_count] + call [scalecalls+ebp*4] + +ENDIF + + @exitp + ENDP + + +;============================================================================ +; +; unwound masked vertical scaling code +; +; eax light table pointer, 0 lowbyte overwritten +; ebx all 0, low byte overwritten +; ecx all 0, low byte overwritten +; edx fractional scale value +; esi start of source pixels +; edi bottom pixel in screenbuffer to blit into +; ebp fractional step value +; +; ebx should be set to 0 0 0 dh to feed the pipeline +;============================================================================ + +ALIGN 4 +MSCALELABEL MACRO number +mvscale&number: +ENDM + +LINE = MAXWINDOWHEIGHT +REPT MAXWINDOWHEIGHT-1 + MSCALELABEL %LINE + mov al,[esi+ebx] ; get source pixel + add edx,ebp ; calculate next location + mov cl,al ; save original color for jcxz + mov al,[eax] ; translate the color + xor ebx,ebx + shld ebx,edx,16 ; get address of next location + jcxz $+9 + mov [edi-(LINE-1)*MAXWINDOWWIDTH],al ; draw a pixel to the buffer +LINE = LINE-1 +ENDM +mvscale1: + mov al,[esi+ebx] + add edx,ecx + mov al,[eax] + test al,0 + jz mvscale0 + mov [edi],al +mvscale0: + ret + + +.DATA + +MSCALEDEFINE MACRO number + dd mvscale&number +ENDM + + ALIGN 4 +mscalecalls LABEL +LINE = 0 +REPT MAXWINDOWHEIGHT+1 + MSCALEDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC mscalecalls + +mscalecall dd 0 + +.CODE + + +;================ +; +; ScaleMaskedPost +; +; Same parameters as ScalePost, but 0 pixels are not drawn +; +;================ + + @Proc ScaleMaskedPost, + +IFE SKIPPRIMITIVES + + mov ebp,[sp_count] + mov eax,[mscalecalls+ebp*4] + mov [mscalecall],eax + + mov edx,[sp_frac] + mov ebp,[sp_fracstep] + mov esi,[sp_source] + mov eax,[sp_colormap] + mov edi,[sp_dest] + xor ebx,ebx + xor ecx,ecx + shld ebx,edx,16 ; get address of first location + call [mscalecall] + +ENDIF + + @exitp + ENDP + + +;============================================================================ +; +; unwound horizontal texture mapping code +; +; eax lighttable +; ebx xtotal 6 bits units 26 bits frac +; ecx ytotal 6 bits units 26 bits frac +; edx xstep +; esi start of block +; edi dest +; ebp scratch offset +; +; [ystep] +; +; ebp should by preset from ebx / ecx before calling +;============================================================================ + +MAPLABEL MACRO number +hmap&number: +ENDM + +LINE = MAXWINDOWWIDTH +REPT MAXWINDOWWIDTH + MAPLABEL %LINE + mov al,[esi+ebp] ; get source pixel + add ebx,edx ; xtotal += xstep + add ecx,[ystep] ; ytotal += ystep + xor ebp,ebp + mov al,[eax] ; translate color + shld ebp,ecx,6 ; shift in new y/x position + shld ebp,ebx,6 + mov [edi-(LINE-1)],al ; write pixel +LINE = LINE-1 +ENDM +hmap0: + ret + + +.DATA + +ystep dd 0 + +MAPDEFINE MACRO number + dd hmap&number +ENDM + + ALIGN 4 +mapcalls LABEL +LINE = 0 +REPT MAXWINDOWWIDTH+1 + MAPDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC mapcalls + + + +mapcall dd 0 + +; +; parameters for RN_MapLine +; +mr_dest dd 0 ; pointer to first pixel in view buffer +mr_count dd 0 +mr_picture dd 0 ; pointer to 4096 pixel block +mr_colormap dd 0 ; page aligned light table +mr_xfrac dd 0 ; 16 frac bits +mr_yfrac dd 0 ; 16 frac bits +mr_xstep dd 0 +mr_ystep dd 0 + +PUBLIC mr_dest,mr_picture,mr_colormap,mr_xfrac,mr_yfrac,mr_xstep,mr_ystep,mr_count + +.CODE + + +;================ +; +; MapRow +; +; Horizontal texture mapping +; +;================ + + +@Proc MapRow, + +IFE SKIPPRIMITIVES + + mov eax,[mr_count] + mov ebx,[mapcalls+eax*4] + mov [mapcall],ebx ; spot to jump into unwound + + mov edi,[mr_dest] + add edi,[mr_count] + dec edi + + mov eax,[mr_ystep] + shl eax,10 + mov [ystep],eax + + mov eax,[mr_colormap] + mov ebx,[mr_xfrac] + shl ebx,10 + mov ecx,[mr_yfrac] + shl ecx,10 + mov edx,[mr_xstep] + shl edx,10 + mov esi,[mr_picture] + + + xor ebp,ebp + shld ebp,ecx,6 + shld ebp,ebx,6 ; do first step for pipeline + + call [mapcall] + + shr ebx,10 + mov [mr_xfrac],ebx + shr ecx,10 + mov [mr_yfrac],ecx + +ENDIF + + @exitp +ENDP + +END diff --git a/SOURCE/RA_DRAW.ORG b/SOURCE/RA_DRAW.ORG new file mode 100644 index 0000000..e2e27e0 --- /dev/null +++ b/SOURCE/RA_DRAW.ORG @@ -0,0 +1,474 @@ + .386 + .MODEL small + +SKIPPRIMITIVES = 0 ; set to 1 to skip unwound drawing + +INCLUDE viewsize.inc +INCLUDE macros.inc + + +SCREEN = 0a0000h +SCREENWIDTH = 320 + +PEL_WRITE_ADR = 03c8h +PEL_DATA = 03c9h + + .DATA + +EXTRN viewbuffer:WORD +EXTRN viewLocation:DWORD +EXTRN windowWidth:DWORD +EXTRN windowHeight:DWORD + + .CODE + +;============================================================================ +; +; Fixed point math +; +;============================================================================ + +@Proc FIXEDMUL, <>, <,> + mov eax,op1 + imul [op2] + shrd eax,edx,16 + @exitp <> +ENDP + +@Proc FIXEDDIV, <>, <,> + mov eax,op1 + cdq + shld edx,eax,16 + sal eax,16 + idiv [op2] +@exitp <> + +ENDP + + + +;============================================================================ +; +; RF_BlitView +; +;============================================================================ + +@Proc RF_BlitView, + + mov esi,OFFSET viewbuffer + mov edi,[viewLocation] + mov ebx,[windowHeight] + mov eax,SCREENWIDTH + sub eax,[windowWidth] + mov edx,eax + mov eax,[windowWidth] + shr eax,2 + +ALIGN 4 +@@blitloop1: + mov ecx,eax + rep movsd + add edi,edx + dec ebx + jnz @@blitloop1 + + @exitp +ENDP + + +;============================================================================ +; +; Merge +; +; merge two parts of the unsorted array to the sorted array +; +;============================================================================ + +.DATA + +EXTRN src1:DWORD +EXTRN src2:DWORD +EXTRN dest:DWORD +EXTRN size1:DWORD +EXTRN size2:DWORD + +PUBLIC mergefrom1 +PUBLIC finishfrom1 +PUBLIC mergefrom2 +PUBLIC finishfrom2 +PUBLIC mergedone + +.CODE + + @Proc Merge, + + mov ebx,[src1] + mov esi,[src2] + mov edi,[dest] + mov ecx,[size1] + mov edx,[size2] + + mov eax,[ebx] + cmp eax,[esi] + jb SHORT mergefrom2 ; if (*src1 < *src2) goto mergefrom2; + +mergefrom1: + stosd + add ebx,4 ; *dest++ = *src1++; + mov eax,[ebx] + dec ecx + jz finishfrom2 ; if (!--size1) goto finishfrom2; + cmp eax,[esi] + ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1; + +mergefrom2: + movsd ; *dest++ = *src2++; + dec edx + jz finishfrom1 ; if (!--size2) goto finishfrom1; + cmp eax,[esi] + ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1; + jmp SHORT mergefrom2 + + ALIGN 4 +finishfrom2: + movsd ; *dest++ = *src2++; + dec edx ; while (size2--) + jnz SHORT finishfrom2 + jmp SHORT mergedone + + ALIGN 4 +finishfrom1: + stosd + add ebx,4 ; *dest++ = *src1++; + mov eax,[ebx] + loop SHORT finishfrom1 ; while (size1--) + +mergedone: + mov [dest],edi + @exitp + ENDP + + +;============================================================================ +; +; unwound vertical scaling code +; +; eax light table pointer, 0 lowbyte overwritten +; ebx all 0, low byte overwritten +; ecx fractional step value +; edx fractional scale value +; esi start of source pixels +; edi bottom pixel in screenbuffer to blit into +; +; ebx should be set to 0 0 0 dh to feed the pipeline +;============================================================================ + +SCALELABEL MACRO number +vscale&number: +ENDM + +LINE = MAXWINDOWHEIGHT +REPT MAXWINDOWHEIGHT-1 + SCALELABEL %LINE + mov al,[esi+ebx] ; get source pixel + add edx,ecx ; calculate next location + mov al,[eax] ; translate the color + xor ebx,ebx + shld ebx,edx,16 ; get address of next location + mov [edi-(LINE-1)*MAXWINDOWWIDTH],al ; draw a pixel to the buffer +LINE = LINE-1 +ENDM +vscale1: + mov al,[esi+ebx] + add edx,ecx + mov al,[eax] + mov [edi],al +vscale0: + ret + + +.DATA + +SCALEDEFINE MACRO number + dd vscale&number +ENDM + + ALIGN 4 +scalecalls LABEL +LINE = 0 +REPT MAXWINDOWHEIGHT+1 + SCALEDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC scalecalls + +;================================================= + +; +; parameters for RN_ScalePost +; +sp_dest dd 0 +sp_count dd 0 +sp_fracstep dd 0 +sp_frac dd 0 +sp_source dd 0 +sp_colormap dd 0 + +PUBLIC sp_dest, sp_count, sp_fracstep, sp_frac, sp_source, sp_colormap + +.CODE + + +;================ +; +; ScalePost +; +;================ + + @Proc ScalePost, + +IFE SKIPPRIMITIVES + + mov edx,[sp_frac] + mov ecx,[sp_fracstep] + mov esi,[sp_source] + mov eax,[sp_colormap] + mov edi,[sp_dest] + xor ebx,ebx + shld ebx,edx,16 ; get address of first location + mov ebp,[sp_count] + call [scalecalls+ebp*4] + +ENDIF + + @exitp + ENDP + + +;============================================================================ +; +; unwound masked vertical scaling code +; +; eax light table pointer, 0 lowbyte overwritten +; ebx all 0, low byte overwritten +; ecx all 0, low byte overwritten +; edx fractional scale value +; esi start of source pixels +; edi bottom pixel in screenbuffer to blit into +; ebp fractional step value +; +; ebx should be set to 0 0 0 dh to feed the pipeline +;============================================================================ + +ALIGN 4 +MSCALELABEL MACRO number +mvscale&number: +ENDM + +LINE = MAXWINDOWHEIGHT +REPT MAXWINDOWHEIGHT-1 + MSCALELABEL %LINE + mov al,[esi+ebx] ; get source pixel + add edx,ebp ; calculate next location + mov cl,al ; save original color for jcxz + mov al,[eax] ; translate the color + xor ebx,ebx + shld ebx,edx,16 ; get address of next location + jcxz $+9 + mov [edi-(LINE-1)*MAXWINDOWWIDTH],al ; draw a pixel to the buffer +LINE = LINE-1 +ENDM +mvscale1: + mov al,[esi+ebx] + add edx,ecx + mov al,[eax] + test al,0 + jz mvscale0 + mov [edi],al +mvscale0: + ret + + +.DATA + +MSCALEDEFINE MACRO number + dd mvscale&number +ENDM + + ALIGN 4 +mscalecalls LABEL +LINE = 0 +REPT MAXWINDOWHEIGHT+1 + MSCALEDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC mscalecalls + +mscalecall dd 0 + +.CODE + + +;================ +; +; ScaleMaskedPost +; +; Same parameters as ScalePost, but 0 pixels are not drawn +; +;================ + + @Proc ScaleMaskedPost, + +IFE SKIPPRIMITIVES + + mov ebp,[sp_count] + mov eax,[mscalecalls+ebp*4] + mov [mscalecall],eax + + mov edx,[sp_frac] + mov ebp,[sp_fracstep] + mov esi,[sp_source] + mov eax,[sp_colormap] + mov edi,[sp_dest] + xor ebx,ebx + xor ecx,ecx + shld ebx,edx,16 ; get address of first location + call [mscalecall] + +ENDIF + + @exitp + ENDP + + +;============================================================================ +; +; unwound horizontal texture mapping code +; +; eax lighttable +; ebx xtotal 6 bits units 26 bits frac +; ecx ytotal 6 bits units 26 bits frac +; edx xstep +; esi start of block +; edi dest +; ebp scratch offset +; +; [ystep] +; +; ebp should by preset from ebx / ecx before calling +;============================================================================ + +MAPLABEL MACRO number +hmap&number: +ENDM + +LINE = MAXWINDOWWIDTH +REPT MAXWINDOWWIDTH + MAPLABEL %LINE + mov al,[esi+ebp] ; get source pixel + add ebx,edx ; xtotal += xstep + add ecx,[ystep] ; ytotal += ystep + xor ebp,ebp + mov al,[eax] ; translate color + shld ebp,ecx,6 ; shift in new y/x position + shld ebp,ebx,6 + mov [edi-(LINE-1)],al ; write pixel +LINE = LINE-1 +ENDM +hmap0: + ret + + +.DATA + +ystep dd 0 + +MAPDEFINE MACRO number + dd hmap&number +ENDM + + ALIGN 4 +mapcalls LABEL +LINE = 0 +REPT MAXWINDOWWIDTH+1 + MAPDEFINE %LINE +LINE = LINE+1 +ENDM + +PUBLIC mapcalls + + + +mapcall dd 0 + +; +; parameters for RN_MapLine +; +mr_dest dd 0 ; pointer to first pixel in view buffer +mr_count dd 0 +mr_picture dd 0 ; pointer to 4096 pixel block +mr_colormap dd 0 ; page aligned light table +mr_xfrac dd 0 ; 16 frac bits +mr_yfrac dd 0 ; 16 frac bits +mr_xstep dd 0 +mr_ystep dd 0 + +PUBLIC mr_dest,mr_picture,mr_colormap,mr_xfrac,mr_yfrac,mr_xstep,mr_ystep,mr_count + +.CODE + + +;================ +; +; MapRow +; +; Horizontal texture mapping +; +;================ + + +@Proc MapRow, + +IFE SKIPPRIMITIVES + + mov eax,[mr_count] + mov ebx,[mapcalls+eax*4] + mov [mapcall],ebx ; spot to jump into unwound + + mov edi,[mr_dest] + add edi,[mr_count] + dec edi + + mov eax,[mr_ystep] + shl eax,10 + mov [ystep],eax + + mov eax,[mr_colormap] + mov ebx,[mr_xfrac] + shl ebx,10 + mov ecx,[mr_yfrac] + shl ecx,10 + mov edx,[mr_xstep] + shl edx,10 + mov esi,[mr_picture] + + + xor ebp,ebp + shld ebp,ecx,6 + shld ebp,ebx,6 ; do first step for pipeline + + call [mapcall] + + shr ebx,10 + mov [mr_xfrac],ebx + shr ecx,10 + mov [mr_yfrac],ecx + +ENDIF + + @exitp +ENDP + +END diff --git a/SOURCE/R_CONTEN.C b/SOURCE/R_CONTEN.C new file mode 100644 index 0000000..3de1d68 --- /dev/null +++ b/SOURCE/R_CONTEN.C @@ -0,0 +1,402 @@ +// R_conten.c +#include "D_global.h" +#include "d_disk.h" +#include "R_refdef.h" +#include "d_misc.h" +#include "d_ints.h" + +#define MINDIST (FRACUNIT*4) +#define PLAYERSIZE MINDIST // almost a half tile +#define FRACTILESHIFT (FRACBITS+TILESHIFT) + +scaleobj_t firstscaleobj, lastscaleobj; // just placeholders for links +scaleobj_t scaleobjlist[MAXSPRITES], *freescaleobj_p; + +doorobj_t doorlist[MAXDOORS]; +int numdoors; + +int doorxl, doorxh; + +void DrawDoor(void); + +//============================================================ + +/* */ +/*================== */ +/*= */ +/*= TransformPoint */ +/*= */ +/*= Returns a vertex pointer, but the only fields filled in are */ +/*= tx, tz, and px (if tz >= MINZ) */ +/*= */ +/*================== */ +/* */ + +vertex_t *TransformPoint(fixed_t x, fixed_t y) +{ + fixed_t trx, try; + fixed_t gxt, gyt; + fixed_t scale; + vertex_t *point; + + point=vertexlist_p++; +#ifdef VALIDATE + if (point>=&vertexlist[MAXVISVERTEXES]) + MS_Error("TransformPoint: Vertexlist overflow"); +#endif + trx=x-viewx; + try=y-viewy; + + gxt=FIXEDMUL(trx, viewsin); + gyt=FIXEDMUL(try, viewcos); + point->tx=gyt+gxt; + + gxt=FIXEDMUL(trx, viewcos); + gyt=FIXEDMUL(try, viewsin); + point->tz=gxt-gyt; + + if (point->tz>=MINZ) { + scale=FIXEDDIV(SCALE, point->tz); + point->px=CENTERX+(FIXEDMUL(point->tx, scale)>>FRACBITS); + } + return point; +} + +/* */ +/*================== */ +/*= */ +/*= ClipDoor */ +/*= */ +/*= Sets p1->px and p2->px correctly for Z values < MINZ */ +/*= */ +/*= Returns false if entire door is too close or far away */ +/*= */ +/*================== */ +/* */ + +boolean ClipDoor(void) +{ + fixed_t frac, clip; + + if (p1->tz>MAXZ&&p2->tz>MAXZ) + return false; // entire face is too far away + + if (p1->tz<0&&p2->tz<0) + return false; // totally behind the projection plane + + if (p1->tztz==0) + clip=p1->tx; + else { + frac=FIXEDDIV(p2->tz, (p2->tz-p1->tz)); + clip=p2->tx+FIXEDMUL((p1->tx-p2->tx), frac); + } + p1->px=clip<0?0:windowWidth; + } + else if (p2->tztz==0) + clip=p2->tx; + else { + frac=FIXEDDIV(p1->tz, (p1->tz-p2->tz)); + clip=p1->tx+FIXEDMUL((p2->tx-p1->tx), frac); + } + p2->px=clip<0?0:windowWidth; + } + return true; +} + +/* */ +/*=============== */ +/*= */ +/*= RenderDoor */ +/*= */ +/*= Posts one pixel wide span events for each visible post of the door a*/ +/*= tilex / tiley / xclipl / xcliph */ +/*= */ +/*= sets doorxl, doorxh based on the position of the door. One of the t*/ +/*= in the tile bounds, the other will be off the edge of the view. The*/ +/*= restrict the flowing into other tiles bounds. */ +/*= */ +/*=============== */ +/* */ + +void RenderDoor(fixed_t playerx, fixed_t playery) +{ + doorobj_t *door_p, *last_p; + fixed_t tx, ty; + byte **postindex; // start of the 64 entry texture table for t + fixed_t pointz; // transformed distance to wall post + fixed_t anglecos; + fixed_t ceilingheight; // top of the wall + fixed_t floorheight; // bottom of the wall + int angle; // the ray angle that strikes the current po + int texture; // 0-63 post number + int x, x1, x2; // collumn and ranges + fixed_t px,py; // player position + span_t *span_p; + unsigned span; + fixed_t distance, absdistance; + int baseangle; + fixed_t textureadjust; // the amount the texture p1ane is shifted + spanobj_t spantype; + + // scan the doorlist for matching tilex/tiley + // this only happens a couple times / frame max, so it's not a big d + last_p=&doorlist[numdoors]; + + for (door_p=doorlist; ; door_p++) { + if (door_p==last_p) + MS_Error("RenderDoor: Door not located"); + + if (door_p->tilex==tilex&&door_p->tiley==tiley) + break; + } + walltype=door_p->pic; + + // + // transform both endpoints of the door + // p1 is the anchored point, p2 is the moveable point + // + tx=tilex<<(TILESHIFT+FRACBITS); + ty=tiley<<(TILESHIFT+FRACBITS); + + px = (int)((playerx) >> FRACTILESHIFT); + py = (int)((playery) >> FRACTILESHIFT); + + switch (door_p->orientation) { + case dr_horizontal: + ty+=FRACUNIT *32; + p1=TransformPoint(tx, ty); + p2=TransformPoint(tx+door_p->position, ty); + textureadjust=viewx+FRACUNIT *TILESIZE-(tx+door_p->position); + baseangle=TANANGLES *2; + distance=viewy-ty; + break; + case dr_vertical: + tx+=FRACUNIT *32; + p1=TransformPoint(tx, ty); + p2=TransformPoint(tx, ty+door_p->position); + textureadjust=viewy+FRACUNIT *TILESIZE-(ty+door_p->position); + baseangle=TANANGLES; + distance=tx-viewx; + break; + } + + if (!door_p->position||!ClipDoor()) { + doorxl=windowWidth+1; + doorxh=-1; + return; + } + if (p1->pxpx) { + doorxl=p1->px; + doorxh=p2->px-1; + x1=p1->px; + x2=p2->px; + } + else { + doorxl=p2->px; + doorxh=p1->px-1; + x1=p2->px; + x2=p1->px; + } + // + // calculate the textures to post into the span list + // + if (x1xcliph+1) + x2=xcliph+1; + if (x1>x2) + return; // totally clipped off side + + // + // set up for loop + // + if (door_p->transparent) + { + spantype=sp_maskeddoor; + doortile = false; + } + else + spantype=sp_door; + + ceilingheight=vertex[0]->ceilingheight; + floorheight=-vertex[0]->floorheight; + +#ifdef VALIDATE + if (walltype>=numwalls) + MS_Error("DrawDoor: Invalid source walltype"); +#endif + walltype=walltranslation[walltype]; // global animation +#ifdef VALIDATE + if (walltype>=numwalls) + MS_Error("DrawDoor: Invalid translated walltype"); +#endif + walltype--; // make 0 based + postindex=wallposts+(walltype<<6); // 64 pointers to texture starts + baseangle+=viewfineangle; + + absdistance=distance<0?-distance : distance; + + // + // step through the individual posts + // + for (x=x1; x>FRACBITS; + texture&=63; + sp_source=postindex[texture]; + + // + // the z distance of the post hit = walldistance*cos(screenangle + // + anglecos=cosines[(angle-TANANGLES)&(TANANGLES *4-1)]; + pointz=FIXEDDIV(absdistance, anglecos); + pointz=FIXEDMUL(pointz, pixelcosine[x]); + + if (pointz>MAXZ||pointzspantype=spantype; + span_p->picture=sp_source; + span_p->y=ceilingheight; + span_p->yh=floorheight; + + span_p->structure=door_p; + + numspans++; + + } +} + +//=========================================================== + +/* */ +/*=============== */ +/*= */ +/*= RenderSprites */ +/*= */ +/*= For each sprite, if the sprite's bounding rect touches a tile with a*/ +/*= vertex, transform and clip the projected view rect. If still visibl*/ +/*= a span into the span list */ +/*= */ +/*=============== */ +/* */ + +void RenderSprites(fixed_t x, fixed_t y, fixed_t z, int angle, byte showBlast) +{ + scaleobj_t *sprite; + fixed_t deltax, deltay; + fixed_t pointx, pointz; + fixed_t gxt, gyt; + int picnum; + unsigned span; + span_t *span_p; + byte animationGraphic; + byte animationMax; + byte animationDelay; + + for (sprite=firstscaleobj.next; sprite!=&lastscaleobj; + sprite=sprite->next) + { + deltax=sprite->x-viewx; + if (deltax<-MAXZ||deltax>MAXZ) + continue; + deltay=sprite->y-viewy; + if (deltay<-MAXZ||deltay>MAXZ) + continue; + + // + // transform the point + // + gxt=FIXEDMUL(deltax, viewsin); + gyt=FIXEDMUL(deltay, viewcos); + pointx=gyt+gxt; + + gxt=FIXEDMUL(deltax, viewcos); + gyt=FIXEDMUL(deltay, viewsin); + pointz=gxt-gyt; + + if (pointzMAXZ) + continue; + + // + // calculate which image to display + // + picnum=sprite->basepic; + if (sprite->rotate) { // this is only aproximate, but ok for 8 + if (sprite->rotate == rt_eight) + picnum+=((viewangle-sprite->angle+0x90)>>5)&7; + else + picnum+=((viewangle-sprite->angle+0x90)>>5)&3; + } + // TML 9-24-94 + // okay to animate sprites here because we don't need to unless + // the player can see them (they only need to move when out of + // sight) + + if ((sprite->animation) && + (timecount > sprite->animationTime)) + { + animationGraphic = (sprite->animation & ANIM_CG_MASK) >> 1; + animationMax = (sprite->animation & ANIM_MG_MASK) >> 5; + animationDelay = (sprite->animation & ANIM_DELAY_MASK) >> 9; + + if (animationGraphic < animationMax-1) + animationGraphic++; + else if (sprite->animation & ANIM_LOOP_MASK) + animationGraphic = 0; + + picnum+=animationGraphic; + + sprite->animation = (sprite->animation & ANIM_LOOP_MASK) + + (animationGraphic << 1) + + (animationMax << 5) + + (animationDelay << 9); + + sprite->animationTime = timecount + animationDelay; + } + +#ifdef VALIDATE +/* + if (picnum>=numsprites) + MS_Error("RenderSprites: picnum > numsprites"); +*/ +#endif + + // + // post the span event + // +#ifdef VALIDATE + if (numspans==MAXSPANS) + MS_Error("MAXSPANS exceeded"); +#endif + span=(pointz<spantype=sp_shape; + span_p->picture=lumpmain[picnum]; + span_p->x2=pointx; + span_p->y=sprite->z-viewz; + span_p->structure=sprite; + + numspans++; + } +} diff --git a/SOURCE/R_DRAW.C b/SOURCE/R_DRAW.C new file mode 100644 index 0000000..f41bd6c --- /dev/null +++ b/SOURCE/R_DRAW.C @@ -0,0 +1,133 @@ +// R_draw.c + +#include +#include "D_global.h" +#include "R_refdef.h" + +/* */ +/*==================== */ +/*= */ +/*= ScalePost */ +/*= */ +/*= Primitive scaling operation, coordinates must be clipped */ +/*= */ +/*= Imp1emented on the IBM by jumping into an unwound loop */ +/*= The destination address is the BOTTOM pixel, but the texture start i*/ +/*= pixel (bottom+1-count) */ +/*= */ +/*==================== */ +/* */ + +byte *sp_dest; // the bottom most pixel to be drawn (in vie +byte *sp_source; // the first pixel in the vertical post (may +byte *sp_colormap; // pointer to a 256 byte color number to pal +int sp_frac; // fixed point location past sp_source +int sp_fracstep; // fixed point step value +int sp_count; // the number of pixels to draw + +void ScalePost(void) +{ + //return; // debug +#ifdef VALIDATE + if (sp_count<1) + MS_Error("sp_count < 1"); + + if (sp_dest>(viewbuffer+windowWidth*windowHeight)) + MS_Error("sp_dest > viewbuffer+windowWidth*windowHeight"); +#endif + sp_dest -= windowWidth*(sp_count-1); // go to the top + +#ifdef VALIDATE + if (sp_dest viewbuffer"); +#endif + while (sp_count--) { + *sp_dest=sp_colormap[sp_source[sp_frac>>FRACBITS]]; + sp_dest += windowWidth; + sp_frac += sp_fracstep; + } +} + +/* */ +/*==================== */ +/*= */ +/*= ScaleMaskedPost */ +/*= */ +/*= Primitive scaling operation, coordinates must be clipped */ +/*= */ +/*= Imp1emented on the IBM by jumping into an unwound loop */ +/*= The destination address is the BOTTOM pixel, but the texture start i*/ +/*= pixel (bottom+1-count) */ +/*= */ +/*==================== */ +/* */ + +void ScaleMaskedPost(void) +{ + pixel_t color; + +#ifdef VALIDATE + if (sp_count<1) + MS_Error("sp_count < 1"); + + if (sp_dest>(viewbuffer+windowWidth*windowHeight) + MS_Error("sp_dest > viewbuffer+windowWidth*windowHeight"); +#endif + sp_dest -= windowWidth*(sp_count-1); // go to the top + +#ifdef VALIDATE + if (sp_dest viewbuffer"); +#endif + while (sp_count--) { + color=sp_source[sp_frac>>FRACBITS]; + if (color) + *sp_dest=sp_colormap[color]; + sp_dest += windowWidth; + sp_frac += sp_fracstep; + } +} + +/* */ +/*==================== */ +/*= */ +/*= MapRow */ +/*= */ +/*= Primitive scaling operation, coordinates must be clipped */ +/*= */ +/*= The destination address and texture spot are for the */ +/*= leftmost (first) pixel */ +/*= */ +/*==================== */ +/* */ + +byte *mr_dest; // the left most pixel to be drawn (in viewb +byte *mr_picture; // pointer to a raw 64*64 pixel picture +byte *mr_colormap; // pointer to a 256 byte color number to pal +int mr_xfrac; // starting texture coordinate +int mr_yfrac; // starting texture coordinate +int mr_xstep; // fixed point step value +int mr_ystep; // fixed point step value +int mr_count; // the number of pixels to draw + +void MapRow(void) +{ + int spot; + //return; // debug + +#ifdef VALIDATE + if (mr_count<1) + MS_Error("mr_count < 1"); + + if (!mr_colormap) + return; + if ((mr_destviewbuffer+windowSize)) + MS_Error("bad destination for MapRow"); +#endif + while (mr_count--) { + spot=((mr_yfrac>>(FRACBITS-6))&(63*64))+((mr_xfrac>>FRACBITS)&63); + *mr_dest++=mr_colormap[mr_picture[spot]]; + mr_xfrac+=mr_xstep; + mr_yfrac+=mr_ystep; + } +} diff --git a/SOURCE/R_PLANE.C b/SOURCE/R_PLANE.C new file mode 100644 index 0000000..67c385f --- /dev/null +++ b/SOURCE/R_PLANE.C @@ -0,0 +1,619 @@ +// R_plane.c +#include +#include +#include "D_global.h" +#include "d_disk.h" +#include "R_refdef.h" +int backvertex; // the farthest vertex in a tile, whcih is t + +int ceilingbit; // set to CEILINGBIT when on ceiling, else 0 + +int mr_y, mr_x1, mr_x2; // used by mapplane to calculate texture end +fixed_t mr_deltaheight; // + +fixed_t mapcache_height[MAX_VIEW_HEIGHT]; +fixed_t mapcache_pointz[MAX_VIEW_HEIGHT]; + +// +// vertexes for drawable polygon +// +int numvertex; +int vertexy[10]; +int vertexx[10]; + +// +// vertexes in need of Z clipping +// +clippoint_t vertexpt[10]; + +// +// coefficients of the plane equation for sloping polygons +// +fixed_t planeA, planeB, planeC, planeD; + +#define COPYFLOOR(s,d) \ +vertexpt[d].tx = vertex[s]->tx; \ +vertexpt[d].ty = vertex[s]->floorheight; \ +vertexpt[d].tz = vertex[s]->tz; \ +vertexpt[d].px = vertex[s]->px; \ +vertexpt[d].py = vertex[s]->floory; + +#define COPYCEILING(s,d) \ +vertexpt[d].tx = vertex[s]->tx; \ +vertexpt[d].ty = vertex[s]->ceilingheight; \ +vertexpt[d].tz = vertex[s]->tz; \ +vertexpt[d].px = vertex[s]->px; \ +vertexpt[d].py = vertex[s]->ceilingy; + + +//============================================================ + +/* */ +/*=============== */ +/*= */ +/*= ClearMapCache */ +/*= */ +/*= Invalidates any cached calculations */ +/*= */ +/*=============== */ +/* */ + +void ClearMapCache(void) +{ + memset(mapcache_height, 0xf0, sizeof(mapcache_height)); +} + +//========================================================= + +/* */ +/*================== */ +/*= */ +/*= FlatSpan */ +/*= */ +/*= used for flat floors and ceilings, coordinates must be pre clipped */ +/*= */ +/*= mr_deltaheight is planeheight - viewheight, with height values incre*/ +/*= */ +/*= mr_picture and mr_deltaheight are set once per polygon */ +/*= */ +/*================== */ +/* */ + +void FlatSpan(void) +{ + fixed_t pointz; // row's distance to view plane + span_t *span_p; + unsigned span; + +#ifdef VALIDATE + if (numspans==MAXSPANS) + MS_Error("MAXSPANS exceeded"); + if ((mr_x1<0)||(mr_x2>windowWidth)||(mr_x1>=mr_x2)||(mr_y<0)||(mr_y>=windowWidth)) + MS_Error("Bad MapPlane coordinates"); +#endif + + // + // use cached pointz if valid + // + if (mapcache_height[mr_y]==mr_deltaheight) + pointz=mapcache_pointz[mr_y]; + else { + mapcache_height[mr_y]=mr_deltaheight; + pointz=mapcache_pointz[mr_y]=FIXEDDIV(mr_deltaheight, yslope[mr_y]); + } + if (pointz>MAXZ) + return; + // + // post the span in the draw list + // + span=(pointz<spantype=sp_flat; + span_p->picture=mr_picture; + span_p->x2=mr_x2; + span_p->y=mr_y; + + numspans++; +} + +//========================================================= + +/* */ +/*================== */ +/*= */ +/*= SlopeSpan */ +/*= */ +/*= used for sloping floors and ceilings */ +/*= */ +/*= planeA, planeB, planeC, planeD must be precalculated */ +/*= */ +/*= mr_picture is set once per polygon */ +/*= */ +/*================== */ +/* */ + +void SlopeSpan(void) +{ + fixed_t pointz, pointz2; // row's distance to view plane + fixed_t partial, denom; + span_t *span_p; + unsigned span; + +#ifdef VALIDATE + if (numspans==MAXSPANS) + MS_Error("MAXSPANS exceeded"); + if ((mr_x1<0)||(mr_x2>windowWidth)||(mr_x1>=mr_x2)||(mr_y<0)||(mr_y>=windowWidth)) + MS_Error("Bad MapPlane coordinates"); +#endif + // + // calculate the Z values for each end of the span + // + partial=FIXEDMUL(planeB, yslope[mr_y])+planeC; + denom=FIXEDMUL(planeA, xslope[mr_x1])+partial; + pointz=FIXEDDIV(planeD, denom); + denom=FIXEDMUL(planeA, xslope[mr_x2])+partial; + pointz2=FIXEDDIV(planeD, denom); + + if (pointz>MAXZ||pointz2>MAXZ) + return; + + // + // post the span in the draw list + // + span=(pointz<spantype=sp_slope; + span_p->picture=mr_picture; + span_p->x2=mr_x2; + span_p->y=mr_y; + span_p->yh=pointz2; + + numspans++; +} + +//========================================================= + +/* */ +/*================== */ +/*= */ +/*= RenderPolygon */ +/*= */ +/*= Vertex list must be precliped, convex, and in clockwise order */ +/*= Backfaces (not in clockwise order) generate no pixels */ +/*= */ +/*= The polygon is divided into trapezoids (from 1 to numvertex-1 can be*/ +/*= which have a constant slope on both sides */ +/*= */ +/*= mr_x1 screen coordinates of the span to draw, used by map */ +/*= mr_x2 plane to calculate textures at the endpoints */ +/*= mr_y along with mr_deltaheight */ +/*= */ +/*= mr_dest pointer inside viewbuffer where span starts */ +/*= mr_count length of span to draw (mr_x2 - mr_x1) */ +/*= */ +/*= spanfunction is a pointer to a function that will handle determining*/ +/*= in the calculated span (FlatSpan or SlopeSpan) */ +/*= */ +/*================== */ +/* */ + +void RenderPolygon(void (*spanfunction)(void)) +{ + int stopy; + fixed_t leftfrac, rightfrac; + fixed_t leftstep, rightstep; + int leftvertex, rightvertex; + int deltax, deltay; + int oldx; + + // + // find topmost vertex + // + rightvertex=0; // topmost so far + for (leftvertex=1; leftvertex=windowHeight) + return; // totally off bottom + + do { + if (mr_y==vertexy[rightvertex]) { + skiprightvertex : oldx=vertexx[rightvertex]; + if (++rightvertex==numvertex) + rightvertex=0; + deltay=vertexy[rightvertex]-mr_y; + if (!deltay) { + if (leftvertex==rightvertex) + return; // the last edge is exactly horizontal + goto skiprightvertex; + } + deltax=vertexx[rightvertex]-oldx; + rightfrac=(oldx<windowHeight) + stopy=windowHeight; + + for (; mr_y>FRACBITS; + mr_x2=rightfrac>>FRACBITS; + if (mr_x1xcliph) + mr_x2=xcliph; + + if (mr_x1mr_x1) + spanfunction(); // different functions for flat and slop + + leftfrac+=leftstep; + rightfrac+=rightstep; + } + } while ((rightvertex!=leftvertex)&&(mr_y!=windowHeight)); + +} + + +//============================================================ + +/* */ +/*================== */ +/*= */ +/*= CalcPlaneEquation */ +/*= */ +/*= Calculates planeA, planeB, planeC, planeD */ +/*= planeD is actually -planeD */ +/*= */ +/*= for vertexpt[0-2] */ +/*= */ +/*================== */ +/* */ + +void CalcPlaneEquation(void) +{ + fixed_t x1, y1, z1; + fixed_t x2, y2, z2; + fixed_t check1, check2; + + // + // calculate two vectors going away from the middle vertex + // + x1=vertexpt[0].tx-vertexpt[1].tx; + y1=vertexpt[0].ty-vertexpt[1].ty; + z1=vertexpt[0].tz-vertexpt[1].tz; + + x2=vertexpt[2].tx-vertexpt[1].tx; + y2=vertexpt[2].ty-vertexpt[1].ty; + z2=vertexpt[2].tz-vertexpt[1].tz; + + // + // the A, B, C coefficients are the cross product of v1 and v2 + // shift over to save some precision bits + planeA=(FIXEDMUL(y1, z2)-FIXEDMUL(z1, y2))>>8; + planeB=(FIXEDMUL(z1, x2)-FIXEDMUL(x1, z2))>>8; + planeC=(FIXEDMUL(x1, y2)-FIXEDMUL(y1, x2))>>8; + + // + // calculate D based on A,B,C and one of the vertex points + // + planeD=FIXEDMUL(planeA, vertexpt[0].tx) + +FIXEDMUL(planeB, vertexpt[0].ty) + +FIXEDMUL(planeC, vertexpt[0].tz); + + check1=FIXEDMUL(planeA, vertexpt[1].tx) + +FIXEDMUL(planeB, vertexpt[1].ty) + +FIXEDMUL(planeC, vertexpt[1].tz); + check2=FIXEDMUL(planeA, vertexpt[2].tx) + +FIXEDMUL(planeB, vertexpt[2].ty) + +FIXEDMUL(planeC, vertexpt[2].tz); +} + +//============================================================ + +/* */ +/*================== */ +/*= */ +/*= ZClipPolygon */ +/*= */ +/*= Returns true if the polygon should be rendered */ +/*= */ +/*================== */ +/* */ + +boolean ZClipPolygon(int numvertexpts, fixed_t minz) +{ + int v; + fixed_t scale; + fixed_t frac, cliptx, clipty; + clippoint_t *p1, *p2; + + numvertex=0; + + if (minztztztz-minz), (p1->tz-p2->tz)); + + cliptx=p1->tx+FIXEDMUL((p2->tx-p1->tx), frac); + clipty=p1->ty+FIXEDMUL((p2->ty-p1->ty), frac); + + vertexx[numvertex]=CENTERX+(FIXEDMUL(cliptx, scale)>>FRACBITS); + vertexy[numvertex]=CENTERY-(FIXEDMUL(clipty, scale)>>FRACBITS); + numvertex++; + } + if (p1->tz>=minz) { + vertexx[numvertex]=p1->px; + vertexy[numvertex]=p1->py; + numvertex++; + } + } + if (!numvertex) + return false; + + return true; +} + +//================================================================ + +/* */ +/*==================*/ +/*= */ +/*= RenderTileEnds */ +/*= */ +/*= Draw the floor */ +/*= and ceiling for */ +/*= a tile */ +/*==================*/ +/* */ + +void RenderTileEnds(void) +{ + int flatpic; + int flags, polytype; + + xcliph++; // debug: handle this globally + flags=mapflags[mapspot]; + + // + // draw the floor + // + flatpic=floorpic[mapspot]; +#ifdef VALIDATE + if (flatpic>=numflats) + MS_Error("RenderTileEnds: Invalid floorpic at (%i,%i)", tilex, tiley); +#endif + flatpic=flattranslation[flatpic]; +#ifdef VALIDATE + if (flatpic>=numflats) + MS_Error("RenderTileEnds: Invalid translated floor"); +#endif + mr_picture=lumpmain[flatlump+flatpic]; + ceilingbit=0; + + polytype=(flags&FL_FLOOR)>>FLS_FLOOR; + switch (polytype) { + case POLY_FLAT: + mr_deltaheight=vertex[0]->floorheight; + if (mr_deltaheight<0) { + COPYFLOOR(0, 0); + COPYFLOOR(1, 1); + COPYFLOOR(2, 2); + COPYFLOOR(3, 3); + if (ZClipPolygon(4, -mr_deltaheight)) + RenderPolygon(FlatSpan); + } + break; + + case POLY_SLOPE: + COPYFLOOR(0, 0); + COPYFLOOR(1, 1); + COPYFLOOR(2, 2); + COPYFLOOR(3, 3); + CalcPlaneEquation(); + if (ZClipPolygon(4, MINZ)) + RenderPolygon(SlopeSpan); + break; + + case POLY_ULTOLR: + COPYFLOOR(0, 0); + COPYFLOOR(1, 1); + COPYFLOOR(2, 2); + CalcPlaneEquation(); + if (ZClipPolygon(3, MINZ)) + RenderPolygon(SlopeSpan); + + COPYFLOOR(2, 0); + COPYFLOOR(3, 1); + COPYFLOOR(0, 2); + CalcPlaneEquation(); + if (ZClipPolygon(3, MINZ)) + RenderPolygon(SlopeSpan); + break; + + case POLY_URTOLL: + COPYFLOOR(0, 0); + COPYFLOOR(1, 1); + COPYFLOOR(3, 2); + CalcPlaneEquation(); + if (ZClipPolygon(3, MINZ)) + RenderPolygon(SlopeSpan); + + COPYFLOOR(1, 0); + COPYFLOOR(2, 1); + COPYFLOOR(3, 2); + CalcPlaneEquation(); + if (ZClipPolygon(3, MINZ)) + RenderPolygon(SlopeSpan); + break; + } + // + // draw the ceiling + // + + //return; // remove to show ceilings + + flatpic=ceilingpic[mapspot]; +#ifdef VALIDATE + if (flatpic>=numflats) + MS_Error("RenderTileEnds: Invalid ceilingpic at (%i,%i)", tilex, + tiley); +#endif + flatpic=flattranslation[flatpic]; +#ifdef VALIDATE + if (flatpic>=numflats) + MS_Error("RenderTileEnds: Invalid ceiling translation for %i", + flatlump); +#endif + mr_picture=lumpmain[flatlump+flatpic]; + + ceilingbit=CEILINGBIT; + + polytype=(flags&FL_CEILING)>>FLS_CEILING; + switch (polytype) { + case POLY_FLAT: + mr_deltaheight=vertex[0]->ceilingheight; + if (mr_deltaheight>0) { + COPYCEILING(3, 0); + COPYCEILING(2, 1); + COPYCEILING(1, 2); + COPYCEILING(0, 3); + if (ZClipPolygon(4, mr_deltaheight)) + RenderPolygon(FlatSpan); + } + break; + + case POLY_SLOPE: + COPYCEILING(3, 0); + COPYCEILING(2, 1); + COPYCEILING(1, 2); + COPYCEILING(0, 3); + CalcPlaneEquation(); + if (ZClipPolygon(4, MINZ)) + RenderPolygon(SlopeSpan); + break; + + case POLY_ULTOLR: + COPYCEILING(3, 0); + COPYCEILING(2, 1); + COPYCEILING(1, 2); + CalcPlaneEquation(); + if (ZClipPolygon(3, MINZ)) + RenderPolygon(SlopeSpan); + + COPYCEILING(3, 0); + COPYCEILING(1, 1); + COPYCEILING(0, 2); + CalcPlaneEquation(); + if (ZClipPolygon(3, MINZ)) + RenderPolygon(SlopeSpan); + break; + + case POLY_URTOLL: + COPYCEILING(3, 0); + COPYCEILING(2, 1); + COPYCEILING(0, 2); + CalcPlaneEquation(); + if (ZClipPolygon(3, MINZ)) + RenderPolygon(SlopeSpan); + + COPYCEILING(2, 0); + COPYCEILING(1, 1); + COPYCEILING(0, 2); + CalcPlaneEquation(); + if (ZClipPolygon(3, MINZ)) + RenderPolygon(SlopeSpan); + break; + } +} + +//=============================================================== + +/* */ +/*==================== */ +/*= */ +/*= FindBackVertex */ +/*= */ +/*==================== */ +/* */ + +void FindBackVertex(void) +{ + int v; + fixed_t greatestz; + + // + // transform the view tile and find the vertex with the greatest Z + // + vertex[0]=TransformVertex(viewtilex, viewtiley); + vertex[1]=TransformVertex(viewtilex+1, viewtiley); + vertex[2]=TransformVertex(viewtilex+1, viewtiley+1); + vertex[3]=TransformVertex(viewtilex, viewtiley+1); + + backvertex=0; + greatestz=vertex[0]->tz; + + for (v=1; v<4; v++) + if (vertex[v]->tz>greatestz) { + backvertex=v; + greatestz=vertex[v]->tz; + } +} diff --git a/SOURCE/R_PUBLIC.C b/SOURCE/R_PUBLIC.C new file mode 100644 index 0000000..8206088 --- /dev/null +++ b/SOURCE/R_PUBLIC.C @@ -0,0 +1,662 @@ + +#include +#include +#include +//#include "r_public.h" +#include "D_global.h" +#include "d_disk.h" +#include "R_refdef.h" + +int windowHeight = INIT_VIEW_HEIGHT; +int windowWidth = INIT_VIEW_WIDTH; +int windowLeft = (320-INIT_VIEW_WIDTH) >> 1; +int windowTop = (200-INIT_VIEW_HEIGHT) >> 1; +int windowSize = INIT_VIEW_HEIGHT*INIT_VIEW_WIDTH; +int viewLocation = 0xA0000+VIEW_TOP*320+VIEW_LEFT; + +//============================================================= + +/* */ +/*===================== */ +/*= */ +/*= RF_PreloadGraphics */ +/*= */ +/*===================== */ +/* */ + +void RF_PreloadGraphics(void) +{ + int i, x; + byte *base; + byte *wall; + int size; + + // + // find the number of lumps of each type + // + spritelump=CA_GetNamedNum("startsprites"); + numsprites=CA_GetNamedNum("endsprites")-spritelump; + + walllump=CA_GetNamedNum("startwalls"); + numwalls=CA_GetNamedNum("endwalls")-walllump; + + flatlump=CA_GetNamedNum("startflats"); + numflats=CA_GetNamedNum("endflats")-flatlump; + + // + // load the lumps + // + for (i=1; itilex=tilex; + door->tiley=tiley; + + mapflags[tiley*MAPROWS+tilex] |= FL_DOOR; + + return door; +} + +//========================================================== + +/* */ +/*================ */ +/*= */ +/*= RF_GetSprite */ +/*= */ +/*= Return a free sprite structure that has been added to the end of */ +/*= the active list */ +/*= */ +/*================ */ +/* */ + +scaleobj_t *RF_GetSprite(void) +{ + scaleobj_t *new; + + if (!freescaleobj_p) + MS_Error("GetSprite: Out of spots in scaleobjlist!"); + + new=freescaleobj_p; + freescaleobj_p=freescaleobj_p->next; + + memset(new, 0, sizeof(*new)); + new->next=(scaleobj_t *)&lastscaleobj; + new->prev=lastscaleobj.prev; + lastscaleobj.prev=new; + new->prev->next=new; + + return new; +} + +//========================================================== + +/* */ +/*====================*/ +/*= */ +/*= RF_RemoveSprite */ +/*= */ +/*= Unlink the sprite */ +/*= from the active */ +/*= list */ +/*= */ +/*====================*/ +/* */ + +void RF_RemoveSprite(scaleobj_t *spr) +{ + spr->next->prev=spr->prev; + spr->prev->next=spr->next; + + memset(spr, 0, sizeof(spr)); + spr->next=freescaleobj_p; + freescaleobj_p=spr; +} + +//========================================================== + + +/* */ +/*=====================*/ +/*= */ +/*= RF_GetFloorZ */ +/*= */ +/*=====================*/ +/* */ + +fixed_t RF_GetFloorZ(fixed_t x, fixed_t y) +{ + fixed_t h1, h2, h3, h4; + int tilex, tiley, mapspot; + int polytype; + fixed_t fx, fy; + fixed_t top, bottom; + + tilex=x>>(FRACBITS+TILESHIFT); + tiley=y>>(FRACBITS+TILESHIFT); + + mapspot=tiley *MAPSIZE+tilex; + polytype=(mapflags[mapspot]&FL_FLOOR)>>FLS_FLOOR; + + // + // flat + // + if (polytype==POLY_FLAT) + return floorheight[mapspot]<>6; // range from 0 to fracunit-1 + fy=(y&(TILEUNIT-1))>>6; + + if (polytype==POLY_SLOPE) { + if (h1==h2) // north/south slope + return h1+FIXEDMUL(h3-h1, fy); + else // east/west slope + return h1+FIXEDMUL(h2-h1, fx); + } + // + // triangulated slopes + // + + // set the outside corner of the triangle that the point is NOT in s + // plane with the other three + + if (polytype==POLY_ULTOLR) { + if (fx>fy) + h3=h1-(h2-h1); + else + h2=h1+(h1-h3); + } + else { + if (fx>(FRACBITS+TILESHIFT); + tiley=y>>(FRACBITS+TILESHIFT); + + mapspot=tiley *MAPSIZE+tilex; + polytype=(mapflags[mapspot]&FL_CEILING)>>FLS_CEILING; + + // + // flat + // + if (polytype==POLY_FLAT) + return ceilingheight[mapspot]<>6; // range from 0 to fracunit-1 + fy=(y&(TILEUNIT-1))>>6; + + if (polytype==POLY_SLOPE) { + if (h1==h2) // north/south slope + return h1+FIXEDMUL(h3-h1, fy); + else // east/west slope + return h1+FIXEDMUL(h2-h1, fx); + } + // + // triangulated slopes + // + + // set the outside corner of the triangle that the point is NOT in s + // plane with the other three + + if (polytype==POLY_ULTOLR) { + if (fx>fy) + h3=h1-(h2-h1); + else + h2=h1+(h1-h3); + } + else { + if (fxpicture; + shapebottom=span_p->y; + + scale=FIXEDDIV(SCALE, pointz); + fracstep=FIXEDMUL(pointz, ISCALE); + sp_fracstep=fracstep; + leftx=span_p->x2; + leftx-=pic->leftoffset<>FRACBITS); + if (x>sx) + return false; // the sprite is to the right of the point + deltascreen=sx-x; + post=(fracstep *deltascreen)>>FRACBITS; + + if (post>=pic->width) + return false; // the sprite is to the left of the point + + if (pointz>wallz[sx]) + return false; // this post is obscured by a closer wall + + collumn=(byte *)pic+pic->collumnofs[post]; + + topheight=shapebottom+(*collumn<>FRACBITS); + if (topy>sy) + return false; // shape is below point + bottomy=CENTERY-(FIXEDMUL(bottomheight, scale)>>FRACBITS); + if (bottomy>FRACBITS; + + if (!collumn[posty]) + return false; // point is in a transparent area + + id_type=id_sprite; + id_structure=span_p->structure; + return true; +} + +/* */ +/*========================*/ +/*= =*/ +/*= RF_PixelIdentity =*/ +/*= =*/ +/*= You can only call =*/ +/*= this between frames, =*/ +/*= not during an action =*/ +/*= hook routine call =*/ +/*= =*/ +/*========================*/ +/* */ + +void RF_PixelIdentity(int sx, int sy) +{ + unsigned tag, *spantag_p; + int spannum; + span_t *span_p; + int spanx; + fixed_t pointz, length, fracstep; + int deltay; + int angle; + + // + // scan the sorted span lists from closest to farthest + // + spantag_p=endtaglist_p-1; + while (spantag_p>=starttaglist_p) { + tag=*spantag_p--; + + spannum=tag&SPANMASK; + span_p=&spans[spannum]; + spanx=tag&XMASK; + pointz=(tag&ZMASK)>>ZTOFRAC; + + if (span_p->spantype==sp_shape) { + // check for intersection with the sprite's pixels + if (CheckSpriteContact(span_p, pointz, sx, sy)) + return; + continue; + } + spanx=(spanx>>XSHIFT)^0x1ff; // invert back to regular x + + if ((span_p->spantype==sp_door)||(span_p->spantype==sp_maskeddoor)) { + // if it got here, it didn't hit a floor or ceiling in front + if (spanx!=sx) + continue; + id_type=id_door; + id_structure=span_p->structure; + return; + } + /// its just a floor/ ceiling span + // check the extent of the span + if (span_p->y!=sy||spanx>sx||span_p->x2<=sx) + continue; + if (tag&CEILINGBIT) + id_type=id_ceiling; + else + id_type=id_floor; + + angle=viewfineangle+pixelangle[sx]; + angle&=TANANGLES *4-1; + + length=FIXEDDIV(pointz, pixelcosine[sx]); + id_px=viewx+FIXEDMUL(length, cosines[angle]); + id_py=viewy-FIXEDMUL(length, sines[angle]); + return; + } + // + // if there is a wall post at sx, the click was somewhere in it + // + if (wallz[sx]==MAXZ+1) { + // didn't click on anything + id_type=id_empty; + return; + } + id_type=id_wall; + id_tilex=wallnumber[sx]>>17; + id_tiley=(wallnumber[sx]>>2)&63; + id_side=wallnumber[sx]&3; + id_px=walltexture[sx]; + deltay=sy-walltopy[sx]; + fracstep=FIXEDMUL(wallz[sx], ISCALEFUDGE); + id_py=(deltay *fracstep)>>FRACBITS; + if (id_py<0) + id_py=0; + +} + +/* */ +/*=====================*/ +/*= */ +/*= RF_SetLights */ +/*= */ +/*= Spreads the light */ +/*= translation tables */ +/*= from 0 - MAXZ, with*/ +/*= the black point at */ +/*= blackz. It is OK to*/ +/*= have blackz>MAXZ, */ +/*= things will be */ +/*= brighter when they */ +/*= appear */ +/*=====================*/ +/* */ + +void RF_SetLights(fixed_t blackz) +{ + // linear diminishing + int i; + int table; + + blackz>>=FRACBITS; + for (i=0; i<=MAXZ>>FRACBITS; i++) { + table=numcolormaps *i/blackz; + if (table>=numcolormaps) + table=numcolormaps-1; + zcolormap[i]=colormaps+table *256; + } +} + +//========================================================== + +/* */ +/*===================== */ +/*= */ +/*= RF_CheckActionFlag */ +/*= */ +/*===================== */ +/* */ + +void RF_CheckActionFlag(void) +{ + if (!actionflag) + return; + + if (!actionhook) + MS_Error("RF_CheckActionFlag: Actionhook not set"); + + actionhook(); + actionflag=0; +} + +/* */ +/*===================== */ +/*= */ +/*= RF_SetActionHook */ +/*= */ +/*===================== */ +/* */ + +void RF_SetActionHook(void (*hook)(void)) +{ + actionhook=hook; +} + +//========================================================== + +/* */ +/*=============== */ +/*= */ +/*= RF_RenderView */ +/*= */ +/*=============== */ +/* */ + +void RF_RenderView(fixed_t x, fixed_t y, fixed_t z, int angle, byte showBlast) +{ + if ((x<=0)||(x>=((MAPSIZE-1)<<(FRACBITS+TILESHIFT)))||(y<=0)|| + (y>=((MAPSIZE-1)<<(FRACBITS+TILESHIFT))||angle<0||angle>=ANGLES)) + MS_Error("Invalid RF_RenderView (%p, %p, %p, %i)\n", x, y, z, angle); + + viewx=(x&~0xfff) + 0x800; + viewy=(y&~0xfff) + 0x800; + viewz=(z&~0xfff) + 0x800; + viewangle=angle; + + SetupFrame(); + RF_CheckActionFlag(); + FlowView(x,y); + RF_CheckActionFlag(); + RenderSprites(x, y, z, angle, showBlast); + RF_CheckActionFlag(); + DrawSpans(); + RF_CheckActionFlag(); +} + +void SetViewSize(int width, int height) +{ + int i; + + if (width>MAX_VIEW_WIDTH) width = MAX_VIEW_WIDTH; + if (height>MAX_VIEW_HEIGHT) height = MAX_VIEW_HEIGHT; + windowHeight = height; + windowWidth = width; + windowSize = width*height; + for (i=0;i 0 + int floory; + int ceilingy; +#ifdef FLOATCOORD + float ftx, ftz; +#endif +} vertex_t; + +typedef struct { + int tilex, tiley; + int xmin, xmax; +} entry_t; + +/* */ +/*The span_t structure is used with the spantags bit fields to determine*/ +/*after sorting all the draw events. */ +/* */ +/* floor/ceiling doorpost scaled shape slop*/ +/* --------------- ------------ ----------------- */ +/*tagz pointz pointz pointz p*/ +/*tagx ~xstart ~xposition 0 */ +/* */ +/*picture texture block top of post scale pic */ +/*x2 x end + 1 ?? pointx */ +/*y screen y ceiling height pointy */ +/*yh ?? floor height ?? */ +/*structure ?? doorobj scaleobj ?? */ +/* */ +/* */ + +typedef enum { + sp_flat, sp_slope, sp_door, sp_shape, sp_maskeddoor +} spanobj_t; + +typedef struct { + spanobj_t spantype; + byte *picture; + void *structure; // either doorobj or scaleobj + int x2; + int y; + int yh; +} span_t; + +typedef struct { + short leftoffset, width; + short collumnofs[256]; // only uses [width] entries +} scalepic_t; + +typedef struct { + fixed_t tx, ty, tz; + int px, py; +} clippoint_t; + +//================= +// R_render +//================= +extern void (*actionhook)(void); + +extern int framevalid[MAPROWS][MAPCOLS]; +extern vertex_t *cornervertex[MAPROWS][MAPCOLS]; +extern vertex_t vertexlist[MAXVISVERTEXES], *vertexlist_p; + +extern int yslope[MAX_VIEW_HEIGHT], xslope[MAX_VIEW_WIDTH+1]; + +extern byte **wallposts; + +extern byte *colormaps; +extern int numcolormaps; +extern byte *zcolormap[(MAXZ>>FRACBITS) ++1]; + +extern fixed_t viewx, viewy, viewz; +extern fixed_t viewcos, viewsin; +extern fixed_t xscale, yscale; +extern int viewangle, viewfineangle; +extern int viewtilex, viewtiley; + +extern int side; +extern int walltype; +extern int wallshadow; +extern vertex_t *vertex[4]; // points to the for corner vertexes in vert +extern vertex_t *p1, *p2; + +extern int xclipl, xcliph; // clip window for current tile +extern int tilex, tiley; // coordinates of the tile being rendered +extern int mapspot; // tiley*MAPSIZE+tilex + +extern boolean doortile; // true if the tile being renderd has a door + +void SetupFrame(void); +vertex_t *TransformVertex(int tilex, int tiley); +void FlowView(fixed_t x, fixed_t y); + +//================= +// R_walls +//================= + +extern fixed_t tangents[TANANGLES *2]; +extern fixed_t sines[TANANGLES *5]; +extern fixed_t *cosines; // point 1/4 phase into sines + +extern int pixelangle[MAX_VIEW_WIDTH+1]; // +1 because span ends go one past +extern fixed_t pixelcosine[MAX_VIEW_WIDTH+1]; + +extern int wallnumber[MAX_VIEW_WIDTH]; +extern int walltopy[MAX_VIEW_WIDTH]; +extern int walltexture[MAX_VIEW_WIDTH]; +extern fixed_t wallz[MAX_VIEW_WIDTH]; + +void InitWalls(void); +void ClearWalls(void); +void RenderTileWalls(entry_t *e, fixed_t playerx, fixed_t playery); +void DrawWall(void); + +//================= +// R_plane +//================= + +extern byte *mr_picture; // pointer to a raw 64*64 pixel picture +extern fixed_t mf_deltaheight; +extern int spancount; + +void InitPlane(void); +void ClearMapCache(void); +void RenderTileEnds(void); +void FindBackVertex(void); + +//================= +// R_conten +//================= + +extern scaleobj_t firstscaleobj, lastscaleobj; +extern scaleobj_t scaleobjlist[MAXSPRITES], *freescaleobj_p; + +extern doorobj_t doorlist[MAXDOORS]; +extern int numdoors; + +extern int doorxl, doorxh; + +void RenderDoor(fixed_t playerx, fixed_t playery); +void RenderSprites(fixed_t x, fixed_t y, fixed_t z, int angle, byte showBlast); + +//================= +// R_draw +//================= + +extern byte *sp_dest; // the bottom most pixel to be drawn (in vie +extern byte *sp_source; // the first pixel in the vertical post (may +extern byte *sp_colormap; // pointer to a 256 byte color number to pal +extern int sp_frac; // fixed point location past sp_source +extern int sp_fracstep; // fixed point step value +extern int sp_count; // the number of pixels to draw + +void ScalePost(void); +void ScaleMaskedPost(void); + +extern byte *mr_dest; // the left most pixel to be drawn (in viewb +extern byte *mr_picture; // pointer to a raw 64*64 pixel picture +extern byte *mr_colormap; // pointer to a 256 byte color number to pal +extern int mr_xfrac; // starting texture coordinate +extern int mr_yfrac; // starting texture coordinate +extern int mr_xstep; // fixed point step value +extern int mr_ystep; // fixed point step value +extern int mr_count; // the number of pixels to draw + +void MapRow(void); + +//================= +// R_spans +//================= + +extern unsigned spantags[2][MAXSPANS]; +extern unsigned *starttaglist_p, *endtaglist_p; +extern span_t spans[MAXSPANS], *spans_p; +extern int numspans; + +void DrawSpans(void); diff --git a/SOURCE/R_RENDER.C b/SOURCE/R_RENDER.C new file mode 100644 index 0000000..d71b83e --- /dev/null +++ b/SOURCE/R_RENDER.C @@ -0,0 +1,468 @@ +// R_render.c +#include +#include +#include +#include "D_global.h" +#include "R_refdef.h" + +/* */ +/*=================== */ +/*CONSTANTS */ +/*=================== */ +/* */ + +/* */ +/*=================== */ +/*TYPES */ +/*=================== */ +/* */ + +/* */ +/*=================== */ +/*GLOBALS */ +/*=================== */ + /* */ +hit_t id_type; +int id_tilex, id_tiley; // not valid for sprites +int id_side; // 0(north)-3(west) for walls +int id_px, id_py; // position in texture +void *id_structure; // either doorobj_t or scaleobj_t + +byte floorpic[MAPROWS*MAPCOLS]; +byte ceilingpic[MAPROWS*MAPCOLS]; +byte floorheight[MAPROWS*MAPCOLS]; +byte ceilingheight[MAPROWS*MAPCOLS]; +byte northwall[MAPROWS*MAPCOLS]; +byte westwall[MAPROWS*MAPCOLS]; +byte northbottom[MAPROWS*MAPCOLS]; +byte westbottom[MAPROWS*MAPCOLS]; +byte mapflags[MAPROWS*MAPCOLS]; +byte mapsprites[MAPROWS*MAPCOLS]; + +void (*actionhook)(void); +int actionflag; + +// each visible vertex is used up to four times, so to prevent recalcula +// the vertex info is reused if it has been calculated previously that f +// The calculated flag is also used to determine if a moving sprite is i +// is at least partially visable. +// +// frameon is incremented at the start of each frame, so it is 1 on the +// framevalid[][] holds the frameon number for which vertex[][] is valid +// set to 0 at initialization, so no points are valid +// cornervertex[][] is a pointer into vertexlist[] +// vertexlist[] holds the currently valid transformed vertexes +// vertexlist_p is set to vertexlist[0] at the start of each frame, and +// after transforming a new vertex +int frameon; +int framevalid[MAPROWS][MAPCOLS]; +vertex_t *cornervertex[MAPROWS][MAPCOLS]; +vertex_t vertexlist[MAXVISVERTEXES], *vertexlist_p; + +fixed_t costable[ANGLES]; +fixed_t sintable[ANGLES]; + +pixel_t viewbuffer[MAX_VIEW_WIDTH*MAX_VIEW_HEIGHT]; +pixel_t *viewylookup[MAX_VIEW_HEIGHT]; + +fixed_t yslope[MAX_VIEW_HEIGHT], xslope[MAX_VIEW_WIDTH+1]; + +byte **wallposts; + +byte *colormaps; +int numcolormaps; +byte *zcolormap[(MAXZ>>FRACBITS)+1]; + +fixed_t viewx, viewy, viewz; +fixed_t viewcos, viewsin; +fixed_t xscale, yscale; // SCALE/viewcos , SCALE/viewsin +int viewangle, viewfineangle; +int viewtilex, viewtiley; + +vertex_t *vertex[4]; // points to the for corner vertexes in vert +vertex_t *p1, *p2; +int side; // wall number 0-3 +int walltype; // wall number (picture) of p1-p2 edge +int wallshadow; // degree of shadow for a tile + +int xclipl, xcliph; // clip window for current tile +int tilex, tiley; // coordinates of the tile being rendered +int mapspot; // tiley*MAPSIZE+tilex + +int *flattranslation; // global animation tables +int *walltranslation; + +int spritelump, walllump, flatlump; +int numsprites, numwalls, numflats; + +boolean doortile; // true if the tile being renderd has a door + +/* */ +/*=================== */ +/*LOCALS */ +/*=================== */ +/* */ + +int adjacentx[4]= +{ + 0, 1, 0, -1 +}; + +// deltas to the tile facing the given wall +int adjacenty[4]= +{ + -1, 0, 1, 0 +}; + + + +entry_t entries[2][30], *entry_p; // holds tile numbers and clip windo +// entries are read out of one list, checked for +// duplication, and passed to RenderTile +// The other list collects new entries from the +// exits detected by RenderTile + +/* */ +/*================== */ +/*= */ +/*= TransformVertex */ +/*= */ +/*= Returns a pointer to the vertex for a given coordinate */ +/*= tx,tz will be the transformed coordinates */ +/*= px, floorheight, ceilingheight will be valid if tz >= MINZ */ +/*= */ +/*================== */ +/* */ + +vertex_t *TransformVertex(int tilex, int tiley) +{ + fixed_t trx, try; + fixed_t gxt, gyt; + fixed_t scale; + vertex_t *point; + int mapspot; + + mapspot=tiley*MAPROWS+tilex; + + if (framevalid[tiley][tilex]==frameon) + return cornervertex[tiley][tilex]; // vertex has already been t + + point=vertexlist_p++; +#ifdef VALIDATE + if (point>=&vertexlist[MAXVISVERTEXES]) + MS_Error("Vertexlist overflow"); +#endif + framevalid[tiley][tilex]=frameon; + cornervertex[tiley][tilex]=point; + + point->floorheight=(floorheight[mapspot]<ceilingheight=(ceilingheight[mapspot]<tx=gyt+gxt; + + gxt=FIXEDMUL(trx, viewcos); + gyt=FIXEDMUL(try, viewsin); + point->tz=gxt-gyt; + +#ifdef FLOATCOORD + point->ftx=(float)point->tx/FRACUNIT; + point->ftz=(float)point->tz/FRACUNIT; +#endif + if (point->tz>=MINZ) { + scale=FIXEDDIV(SCALE, point->tz); + point->px=CENTERX+(FIXEDMUL(point->tx, scale)>>FRACBITS); + point->floory=CENTERY-(FIXEDMUL(point->floorheight, scale)>>FRACBITS); + point->ceilingy=CENTERY-(FIXEDMUL(point->ceilingheight,scale)>>FRACBITS); + } + return point; +} + +/* */ +/*================== */ +/*= */ +/*= ClipEdge */ +/*= */ +/*= Sets p1->px and p2->px correctly for Z values < MINZ */ +/*= */ +/*= Returns false if entire edge is too close or far away */ +/*= */ +/*================== */ +/* */ + +boolean ClipEdge(void) +{ + fixed_t leftfrac, rightfrac, clipz; + fixed_t dx,dz; + + if (p1->tz>MAXZ&&p2->tz>MAXZ) + return false; // entire face is too far away + + if (p1->tz<0&&p2->tz<0) + return false; // totally behind the projection plane + + if (p1->tztztx - p1->tx; + dz = p2->tz - p1->tz; + if (p1->tztx - p1->tz , dx+dz); + } + if (p2->tztx - p1->tz , -dx+dz); + if (p1->tztz + FIXEDMUL(dz,rightfrac); + if (clipz<0) + return false; + p2->px = windowWidth; + } + } + + if (p1->tztz + FIXEDMUL(dz,leftfrac); + if (clipz<0) + return false; + p1->px = 0; + } + + if (p1->px==p2->px) + return false; + + return true; +} + + +/* */ +/*=============== */ +/*= */ +/*= RenderTileWalls */ +/*= */ +/*=============== */ +/* */ + +void RenderTileWalls(entry_t *e, fixed_t playerx, fixed_t playery) +{ + int xl, xh; + + tilex=e->tilex; + tiley=e->tiley; + mapspot=tiley*MAPROWS+tilex; + + xclipl=e->xmin; + xcliph=e->xmax; + +#ifdef VALIDATE + if ((tilex<0)||(tilex>=MAPCOLS)||(tiley<0)||(tiley>=MAPROWS)||(xclipl<0)|| + (xclipl>=windowWidth)||(xcliph<0)||(xcliph>=windowWidth)||(xclipl>xcliph)) + MS_Error("Invalid RenderTile (%i, %i, %i, %i)\n", e->tilex, e->tiley, + e->xmin, e->xmax); +#endif + + // + // validate or transform the four corner vertexes + // + vertex[0]=TransformVertex(tilex, tiley); + vertex[1]=TransformVertex(tilex+1, tiley); + vertex[2]=TransformVertex(tilex+1, tiley+1); + vertex[3]=TransformVertex(tilex, tiley+1); + + // + // handle a door if present + // + if (mapflags[mapspot]&FL_DOOR) { + doortile=true; + RenderDoor(playerx,playery); // sets doorxl / doorxh + } + else + doortile=false; + + // + // draw or flow through the walls + // + for (side=0; side<4; side++) { + p1=vertex[side]; + p2=vertex[(side+1)&3]; + if (!ClipEdge()) continue; + if (p1->px>=p2->px) continue; // back face + switch (side) { + // only 64 wall types allowed so &63 ensures that + // all values are mapped into a correct value; + // any portion above 63 is assumed to be a shadowing + // factor + case 0: + wallshadow=northwall[mapspot] >> 6; + walltype=northwall[mapspot] & 63; + break; + case 1: + wallshadow=westwall[mapspot+1] >> 6; + walltype=westwall[mapspot+1] & 63; + break; + case 2: + wallshadow=northwall[mapspot+MAPSIZE] >> 6; + walltype=northwall[mapspot+MAPSIZE] & 63; + break; + case 3: + wallshadow=westwall[mapspot] >> 6; + walltype=westwall[mapspot] & 63; + break; + } + if (walltype) + { + DrawWall(); + } + else { + // + // restrict outward flow by the door, if present + // + xl=p1->px; + xh=p2->px-1; + + if (doortile) { + if ((doorxl<=xclipl)&&(doorxh>=xl)) xl=doorxh+1; + if ((doorxh>=xcliph)&&(doorxl<=xh)) xh=doorxl-1; + } + // + // restrict by clipping window + // + if (xlxcliph) xh=xcliph; + // + // flow into the adjacent tile if there is at lest a one pix + // + if (xh>=xl) { + entry_p->tilex=tilex+adjacentx[side]; + entry_p->tiley=tiley+adjacenty[side]; + entry_p->xmin=xl; + entry_p->xmax=xh; + entry_p++; + } + } + } +} + +//============================================================ + +/* */ +/*================ */ +/*= */ +/*= SetupFrame */ +/*= */ +/*================ */ +/* */ +void SetupFrame(void) +{ + // + // clear buffers + // + memset(viewbuffer, 0, sizeof(viewbuffer)); + ClearWalls(); // no walls drawn yet + ClearMapCache(); // invalidate cached pointz calculations + numspans=0; + frameon++; // vertexes from last frame are now invalid + vertexlist_p=&vertexlist[0]; // put the first transformed vertex + // begining of the list + + viewtilex=viewx>>TILEFRACSHIFT; + viewtiley=viewy>>TILEFRACSHIFT; + + viewfineangle=viewangle<tilex=viewtilex; + process_p->tiley=viewtiley; + process_p->xmin=0; + process_p->xmax=windowWidth-1; + endprocess_p=process_p+1; + table=1; + do { + entry_p=&entries[table][0]; + while (process_p!=endprocess_p) { + if (process_p->tilex==-1) { // the entry was combined away + process_p++; + continue; + } + // + // check for combining two entries + // + /* + for (nextprocess_p=process_p+1; nextprocess_p!=endprocess_p;nextprocess_p++) { + if ((nextprocess_p->tilex!=process_p->tilex)|| + (nextprocess_p->tiley!=process_p->tiley)) continue; + + if (nextprocess_p->xmin==process_p->xmax+1) + process_p->xmax=nextprocess_p->xmax; + else if (nextprocess_p->xmax==process_p->xmin-1) + process_p->xmin=nextprocess_p->xmin; + else { +// 1992-12-02 12:38 REB adding more output info for this error + unsigned char buf[256]; + unsigned char msg[256]; + unsigned char inf[256]; + buf[0]=msg[0]=inf[0]=0; + sprintf(buf,"nextprocess_p=%d,process_p=%d/n",(int)nextprocess_p,(int)process_p); + strcat(inf,buf); + sprintf(buf,"nextprocess_p->xmin=%d,nextprocess_p->xmax=%d\n",nextprocess_p->xmin,nextprocess_p->xmax); + strcat(inf,buf); + sprintf(buf,"process_p->xmin=%d,process_p->xmax=%d\n",process_p->xmin,process_p->xmax); + strcat(inf,buf); + strcat(msg,"Bad tile event combination\n"); + strcat(msg,inf); + MS_Error(msg); +// MS_Error("Bad tile event combination"); + } + nextprocess_p->tilex=-1; // don't use again + break; + } + */ + // + // draw or post everything for process_p + // + RenderTileWalls(process_p,playerx,playery); + RenderTileEnds(); + + process_p++; + } + endprocess_p=entry_p; + process_p=&entries[table][0]; + table^=1; + } while (endprocess_p!=process_p); + +} diff --git a/SOURCE/R_SPANS.C b/SOURCE/R_SPANS.C new file mode 100644 index 0000000..a131765 --- /dev/null +++ b/SOURCE/R_SPANS.C @@ -0,0 +1,418 @@ +// R_spans.c +#include "D_global.h" +#include "R_refdef.h" + +/* */ +/*MAXZ must be 511 or less! (384 now) */ +/* */ +/*(pointz<<7)&0xfff00000 // 9 unit bits, 3 frac bits */ +/*ceiling // 1 bit */ +/*x1<<12 // 8 bits */ +/*span number // 12 bits */ +/* */ +/*a scaled object is just encoded like a span */ +/* */ +/* */ + +unsigned spantags[2][MAXSPANS]; +unsigned *starttaglist_p, *endtaglist_p; // set by SortSpans +span_t spans[MAXSPANS], *spans_p; +int numspans; + +int spanx; +fixed_t pointz; +span_t *span_p; + +//================================================================ + +int size1; +int size2; +unsigned *src1, *src2, *dest; + +#ifdef NeXT + +/* */ +/*========== */ +/*= */ +/*= Merge */ +/*= */ +/*= Merges src1/size1 and src2/size2 to dest */ +/*= */ +/*========== */ +/* */ + +void Merge(void) +{ + // + // merge two parts of the unsorted array to the sorted array + // + if (*src1<*src2) + goto mergefrom2; + +mergefrom1: + *dest++=*src1++; + if (!--size1) + goto finishfrom2; + if (*src1>*src2) + goto mergefrom1; + +mergefrom2: + *dest++=*src2++; + if (!--size2) + goto finishfrom1; + if (*src1>*src2) + goto mergefrom1; + goto mergefrom2; + +finishfrom2: + while (size2--)*dest++=*src2++; + return; + +finishfrom1: + while (size1--)*dest++=*src1++; +} + + +#else +void Merge(void); // in assembly + +#endif + +/* */ +/*================== */ +/*= */ +/*= SortSpans */ +/*= */ +/*= Sorts the unsigned values in spantags[0] */ +/*= Sets starttaglist_p and endtaglist_p to the sorted list, which can b*/ +/*= */ +/*================== */ +/* */ + +void SortSpans(void) +{ + int size, start; + int sort; + unsigned *sorted, *unsorted, *temp; + + if (numspans<2) { + starttaglist_p=&spantags[0][0]; + endtaglist_p=starttaglist_p+numspans; + return; + } + size=1; + sort=0; + + sorted=spantags[sort]; + unsorted=spantags[!sort]; + + do { + start=0; + dest=unsorted; // this will be incremented by the merge + + do { + src1=sorted+start; + size1=size; + src2=src1+size; + start+=size; + size2=numspans-start; + if (size2>size) + size2=size; + start+=size2; // for next iteration + + Merge(); + } while (numspans-start>size); + + // + // copy any remnants (0-size possible) + // + while (start!=numspans) { + *dest++=spantags[sort][start]; + start++; + } + // + // get ready to sort back to the other array + // + sort^=1; + temp=sorted; + sorted=unsorted; + unsorted=temp; + size<<=1; + +#if 0 + { + int i; + for (i=0; ipicture; + sp_colormap=zcolormap[pointz>>FRACBITS]; + sp_fracstep=FIXEDMUL(pointz, ISCALE); + + top=FIXEDDIV(span_p->y, sp_fracstep); + topy=top>>FRACBITS; + fracadjust=top&(FRACUNIT-1); + sp_frac=FIXEDMUL(fracadjust, sp_fracstep); + topy=CENTERY-topy; + if (topy<0) { + sp_frac-=topy *sp_fracstep; + topy=0; + } + bottom=FIXEDDIV(span_p->yh, sp_fracstep)+FRACUNIT; + bottomy=bottom>=(CENTERY<>FRACBITS); + + if ((bottomy<=0)||(topy>=windowHeight)) + return; + + sp_count=bottomy-topy+1; + sp_dest=viewylookup[bottomy]+spanx; + + if (span_p->spantype==sp_maskeddoor) ScaleMaskedPost(); + else ScalePost(); +} + +//========================================================== + +/* */ +/*=================== */ +/*= */ +/*= DrawSprite */ +/*= */ +/*=================== */ +/* */ + +void DrawSprite(void) +{ + int x; + fixed_t leftx; + fixed_t scale; + fixed_t xfrac, fracstep; + fixed_t shapebottom, topheight, bottomheight; + int post; + int topy, bottomy; + scalepic_t *pic; + byte *collumn; + + sp_colormap=zcolormap[pointz>>FRACBITS]; + pic=(scalepic_t *)span_p->picture; + shapebottom=span_p->y; + // + // project the x and height + // + scale=FIXEDDIV(SCALE, pointz); + fracstep=FIXEDMUL(pointz, ISCALE); + sp_fracstep=fracstep; + leftx=span_p->x2; + leftx-=pic->leftoffset<>FRACBITS); + + // + // step through the shape, drawing posts where visible + // + xfrac=0; + if (x<0) { + xfrac-=fracstep *x; + x=0; + } + for (; x>FRACBITS; + xfrac+=fracstep; + + if (post>=pic->width) + return; // entire shape is too far away + if (pointz>wallz[x]) + continue; // this post is obscured by a closer wall + +// Temporary Mod by Ray and Ben to attempt a fix for empty sprite posts +// 1992-12-02 11:58 +// If the offset of the columns is zero then there is no data for the post + if (pic->collumnofs[post]==0) + continue; + collumn=(byte *)pic+pic->collumnofs[post]; + + topheight=shapebottom+(*collumn<>FRACBITS); + if (topy<0) { + sp_frac=-topy *sp_fracstep; + topy=0; + } + else + sp_frac=0; + + bottomy=CENTERY-(FIXEDMUL(bottomheight, scale)>>FRACBITS); + if (bottomy>windowHeight-1) bottomy=windowHeight-1; + + if ((bottomy<0)||(topy>=windowHeight)) continue; + + sp_count=bottomy-topy+1; + sp_dest=viewylookup[bottomy]+x; + sp_source=collumn; + + ScaleMaskedPost(); + } +} + +//========================================================== + +/* */ +/*============== */ +/*= */ +/*= DrawSpans */ +/*= */ +/*= Spans farther than MAXZ away should NOT have been entered into the l*/ +/* */ +/*============== */ +/* */ + +void DrawSpans(void) +{ + unsigned *spantag_p, tag; + int spannum; + int x2; + fixed_t lastz; // the pointz for which xystep is valid + fixed_t length; + fixed_t zerocosine, zerosine; + fixed_t zeroxfrac, zeroyfrac; + fixed_t xf2, yf2; // endpoint texture for sloping spans + int angle; + + // + // set up for drawing + // + SortSpans(); + spantag_p=starttaglist_p; + + angle=viewfineangle+pixelangle[0]; + angle&=TANANGLES *4-1; + zerocosine=cosines[angle]; + zerosine=sines[angle]; + + // + // draw from back to front + // + x2=-1; + lastz=-1; + + // + // draw everything else + // + while (spantag_p!=endtaglist_p) { + tag=*spantag_p++; + + pointz=(tag&ZMASK)>>ZTOFRAC; + spannum=tag&SPANMASK; + span_p=&spans[spannum]; + spanx=tag&XMASK; + spanx=(spanx>>XSHIFT)^0x1ff; // invert back to regular x + + if (span_p->spantype==sp_flat) { // its just a floor/ ceiling + //=============== + // + // floor / ceiling span + // + //=============== + if (pointz!=lastz) { + lastz=pointz; + mr_xstep=FIXEDMUL(pointz, xscale); + mr_ystep=FIXEDMUL(pointz, yscale); + mr_colormap=zcolormap[pointz>>FRACBITS]; + // + // calculate starting texture point + // + length=FIXEDDIV(pointz, pixelcosine[0]); + zeroxfrac=mr_xfrac=viewx+FIXEDMUL(length, zerocosine); + zeroyfrac=mr_yfrac=viewy-FIXEDMUL(length, zerosine); + x2=0; + } + if (spanx!=x2) { + mr_xfrac=zeroxfrac+mr_xstep *spanx; + mr_yfrac=zeroyfrac+mr_ystep *spanx; + } + mr_dest=viewylookup[span_p->y]+spanx; + mr_picture=span_p->picture; + x2=span_p->x2; + mr_count=x2-spanx; + + MapRow(); + continue; + } + if (span_p->spantype==sp_slope) { // its just a floor/ ceiling + //=============== + // + // sloping floor / ceiling span + // + //=============== + lastz=-1; // we are going to get out of order here, so + + mr_colormap=zcolormap[pointz>>FRACBITS]; + x2=span_p->x2; + mr_dest=viewylookup[span_p->y]+spanx; + mr_picture=span_p->picture; + mr_count=x2-spanx; + // + // calculate starting texture point + // + length=FIXEDDIV(pointz, pixelcosine[spanx]); + angle=viewfineangle+pixelangle[spanx]; + angle&=TANANGLES *4-1; + mr_xfrac=viewx+FIXEDMUL(length, cosines[angle]); + mr_yfrac=viewy-FIXEDMUL(length, sines[angle]); + // + // calculate ending texture point + // (yh is pointz2 for ending point) + length=FIXEDDIV(span_p->yh, pixelcosine[x2]); + angle=viewfineangle+pixelangle[x2]; + angle&=TANANGLES *4-1; + xf2=viewx+FIXEDMUL(length, cosines[angle]); + yf2=viewy-FIXEDMUL(length, sines[angle]); + + mr_xstep=(xf2-mr_xfrac)/mr_count; + mr_ystep=(yf2-mr_yfrac)/mr_count; + MapRow(); + continue; + } + //================ + // + // other spans + // + //================ + if (span_p->spantype==sp_shape) { + DrawSprite(); + continue; + } + if (span_p->spantype==sp_door||span_p->spantype==sp_maskeddoor) { + DrawDoorPost(); + continue; + } + } +} diff --git a/SOURCE/R_WALLS.C b/SOURCE/R_WALLS.C new file mode 100644 index 0000000..0d310f3 --- /dev/null +++ b/SOURCE/R_WALLS.C @@ -0,0 +1,275 @@ +// RV_Walls.c +#include +#include +#include "D_global.h" +#include "R_refdef.h" +#include "d_disk.h" +int angleadjust[4]= +{ + 0, TANANGLES, 0, TANANGLES +}; + + + +fixed_t tangents[TANANGLES *2]; +fixed_t sines[TANANGLES *5]; +fixed_t *cosines; // point 1/4 phase into sines + +int pixelangle[MAX_VIEW_WIDTH+1]; +fixed_t pixelcosine[MAX_VIEW_WIDTH+1]; + +// +// the wall_??[x] arrays are used to determine where a mouse click is +// +int wallnumber[MAX_VIEW_WIDTH]; // tilex<<17 + tiley<<2 + side, -1 = no wall +int walltopy[MAX_VIEW_WIDTH]; +int walltexture[MAX_VIEW_WIDTH]; // 0-63 +fixed_t wallz[MAX_VIEW_WIDTH]; // pointx + +/* */ +/*================== */ +/*= */ +/*= InitWalls */ +/*= */ +/*= Builds tangent tables for -90 degrees to +90 degrees */ +/*= and pixel angle table */ +/*= */ +/*================== */ +/* */ + +void InitWalls(void) +{ + int i; + int intval; + double tang, value, ivalue; + + // + // tangent values for wall tracing + // + for (i=0; ipx to p2->px-1 with wall picture wal*/ +/*= p1/p2 are projected and Z clipped, but unclipped to the view window */ +/*= */ +/*==================== */ +/* */ + +void DrawWall(void) +{ + int baseangle, wallnum; + byte **postindex; // start of the 64 entry texture table for t + fixed_t distance; // horizontal / vertical dist to wall segmen + fixed_t pointz; // transformed distance to wall post + fixed_t anglecos; + fixed_t textureadjust; // the amount the texture p1ane is shifted + fixed_t ceilingheight; // top of the wall + fixed_t floorheight; // bottom of the wall + fixed_t top, bottom; // precise y coordinates for post + int topy, bottomy; // pixel y coordinates for post + fixed_t fracadjust; // the amount to prestep for the top pixel + int angle; // the ray angle that strikes the current po + int texture; // 0-63 post number + int x, x1, x2; // collumn and ranges + int p1mapspot, p2mapspot; + short *wall; + + x1=p1->pxpx; + x2=p2->px-1>xcliph?xcliph : p2->px-1; + if (x1>x2) + return; // totally clipped off side + + // + // set up for loop + // + +#ifdef VALIDATE + if (walltype>=numwalls) + MS_Error("DrawWall: Invalid source walltype"); +#endif + walltype=walltranslation[walltype]; // global animation +#ifdef VALIDATE + if (walltype>=numwalls) + MS_Error("DrawWall: Invalid translated walltype"); +#endif + wall=lumpmain[walllump+walltype]; // to get wall height + postindex=wallposts+((walltype-1)<<6); // 64 pointers to texture st + baseangle=viewfineangle; + wallnum=(tilex<<17)+(tiley<<2)+side; // so a mouse click can be l + + switch (side) { + case 0: // south facing wall + distance=viewy-(tiley<<(FRACBITS+TILESHIFT)); + textureadjust=viewx; + baseangle+=TANANGLES *2; + floorheight=northbottom[mapspot]; + break; + case 1: // west facing wall + distance=((tilex+1)<<(FRACBITS+TILESHIFT))-viewx; + textureadjust=viewy; + baseangle+=TANANGLES; + floorheight=westbottom[mapspot+1]; + break; + case 2: // north facing wall + distance=((tiley+1)<<(FRACBITS+TILESHIFT))-viewy; + textureadjust=-viewx; + baseangle+=TANANGLES *2; + floorheight=northbottom[mapspot+MAPSIZE]; + break; + case 3: // east facing wall + distance=viewx-(tilex<<(FRACBITS+TILESHIFT)); + textureadjust=-viewy; + baseangle+=TANANGLES; + floorheight=westbottom[mapspot]; + break; + } + // + // the floor and ceiling height is the max of the points + // + ceilingheight = floorheight + *wall *4; // based on height of wall pic + //ceilingheight = floorheight + (*wall)*4 *4; + + ceilingheight=(ceilingheight<>FRACBITS; + + texture&=63; + if (x==x1 && texture==63) + texture = 0; // this is a hack to ensure two tile wide + else if (x==x2 && !texture) + texture = 63; // pics don't wrap inside their wall segments + + + sp_source=postindex[texture]; + + // + // the z distance of the post hit = walldistance*cos(screenangle + // + anglecos=cosines[(angle-TANANGLES)&(TANANGLES *4-1)]; + pointz=FIXEDDIV(distance, anglecos); + pointz=FIXEDMUL(pointz, pixelcosine[x]); + + if (pointz>MAXZ) + continue; + + // test to adjust shadowing + + //sp_colormap=zcolormap[pointz>>FRACBITS]; + if (pointz > MAXZ) + continue; + sp_colormap=zcolormap[(pointz>>FRACBITS)]; +//if (*wall > 45) +//sp_colormap=zcolormap[0]; + + // + // calculate the size and scale of the post + // the scale is calculated a little smaller than true to guarant + // any adjacent floors / ceilings + // + sp_fracstep=FIXEDMUL(pointz, ISCALEFUDGE); + + top=FIXEDDIV(ceilingheight, sp_fracstep); + topy=top>>FRACBITS; + fracadjust=top&(FRACUNIT-1); + sp_frac=FIXEDMUL(fracadjust, sp_fracstep); + topy=CENTERY-topy; + + walltopy[x]=topy; + + if (topy<0) { + sp_frac-=topy *sp_fracstep; + topy=0; + } + bottom=FIXEDDIV(floorheight, sp_fracstep)+FRACUNIT; + bottomy=bottom>=(CENTERY<>FRACBITS); + + if ((bottomy<0)||(topy>=windowHeight)) + continue; + + sp_count=bottomy-topy+1; + sp_dest=viewylookup[bottomy]+x; + + ScalePost(); + + wallz[x]=pointz; + wallnumber[x]=wallnum; + walltexture[x]=texture; + } +} diff --git a/SOURCE/SOFT3D.MAP b/SOURCE/SOFT3D.MAP new file mode 100644 index 0000000..527353e Binary files /dev/null and b/SOURCE/SOFT3D.MAP differ diff --git a/SOURCE/SV.EXE b/SOURCE/SV.EXE new file mode 100644 index 0000000..dd0f1a2 Binary files /dev/null and b/SOURCE/SV.EXE differ diff --git a/SOURCE/TODD3D.C b/SOURCE/TODD3D.C new file mode 100644 index 0000000..ad78b1b --- /dev/null +++ b/SOURCE/TODD3D.C @@ -0,0 +1,1101 @@ +// todd3d.c + +/**************************************************************************\ +** ** +** Todd Michael Lewis ** +** Raven Engine Updates ** +**------------------------------------------------------------------------** +** ** +** September 19, 1994 ** +** 1) Enabled door checking whereby door is detected at its actual ** +** recessed position ** +** 2) Enabled door opening with key click while in recessed position ** +** 3) Enabled coding doors to be openable only with certain items ** +** 4) Enabled doors to be opened by bumping or pushing ** +** ** +** September 20, 1994 ** +** 1) Learned how to draw planar bitmaps on screen (for status ** +** updates and text, etc.) ** +** 2) Learned how to update view buffer before display (allows the ** +** display of weapons in foreground) ** +** ** +** September 21, 1994 ** +** 1) Jon optimized routine for blasting bitmaps to viewbuffer which ** +** resulted in a 39% increase in efficiency ** +** ** +** September 22, 1994 ** +** 1) Succesfully changed map then deciphered map structure ** +** 2) Added new tiles succesfully to engine ** +** 3) Discovered door closing problem (would only close if in current ** +** frame rendering); fixed to check for door close separately ** +** 4) Successfully placed mulitiple and differing sprites ** +** ** +** September 23, 1994 ** +** 1) Enabled sprite animation ** +** ** +** September 26, 1994 ** +** 1) Added hit and death animations to sprites ** +** ** +** September 27, 1994 ** +** 1) Enabled successful rendering of walls and ceilings in widths ** +** above 256 ** +** ** +** September 28, 1994 ** +** 1) Enable successful rendering of doors in widths above 256 ** +** ** +** November 21-27, 1994 ** +** 1) Incredible progress with new map editor ** +** 2) Enabled placing of player from map ** +** ** +\**************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "d_global.h" +#include "d_disk.h" +#include "d_misc.h" +#include "d_video.h" +#include "d_ints.h" +#include "d_font.h" + +#include "r_refdef.h" + +#define PLAYERMOVESPEED FRACUNIT +#define PLAYERTURNSPEED 1 + +#define MINDIST (FRACUNIT*4) +#define PLAYERSIZE MINDIST// almost a half tile +#define FRACTILESHIFT (FRACBITS+TILESHIFT) + +#define RED_KEY 1 +#define GREEN_KEY 2 +#define YELLOW_KEY 4 +#define BLUE_KEY 8 + + +fixed_t playerx; +fixed_t playery; +fixed_t playerz; +int playerangle; // 360 degree range spread from 0-ANGLES +int player_keys = 0; + +int tics; + +byte suspendRefresh = 0; +byte resizeScreen = 0; +byte biggerScreen = 0; +byte showBlast = 0; +byte warpActive = 0; +boolean menuActive = false; +byte menuValue = 0; +int keyboardDelay = 0; +int weaponFireDelay = 0; + +int viewSizes[] = +{ + 96, 56, + 128, 72, + 160, 88, + 192, 104, + 224, 120, + 256, 136, + 288, 152, + 320, 168, + 320, 200 +}; +/* +int viewSizes[] = +{ + 320, 200, + 320, 200, + 320, 200, + 320, 200, + 320, 200, + 320, 200, + 320, 200, + 320, 200, + 320, 200 +}; + */ + +byte currentViewSize = 8; + + +int myArray[500]; +int myOffset = 0; + +void ChangeViewSize(byte MakeLarger); +void ResetScalePostWidth (int NewWindowWidth); +void FillRectangle (int x, int y, int width, int height, byte color); +extern void *GetMScaleRoutines (void); +extern void *GetScaleRoutines (void); + + +/* +============================================================================= + + +============================================================================= +*/ + +/* +=================== += += TryDoor += Todd Lewis - 9/13/94 += +=================== +*/ + +boolean TryDoor (fixed_t xcenter, fixed_t ycenter, boolean doorCheck) +{ + int xl,yl,xh,yh,x,y; + struct cellStruct *cs; + doorobj_t *door_p, *last_p; + int dx,dy; + +// These values will probably have to be tweaked for doors that are along +// the vertical opposite axis (northwall) + + xl = (int)((xcenter-PLAYERSIZE) >> FRACTILESHIFT); + yl = (int)((ycenter-PLAYERSIZE - (TILEUNIT >> 1)) >> FRACTILESHIFT); + + xh = (int)((xcenter+PLAYERSIZE) >> FRACTILESHIFT); + yh = (int)((ycenter+PLAYERSIZE - (TILEUNIT >> 1)) >> FRACTILESHIFT); + +// +// check for doors on the north wall +// + for (y=yl+1;y<=yh;y++) + for (x=xl;x<=xh;x++) + { + if (mapflags[y*64+x] & FL_DOOR) // if tile has a door + { + last_p=&doorlist[numdoors]; + + for (door_p=doorlist; door_p != last_p; door_p++) + { + if ((door_p->tilex == x) && + (door_p->tiley == y)) + { + if (door_p->orientation != dr_horizontal) + continue; + if ((door_p->doorOpen) && + (!door_p->doorClosing)) + { + return true; // can move, door is open + } + else if ((!door_p->doorOpen) && + (door_p->doorBumpable)) + { + door_p->doorOpening = true; + return false; + } + else if ((!door_p->doorOpen) || + (door_p->doorClosing)) + return false; + } + } + } + } + +// check for doors on the west wall + + xl = (int)((xcenter-PLAYERSIZE - (TILEUNIT >> 1)) >> FRACTILESHIFT); + yl = (int)((ycenter-PLAYERSIZE) >> FRACTILESHIFT); + + xh = (int)((xcenter+PLAYERSIZE - (TILEUNIT >> 1)) >> FRACTILESHIFT); + yh = (int)((ycenter+PLAYERSIZE) >> FRACTILESHIFT); + + + for (y=yl;y<=yh;y++) + for (x=xl+1;x<=xh;x++) + { + if (mapflags[y*64+x] & FL_DOOR) // if tile has a door + { + last_p=&doorlist[numdoors]; + + for (door_p=doorlist; door_p != last_p; door_p++) + { + if ((door_p->tilex == x) && + (door_p->tiley == y)) + { + if (door_p->orientation != dr_vertical) + continue; + if ((door_p->doorOpen) && + (!door_p->doorClosing)) + { + return true; // can move, door is open + } + else if ((!door_p->doorOpen) && + (door_p->doorBumpable)) + { + door_p->doorOpening = true; + return false; + } + else if ((!door_p->doorOpen) || + (door_p->doorClosing)) + return false; + } + } + } + } + + return true; + +} + +/* +=================== += += TryMove += += returns true if move doesn't go into a solid wall += +=================== +*/ + +boolean TryMove (fixed_t xcenter, fixed_t ycenter) +{ + int xl,yl,xh,yh,x,y; + struct cellStruct *cs; + doorobj_t *doorobj; + int dx,dy; + + xl = (int)((xcenter-PLAYERSIZE) >> FRACTILESHIFT); + yl = (int)((ycenter-PLAYERSIZE) >> FRACTILESHIFT); + + xh = (int)((xcenter+PLAYERSIZE) >> FRACTILESHIFT); + yh = (int)((ycenter+PLAYERSIZE) >> FRACTILESHIFT); +// +// check for solid walls +// + for (y=yl+1;y<=yh;y++) + for (x=xl;x<=xh;x++) + { + if (northwall[y*64+x]) // if tile has a wall + return false; + } + + for (y=yl;y<=yh;y++) + for (x=xl+1;x<=xh;x++) + { + if (westwall[y*64+x]) // if tile has a wall + return false; + } + + return true; +} + +//========================================================================== + +/* +=================== += += ClipMove += +=================== +*/ + +byte ClipMove (fixed_t xmove, fixed_t ymove, fixed_t *x, fixed_t *y) +{ + boolean canMove; + + canMove = (TryMove(*x+xmove,*y+ymove) & + TryDoor(*x+xmove,*y+ymove,false)); + + if (canMove) + { + *x += xmove; + *y += ymove; + return 1; + } + +// +// the move goes into a wall, so try and move along one axis +// + canMove = (TryMove(*x+xmove,*y) & + TryDoor(*x+xmove,*y,false)); + + if (canMove) + { + *x += xmove; + return 2; + } + + canMove = (TryMove(*x,*y+ymove) & + TryDoor(*x,*y+ymove,false)); + + if (canMove) + { + *y += ymove; + return 3; + } + + return 0; +} + +//========================================================================== + +/* +=================== += += Thrust += += Angle is an 8 bit value, speed is a global pixel value += Tries to move the player in the given direction, clipping to walls += if blocked += +=================== +*/ + +byte Thrust (int angle, fixed_t speed, fixed_t *x, fixed_t *y) +{ + fixed_t xmove,ymove; + + angle &= (ANGLES-1); + + xmove = FIXEDMUL(speed,costable[angle]); + ymove = -FIXEDMUL(speed,sintable[angle]); + + return ClipMove(xmove,ymove,x,y); +} + +void MoveSprites(void) +{ + scaleobj_t *sprite; + scaleobj_t *holdSprite; + int picnum; + byte counter; + + for (sprite=firstscaleobj.next; sprite!=&lastscaleobj; + sprite=sprite->next) + { + if (sprite->moveSpeed) + { + counter = 0; + while (counter++ < sprite->moveSpeed) + { + if (Thrust(sprite->angle, PLAYERMOVESPEED, + &sprite->x, &sprite->y) != 1) + { + holdSprite = sprite; + sprite = sprite->prev; + RF_RemoveSprite(holdSprite); + counter = sprite->moveSpeed; + } + } // while + } // if + } +} + + +boolean FindWarpDestination(int *x, int *y, byte warpValue) +{ + int searchX, searchY; + + if (!warpActive) + { + for (searchX = 0; searchX < 64; searchX ++) + for (searchY = 0; searchY < 64; searchY ++) + if ((mapsprites[searchY*64+searchX] == warpValue) && + ((searchX != *x) || (searchY != *y))) + { + *x = searchX; + *y = searchY; + warpActive = warpValue; + + return true; + } // if + } // if + + return false; +} // FindDestinationWarp + +void CheckWarps (int centerx, int centery) +{ + int x, y; + + x = (int)((centerx) >> FRACTILESHIFT); + y = (int)((centery) >> FRACTILESHIFT); + + if ((mapsprites[y*64+x] >= 6) && + (mapsprites[y*64+x] <= 8)) + { + if (FindWarpDestination(&x, &y, mapsprites[y*64+x])) + { + playerx = (x*64+32)*FRACUNIT; + playery = (y*64+32)*FRACUNIT; + } // if + } // if + else + warpActive = 0; + +} // CheckWarps + +void CheckHere (int centerx, int centery, boolean openTheDoor) +{ + // check for door at centerx,centery + int x, y; + doorobj_t *door_p, *last_p; + + x = (int)((centerx) >> FRACTILESHIFT); + y = (int)((centery) >> FRACTILESHIFT); + + if (mapflags[y*64+x] & FL_DOOR) // if tile has a door + { + last_p=&doorlist[numdoors]; + + for (door_p=doorlist; door_p != last_p; door_p++) + { + if ((door_p->tilex == x) && + (door_p->tiley == y)) + { + if ((!door_p->doorOpen) && (openTheDoor))// && + //(player_keys & door_p->doorLocks)) + door_p->doorOpening = true; + } + } + } +} + +void CheckSprites(void) +{ +// +// Added 9-24-94 - Todd Lewis +// + scaleobj_t *sprite; + + for (sprite=firstscaleobj.next; sprite!=&lastscaleobj; + sprite=sprite->next) + { + } +} + +void CheckDoors(fixed_t centerx, fixed_t centery) +{ +// +// Added 9-24-94 - Todd Lewis +// + int x,y; + doorobj_t *door_p, *last_p; + + x = (int)((centerx) >> FRACTILESHIFT); + y = (int)((centery) >> FRACTILESHIFT); + + last_p=&doorlist[numdoors]; + + if ((door_p->tilex == x) && (door_p->tiley == y)) + { + if ((door_p->doorOpen) && (!door_p->doorClosing)) + door_p->doorBlocked = true; + } + else + door_p->doorBlocked = false; + + for (door_p=doorlist; door_p != last_p; door_p++) + { + if ((door_p->tilex == x) && + (door_p->tiley == y)) + { + if ((door_p->doorOpen) && + (!door_p->doorClosing)) + door_p->doorBlocked = true; + } + else + door_p->doorBlocked = false; + + door_p->position = door_p->doorSize * FRACUNIT; + + if (door_p->doorOpening) + { + door_p->doorSize = door_p->doorSize - 4; + if (door_p->doorSize < 0) + { + door_p->doorSize = 0; + door_p->doorOpening = false; + door_p->doorOpen = true; + door_p->doorTimer = timecount + 350; + } + } + else if (door_p->doorClosing) + { + door_p->doorSize = door_p->doorSize + 2; + if (door_p->doorSize > 64) + { + door_p->doorSize = 64; + door_p->doorClosing = false; + door_p->doorOpen = false; + } + } + else if (door_p->doorOpen) + { + if (timecount > door_p->doorTimer) + { + if (!door_p->doorBlocked) + door_p->doorClosing = true; + } + } + } +} // CheckDoors + +void SpawnSprite(byte value, int x, int y) +{ + scaleobj_t *sprite_p; + doorobj_t *door_p; + + + switch (value) + { + case 1: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->moveSpeed = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("chacmool"); + break; + + case 2: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("brazier"); + break; + + case 3: + playerx = (x*64+32)*FRACUNIT; + playery = (y*64+32)*FRACUNIT; + break; + + case 4: // door (temporarily) + door_p = RF_GetDoor (x,y); + door_p->orientation = dr_horizontal; + door_p->doorOpen = false; + door_p->doorOpening = false; + door_p->doorClosing = false; + door_p->doorBlocked = false; + door_p->doorBumpable = false; + door_p->doorSize = 64; + door_p->position = door_p->doorSize*FRACUNIT; + door_p->doorLocks = 0; + door_p->transparent = true; + door_p->pic = CA_GetNamedNum ("wolfdoor") - walllump; + break; + + case 5: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("snake"); + break; + + case 6: + + break; + + case 9: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("urn1"); + break; + + case 10: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("urn2"); + break; + + case 11: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("bowl"); + break; + + case 12: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("cup"); + break; + + case 13: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("jade1"); + break; + + case 14: // door (temporarily) + door_p = RF_GetDoor (x,y); + door_p->orientation = dr_vertical; + door_p->doorOpen = false; + door_p->doorOpening = false; + door_p->doorClosing = false; + door_p->doorBlocked = false; + door_p->doorBumpable = false; + door_p->doorSize = 64; + door_p->position = door_p->doorSize*FRACUNIT; + door_p->doorLocks = 0; + door_p->transparent = true; + door_p->pic = CA_GetNamedNum ("wolfdoor") - walllump; + break; + + case 15: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("ankh"); + break; + + + } // switch + +} // SpawnSprite + +void ActivateSpritesFromMap(void) +{ + int x, y; + + + for (x=0; x<64; x++) + for (y=0; y<64; y++) + { + if (mapsprites[y*64+x]) // sprite or player at this position + SpawnSprite(mapsprites[y*64+x], x, y); + } // for +} // ActivateSpritesFromMap + + +//========================================================================== + +/* +======================= += += ControlMovement += += Takes controlx,controly, and buttonstate[bt_strafe] += += Changes the player's angle and position += +======================= +*/ + +void ControlMovement (void) +{ + fixed_t modifiedSpeed; + int modifiedTurn; + scaleobj_t *sprite_p; + + + if (keyboard[SC_ESCAPE]) + { + MS_Error("Badee, badee, badee ... that's all folks!"); + return; + } + + if ((keyboard[SC_INSERT]) && (!resizeScreen)) + { + if (timecount > keyboardDelay) + { + //ChangeViewSize(true); + resizeScreen = 1; + biggerScreen = true; + keyboardDelay = timecount + 10; + return; + } // if + } + + if ((keyboard[SC_DELETE]) && (!resizeScreen)) + { + if (timecount > keyboardDelay) + { + //ChangeViewSize(false); + resizeScreen = 1; + biggerScreen = false; + keyboardDelay = timecount + 10; + return; + } // if + } + +// adjust movement speed for SLOW OR SPRINT ... TML 9-14-94 + if (keyboard[SC_RSHIFT]) + { + modifiedTurn = 0; + modifiedSpeed = PLAYERMOVESPEED/8; + } + else if (keyboard[SC_LSHIFT]) + { + modifiedSpeed = PLAYERMOVESPEED*4; + modifiedTurn = PLAYERTURNSPEED*4; + } + else + { + modifiedSpeed = PLAYERMOVESPEED*2; + modifiedTurn = PLAYERTURNSPEED*2; + } + +// up / down movement + + if (keyboard[SC_PGUP] && playerz < 252*FRACUNIT) + playerz += FRACUNIT; + if (keyboard[SC_PGDN] && playerz > 4*FRACUNIT) + playerz -= FRACUNIT; + if (keyboard[SC_HOME]) + playerz = 32*FRACUNIT; + +// side to side move + + if (keyboard[SC_ALT]) + { + // + // strafing + // + if (keyboard[SC_LEFTARROW]) + Thrust (playerangle+64,modifiedSpeed,&playerx,&playery); + if (keyboard[SC_RIGHTARROW]) + Thrust (playerangle-64,modifiedSpeed,&playerx,&playery); + } + else + { + // + // not strafing + // + if (keyboard[SC_RIGHTARROW]) + playerangle -= modifiedTurn; + if (keyboard[SC_LEFTARROW]) + playerangle += modifiedTurn; + } + playerangle &= (ANGLES-1); + +// +// forward/backwards move +// + if (keyboard[SC_UPARROW]) + { + Thrust (playerangle,modifiedSpeed,&playerx,&playery); + } + if (keyboard[SC_DOWNARROW]) + { + Thrust (playerangle+128,modifiedSpeed,&playerx,&playery); + } + +// +// try to open a door in front of player +// + if (keyboard[SC_SPACE]) + { + CheckHere(playerx,playery,true); + } + + if (keyboard[SC_CONTROL]) + { + if (timecount > weaponFireDelay) + { + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->animation = 1 + (4 << 5) + (5 << 9); + sprite_p->animationTime = 0; + sprite_p->moveSpeed = 20; + sprite_p->angle = playerangle; + sprite_p->x = playerx; + sprite_p->y = playery; + sprite_p->z = 16*FRACUNIT; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("atk1"); + + weaponFireDelay = timecount + 18; + } + } + +} + +//========================================================================== + +/* +================ += += PlayerCommand += += Called by an interrupt, so if anything time consuming needs to be done, += set actionflag to a non zero value and perform the action in the += ActionHook function += +================ +*/ + +void PlayerCommand (void) +{ + IN_ReadControls (); + ControlMovement (); + tics++; +} + + +/* +================ += += PlayLoop += +================ +*/ + +void PlayLoop (void) +{ + int myTime; // debug purposes + + char test[30]; + + int frametics; + int x; + int i; // get rid off after test + + tics = 0; + INT_TimerHook (PlayerCommand,1); // the players actions are + // sampled by an interrupt + + while (1) + { + MoveSprites(); + CheckDoors(playerx, playery); + CheckWarps(playerx, playery); + + if (resizeScreen) + ChangeViewSize(biggerScreen); + + RF_RenderView (playerx,playery,playerz,playerangle,showBlast); + + if (showBlast) + { + // if (showBlast > 1) + // VI_DrawMaskedPicToBuffer ((windowWidth>>1) - 22, + // windowHeight - 62, + // CA_CacheLump (CA_GetNamedNum ("my_blast") + (3-showBlast))); + showBlast = showBlast - 1; + } + + //myTime = timecount; + + //for (i=0;i<5000;i++) + //VI_DrawMaskedPicToBuffer ((windowWidth>>1) - 64, windowHeight - 32, + // CA_CacheLump (CA_GetNamedNum ("weapons"))); + + if (menuActive) + { + //VI_DrawMaskedPicToBuffer ((windowWidth>>1) - 92, windowHeight - 131, + // CA_CacheLump (CA_GetNamedNum ("menu"))); + //VI_DrawMaskedPicToBuffer ((windowWidth>>1) - 92 + 26, + // windowHeight - 131 + 25 + (menuValue*18), + // CA_CacheLump (CA_GetNamedNum ("binky"))); + } // if + + + //myTime = timecount - myTime; + + RF_BlitView (); + + } +} + + +/* +================ += += ActionHook += += This routine is called by the refresh if actionflag is set, allowing += time consuming functions (like loading something from disk) to be performed += outside an the PlayerCommand function. += +================ +*/ + +void ActionHook (void) +{ + actionflag = 0; +} + + +/* +================ += += LoadNewMap += +================ +*/ + +void LoadNewMap (void) +{ + int lump; + doorobj_t *door_p; + scaleobj_t *sprite_p; + + lump = CA_GetNamedNum("map"); + CA_ReadLump (lump,floorpic); + CA_ReadLump (lump+1,ceilingpic); + CA_ReadLump (lump+2,northwall); + CA_ReadLump (lump+3,westwall); + CA_ReadLump (lump+4,ceilingheight); + CA_ReadLump (lump+5,floorheight); + CA_ReadLump (lump+6,northbottom); + CA_ReadLump (lump+7,westbottom); + CA_ReadLump (lump+8,mapflags); + CA_ReadLump (lump+9,mapsprites); + + // initialize to default in case not placed in mapsprites + playerx = (3*64+32)*FRACUNIT; + playery = (3*64+32)*FRACUNIT; + playerz = 32*FRACUNIT; + playerangle = 64; // face north to start + + ActivateSpritesFromMap(); +} + +/* +================ += += main += +================ +*/ + +void main(int argc, char *argv[]) +{ + int i; +// +// start up the library +// + //player_keys |= RED_KEY | YELLOW_KEY | GREEN_KEY | BLUE_KEY; + CA_InitFile ("TODD3D.TOD"); + + VI_Init(); + VI_FillPalette (0,0,0); + + VI_DrawPic (0,0,CA_CacheLump (CA_GetNamedNum ("playscreen"))); + VI_FadeIn (0,255,CA_CacheLump(CA_GetNamedNum ("palette")),16); + + INT_Setup (); + RF_Startup (); + RF_SetActionHook (ActionHook); + +// +// init the game +// + LoadNewMap (); + + +// +// run the game +// + PlayLoop (); +} + +void ChangeViewSize(byte MakeLarger) +{ + resizeScreen = 0; + + if (MakeLarger) + { + if (currentViewSize < 8) + currentViewSize++; + else + return; + } // if + else + { + if (currentViewSize > 0) + currentViewSize--; + else + return; + } // else + + FillRectangle(0, 0, 320, 200, 0); + + windowWidth = viewSizes[currentViewSize*2]; + windowHeight = viewSizes[currentViewSize*2+1]; + + windowLeft = (320-windowWidth) >> 1; + windowTop = (200-windowHeight) >> 1; + + windowSize = windowHeight*windowWidth; + viewLocation = 0xA0000+windowTop*320+windowLeft; + + ResetScalePostWidth (windowWidth); + InitWalls (); + memset (framevalid, 0, sizeof (framevalid)); + frameon = 0; + + SetViewSize(windowWidth, windowHeight); + RF_SetLights(MAXZ); +} // ChangeViewSize + +void ResetScalePostWidth (int NewWindowWidth) + { + int i; + int *iptr; + byte *bptr; + + bptr = GetScaleRoutines (); + for (i = MAX_VIEW_HEIGHT; i > 1; i--, bptr += 19) + *(int *)(bptr+15) = (i - 1) * -NewWindowWidth; + + iptr = GetMScaleRoutines (); + for (i = MAX_VIEW_HEIGHT; i > 1; i--, iptr += 6) + *(iptr+5) = (i -1) * -NewWindowWidth; + } + +void FillRectangle (int x, int y, int width, int height, byte color) + { + int i; + byte *bptr; + + bptr = (byte *) 0xA0000 + y * 320 + x; + for (i = 0; i < height; i++, bptr += 320) + memset (bptr,color,width); + } diff --git a/SOURCE/TPE.RLL b/SOURCE/TPE.RLL new file mode 100644 index 0000000..8d16b72 Binary files /dev/null and b/SOURCE/TPE.RLL differ diff --git a/SOURCE/VIEWSIZE.H b/SOURCE/VIEWSIZE.H new file mode 100644 index 0000000..9c8c02b --- /dev/null +++ b/SOURCE/VIEWSIZE.H @@ -0,0 +1,7 @@ +#define MAX_VIEW_WIDTH (320) +#define MAX_VIEW_HEIGHT (200) +#define INIT_VIEW_WIDTH (320) +#define INIT_VIEW_HEIGHT (200) +#define VIEW_LEFT (0) +#define VIEW_TOP (0) + diff --git a/SOURCE/VIEWSIZE.INC b/SOURCE/VIEWSIZE.INC new file mode 100644 index 0000000..edc2ea4 --- /dev/null +++ b/SOURCE/VIEWSIZE.INC @@ -0,0 +1,7 @@ +;Filename : viewsize.inc +;Author : Todd Lewis +;Date : September 21, 1994 +;Notes : This must be altered whenever windowsize is changed + +MAXWINDOWWIDTH = 320 +MAXWINDOWHEIGHT = 200 diff --git a/SOURCE/WHATMAKE b/SOURCE/WHATMAKE new file mode 100644 index 0000000..bef187f --- /dev/null +++ b/SOURCE/WHATMAKE @@ -0,0 +1,29 @@ +EXE = todd3d + +AFLAGS = /mx +CFLAGS = /g /t /d2 /O3 /znoansi +LFLAGS = /g /t + +OBJS = todd3d.obj \ + r_public.obj \ + r_spans.obj \ + r_conten.obj \ + r_plane.obj \ + r_render.obj \ + r_walls.obj \ + ra_draw.obj \ + blitbuf.obj \ + d_disk.obj \ + d_ints.obj \ + d_misc.obj \ + d_video.obj + + +$(EXE): $(OBJS) + $(CC) $(LFLAGS) /m /e $(EXE) *.obj mouse.lib + +.c.obj: + $(CC) /c $(CFLAGS) /o $(.TARGET) $(.NEWER) + +.asm.obj: + tasm $(AFLAGS) $(.NEWER),$(.TARGET) diff --git a/TEMP/MENU.DAT b/TEMP/MENU.DAT new file mode 100644 index 0000000..1af2121 Binary files /dev/null and b/TEMP/MENU.DAT differ diff --git a/TEMP/MENU.LBM b/TEMP/MENU.LBM new file mode 100644 index 0000000..2302e20 Binary files /dev/null and b/TEMP/MENU.LBM differ diff --git a/TEMP/TODD3D.C b/TEMP/TODD3D.C new file mode 100644 index 0000000..62e5aea --- /dev/null +++ b/TEMP/TODD3D.C @@ -0,0 +1,1012 @@ +// todd3d.c + +/**************************************************************************\ +** ** +** Todd Michael Lewis ** +** Raven Engine Updates ** +**------------------------------------------------------------------------** +** ** +** September 19, 1994 ** +** 1) Enabled door checking whereby door is detected at its actual ** +** recessed position ** +** 2) Enabled door opening with key click while in recessed position ** +** 3) Enabled coding doors to be openable only with certain items ** +** 4) Enabled doors to be opened by bumping or pushing ** +** ** +** September 20, 1994 ** +** 1) Learned how to draw planar bitmaps on screen (for status ** +** updates and text, etc.) ** +** 2) Learned how to update view buffer before display (allows the ** +** display of weapons in foreground) ** +** ** +** September 21, 1994 ** +** 1) Jon optimized routine for blasting bitmaps to viewbuffer which ** +** resulted in a 39% increase in efficiency ** +** ** +** September 22, 1994 ** +** 1) Succesfully changed map then deciphered map structure ** +** 2) Added new tiles succesfully to engine ** +** 3) Discovered door closing problem (would only close if in current ** +** frame rendering); fixed to check for door close separately ** +** 4) Successfully placed mulitiple and differing sprites ** +** ** +** September 23, 1994 ** +** 1) Enabled sprite animation ** +** ** +** September 26, 1994 ** +** 1) Added hit and death animations to sprites ** +** ** +** September 27, 1994 ** +** 1) Enabled successful rendering of walls and ceilings in widths ** +** above 256 ** +** ** +** September 28, 1994 ** +** 1) Enable successful rendering of doors in widths above 256 ** +** ** +** November 21-27, 1994 ** +** 1) Incredible progress with new map editor ** +** 2) Enabled placing of player from map ** +** ** +\**************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "d_global.h" +#include "d_disk.h" +#include "d_misc.h" +#include "d_video.h" +#include "d_ints.h" +#include "d_font.h" + +#include "r_refdef.h" + +#define PLAYERMOVESPEED FRACUNIT +#define PLAYERTURNSPEED 1 + +#define MINDIST (FRACUNIT*4) +#define PLAYERSIZE MINDIST// almost a half tile +#define FRACTILESHIFT (FRACBITS+TILESHIFT) + +#define RED_KEY 1 +#define GREEN_KEY 2 +#define YELLOW_KEY 4 +#define BLUE_KEY 8 + + +fixed_t playerx; +fixed_t playery; +fixed_t playerz; +int playerangle; // 360 degree range spread from 0-ANGLES +int player_keys = 0; + +int tics; + +byte showBlast = 0; +byte warpActive = 0; +boolean menuActive = false; +byte menuValue = 0; +int keyboardDelay = 0; +int weaponFireDelay = 0; + + +int myArray[500]; +int myOffset = 0; + +/* +============================================================================= + + +============================================================================= +*/ + +/* +=================== += += TryDoor += Todd Lewis - 9/13/94 += +=================== +*/ + +boolean TryDoor (fixed_t xcenter, fixed_t ycenter, boolean doorCheck) +{ + int xl,yl,xh,yh,x,y; + struct cellStruct *cs; + doorobj_t *door_p, *last_p; + int dx,dy; + +// These values will probably have to be tweaked for doors that are along +// the vertical opposite axis (northwall) + + xl = (int)((xcenter-PLAYERSIZE) >> FRACTILESHIFT); + yl = (int)((ycenter-PLAYERSIZE - (TILEUNIT >> 1)) >> FRACTILESHIFT); + + xh = (int)((xcenter+PLAYERSIZE) >> FRACTILESHIFT); + yh = (int)((ycenter+PLAYERSIZE - (TILEUNIT >> 1)) >> FRACTILESHIFT); + +// +// check for doors on the north wall +// + for (y=yl+1;y<=yh;y++) + for (x=xl;x<=xh;x++) + { + if (mapflags[y*64+x] & FL_DOOR) // if tile has a door + { + last_p=&doorlist[numdoors]; + + for (door_p=doorlist; door_p != last_p; door_p++) + { + if ((door_p->tilex == x) && + (door_p->tiley == y)) + { + if (door_p->orientation != dr_horizontal) + continue; + if ((door_p->doorOpen) && + (!door_p->doorClosing)) + { + return true; // can move, door is open + } + else if ((!door_p->doorOpen) && + (door_p->doorBumpable)) + { + door_p->doorOpening = true; + return false; + } + else if ((!door_p->doorOpen) || + (door_p->doorClosing)) + return false; + } + } + } + } + +// check for doors on the west wall + + xl = (int)((xcenter-PLAYERSIZE - (TILEUNIT >> 1)) >> FRACTILESHIFT); + yl = (int)((ycenter-PLAYERSIZE) >> FRACTILESHIFT); + + xh = (int)((xcenter+PLAYERSIZE - (TILEUNIT >> 1)) >> FRACTILESHIFT); + yh = (int)((ycenter+PLAYERSIZE) >> FRACTILESHIFT); + + + for (y=yl;y<=yh;y++) + for (x=xl+1;x<=xh;x++) + { + if (mapflags[y*64+x] & FL_DOOR) // if tile has a door + { + last_p=&doorlist[numdoors]; + + for (door_p=doorlist; door_p != last_p; door_p++) + { + if ((door_p->tilex == x) && + (door_p->tiley == y)) + { + if (door_p->orientation != dr_vertical) + continue; + if ((door_p->doorOpen) && + (!door_p->doorClosing)) + { + return true; // can move, door is open + } + else if ((!door_p->doorOpen) && + (door_p->doorBumpable)) + { + door_p->doorOpening = true; + return false; + } + else if ((!door_p->doorOpen) || + (door_p->doorClosing)) + return false; + } + } + } + } + + return true; + +} + +/* +=================== += += TryMove += += returns true if move doesn't go into a solid wall += +=================== +*/ + +boolean TryMove (fixed_t xcenter, fixed_t ycenter) +{ + int xl,yl,xh,yh,x,y; + struct cellStruct *cs; + doorobj_t *doorobj; + int dx,dy; + + xl = (int)((xcenter-PLAYERSIZE) >> FRACTILESHIFT); + yl = (int)((ycenter-PLAYERSIZE) >> FRACTILESHIFT); + + xh = (int)((xcenter+PLAYERSIZE) >> FRACTILESHIFT); + yh = (int)((ycenter+PLAYERSIZE) >> FRACTILESHIFT); +// +// check for solid walls +// + for (y=yl+1;y<=yh;y++) + for (x=xl;x<=xh;x++) + { + if (northwall[y*64+x]) // if tile has a wall + return false; + } + + for (y=yl;y<=yh;y++) + for (x=xl+1;x<=xh;x++) + { + if (westwall[y*64+x]) // if tile has a wall + return false; + } + + return true; +} + +//========================================================================== + +/* +=================== += += ClipMove += +=================== +*/ + +byte ClipMove (fixed_t xmove, fixed_t ymove, fixed_t *x, fixed_t *y) +{ + boolean canMove; + + canMove = (TryMove(*x+xmove,*y+ymove) & + TryDoor(*x+xmove,*y+ymove,false)); + + if (canMove) + { + *x += xmove; + *y += ymove; + return 1; + } + +// +// the move goes into a wall, so try and move along one axis +// + canMove = (TryMove(*x+xmove,*y) & + TryDoor(*x+xmove,*y,false)); + + if (canMove) + { + *x += xmove; + return 2; + } + + canMove = (TryMove(*x,*y+ymove) & + TryDoor(*x,*y+ymove,false)); + + if (canMove) + { + *y += ymove; + return 3; + } + + return 0; +} + +//========================================================================== + +/* +=================== += += Thrust += += Angle is an 8 bit value, speed is a global pixel value += Tries to move the player in the given direction, clipping to walls += if blocked += +=================== +*/ + +byte Thrust (int angle, fixed_t speed, fixed_t *x, fixed_t *y) +{ + fixed_t xmove,ymove; + + angle &= (ANGLES-1); + + xmove = FIXEDMUL(speed,costable[angle]); + ymove = -FIXEDMUL(speed,sintable[angle]); + + return ClipMove(xmove,ymove,x,y); +} + +void MoveSprites(void) +{ + scaleobj_t *sprite; + scaleobj_t *holdSprite; + int picnum; + byte counter; + + for (sprite=firstscaleobj.next; sprite!=&lastscaleobj; + sprite=sprite->next) + { + if (sprite->moveSpeed) + { + counter = 0; + while (counter++ < sprite->moveSpeed) + { + if (Thrust(sprite->angle, PLAYERMOVESPEED, + &sprite->x, &sprite->y) != 1) + { + holdSprite = sprite; + sprite = sprite->prev; + RF_RemoveSprite(holdSprite); + counter = sprite->moveSpeed; + } + } // while + } // if + } +} + + +boolean FindWarpDestination(int *x, int *y, byte warpValue) +{ + int searchX, searchY; + + if (!warpActive) + { + for (searchX = 0; searchX < 64; searchX ++) + for (searchY = 0; searchY < 64; searchY ++) + if ((mapsprites[searchY*64+searchX] == warpValue) && + ((searchX != *x) || (searchY != *y))) + { + *x = searchX; + *y = searchY; + warpActive = warpValue; + + return true; + } // if + } // if + + return false; +} // FindDestinationWarp + +void CheckWarps (int centerx, int centery) +{ + int x, y; + + x = (int)((centerx) >> FRACTILESHIFT); + y = (int)((centery) >> FRACTILESHIFT); + + if ((mapsprites[y*64+x] >= 6) && + (mapsprites[y*64+x] <= 8)) + { + if (FindWarpDestination(&x, &y, mapsprites[y*64+x])) + { + playerx = (x*64+32)*FRACUNIT; + playery = (y*64+32)*FRACUNIT; + } // if + } // if + else + warpActive = 0; + +} // CheckWarps + +void CheckHere (int centerx, int centery, boolean openTheDoor) +{ + // check for door at centerx,centery + int x, y; + doorobj_t *door_p, *last_p; + + x = (int)((centerx) >> FRACTILESHIFT); + y = (int)((centery) >> FRACTILESHIFT); + + if (mapflags[y*64+x] & FL_DOOR) // if tile has a door + { + last_p=&doorlist[numdoors]; + + for (door_p=doorlist; door_p != last_p; door_p++) + { + if ((door_p->tilex == x) && + (door_p->tiley == y)) + { + if ((!door_p->doorOpen) && (openTheDoor))// && + //(player_keys & door_p->doorLocks)) + door_p->doorOpening = true; + } + } + } +} + +void CheckSprites(void) +{ +// +// Added 9-24-94 - Todd Lewis +// + scaleobj_t *sprite; + + for (sprite=firstscaleobj.next; sprite!=&lastscaleobj; + sprite=sprite->next) + { + } +} + +void CheckDoors(fixed_t centerx, fixed_t centery) +{ +// +// Added 9-24-94 - Todd Lewis +// + int x,y; + doorobj_t *door_p, *last_p; + + x = (int)((centerx) >> FRACTILESHIFT); + y = (int)((centery) >> FRACTILESHIFT); + + last_p=&doorlist[numdoors]; + + if ((door_p->tilex == x) && (door_p->tiley == y)) + { + if ((door_p->doorOpen) && (!door_p->doorClosing)) + door_p->doorBlocked = true; + } + else + door_p->doorBlocked = false; + + for (door_p=doorlist; door_p != last_p; door_p++) + { + if ((door_p->tilex == x) && + (door_p->tiley == y)) + { + if ((door_p->doorOpen) && + (!door_p->doorClosing)) + door_p->doorBlocked = true; + } + else + door_p->doorBlocked = false; + + door_p->position = door_p->doorSize * FRACUNIT; + + if (door_p->doorOpening) + { + door_p->doorSize = door_p->doorSize - 4; + if (door_p->doorSize < 0) + { + door_p->doorSize = 0; + door_p->doorOpening = false; + door_p->doorOpen = true; + door_p->doorTimer = timecount + 350; + } + } + else if (door_p->doorClosing) + { + door_p->doorSize = door_p->doorSize + 2; + if (door_p->doorSize > 64) + { + door_p->doorSize = 64; + door_p->doorClosing = false; + door_p->doorOpen = false; + } + } + else if (door_p->doorOpen) + { + if (timecount > door_p->doorTimer) + { + if (!door_p->doorBlocked) + door_p->doorClosing = true; + } + } + } +} // CheckDoors + +void SpawnSprite(byte value, int x, int y) +{ + scaleobj_t *sprite_p; + doorobj_t *door_p; + + + switch (value) + { + case 1: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->moveSpeed = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("chacmool"); + break; + + case 2: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("brazier"); + break; + + case 3: + playerx = (x*64+32)*FRACUNIT; + playery = (y*64+32)*FRACUNIT; + break; + + case 4: // door (temporarily) + door_p = RF_GetDoor (x,y); + door_p->orientation = dr_horizontal; + door_p->doorOpen = false; + door_p->doorOpening = false; + door_p->doorClosing = false; + door_p->doorBlocked = false; + door_p->doorBumpable = false; + door_p->doorSize = 64; + door_p->position = door_p->doorSize*FRACUNIT; + door_p->doorLocks = 0; + door_p->transparent = true; + door_p->pic = CA_GetNamedNum ("wolfdoor") - walllump; + break; + + case 5: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("snake"); + break; + + case 6: + + break; + + case 9: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("urn1"); + break; + + case 10: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("urn2"); + break; + + case 11: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("bowl"); + break; + + case 12: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("cup"); + break; + + case 13: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("jade1"); + break; + + case 14: // door (temporarily) + door_p = RF_GetDoor (x,y); + door_p->orientation = dr_vertical; + door_p->doorOpen = false; + door_p->doorOpening = false; + door_p->doorClosing = false; + door_p->doorBlocked = false; + door_p->doorBumpable = false; + door_p->doorSize = 64; + door_p->position = door_p->doorSize*FRACUNIT; + door_p->doorLocks = 0; + door_p->transparent = true; + door_p->pic = CA_GetNamedNum ("wolfdoor") - walllump; + break; + + case 15: + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->angle = 0; + sprite_p->x = (x*64+32)*FRACUNIT; + sprite_p->y = (y*64+32)*FRACUNIT; + sprite_p->z = 0; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("ankh"); + break; + + + } // switch + +} // SpawnSprite + +void ActivateSpritesFromMap(void) +{ + int x, y; + + + for (x=0; x<64; x++) + for (y=0; y<64; y++) + { + if (mapsprites[y*64+x]) // sprite or player at this position + SpawnSprite(mapsprites[y*64+x], x, y); + } // for +} // ActivateSpritesFromMap + + +//========================================================================== + +/* +======================= += += ControlMovement += += Takes controlx,controly, and buttonstate[bt_strafe] += += Changes the player's angle and position += +======================= +*/ + +void ControlMovement (void) +{ + fixed_t modifiedSpeed; + int modifiedTurn; + scaleobj_t *sprite_p; + + + if (keyboard[SC_ESCAPE]) + { + if (timecount > keyboardDelay) + { + if (menuActive) + menuActive = false; + else + menuActive = true; + + keyboardDelay = timecount + 20; + } + } + if (menuActive) + { + if (timecount > keyboardDelay) + { + if (keyboard[SC_UPARROW]) + { + if (menuValue) + menuValue--; + else + menuValue = 2; + + keyboardDelay = timecount + 10; + } + else if (keyboard[SC_DOWNARROW]) + { + if (menuValue < 2) + menuValue++; + else + menuValue = 0; + + keyboardDelay = timecount + 10; + } + else if (keyboard[SC_ENTER]) + { + if (menuValue == 2) + MS_Error("Badee, badee, badee ... that's all folks!"); + } + } + + return; + } + +// adjust movement speed for SLOW OR SPRINT ... TML 9-14-94 + if (keyboard[SC_RSHIFT]) + { + modifiedTurn = 0; + modifiedSpeed = PLAYERMOVESPEED/8; + } + else if (keyboard[SC_LSHIFT]) + { + modifiedSpeed = PLAYERMOVESPEED*4; + modifiedTurn = PLAYERTURNSPEED*4; + } + else + { + modifiedSpeed = PLAYERMOVESPEED*2; + modifiedTurn = PLAYERTURNSPEED*2; + } + +// up / down movement + + if (keyboard[SC_PGUP] && playerz < 252*FRACUNIT) + playerz += FRACUNIT; + if (keyboard[SC_PGDN] && playerz > 4*FRACUNIT) + playerz -= FRACUNIT; + if (keyboard[SC_HOME]) + playerz = 32*FRACUNIT; + +// side to side move + + if (keyboard[SC_ALT]) + { + // + // strafing + // + if (keyboard[SC_LEFTARROW]) + Thrust (playerangle+64,modifiedSpeed,&playerx,&playery); + if (keyboard[SC_RIGHTARROW]) + Thrust (playerangle-64,modifiedSpeed,&playerx,&playery); + } + else + { + // + // not strafing + // + if (keyboard[SC_RIGHTARROW]) + playerangle -= modifiedTurn; + if (keyboard[SC_LEFTARROW]) + playerangle += modifiedTurn; + } + playerangle &= (ANGLES-1); + +// +// forward/backwards move +// + if (keyboard[SC_UPARROW]) + { + Thrust (playerangle,modifiedSpeed,&playerx,&playery); + } + if (keyboard[SC_DOWNARROW]) + { + Thrust (playerangle+128,modifiedSpeed,&playerx,&playery); + } + +// +// try to open a door in front of player +// + if (keyboard[SC_SPACE]) + { + CheckHere(playerx,playery,true); + } + + if (keyboard[SC_CONTROL]) + { + if (timecount > weaponFireDelay) + { + sprite_p = RF_GetSprite (); + sprite_p->animation = 0; + sprite_p->animation = 1 + (4 << 5) + (5 << 9); + sprite_p->animationTime = 0; + sprite_p->moveSpeed = 20; + sprite_p->angle = playerangle; + sprite_p->x = playerx; + sprite_p->y = playery; + sprite_p->z = 16*FRACUNIT; + sprite_p->rotate = rt_one; + sprite_p->basepic = CA_GetNamedNum ("atk1"); + + weaponFireDelay = timecount + 18; + } + } + +} + +//========================================================================== + +/* +================ += += PlayerCommand += += Called by an interrupt, so if anything time consuming needs to be done, += set actionflag to a non zero value and perform the action in the += ActionHook function += +================ +*/ + +void PlayerCommand (void) +{ + IN_ReadControls (); + ControlMovement (); + tics++; +} + + +/* +================ += += PlayLoop += +================ +*/ + +void PlayLoop (void) +{ + int myTime; // debug purposes + + char test[30]; + + int frametics; + int x; + int i; // get rid off after test + + tics = 0; + INT_TimerHook (PlayerCommand,1); // the players actions are + // sampled by an interrupt + + while (1) + { + MoveSprites(); + CheckDoors(playerx, playery); + CheckWarps(playerx, playery); + + if (showBlast > 1) + showBlast = 1; + + RF_RenderView (playerx,playery,playerz,playerangle,showBlast); + + if (showBlast) + { + // if (showBlast > 1) + // VI_DrawMaskedPicToBuffer ((windowWidth>>1) - 22, + // windowHeight - 62, + // CA_CacheLump (CA_GetNamedNum ("my_blast") + (3-showBlast))); + showBlast = showBlast - 1; + } + + //myTime = timecount; + + //for (i=0;i<5000;i++) + VI_DrawMaskedPicToBuffer ((windowWidth>>1) - 64, windowHeight - 32, + CA_CacheLump (CA_GetNamedNum ("weapons"))); + + if (menuActive) + { + VI_DrawMaskedPicToBuffer ((windowWidth>>1) - 92, windowHeight - 131, + CA_CacheLump (CA_GetNamedNum ("menu"))); + VI_DrawMaskedPicToBuffer ((windowWidth>>1) - 92 + 26, + windowHeight - 131 + 25 + (menuValue*18), + CA_CacheLump (CA_GetNamedNum ("binky"))); + } // if + + + //myTime = timecount - myTime; + + RF_BlitView (); + + } +} + + +/* +================ += += ActionHook += += This routine is called by the refresh if actionflag is set, allowing += time consuming functions (like loading something from disk) to be performed += outside an the PlayerCommand function. += +================ +*/ + +void ActionHook (void) +{ + actionflag = 0; +} + + +/* +================ += += LoadNewMap += +================ +*/ + +void LoadNewMap (void) +{ + int lump; + doorobj_t *door_p; + scaleobj_t *sprite_p; + + lump = CA_GetNamedNum("map"); + CA_ReadLump (lump,floorpic); + CA_ReadLump (lump+1,ceilingpic); + CA_ReadLump (lump+2,northwall); + CA_ReadLump (lump+3,westwall); + CA_ReadLump (lump+4,ceilingheight); + CA_ReadLump (lump+5,floorheight); + CA_ReadLump (lump+6,northbottom); + CA_ReadLump (lump+7,westbottom); + CA_ReadLump (lump+8,mapflags); + CA_ReadLump (lump+9,mapsprites); + + // initialize to default in case not placed in mapsprites + playerx = (3*64+32)*FRACUNIT; + playery = (3*64+32)*FRACUNIT; + playerz = 32*FRACUNIT; + playerangle = 64; // face north to start + + ActivateSpritesFromMap(); +} + +/* +================ += += main += +================ +*/ + +void main(int argc, char *argv[]) +{ + int i; +// +// start up the library +// + //player_keys |= RED_KEY | YELLOW_KEY | GREEN_KEY | BLUE_KEY; + CA_InitFile ("TODD3D.TOD"); + + VI_Init(); + VI_FillPalette (0,0,0); + + VI_DrawPic (0,0,CA_CacheLump (CA_GetNamedNum ("playscreen"))); + VI_FadeIn (0,255,CA_CacheLump(CA_GetNamedNum ("palette")),16); + + INT_Setup (); + RF_Startup (); + RF_SetActionHook (ActionHook); + +// +// init the game +// + LoadNewMap (); + + +// +// run the game +// + PlayLoop (); +} diff --git a/TODD3D.EXE b/TODD3D.EXE new file mode 100644 index 0000000..08f4ac7 Binary files /dev/null and b/TODD3D.EXE differ diff --git a/TODD3D.MAP b/TODD3D.MAP new file mode 100644 index 0000000..f1e4a36 Binary files /dev/null and b/TODD3D.MAP differ diff --git a/TODD3D.TOD b/TODD3D.TOD new file mode 100644 index 0000000..d0dc423 Binary files /dev/null and b/TODD3D.TOD differ diff --git a/crashing bug.txt b/crashing bug.txt new file mode 100644 index 0000000..ce5c4ee --- /dev/null +++ b/crashing bug.txt @@ -0,0 +1,54 @@ +There's a nasty bug in FlowView in R_Render.c. + +Here's the modified version that was used in Greed: + +void FlowView() +{ + entry_t *process_p, *nextprocess_p; + + process_p=entries; + process_p->tilex=viewtilex; + process_p->tiley=viewtiley; + process_p->mapspot=(viewtiley<<6)+viewtilex; + process_p->xmin=0; + process_p->xmax=windowWidth-1; + entry_p=process_p+1; + memset(entrycount,0,MAPCOLS*MAPROWS*4); + entrycounter=1; + while (process_pmapspot==-1) // entry has been merged + { + process_p++; + continue; + } + + /* check for mergeable entries */ + if (entrycount[process_p->mapspot]>process_p->counter) // mergeable tile + for (nextprocess_p=process_p+1;nextprocess_pmapspot==process_p->mapspot) + { + if (nextprocess_p->xmin==process_p->xmax+1) process_p->xmax=nextprocess_p->xmax; + else if (nextprocess_p->xmax==process_p->xmin-1) process_p->xmin=nextprocess_p->xmin; + else // bad merge! + MS_Error("Bad tile event combination:\n" + " nextprocess_p=%d process_p=%d\n" + " nextprocess_p->xmin=%d nextprocess_p->xmax=%d\n" + " process_p->xmin=%d process_p->xmax=%d\n", + (int)nextprocess_p,(int)process_p, + nextprocess_p->xmin,nextprocess_p->xmax, + process_p->xmin,process_p->xmax); + entrycount[nextprocess_p->mapspot]=0; + nextprocess_p->mapspot=-1; + } + + /* check for a dublicate entry */ + if (entrymap[process_p->mapspot]==frameon) goto end; + + entrymap[process_p->mapspot]=frameon; + RenderTileWalls(process_p); + RenderTileEnds(); +end: + process_p++; + } + } \ No newline at end of file