summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ac.dsp106
-rw-r--r--Ac.plg40
-rw-r--r--Cfilearchiver.dsp90
-rw-r--r--Cfilearchiver.plg32
-rw-r--r--Cryptstring.dsp89
-rw-r--r--Cryptstring.plg32
-rw-r--r--FS2AutoRun.icobin0 -> 3310 bytes
-rw-r--r--Fonttool.dsp110
-rw-r--r--Fonttool.plg46
-rw-r--r--Fred2.dsp593
-rw-r--r--Fred2.plg77
-rw-r--r--Freespace2.dsp140
-rw-r--r--Freespace2.plg803
-rw-r--r--HelpEd.dsp167
-rw-r--r--HelpEd.exebin0 -> 79653 bytes
-rw-r--r--HelpEd.plg52
-rw-r--r--Nebedit.dsp99
-rw-r--r--Nebedit.plg37
-rw-r--r--Pofview.dsp179
-rw-r--r--Pofview.plg58
-rw-r--r--Scramble.dsp94
-rw-r--r--Scramble.plg33
-rw-r--r--code/AC/ac.cpp224
-rw-r--r--code/AC/ac.h36
-rw-r--r--code/AC/ac_stubs.cpp141
-rw-r--r--code/AC/convert.cpp788
-rw-r--r--code/AC/convert.h99
-rw-r--r--code/Anim/AnimPlay.cpp1312
-rw-r--r--code/Anim/AnimPlay.h145
-rw-r--r--code/Anim/PackUnpack.cpp1275
-rw-r--r--code/Anim/PackUnpack.h247
-rw-r--r--code/Asteroid/Asteroid.cpp2271
-rw-r--r--code/Asteroid/Asteroid.h258
-rw-r--r--code/Bmpman/BmpMan.cpp2561
-rw-r--r--code/Bmpman/BmpMan.h351
-rw-r--r--code/CFile/CfileArchive.cpp278
-rw-r--r--code/CFile/CfileArchive.h75
-rw-r--r--code/CFile/CfileList.cpp484
-rw-r--r--code/CFile/CfileSystem.cpp1122
-rw-r--r--code/CFile/CfileSystem.h72
-rw-r--r--code/CFile/cfile.cpp1647
-rw-r--r--code/CFile/cfile.h600
-rw-r--r--code/CMeasure/CMeasure.cpp486
-rw-r--r--code/CMeasure/CMeasure.h167
-rw-r--r--code/Cfilearchiver/CfileArchiver.cpp279
-rw-r--r--code/Cmdline/cmdline.cpp592
-rw-r--r--code/Cmdline/cmdline.h185
-rw-r--r--code/ControlConfig/ControlsConfig.cpp2535
-rw-r--r--code/ControlConfig/ControlsConfig.h486
-rw-r--r--code/ControlConfig/ControlsConfigCommon.cpp864
-rw-r--r--code/Cryptstring/cryptstring.cpp78
-rw-r--r--code/Cutscene/Cutscenes.cpp747
-rw-r--r--code/Cutscene/Cutscenes.h81
-rw-r--r--code/Debris/Debris.cpp1268
-rw-r--r--code/Debris/Debris.h200
-rw-r--r--code/DebugConsole/Console.cpp796
-rw-r--r--code/Demo/Demo.cpp1002
-rw-r--r--code/Demo/Demo.h109
-rw-r--r--code/DirectX/vD3d.h896
-rw-r--r--code/DirectX/vD3dcaps.h313
-rw-r--r--code/DirectX/vD3dtypes.h1201
-rw-r--r--code/DirectX/vDdraw.h3791
-rw-r--r--code/DirectX/vDdraw.libbin0 -> 14628 bytes
-rw-r--r--code/DirectX/vDinput.h1849
-rw-r--r--code/DirectX/vDinput.libbin0 -> 15336 bytes
-rw-r--r--code/DirectX/vDsound.h863
-rw-r--r--code/DirectX/vDsound.libbin0 -> 5646 bytes
-rw-r--r--code/DirectX/vDxguid.libbin0 -> 56332 bytes
-rw-r--r--code/DirectX/vasync.h131
-rw-r--r--code/DirectX/vd3di.h793
-rw-r--r--code/DirectX/vd3drm.h229
-rw-r--r--code/DirectX/vd3drmdef.h472
-rw-r--r--code/DirectX/vd3drmobj.h1100
-rw-r--r--code/DirectX/vd3drmwin.h48
-rw-r--r--code/DirectX/vd3dvec.inl240
-rw-r--r--code/DirectX/vdplay.h1710
-rw-r--r--code/DirectX/vdplobby.h627
-rw-r--r--code/DirectX/vdsetup.h267
-rw-r--r--code/DirectX/vdvp.h831
-rw-r--r--code/ExceptionHandler/ExceptionHandler.cpp508
-rw-r--r--code/ExceptionHandler/ExceptionHandler.h87
-rw-r--r--code/FRED2/AddVariableDlg.cpp228
-rw-r--r--code/FRED2/AddVariableDlg.h67
-rw-r--r--code/FRED2/AdjustGridDlg.cpp167
-rw-r--r--code/FRED2/AdjustGridDlg.h78
-rw-r--r--code/FRED2/AsteroidEditorDlg.cpp679
-rw-r--r--code/FRED2/AsteroidEditorDlg.h85
-rw-r--r--code/FRED2/BgBitmapDlg.cpp886
-rw-r--r--code/FRED2/BgBitmapDlg.h190
-rw-r--r--code/FRED2/BriefingEditorDlg.cpp1438
-rw-r--r--code/FRED2/BriefingEditorDlg.h231
-rw-r--r--code/FRED2/CampaignEditorDlg.cpp885
-rw-r--r--code/FRED2/CampaignEditorDlg.h118
-rw-r--r--code/FRED2/CampaignFilelistBox.cpp87
-rw-r--r--code/FRED2/CampaignFilelistBox.h47
-rw-r--r--code/FRED2/CampaignTreeView.cpp1338
-rw-r--r--code/FRED2/CampaignTreeView.h115
-rw-r--r--code/FRED2/CampaignTreeWnd.cpp570
-rw-r--r--code/FRED2/CampaignTreeWnd.h130
-rw-r--r--code/FRED2/CmdBrief.cpp346
-rw-r--r--code/FRED2/CmdBrief.h97
-rw-r--r--code/FRED2/CreateWingDlg.cpp117
-rw-r--r--code/FRED2/CreateWingDlg.h45
-rw-r--r--code/FRED2/DebriefingEditorDlg.cpp507
-rw-r--r--code/FRED2/DebriefingEditorDlg.h119
-rw-r--r--code/FRED2/DumpStats.cpp917
-rw-r--r--code/FRED2/DumpStats.h64
-rw-r--r--code/FRED2/EventEditor.cpp1597
-rw-r--r--code/FRED2/EventEditor.h250
-rw-r--r--code/FRED2/FRED.APSbin0 -> 143592 bytes
-rw-r--r--code/FRED2/FRED.cpp828
-rw-r--r--code/FRED2/FRED.h217
-rw-r--r--code/FRED2/FRED.rc2934
-rw-r--r--code/FRED2/FREDDoc.cpp1051
-rw-r--r--code/FRED2/FREDDoc.h174
-rw-r--r--code/FRED2/FREDView.cpp4825
-rw-r--r--code/FRED2/FREDView.h524
-rw-r--r--code/FRED2/FredRender.cpp1847
-rw-r--r--code/FRED2/FredRender.h151
-rw-r--r--code/FRED2/FredStubs.cpp639
-rw-r--r--code/FRED2/Grid.cpp230
-rw-r--r--code/FRED2/Grid.h83
-rw-r--r--code/FRED2/IgnoreOrdersDlg.cpp367
-rw-r--r--code/FRED2/IgnoreOrdersDlg.h86
-rw-r--r--code/FRED2/InitialShips.cpp168
-rw-r--r--code/FRED2/InitialShips.h53
-rw-r--r--code/FRED2/InitialStatus.cpp608
-rw-r--r--code/FRED2/InitialStatus.h78
-rw-r--r--code/FRED2/MainFrm.cpp716
-rw-r--r--code/FRED2/MainFrm.h158
-rw-r--r--code/FRED2/MakeHelp.bat31
-rw-r--r--code/FRED2/Management.cpp2661
-rw-r--r--code/FRED2/Management.h348
-rw-r--r--code/FRED2/MessageEditorDlg.cpp693
-rw-r--r--code/FRED2/MessageEditorDlg.h129
-rw-r--r--code/FRED2/MissionGoalsDlg.cpp796
-rw-r--r--code/FRED2/MissionGoalsDlg.h171
-rw-r--r--code/FRED2/MissionNotesDlg.cpp492
-rw-r--r--code/FRED2/MissionNotesDlg.h160
-rw-r--r--code/FRED2/MissionSave.cpp2748
-rw-r--r--code/FRED2/MissionSave.h144
-rw-r--r--code/FRED2/ModifyVariableDlg.cpp494
-rw-r--r--code/FRED2/ModifyVariableDlg.h81
-rw-r--r--code/FRED2/OperatorArgTypeSelect.cpp100
-rw-r--r--code/FRED2/OperatorArgTypeSelect.h72
-rw-r--r--code/FRED2/OrientEditor.cpp344
-rw-r--r--code/FRED2/OrientEditor.h105
-rw-r--r--code/FRED2/PlayerStartEditor.cpp387
-rw-r--r--code/FRED2/PlayerStartEditor.h146
-rw-r--r--code/FRED2/PrefsDlg.cpp120
-rw-r--r--code/FRED2/PrefsDlg.h78
-rw-r--r--code/FRED2/ReinforcementEditorDlg.cpp468
-rw-r--r--code/FRED2/ReinforcementEditorDlg.h152
-rw-r--r--code/FRED2/Sexp_tree.cpp5537
-rw-r--r--code/FRED2/Sexp_tree.h258
-rw-r--r--code/FRED2/ShieldSysDlg.cpp199
-rw-r--r--code/FRED2/ShieldSysDlg.h75
-rw-r--r--code/FRED2/ShipCheckListBox.cpp73
-rw-r--r--code/FRED2/ShipCheckListBox.h53
-rw-r--r--code/FRED2/ShipClassEditorDlg.cpp129
-rw-r--r--code/FRED2/ShipClassEditorDlg.h97
-rw-r--r--code/FRED2/ShipEditorDlg.cpp2170
-rw-r--r--code/FRED2/ShipEditorDlg.h263
-rw-r--r--code/FRED2/ShipFlagsDlg.cpp700
-rw-r--r--code/FRED2/ShipFlagsDlg.h84
-rw-r--r--code/FRED2/ShipGoalsDlg.cpp1384
-rw-r--r--code/FRED2/ShipGoalsDlg.h142
-rw-r--r--code/FRED2/ShipSpecialDamage.cpp213
-rw-r--r--code/FRED2/ShipSpecialDamage.h67
-rw-r--r--code/FRED2/StarfieldEditor.cpp137
-rw-r--r--code/FRED2/StarfieldEditor.h85
-rw-r--r--code/FRED2/StdAfx.cpp42
-rw-r--r--code/FRED2/TextViewDlg.cpp111
-rw-r--r--code/FRED2/TextViewDlg.h45
-rw-r--r--code/FRED2/WaypointPathDlg.cpp453
-rw-r--r--code/FRED2/WaypointPathDlg.h88
-rw-r--r--code/FRED2/WeaponEditorDlg.cpp673
-rw-r--r--code/FRED2/WeaponEditorDlg.h129
-rw-r--r--code/FRED2/dialog1.cpp72
-rw-r--r--code/FRED2/dialog1.h67
-rw-r--r--code/FRED2/editor.h48
-rw-r--r--code/FRED2/hlp/AFXHELP.HM272
-rw-r--r--code/FRED2/hlp/AfxCore.rtf23
-rw-r--r--code/FRED2/hlp/AfxPrint.rtf98
-rw-r--r--code/FRED2/hlp/AppExit.bmpbin0 -> 2262 bytes
-rw-r--r--code/FRED2/hlp/Bullet.bmpbin0 -> 142 bytes
-rw-r--r--code/FRED2/hlp/CurArw2.bmpbin0 -> 310 bytes
-rw-r--r--code/FRED2/hlp/CurArw4.bmpbin0 -> 566 bytes
-rw-r--r--code/FRED2/hlp/CurHelp.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/EditCopy.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/EditCut.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/EditPast.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/EditUndo.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/FileNew.bmpbin0 -> 566 bytes
-rw-r--r--code/FRED2/hlp/FileOpen.bmpbin0 -> 566 bytes
-rw-r--r--code/FRED2/hlp/FilePrnt.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/FileSave.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/Fred.hpj65
-rw-r--r--code/FRED2/hlp/HlpSBar.bmpbin0 -> 7158 bytes
-rw-r--r--code/FRED2/hlp/HlpTBar.bmpbin0 -> 2354 bytes
-rw-r--r--code/FRED2/hlp/RecFirst.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/RecLast.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/RecNext.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/RecPrev.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/ScMenu.bmpbin0 -> 2134 bytes
-rw-r--r--code/FRED2/hlp/Scmax.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/Scmin.bmpbin0 -> 502 bytes
-rw-r--r--code/FRED2/hlp/fred.hm351
-rw-r--r--code/FRED2/hlp/help.log0
-rw-r--r--code/FRED2/res/FRED.icobin0 -> 3310 bytes
-rw-r--r--code/FRED2/res/FRED.rc213
-rw-r--r--code/FRED2/res/FREDDoc.icobin0 -> 3310 bytes
-rw-r--r--code/FRED2/res/Toolbar.bmpbin0 -> 5178 bytes
-rw-r--r--code/FRED2/res/bitmap1.bmpbin0 -> 246 bytes
-rw-r--r--code/FRED2/res/black_do.bmpbin0 -> 246 bytes
-rw-r--r--code/FRED2/res/bmp00001.bmpbin0 -> 162 bytes
-rw-r--r--code/FRED2/res/chained.bmpbin0 -> 246 bytes
-rw-r--r--code/FRED2/res/chained_directive.bmpbin0 -> 246 bytes
-rw-r--r--code/FRED2/res/cursor1.curbin0 -> 326 bytes
-rw-r--r--code/FRED2/res/cursor2.curbin0 -> 326 bytes
-rw-r--r--code/FRED2/res/data.bmpbin0 -> 246 bytes
-rw-r--r--code/FRED2/res/green_do.bmpbin0 -> 246 bytes
-rw-r--r--code/FRED2/res/root.bmpbin0 -> 246 bytes
-rw-r--r--code/FRED2/res/root_directive.bmpbin0 -> 246 bytes
-rw-r--r--code/FRED2/res/toolbar1.bmpbin0 -> 2234 bytes
-rw-r--r--code/FRED2/res/variable.bmpbin0 -> 246 bytes
-rw-r--r--code/FRED2/resource.h1173
-rw-r--r--code/FRED2/resource.hm5
-rw-r--r--code/FRED2/ship_select.cpp598
-rw-r--r--code/FRED2/ship_select.h119
-rw-r--r--code/FRED2/stdafx.h48
-rw-r--r--code/FRED2/wing.cpp764
-rw-r--r--code/FRED2/wing.h61
-rw-r--r--code/FRED2/wing_editor.cpp1380
-rw-r--r--code/FRED2/wing_editor.h206
-rw-r--r--code/FREESPACE2/FreeSpace.cpp8566
-rw-r--r--code/FREESPACE2/FreeSpace.h351
-rw-r--r--code/FREESPACE2/FreeSpace.rc376
-rw-r--r--code/FREESPACE2/FreespaceResource.h93
-rw-r--r--code/FREESPACE2/LevelPaging.cpp110
-rw-r--r--code/FREESPACE2/LevelPaging.h37
-rw-r--r--code/FREESPACE2/app_icon.icobin0 -> 3310 bytes
-rw-r--r--code/FREESPACE2/goal_com.bmpbin0 -> 246 bytes
-rw-r--r--code/FREESPACE2/goal_fail.bmpbin0 -> 246 bytes
-rw-r--r--code/FREESPACE2/goal_inc.bmpbin0 -> 246 bytes
-rw-r--r--code/FREESPACE2/goal_none.bmpbin0 -> 246 bytes
-rw-r--r--code/FREESPACE2/goal_ord.bmpbin0 -> 246 bytes
-rw-r--r--code/Fireball/FireBalls.cpp1168
-rw-r--r--code/Fireball/FireBalls.h203
-rw-r--r--code/Fireball/WarpInEffect.cpp264
-rw-r--r--code/Fonttool/FontCreate.cpp598
-rw-r--r--code/Fonttool/FontKern.cpp602
-rw-r--r--code/Fonttool/FontKernCopy.cpp63
-rw-r--r--code/Fonttool/FontStubs.cpp105
-rw-r--r--code/Fonttool/FontTool.cpp129
-rw-r--r--code/Fonttool/FontTool.h49
-rw-r--r--code/Fonttool/FontTool.pcxbin0 -> 94669 bytes
-rw-r--r--code/GameHelp/ContextHelp.cpp907
-rw-r--r--code/GameHelp/ContextHelp.h63
-rw-r--r--code/GameHelp/GameplayHelp.cpp948
-rw-r--r--code/GameHelp/GameplayHelp.h40
-rw-r--r--code/GameSequence/GameSequence.cpp620
-rw-r--r--code/GameSequence/GameSequence.h488
-rw-r--r--code/Gamesnd/EventMusic.cpp1486
-rw-r--r--code/Gamesnd/EventMusic.h217
-rw-r--r--code/Gamesnd/GameSnd.cpp420
-rw-r--r--code/Gamesnd/GameSnd.h571
-rw-r--r--code/Glide/3DFX.H97
-rw-r--r--code/Glide/FXDLL.H111
-rw-r--r--code/Glide/FXGLOB.H19
-rw-r--r--code/Glide/FXOS.H38
-rw-r--r--code/Glide/Glide.cpp452
-rw-r--r--code/Glide/SST1VID.H105
-rw-r--r--code/Glide/glide.h1365
-rw-r--r--code/Glide/glidesys.h113
-rw-r--r--code/Glide/glideutl.h118
-rw-r--r--code/GlobalIncs/AlphaColors.cpp74
-rw-r--r--code/GlobalIncs/AlphaColors.h58
-rw-r--r--code/GlobalIncs/LinkList.h101
-rw-r--r--code/GlobalIncs/PsTypes.h693
-rw-r--r--code/GlobalIncs/SystemVars.cpp706
-rw-r--r--code/GlobalIncs/SystemVars.h343
-rw-r--r--code/GlobalIncs/WinDebug.cpp1207
-rw-r--r--code/GlobalIncs/crypt.cpp55
-rw-r--r--code/GlobalIncs/crypt.h47
-rw-r--r--code/GlobalIncs/version.cpp147
-rw-r--r--code/GlobalIncs/version.h157
-rw-r--r--code/Graphics/2d.cpp1359
-rw-r--r--code/Graphics/2d.h718
-rw-r--r--code/Graphics/Bitblt.cpp496
-rw-r--r--code/Graphics/Bitblt.h42
-rw-r--r--code/Graphics/Circle.cpp102
-rw-r--r--code/Graphics/Circle.h44
-rw-r--r--code/Graphics/Colors.cpp612
-rw-r--r--code/Graphics/Colors.h58
-rw-r--r--code/Graphics/Font.cpp890
-rw-r--r--code/Graphics/Font.h152
-rw-r--r--code/Graphics/GrD3D.cpp3051
-rw-r--r--code/Graphics/GrD3D.h65
-rw-r--r--code/Graphics/GrD3DInternal.h219
-rw-r--r--code/Graphics/GrD3DRender.cpp2264
-rw-r--r--code/Graphics/GrD3DTexture.cpp1409
-rw-r--r--code/Graphics/GrDirectDraw.cpp1292
-rw-r--r--code/Graphics/GrDirectDraw.h38
-rw-r--r--code/Graphics/GrGlide.cpp3764
-rw-r--r--code/Graphics/GrGlide.h42
-rw-r--r--code/Graphics/GrGlideInternal.h63
-rw-r--r--code/Graphics/GrGlideTexture.cpp1058
-rw-r--r--code/Graphics/GrInternal.h216
-rw-r--r--code/Graphics/GrOpenGL.cpp730
-rw-r--r--code/Graphics/GrOpenGL.h42
-rw-r--r--code/Graphics/GrSoft.cpp1849
-rw-r--r--code/Graphics/GrSoft.h61
-rw-r--r--code/Graphics/GrZbuffer.cpp116
-rw-r--r--code/Graphics/GrZbuffer.h53
-rw-r--r--code/Graphics/Gradient.cpp200
-rw-r--r--code/Graphics/Gradient.h58
-rw-r--r--code/Graphics/Line.cpp192
-rw-r--r--code/Graphics/Line.h217
-rw-r--r--code/Graphics/Pixel.cpp105
-rw-r--r--code/Graphics/Pixel.h65
-rw-r--r--code/Graphics/Rect.cpp132
-rw-r--r--code/Graphics/Rect.h44
-rw-r--r--code/Graphics/Scaler.cpp1145
-rw-r--r--code/Graphics/Scaler.h64
-rw-r--r--code/Graphics/Shade.cpp256
-rw-r--r--code/Graphics/Shade.h58
-rw-r--r--code/Graphics/TMAPPER.H127
-rw-r--r--code/Graphics/TmapGenericScans.cpp6950
-rw-r--r--code/Graphics/TmapScanTiled128x128.cpp1244
-rw-r--r--code/Graphics/TmapScanTiled16x16.cpp1285
-rw-r--r--code/Graphics/TmapScanTiled256x256.cpp2242
-rw-r--r--code/Graphics/TmapScanTiled32x32.cpp1284
-rw-r--r--code/Graphics/TmapScanTiled64x64.cpp1290
-rw-r--r--code/Graphics/TmapScanline.cpp4520
-rw-r--r--code/Graphics/TmapScanline.h195
-rw-r--r--code/Graphics/Tmapper.cpp881
-rw-r--r--code/Graphics/aaline.cpp679
-rw-r--r--code/HelpEd/HelpEd.cpp166
-rw-r--r--code/HelpEd/HelpEd.h58
-rw-r--r--code/HelpEd/HelpEd.rc357
-rw-r--r--code/HelpEd/HelpEdDoc.cpp124
-rw-r--r--code/HelpEd/HelpEdDoc.h71
-rw-r--r--code/HelpEd/HelpEdLine.cpp50
-rw-r--r--code/HelpEd/HelpEdLine.h34
-rw-r--r--code/HelpEd/HelpEdView.cpp109
-rw-r--r--code/HelpEd/HelpEdView.h74
-rw-r--r--code/HelpEd/MainFrm.cpp114
-rw-r--r--code/HelpEd/MainFrm.h69
-rw-r--r--code/HelpEd/Resource.h19
-rw-r--r--code/HelpEd/StdAfx.cpp17
-rw-r--r--code/HelpEd/StdAfx.h35
-rw-r--r--code/HelpEd/Tga.cpp27
-rw-r--r--code/HelpEd/Tga.h20
-rw-r--r--code/HelpEd/res/HelpEd.icobin0 -> 1078 bytes
-rw-r--r--code/HelpEd/res/HelpEd.rc213
-rw-r--r--code/HelpEd/res/HelpEdDoc.icobin0 -> 1078 bytes
-rw-r--r--code/HelpEd/res/Toolbar.bmpbin0 -> 1078 bytes
-rw-r--r--code/Hud/HUD.cpp3162
-rw-r--r--code/Hud/HUD.h413
-rw-r--r--code/Hud/HUDObserver.cpp82
-rw-r--r--code/Hud/HUDObserver.h40
-rw-r--r--code/Hud/HUDWingmanStatus.cpp867
-rw-r--r--code/Hud/HUDWingmanStatus.h56
-rw-r--r--code/Hud/HUDbrackets.cpp773
-rw-r--r--code/Hud/HUDbrackets.h89
-rw-r--r--code/Hud/HUDconfig.cpp2071
-rw-r--r--code/Hud/HUDconfig.h216
-rw-r--r--code/Hud/HUDescort.cpp1014
-rw-r--r--code/Hud/HUDescort.h86
-rw-r--r--code/Hud/HUDets.cpp903
-rw-r--r--code/Hud/HUDets.h75
-rw-r--r--code/Hud/HUDgauges.h125
-rw-r--r--code/Hud/HUDlock.cpp1244
-rw-r--r--code/Hud/HUDlock.h82
-rw-r--r--code/Hud/HUDmessage.cpp1569
-rw-r--r--code/Hud/HUDmessage.h201
-rw-r--r--code/Hud/HUDresource.cpp0
-rw-r--r--code/Hud/HUDresource.h0
-rw-r--r--code/Hud/HUDreticle.cpp840
-rw-r--r--code/Hud/HUDreticle.h66
-rw-r--r--code/Hud/HUDshield.cpp851
-rw-r--r--code/Hud/HUDshield.h89
-rw-r--r--code/Hud/HUDsquadmsg.cpp2743
-rw-r--r--code/Hud/HUDsquadmsg.h218
-rw-r--r--code/Hud/HUDtarget.cpp5544
-rw-r--r--code/Hud/HUDtarget.h415
-rw-r--r--code/Hud/HUDtargetbox.cpp1925
-rw-r--r--code/Hud/HUDtargetbox.h171
-rw-r--r--code/Hud/HudArtillery.cpp361
-rw-r--r--code/Hud/HudArtillery.h50
-rw-r--r--code/Inetfile/CFtp.cpp565
-rw-r--r--code/Inetfile/CFtp.h102
-rw-r--r--code/Inetfile/Chttpget.cpp780
-rw-r--r--code/Inetfile/Chttpget.h114
-rw-r--r--code/Inetfile/inetgetfile.cpp287
-rw-r--r--code/Inetfile/inetgetfile.h122
-rw-r--r--code/Io/Joy.cpp1461
-rw-r--r--code/Io/Joy.h118
-rw-r--r--code/Io/Joy_ff.cpp815
-rw-r--r--code/Io/Joy_ff.h61
-rw-r--r--code/Io/Key.cpp1162
-rw-r--r--code/Io/Key.h249
-rw-r--r--code/Io/KeyControl.cpp2862
-rw-r--r--code/Io/KeyControl.h74
-rw-r--r--code/Io/Mouse.cpp732
-rw-r--r--code/Io/Mouse.h126
-rw-r--r--code/Io/Timer.cpp560
-rw-r--r--code/Io/Timer.h184
-rw-r--r--code/Io/sw_error.hpp144
-rw-r--r--code/Io/sw_force.h476
-rw-r--r--code/Io/sw_guid.hpp296
-rw-r--r--code/Io/swff_lib.cpp2485
-rw-r--r--code/JumpNode/JumpNode.cpp138
-rw-r--r--code/JumpNode/JumpNode.h53
-rw-r--r--code/Lighting/Lighting.cpp1012
-rw-r--r--code/Lighting/Lighting.h131
-rw-r--r--code/Localization/fhash.cpp233
-rw-r--r--code/Localization/fhash.h59
-rw-r--r--code/Localization/localize.cpp1620
-rw-r--r--code/Localization/localize.h152
-rw-r--r--code/Math/Fix.cpp53
-rw-r--r--code/Math/Floating.cpp199
-rw-r--r--code/Math/Floating.h142
-rw-r--r--code/Math/Fvi.cpp1555
-rw-r--r--code/Math/Fvi.h193
-rw-r--r--code/Math/StaticRand.cpp131
-rw-r--r--code/Math/StaticRand.h57
-rw-r--r--code/Math/VecMat.cpp2833
-rw-r--r--code/Math/VecMat.h646
-rw-r--r--code/Math/fix.h47
-rw-r--r--code/Math/spline.cpp316
-rw-r--r--code/Math/spline.h101
-rw-r--r--code/MenuUI/Barracks.cpp1668
-rw-r--r--code/MenuUI/Barracks.h38
-rw-r--r--code/MenuUI/Credits.cpp759
-rw-r--r--code/MenuUI/Credits.h41
-rw-r--r--code/MenuUI/MainHallMenu.cpp2156
-rw-r--r--code/MenuUI/MainHallMenu.h93
-rw-r--r--code/MenuUI/MainHallTemp.cpp277
-rw-r--r--code/MenuUI/MainHallTemp.h48
-rw-r--r--code/MenuUI/OptionsMenu.cpp1733
-rw-r--r--code/MenuUI/OptionsMenu.h92
-rw-r--r--code/MenuUI/OptionsMenuMulti.cpp2534
-rw-r--r--code/MenuUI/OptionsMenuMulti.h75
-rw-r--r--code/MenuUI/PlayerMenu.cpp1523
-rw-r--r--code/MenuUI/PlayerMenu.h73
-rw-r--r--code/MenuUI/ReadyRoom.cpp1903
-rw-r--r--code/MenuUI/ReadyRoom.h51
-rw-r--r--code/MenuUI/SnazzyUI.cpp477
-rw-r--r--code/MenuUI/SnazzyUI.h104
-rw-r--r--code/MenuUI/TechMenu.cpp1670
-rw-r--r--code/MenuUI/TechMenu.h94
-rw-r--r--code/MenuUI/TrainingMenu.cpp226
-rw-r--r--code/MenuUI/TrainingMenu.h62
-rw-r--r--code/MenuUI/fishtank.cpp271
-rw-r--r--code/MenuUI/fishtank.h34
-rw-r--r--code/Mission/MissionBriefCommon.cpp2590
-rw-r--r--code/Mission/MissionBriefCommon.h416
-rw-r--r--code/Mission/MissionCampaign.cpp1874
-rw-r--r--code/Mission/MissionCampaign.h480
-rw-r--r--code/Mission/MissionGoals.cpp1686
-rw-r--r--code/Mission/MissionGoals.h249
-rw-r--r--code/Mission/MissionGrid.cpp337
-rw-r--r--code/Mission/MissionGrid.h87
-rw-r--r--code/Mission/MissionHotKey.cpp1440
-rw-r--r--code/Mission/MissionHotKey.h73
-rw-r--r--code/Mission/MissionLoad.cpp563
-rw-r--r--code/Mission/MissionLoad.h61
-rw-r--r--code/Mission/MissionLog.cpp1016
-rw-r--r--code/Mission/MissionLog.h181
-rw-r--r--code/Mission/MissionMessage.cpp2097
-rw-r--r--code/Mission/MissionMessage.h381
-rw-r--r--code/Mission/MissionParse.cpp5122
-rw-r--r--code/Mission/MissionParse.h555
-rw-r--r--code/Mission/MissionTraining.cpp1186
-rw-r--r--code/Mission/MissionTraining.h64
-rw-r--r--code/MissionUI/Chatbox.cpp1394
-rw-r--r--code/MissionUI/Chatbox.h147
-rw-r--r--code/MissionUI/MissionBrief.cpp2264
-rw-r--r--code/MissionUI/MissionBrief.h177
-rw-r--r--code/MissionUI/MissionCmdBrief.cpp817
-rw-r--r--code/MissionUI/MissionCmdBrief.h77
-rw-r--r--code/MissionUI/MissionDebrief.cpp2847
-rw-r--r--code/MissionUI/MissionDebrief.h87
-rw-r--r--code/MissionUI/MissionLoopBrief.cpp293
-rw-r--r--code/MissionUI/MissionLoopBrief.h48
-rw-r--r--code/MissionUI/MissionPause.cpp319
-rw-r--r--code/MissionUI/MissionPause.h61
-rw-r--r--code/MissionUI/MissionRecommend.cpp28
-rw-r--r--code/MissionUI/MissionRecommend.h36
-rw-r--r--code/MissionUI/MissionScreenCommon.cpp1572
-rw-r--r--code/MissionUI/MissionScreenCommon.h209
-rw-r--r--code/MissionUI/MissionShipChoice.cpp3390
-rw-r--r--code/MissionUI/MissionShipChoice.h295
-rw-r--r--code/MissionUI/MissionStats.cpp28
-rw-r--r--code/MissionUI/MissionStats.h33
-rw-r--r--code/MissionUI/MissionWeaponChoice.cpp3832
-rw-r--r--code/MissionUI/MissionWeaponChoice.h176
-rw-r--r--code/MissionUI/RedAlert.cpp937
-rw-r--r--code/MissionUI/RedAlert.h71
-rw-r--r--code/Model/MODEL.H1110
-rw-r--r--code/Model/ModelCollide.cpp1050
-rw-r--r--code/Model/ModelInterp.cpp3318
-rw-r--r--code/Model/ModelOctant.cpp561
-rw-r--r--code/Model/ModelRead.cpp3434
-rw-r--r--code/Model/ModelsInc.h82
-rw-r--r--code/Nebula/Neb.cpp1851
-rw-r--r--code/Nebula/Neb.h158
-rw-r--r--code/Nebula/NebLightning.cpp1328
-rw-r--r--code/Nebula/NebLightning.h112
-rw-r--r--code/Network/Multi.cpp1972
-rw-r--r--code/Network/Multi.h1107
-rw-r--r--code/Network/MultiMsgs.cpp8065
-rw-r--r--code/Network/MultiTeamSelect.cpp3161
-rw-r--r--code/Network/MultiTeamSelect.h213
-rw-r--r--code/Network/MultiUI.cpp9441
-rw-r--r--code/Network/MultiUI.h457
-rw-r--r--code/Network/MultiUtil.cpp4046
-rw-r--r--code/Network/MultiUtil.h362
-rw-r--r--code/Network/PsNet.cpp3095
-rw-r--r--code/Network/PsNet.h329
-rw-r--r--code/Network/Psnet2.cpp2595
-rw-r--r--code/Network/Psnet2.h229
-rw-r--r--code/Network/multi_campaign.cpp928
-rw-r--r--code/Network/multi_campaign.h114
-rw-r--r--code/Network/multi_data.cpp532
-rw-r--r--code/Network/multi_data.h81
-rw-r--r--code/Network/multi_dogfight.cpp540
-rw-r--r--code/Network/multi_dogfight.h54
-rw-r--r--code/Network/multi_endgame.cpp745
-rw-r--r--code/Network/multi_endgame.h125
-rw-r--r--code/Network/multi_ingame.cpp2126
-rw-r--r--code/Network/multi_ingame.h237
-rw-r--r--code/Network/multi_kick.cpp367
-rw-r--r--code/Network/multi_kick.h79
-rw-r--r--code/Network/multi_log.cpp237
-rw-r--r--code/Network/multi_log.h62
-rw-r--r--code/Network/multi_obj.cpp1996
-rw-r--r--code/Network/multi_obj.h101
-rw-r--r--code/Network/multi_observer.cpp292
-rw-r--r--code/Network/multi_observer.h70
-rw-r--r--code/Network/multi_oo.cpp2093
-rw-r--r--code/Network/multi_oo.h138
-rw-r--r--code/Network/multi_options.cpp791
-rw-r--r--code/Network/multi_options.h238
-rw-r--r--code/Network/multi_pause.cpp547
-rw-r--r--code/Network/multi_pause.h93
-rw-r--r--code/Network/multi_pinfo.cpp939
-rw-r--r--code/Network/multi_pinfo.h64
-rw-r--r--code/Network/multi_ping.cpp203
-rw-r--r--code/Network/multi_ping.h90
-rw-r--r--code/Network/multi_pmsg.cpp865
-rw-r--r--code/Network/multi_pmsg.h127
-rw-r--r--code/Network/multi_rate.cpp259
-rw-r--r--code/Network/multi_rate.h53
-rw-r--r--code/Network/multi_respawn.cpp1022
-rw-r--r--code/Network/multi_respawn.h86
-rw-r--r--code/Network/multi_team.cpp990
-rw-r--r--code/Network/multi_team.h142
-rw-r--r--code/Network/multi_update.cpp313
-rw-r--r--code/Network/multi_update.h55
-rw-r--r--code/Network/multi_voice.cpp2337
-rw-r--r--code/Network/multi_voice.h166
-rw-r--r--code/Network/multi_xfer.cpp1340
-rw-r--r--code/Network/multi_xfer.h171
-rw-r--r--code/Network/multilag.cpp747
-rw-r--r--code/Network/multilag.h105
-rw-r--r--code/Network/multimsgs.h704
-rw-r--r--code/Network/stand_gui.cpp2383
-rw-r--r--code/Network/stand_gui.h327
-rw-r--r--code/Object/CollideDebrisShip.cpp449
-rw-r--r--code/Object/CollideDebrisWeapon.cpp141
-rw-r--r--code/Object/CollideShipShip.cpp1901
-rw-r--r--code/Object/CollideShipWeapon.cpp516
-rw-r--r--code/Object/CollideWeaponWeapon.cpp166
-rw-r--r--code/Object/ObjCollide.cpp1144
-rw-r--r--code/Object/ObjCollide.h230
-rw-r--r--code/Object/Object.cpp2154
-rw-r--r--code/Object/Object.h598
-rw-r--r--code/Object/ObjectSnd.cpp1059
-rw-r--r--code/Object/ObjectSnd.h94
-rw-r--r--code/Object/ObjectSort.cpp342
-rw-r--r--code/Observer/Observer.cpp118
-rw-r--r--code/Observer/Observer.h51
-rw-r--r--code/OsApi/MONOPUB.H58
-rw-r--r--code/OsApi/OsApi.cpp699
-rw-r--r--code/OsApi/OsApi.h74
-rw-r--r--code/OsApi/OsRegistry.cpp497
-rw-r--r--code/OsApi/OsRegistry.h62
-rw-r--r--code/OsApi/OutWnd.cpp1360
-rw-r--r--code/OsApi/OutWnd.h25
-rw-r--r--code/Palman/PalMan.cpp860
-rw-r--r--code/Palman/PalMan.h111
-rw-r--r--code/Parse/Encrypt.cpp459
-rw-r--r--code/Parse/Encrypt.h59
-rw-r--r--code/Parse/PARSELO.CPP1882
-rw-r--r--code/Parse/SEXP.CPP9667
-rw-r--r--code/Parse/SEXP.H829
-rw-r--r--code/Parse/parselo.h357
-rw-r--r--code/Particle/Particle.cpp777
-rw-r--r--code/Particle/Particle.h150
-rw-r--r--code/PcxUtils/pcxutils.cpp724
-rw-r--r--code/PcxUtils/pcxutils.h94
-rw-r--r--code/Physics/Physics.cpp1387
-rw-r--r--code/Physics/Physics.h273
-rw-r--r--code/Playerman/ManagePilot.cpp1389
-rw-r--r--code/Playerman/ManagePilot.h175
-rw-r--r--code/Playerman/Player.h393
-rw-r--r--code/Playerman/PlayerControl.cpp2290
-rw-r--r--code/Popup/Popup.cpp1310
-rw-r--r--code/Popup/Popup.h196
-rw-r--r--code/Popup/PopupDead.cpp679
-rw-r--r--code/Popup/PopupDead.h51
-rw-r--r--code/Radar/Radar.cpp864
-rw-r--r--code/Radar/Radar.h65
-rw-r--r--code/Render/3D.H338
-rw-r--r--code/Render/3dClipper.cpp323
-rw-r--r--code/Render/3dInternal.h72
-rw-r--r--code/Render/3dLaser.cpp467
-rw-r--r--code/Render/3dMath.cpp417
-rw-r--r--code/Render/3dSetup.cpp438
-rw-r--r--code/Render/3ddraw.cpp1843
-rw-r--r--code/Scramble/scramble.cpp320
-rw-r--r--code/Scramble/scramble.h47
-rw-r--r--code/Ship/AWACS.cpp551
-rw-r--r--code/Ship/AWACS.h70
-rw-r--r--code/Ship/Afterburner.cpp453
-rw-r--r--code/Ship/Afterburner.h66
-rw-r--r--code/Ship/AiBig.cpp1896
-rw-r--r--code/Ship/AiBig.h84
-rw-r--r--code/Ship/AiCode.cpp15290
-rw-r--r--code/Ship/AiGoals.cpp2320
-rw-r--r--code/Ship/AiGoals.h231
-rw-r--r--code/Ship/AiLocal.h16
-rw-r--r--code/Ship/Shield.cpp1248
-rw-r--r--code/Ship/Ship.cpp9462
-rw-r--r--code/Ship/Ship.h1251
-rw-r--r--code/Ship/ShipContrails.cpp272
-rw-r--r--code/Ship/ShipContrails.h60
-rw-r--r--code/Ship/ShipFX.cpp2974
-rw-r--r--code/Ship/ShipFX.h243
-rw-r--r--code/Ship/ShipHit.cpp2487
-rw-r--r--code/Ship/ShipHit.h146
-rw-r--r--code/Ship/SubsysDamage.h81
-rw-r--r--code/Ship/ai.cpp102
-rw-r--r--code/Ship/ai.h720
-rw-r--r--code/Sound/AudioStr.cpp1928
-rw-r--r--code/Sound/AudioStr.h145
-rw-r--r--code/Sound/RBAudio.cpp719
-rw-r--r--code/Sound/RBAudio.h80
-rw-r--r--code/Sound/Sound.cpp1531
-rw-r--r--code/Sound/Sound.h366
-rw-r--r--code/Sound/WinMIDI.cpp30
-rw-r--r--code/Sound/WinMIDI.h35
-rw-r--r--code/Sound/acm.cpp369
-rw-r--r--code/Sound/acm.h63
-rw-r--r--code/Sound/channel.h75
-rw-r--r--code/Sound/ds.cpp2702
-rw-r--r--code/Sound/ds.h300
-rw-r--r--code/Sound/ds3d.cpp345
-rw-r--r--code/Sound/ds3d.h61
-rw-r--r--code/Sound/dscap.cpp370
-rw-r--r--code/Sound/dscap.h54
-rw-r--r--code/Sound/midifile.cpp31
-rw-r--r--code/Sound/midifile.h37
-rw-r--r--code/Sound/midiseq.h156
-rw-r--r--code/Sound/rtvoice.cpp704
-rw-r--r--code/Sound/rtvoice.h94
-rw-r--r--code/Sound/winmidi_base.cpp30
-rw-r--r--code/Starfield/Nebula.cpp350
-rw-r--r--code/Starfield/Nebula.h53
-rw-r--r--code/Starfield/StarField.cpp1407
-rw-r--r--code/Starfield/StarField.h185
-rw-r--r--code/Starfield/Supernova.cpp408
-rw-r--r--code/Starfield/Supernova.h96
-rw-r--r--code/Stats/Medals.cpp740
-rw-r--r--code/Stats/Medals.h113
-rw-r--r--code/Stats/Scoring.cpp1194
-rw-r--r--code/Stats/Scoring.h312
-rw-r--r--code/Stats/Stats.cpp513
-rw-r--r--code/Stats/Stats.h87
-rw-r--r--code/TgaUtils/TgaUtils.cpp769
-rw-r--r--code/TgaUtils/TgaUtils.h57
-rw-r--r--code/UI/BUTTON.cpp627
-rw-r--r--code/UI/CHECKBOX.cpp250
-rw-r--r--code/UI/GADGET.cpp747
-rw-r--r--code/UI/INPUTBOX.cpp716
-rw-r--r--code/UI/KEYTRAP.cpp75
-rw-r--r--code/UI/LISTBOX.cpp609
-rw-r--r--code/UI/RADIO.cpp273
-rw-r--r--code/UI/SCROLL.cpp391
-rw-r--r--code/UI/SLIDER2.cpp345
-rw-r--r--code/UI/UI.H1046
-rw-r--r--code/UI/UIDRAW.cpp154
-rw-r--r--code/UI/UIMOUSE.cpp139
-rw-r--r--code/UI/UiDefs.h117
-rw-r--r--code/UI/WINDOW.cpp939
-rw-r--r--code/UI/icon.cpp151
-rw-r--r--code/UI/slider.cpp605
-rw-r--r--code/VCodec/CODEC1.CPP1964
-rw-r--r--code/VCodec/CODEC1.H133
-rw-r--r--code/Weapon/Beam.cpp3261
-rw-r--r--code/Weapon/Beam.h236
-rw-r--r--code/Weapon/Corkscrew.cpp372
-rw-r--r--code/Weapon/Corkscrew.h43
-rw-r--r--code/Weapon/Emp.cpp682
-rw-r--r--code/Weapon/Emp.h147
-rw-r--r--code/Weapon/Flak.cpp310
-rw-r--r--code/Weapon/Flak.h76
-rw-r--r--code/Weapon/MuzzleFlash.cpp302
-rw-r--r--code/Weapon/MuzzleFlash.h74
-rw-r--r--code/Weapon/Shockwave.cpp650
-rw-r--r--code/Weapon/Shockwave.h143
-rw-r--r--code/Weapon/Swarm.cpp701
-rw-r--r--code/Weapon/Swarm.h65
-rw-r--r--code/Weapon/Trails.cpp469
-rw-r--r--code/Weapon/Trails.h81
-rw-r--r--code/Weapon/Weapon.h611
-rw-r--r--code/Weapon/Weapons.cpp3728
-rw-r--r--code/code.dsp2479
-rw-r--r--code/nebedit/NebEdit.cpp973
-rw-r--r--code/nebedit/Nebstubs.cpp91
-rw-r--r--code/pofview/ChildFrm.cpp77
-rw-r--r--code/pofview/ChildFrm.h50
-rw-r--r--code/pofview/MainFrm.cpp116
-rw-r--r--code/pofview/MainFrm.h54
-rw-r--r--code/pofview/ObjectTree.cpp294
-rw-r--r--code/pofview/ObjectTree.h74
-rw-r--r--code/pofview/PofView.cpp415
-rw-r--r--code/pofview/PofView.h59
-rw-r--r--code/pofview/PofView.rc520
-rw-r--r--code/pofview/PofViewDoc.cpp96
-rw-r--r--code/pofview/PofViewDoc.h54
-rw-r--r--code/pofview/PofViewStubs.cpp115
-rw-r--r--code/pofview/PofViewView.cpp863
-rw-r--r--code/pofview/PofViewView.h148
-rw-r--r--code/pofview/StdAfx.cpp15
-rw-r--r--code/pofview/StdAfx.h25
-rw-r--r--code/pofview/res/PofView.icobin0 -> 766 bytes
-rw-r--r--code/pofview/res/PofView.rc213
-rw-r--r--code/pofview/res/PofViewDoc.icobin0 -> 766 bytes
-rw-r--r--code/pofview/res/Toolbar.bmpbin0 -> 2278 bytes
-rw-r--r--code/pofview/resource.h60
-rw-r--r--freespace2.dsw173
-rw-r--r--freespace2.optbin0 -> 118272 bytes
-rw-r--r--fs.log0
-rw-r--r--guided_tour.txt176
-rw-r--r--interesting_stats.txt58
-rw-r--r--release_log.txt24
750 files changed, 474559 insertions, 0 deletions
diff --git a/Ac.dsp b/Ac.dsp
new file mode 100644
index 0000000..b5155da
--- /dev/null
+++ b/Ac.dsp
@@ -0,0 +1,106 @@
+# Microsoft Developer Studio Project File - Name="Ac" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Ac - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Ac.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Ac.mak" CFG="Ac - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Ac - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Ac - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Freespace2", ZNCCAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Ac - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "AcRelease"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /U "_DEBUG" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /libpath:"release"
+
+!ELSEIF "$(CFG)" == "Ac - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Ac___Win32_Debug"
+# PROP BASE Intermediate_Dir "Ac___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "AcDebug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G5 /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib vfw32.lib wsock32.lib msacm32.lib winmm.lib comctl32.lib code.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /pdbtype:sept /libpath:"debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Ac - Win32 Release"
+# Name "Ac - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\code\AC\ac.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\AC\ac.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\AC\ac_stubs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\AC\convert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\AC\convert.h
+# End Source File
+# End Target
+# End Project
diff --git a/Ac.plg b/Ac.plg
new file mode 100644
index 0000000..fe2f79d
--- /dev/null
+++ b/Ac.plg
@@ -0,0 +1,40 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: Ac - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP33F.tmp" with contents
+[
+/nologo /G5 /MLd /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"AcDebug/" /Fd"AcDebug/" /FD /GZ /c
+"C:\projects\freespace2_public\code\AC\ac.cpp"
+"C:\projects\freespace2_public\code\AC\ac_stubs.cpp"
+"C:\projects\freespace2_public\code\AC\convert.cpp"
+]
+Creating command line "cwcl.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP33F.tmp"
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP340.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib vfw32.lib wsock32.lib msacm32.lib winmm.lib comctl32.lib code.lib /nologo /subsystem:console /incremental:yes /pdb:"Ac.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /out:"Ac.exe" /pdbtype:sept /libpath:"debug"
+.\AcDebug\ac.obj
+.\AcDebug\ac_stubs.obj
+.\AcDebug\convert.obj
+.\Debug\code.lib
+]
+Creating command line "cwlink.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP340.tmp"
+<h3>Output Window</h3>
+Compiling...
+ac.cpp
+ac_stubs.cpp
+convert.cpp
+Generating Code...
+Linking...
+
+
+
+<h3>Results</h3>
+Ac.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
diff --git a/Cfilearchiver.dsp b/Cfilearchiver.dsp
new file mode 100644
index 0000000..1aae1d3
--- /dev/null
+++ b/Cfilearchiver.dsp
@@ -0,0 +1,90 @@
+# Microsoft Developer Studio Project File - Name="Cfilearchiver" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Cfilearchiver - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Cfilearchiver.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Cfilearchiver.mak" CFG="Cfilearchiver - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Cfilearchiver - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Cfilearchiver - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Freespace2", FPCCAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Cfilearchiver - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "CFileArchiverRelease"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /U "_DEBUG" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "Cfilearchiver - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Cfilearchiver___Win32_Debug"
+# PROP BASE Intermediate_Dir "Cfilearchiver___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "CFileArchiverDebug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G5 /W4 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Cfilearchiver - Win32 Release"
+# Name "Cfilearchiver - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\code\Cfilearchiver\CfileArchiver.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/Cfilearchiver.plg b/Cfilearchiver.plg
new file mode 100644
index 0000000..226a15e
--- /dev/null
+++ b/Cfilearchiver.plg
@@ -0,0 +1,32 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: Cfilearchiver - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP342.tmp" with contents
+[
+/nologo /G5 /MLd /W4 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"CFileArchiverDebug/" /Fd"CFileArchiverDebug/" /FD /GZ /c
+"C:\projects\freespace2_public\code\Cfilearchiver\CfileArchiver.cpp"
+]
+Creating command line "cwcl.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP342.tmp"
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP343.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"Cfilearchiver.pdb" /debug /machine:I386 /out:"Cfilearchiver.exe" /pdbtype:sept
+.\CFileArchiverDebug\CfileArchiver.obj
+]
+Creating command line "cwlink.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP343.tmp"
+<h3>Output Window</h3>
+Compiling...
+CfileArchiver.cpp
+Linking...
+
+
+
+<h3>Results</h3>
+Cfilearchiver.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
diff --git a/Cryptstring.dsp b/Cryptstring.dsp
new file mode 100644
index 0000000..d22d71f
--- /dev/null
+++ b/Cryptstring.dsp
@@ -0,0 +1,89 @@
+# Microsoft Developer Studio Project File - Name="Cryptstring" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Cryptstring - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Cryptstring.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Cryptstring.mak" CFG="Cryptstring - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Cryptstring - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Cryptstring - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Freespace2", KPCCAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Cryptstring - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "CryptstringRelease"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /U "_DEBUG" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "Cryptstring - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Cryptstring___Win32_Debug"
+# PROP BASE Intermediate_Dir "Cryptstring___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "CryptstringDebug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G5 /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Cryptstring - Win32 Release"
+# Name "Cryptstring - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\code\Cryptstring\cryptstring.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/Cryptstring.plg b/Cryptstring.plg
new file mode 100644
index 0000000..d0f9fcd
--- /dev/null
+++ b/Cryptstring.plg
@@ -0,0 +1,32 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: Cryptstring - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP345.tmp" with contents
+[
+/nologo /G5 /MLd /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"CryptstringDebug/" /Fd"CryptstringDebug/" /FD /GZ /c
+"C:\projects\freespace2_public\code\Cryptstring\cryptstring.cpp"
+]
+Creating command line "cwcl.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP345.tmp"
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP346.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"Cryptstring.pdb" /debug /machine:I386 /out:"Cryptstring.exe" /pdbtype:sept
+.\CryptstringDebug\cryptstring.obj
+]
+Creating command line "cwlink.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP346.tmp"
+<h3>Output Window</h3>
+Compiling...
+cryptstring.cpp
+Linking...
+
+
+
+<h3>Results</h3>
+Cryptstring.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
diff --git a/FS2AutoRun.ico b/FS2AutoRun.ico
new file mode 100644
index 0000000..3c8ce7e
--- /dev/null
+++ b/FS2AutoRun.ico
Binary files differ
diff --git a/Fonttool.dsp b/Fonttool.dsp
new file mode 100644
index 0000000..6778ca5
--- /dev/null
+++ b/Fonttool.dsp
@@ -0,0 +1,110 @@
+# Microsoft Developer Studio Project File - Name="Fonttool" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Fonttool - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Fonttool.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Fonttool.mak" CFG="Fonttool - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Fonttool - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Fonttool - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Freespace2", WPCCAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Fonttool - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "FonttoolRelease"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /U "_DEBUG" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /libpath:"release"
+
+!ELSEIF "$(CFG)" == "Fonttool - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Fonttool___Win32_Debug"
+# PROP BASE Intermediate_Dir "Fonttool___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "FonttoolDebug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G5 /MTd /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib comctl32.lib winmm.lib msacm32.lib code.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /pdbtype:sept /libpath:"debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Fonttool - Win32 Release"
+# Name "Fonttool - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\code\Fonttool\FontCreate.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\Fonttool\FontKern.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\Fonttool\FontKernCopy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\Fonttool\FontStubs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\Fonttool\FontTool.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\Fonttool\FontTool.h
+# End Source File
+# End Target
+# End Project
diff --git a/Fonttool.plg b/Fonttool.plg
new file mode 100644
index 0000000..96d21b6
--- /dev/null
+++ b/Fonttool.plg
@@ -0,0 +1,46 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: Fonttool - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP348.tmp" with contents
+[
+/nologo /G5 /MTd /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"FonttoolDebug/" /Fd"FonttoolDebug/" /FD /GZ /c
+"C:\projects\freespace2_public\code\Fonttool\FontCreate.cpp"
+"C:\projects\freespace2_public\code\Fonttool\FontKern.cpp"
+"C:\projects\freespace2_public\code\Fonttool\FontKernCopy.cpp"
+"C:\projects\freespace2_public\code\Fonttool\FontStubs.cpp"
+"C:\projects\freespace2_public\code\Fonttool\FontTool.cpp"
+]
+Creating command line "cwcl.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP348.tmp"
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP349.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib comctl32.lib winmm.lib msacm32.lib code.lib /nologo /subsystem:console /incremental:yes /pdb:"Fonttool.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /out:"Fonttool.exe" /pdbtype:sept /libpath:"debug"
+.\FonttoolDebug\FontCreate.obj
+.\FonttoolDebug\FontKern.obj
+.\FonttoolDebug\FontKernCopy.obj
+.\FonttoolDebug\FontStubs.obj
+.\FonttoolDebug\FontTool.obj
+.\Debug\code.lib
+]
+Creating command line "cwlink.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP349.tmp"
+<h3>Output Window</h3>
+Compiling...
+FontCreate.cpp
+FontKern.cpp
+FontKernCopy.cpp
+FontStubs.cpp
+FontTool.cpp
+Generating Code...
+Linking...
+
+
+
+<h3>Results</h3>
+Fonttool.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
diff --git a/Fred2.dsp b/Fred2.dsp
new file mode 100644
index 0000000..35883e7
--- /dev/null
+++ b/Fred2.dsp
@@ -0,0 +1,593 @@
+# Microsoft Developer Studio Project File - Name="fred2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=fred2 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Fred2.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Fred2.mak" CFG="fred2 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "fred2 - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "fred2 - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Freespace2", RHWBAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "fred2 - Win32 Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /G5 /MT /W4 /GX /Ot /Ow /Og /Oi /Oy /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /FI"PSTypes.h" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "FRED" /U "_DEBUG" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 winmm.lib vfw32.lib msacm32.lib code.lib wsock32.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmtd.lib" /nodefaultlib:"nafxcwd.lib" /out:"E:\games\Freespace2\Fred2.exe" /libpath:"release"
+# SUBTRACT LINK32 /debug
+
+!ELSEIF "$(CFG)" == "fred2 - Win32 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "fred2___Win32_Debug"
+# PROP BASE Intermediate_Dir "fred2___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "FredDebug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /G5 /MDd /W4 /GX /ZI /Od /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /FI"PSTypes.h" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_AFXDLL" /U "NDEBUG" /FR /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo "./FredDebug/*.sbr"
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 winmm.lib vfw32.lib msacm32.lib wsock32.lib code.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmtd.lib" /nodefaultlib:"nafxcwd.lib" /out:"e:\games\freespace2\Fred2.exe" /pdbtype:sept /libpath:"debug"
+# SUBTRACT LINK32 /incremental:no
+
+!ENDIF
+
+# Begin Target
+
+# Name "fred2 - Win32 Release"
+# Name "fred2 - Win32 Debug"
+# Begin Group "res"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\code\fred2\res\bitmap1.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\res\black_do.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\res\bmp00001.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\res\chained.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\res\chained_directive.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\res\cursor1.cur
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\res\cursor2.cur
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\res\data.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\res\FRED.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\FRED.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\res\FRED.rc2
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\res\FREDDoc.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\res\green_do.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\resource.hm
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\res\root.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\res\root_directive.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\res\Toolbar.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\res\toolbar1.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\res\variable.bmp
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\code\FRED2\AddVariableDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\AddVariableDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\AdjustGridDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\AdjustGridDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\AsteroidEditorDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\AsteroidEditorDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\BgBitmapDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\BgBitmapDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\BriefingEditorDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\BriefingEditorDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CampaignEditorDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CampaignEditorDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CampaignFilelistBox.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CampaignFilelistBox.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CampaignTreeView.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CampaignTreeView.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CampaignTreeWnd.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CampaignTreeWnd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CmdBrief.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CmdBrief.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CreateWingDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\CreateWingDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\DebriefingEditorDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\DebriefingEditorDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\dialog1.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\dialog1.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\DumpStats.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\fred2\DumpStats.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\editor.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\EventEditor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\EventEditor.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\FRED.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\FRED.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\FREDDoc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\FREDDoc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\FredRender.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\FredRender.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\FredStubs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\FREDView.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\FREDView.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\Grid.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\Grid.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\IgnoreOrdersDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\IgnoreOrdersDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\InitialShips.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\InitialShips.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\InitialStatus.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\InitialStatus.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\MainFrm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\MainFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\Management.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\Management.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\MessageEditorDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\MessageEditorDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\MissionGoalsDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\MissionGoalsDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\MissionNotesDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\MissionNotesDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\MissionSave.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\MissionSave.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ModifyVariableDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ModifyVariableDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\OperatorArgTypeSelect.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\OperatorArgTypeSelect.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\OrientEditor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\OrientEditor.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\PlayerStartEditor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\PlayerStartEditor.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\PrefsDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\PrefsDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ReinforcementEditorDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ReinforcementEditorDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\Sexp_tree.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\Sexp_tree.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShieldSysDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShieldSysDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ship_select.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ship_select.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipCheckListBox.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipCheckListBox.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipClassEditorDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipClassEditorDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipEditorDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipEditorDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipFlagsDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipFlagsDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipGoalsDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipGoalsDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipSpecialDamage.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\ShipSpecialDamage.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\StarfieldEditor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\StarfieldEditor.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\StdAfx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\stdafx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\TextViewDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\TextViewDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\WaypointPathDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\WaypointPathDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\WeaponEditorDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\WeaponEditorDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\wing.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\wing.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\wing_editor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FRED2\wing_editor.h
+# End Source File
+# End Target
+# End Project
diff --git a/Fred2.plg b/Fred2.plg
new file mode 100644
index 0000000..d84a8b3
--- /dev/null
+++ b/Fred2.plg
@@ -0,0 +1,77 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: fred2 - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP3BB.tmp" with contents
+[
+winmm.lib vfw32.lib msacm32.lib wsock32.lib code.lib /nologo /subsystem:windows /incremental:yes /pdb:"Fred2.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmtd.lib" /nodefaultlib:"nafxcwd.lib" /out:"e:\games\freespace2\Fred2.exe" /pdbtype:sept /libpath:"debug"
+.\FredDebug\AddVariableDlg.obj
+.\FredDebug\AdjustGridDlg.obj
+.\FredDebug\AsteroidEditorDlg.obj
+.\FredDebug\BgBitmapDlg.obj
+.\FredDebug\BriefingEditorDlg.obj
+.\FredDebug\CampaignEditorDlg.obj
+.\FredDebug\CampaignFilelistBox.obj
+.\FredDebug\CampaignTreeView.obj
+.\FredDebug\CampaignTreeWnd.obj
+.\FredDebug\CmdBrief.obj
+.\FredDebug\CreateWingDlg.obj
+.\FredDebug\DebriefingEditorDlg.obj
+.\FredDebug\dialog1.obj
+.\FredDebug\DumpStats.obj
+.\FredDebug\EventEditor.obj
+.\FredDebug\FRED.obj
+.\FredDebug\FREDDoc.obj
+.\FredDebug\FredRender.obj
+.\FredDebug\FredStubs.obj
+.\FredDebug\FREDView.obj
+.\FredDebug\Grid.obj
+.\FredDebug\IgnoreOrdersDlg.obj
+.\FredDebug\InitialShips.obj
+.\FredDebug\InitialStatus.obj
+.\FredDebug\MainFrm.obj
+.\FredDebug\Management.obj
+.\FredDebug\MessageEditorDlg.obj
+.\FredDebug\MissionGoalsDlg.obj
+.\FredDebug\MissionNotesDlg.obj
+.\FredDebug\MissionSave.obj
+.\FredDebug\ModifyVariableDlg.obj
+.\FredDebug\OperatorArgTypeSelect.obj
+.\FredDebug\OrientEditor.obj
+.\FredDebug\PlayerStartEditor.obj
+.\FredDebug\PrefsDlg.obj
+.\FredDebug\ReinforcementEditorDlg.obj
+.\FredDebug\Sexp_tree.obj
+.\FredDebug\ShieldSysDlg.obj
+.\FredDebug\ship_select.obj
+.\FredDebug\ShipCheckListBox.obj
+.\FredDebug\ShipClassEditorDlg.obj
+.\FredDebug\ShipEditorDlg.obj
+.\FredDebug\ShipFlagsDlg.obj
+.\FredDebug\ShipGoalsDlg.obj
+.\FredDebug\ShipSpecialDamage.obj
+.\FredDebug\StarfieldEditor.obj
+.\FredDebug\StdAfx.obj
+.\FredDebug\TextViewDlg.obj
+.\FredDebug\WaypointPathDlg.obj
+.\FredDebug\WeaponEditorDlg.obj
+.\FredDebug\wing.obj
+.\FredDebug\wing_editor.obj
+.\FredDebug\FRED.res
+.\Debug\code.lib
+]
+Creating command line "cwlink.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP3BB.tmp"
+<h3>Output Window</h3>
+Linking...
+
+
+
+<h3>Results</h3>
+Fred2.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
diff --git a/Freespace2.dsp b/Freespace2.dsp
new file mode 100644
index 0000000..cc17ef6
--- /dev/null
+++ b/Freespace2.dsp
@@ -0,0 +1,140 @@
+# Microsoft Developer Studio Project File - Name="Freespace2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=Freespace2 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Freespace2.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Freespace2.mak" CFG="Freespace2 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Freespace2 - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "Freespace2 - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Freespace2", RHWBAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Freespace2 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G5 /MT /W4 /GX /Zi /Ot /Ow /Og /Oi /Oy /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /I "code\demo" /I "code\inetfile" /I "code\ExceptionHandler" /I "code\3dnow" /FI"PSTypes.h" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /U "_DEBUG" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib winmm.lib vfw32.lib msacm32.lib comctl32.lib code.lib /nologo /subsystem:windows /map /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /out:"E:\games\freespace2\FS2.exe" /libpath:"release"
+
+!ELSEIF "$(CFG)" == "Freespace2 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G5 /MTd /W4 /Gm /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /I "code\demo" /I "code\inetfile" /I "code\ExceptionHandler" /I "code\3dnow" /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "NO_CD_CHECK" /U "NDEBUG" /Fr /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo "./debug/*.sbr"
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib winmm.lib vfw32.lib msacm32.lib comctl32.lib code.lib /nologo /subsystem:windows /incremental:no /debug /debugtype:both /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /out:"e:\games\freespace2\FS2.exe" /libpath:"debug"
+# SUBTRACT LINK32 /pdb:none /map
+
+!ENDIF
+
+# Begin Target
+
+# Name "Freespace2 - Win32 Release"
+# Name "Freespace2 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\code\FREESPACE2\app_icon.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FREESPACE2\FreeSpace.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FREESPACE2\FreeSpace.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FREESPACE2\FreeSpace.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FREESPACE2\FreespaceResource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\freespace2\goal_com.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\freespace2\goal_fail.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\freespace2\goal_inc.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\freespace2\goal_none.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\freespace2\goal_ord.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FREESPACE2\LevelPaging.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\FREESPACE2\LevelPaging.h
+# End Source File
+# End Target
+# End Project
diff --git a/Freespace2.plg b/Freespace2.plg
new file mode 100644
index 0000000..9f5a408
--- /dev/null
+++ b/Freespace2.plg
@@ -0,0 +1,803 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: code - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP3B4.tmp" with contents
+[
+/nologo /G5 /MTd /W4 /GX /Zi /Od /Ob2 /I ".." /I "anim" /I "asteroid" /I "bmpman" /I "cfile" /I "cmdline" /I "cmeasure" /I "controlconfig" /I "cutscene" /I "debris" /I "debugconsole" /I "directx" /I "fireball" /I "fred" /I "freespace2" /I "fs2launch" /I "gamehelp" /I "gamesequence" /I "gamesnd" /I "glide" /I "globalincs" /I "graphics" /I "hud" /I "io" /I "jumpnode" /I "lighting" /I "math" /I "menuui" /I "mission" /I "missionui" /I "model" /I "movie" /I "network" /I "object" /I "observer" /I "osapi" /I "palman" /I "parse" /I "particle" /I "pcxutils" /I "physics" /I "playerman" /I "popup" /I "radar" /I "render" /I "ship" /I "sndman" /I "sound" /I "starfield" /I "stats" /I "ui" /I "vcodec" /I "weapon" /I "localization" /I "fred2" /I "nebula" /I "TgaUtils" /I "demo" /I "inetfile" /I "exceptionhandler" /I "3dnow" /FI"PSTypes.h" /D "_WINDOWS" /D "WIN32" /D "_DEBUG" /U "NDEBUG" /FR"..\Debug/" /Fp"..\Debug/code.pch" /YX /Fo"..\Debug/" /Fd"..\Debug/" /FD /GZ /c
+"C:\projects\freespace2_public\code\Anim\AnimPlay.cpp"
+"C:\projects\freespace2_public\code\Anim\PackUnpack.cpp"
+"C:\projects\freespace2_public\code\Asteroid\Asteroid.cpp"
+"C:\projects\freespace2_public\code\Bmpman\BmpMan.cpp"
+"C:\projects\freespace2_public\code\CFile\cfile.cpp"
+"C:\projects\freespace2_public\code\CFile\CfileArchive.cpp"
+"C:\projects\freespace2_public\code\CFile\CfileList.cpp"
+"C:\projects\freespace2_public\code\CFile\CfileSystem.cpp"
+"C:\projects\freespace2_public\code\Cmdline\cmdline.cpp"
+"C:\projects\freespace2_public\code\CMeasure\CMeasure.cpp"
+"C:\projects\freespace2_public\code\ControlConfig\ControlsConfig.cpp"
+"C:\projects\freespace2_public\code\ControlConfig\ControlsConfigCommon.cpp"
+"C:\projects\freespace2_public\code\Cutscene\Cutscenes.cpp"
+"C:\projects\freespace2_public\code\Debris\Debris.cpp"
+"C:\projects\freespace2_public\code\DebugConsole\Console.cpp"
+"C:\projects\freespace2_public\code\Fireball\FireBalls.cpp"
+"C:\projects\freespace2_public\code\Fireball\WarpInEffect.cpp"
+"C:\projects\freespace2_public\code\GameHelp\ContextHelp.cpp"
+"C:\projects\freespace2_public\code\GameHelp\GameplayHelp.cpp"
+"C:\projects\freespace2_public\code\GameSequence\GameSequence.cpp"
+"C:\projects\freespace2_public\code\Gamesnd\EventMusic.cpp"
+"C:\projects\freespace2_public\code\Gamesnd\GameSnd.cpp"
+"C:\projects\freespace2_public\code\Glide\Glide.cpp"
+"C:\projects\freespace2_public\code\GlobalIncs\AlphaColors.cpp"
+"C:\projects\freespace2_public\code\GlobalIncs\crypt.cpp"
+"C:\projects\freespace2_public\code\GlobalIncs\SystemVars.cpp"
+"C:\projects\freespace2_public\code\GlobalIncs\version.cpp"
+"C:\projects\freespace2_public\code\GlobalIncs\WinDebug.cpp"
+"C:\projects\freespace2_public\code\Graphics\2d.cpp"
+"C:\projects\freespace2_public\code\Graphics\aaline.cpp"
+"C:\projects\freespace2_public\code\Graphics\Bitblt.cpp"
+"C:\projects\freespace2_public\code\Graphics\Circle.cpp"
+"C:\projects\freespace2_public\code\Graphics\Colors.cpp"
+"C:\projects\freespace2_public\code\Graphics\Font.cpp"
+"C:\projects\freespace2_public\code\Graphics\Gradient.cpp"
+"C:\projects\freespace2_public\code\Graphics\GrD3D.cpp"
+"C:\projects\freespace2_public\code\Graphics\GrD3DRender.cpp"
+"C:\projects\freespace2_public\code\Graphics\GrD3DTexture.cpp"
+"C:\projects\freespace2_public\code\Graphics\GrDirectDraw.cpp"
+"C:\projects\freespace2_public\code\Graphics\GrGlide.cpp"
+"C:\projects\freespace2_public\code\Graphics\GrGlideTexture.cpp"
+"C:\projects\freespace2_public\code\Graphics\GrOpenGL.cpp"
+"C:\projects\freespace2_public\code\Graphics\GrSoft.cpp"
+"C:\projects\freespace2_public\code\Graphics\GrZbuffer.cpp"
+"C:\projects\freespace2_public\code\Graphics\Line.cpp"
+"C:\projects\freespace2_public\code\Graphics\Pixel.cpp"
+"C:\projects\freespace2_public\code\Graphics\Rect.cpp"
+"C:\projects\freespace2_public\code\Graphics\Scaler.cpp"
+"C:\projects\freespace2_public\code\Graphics\Shade.cpp"
+"C:\projects\freespace2_public\code\Graphics\TmapGenericScans.cpp"
+"C:\projects\freespace2_public\code\Graphics\Tmapper.cpp"
+"C:\projects\freespace2_public\code\Graphics\TmapScanline.cpp"
+"C:\projects\freespace2_public\code\Graphics\TmapScanTiled128x128.cpp"
+"C:\projects\freespace2_public\code\Graphics\TmapScanTiled16x16.cpp"
+"C:\projects\freespace2_public\code\Graphics\TmapScanTiled256x256.cpp"
+"C:\projects\freespace2_public\code\Graphics\TmapScanTiled32x32.cpp"
+"C:\projects\freespace2_public\code\Graphics\TmapScanTiled64x64.cpp"
+"C:\projects\freespace2_public\code\Hud\HUD.cpp"
+"C:\projects\freespace2_public\code\Hud\HudArtillery.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDbrackets.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDconfig.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDescort.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDets.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDlock.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDmessage.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDObserver.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDreticle.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDshield.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDsquadmsg.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDtarget.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDtargetbox.cpp"
+"C:\projects\freespace2_public\code\Hud\HUDWingmanStatus.cpp"
+"C:\projects\freespace2_public\code\Io\Joy.cpp"
+"C:\projects\freespace2_public\code\Io\Joy_ff.cpp"
+"C:\projects\freespace2_public\code\Io\Key.cpp"
+"C:\projects\freespace2_public\code\Io\KeyControl.cpp"
+"C:\projects\freespace2_public\code\Io\Mouse.cpp"
+"C:\projects\freespace2_public\code\Io\swff_lib.cpp"
+"C:\projects\freespace2_public\code\Io\Timer.cpp"
+"C:\projects\freespace2_public\code\JumpNode\JumpNode.cpp"
+"C:\projects\freespace2_public\code\Lighting\Lighting.cpp"
+"C:\projects\freespace2_public\code\Math\Fix.cpp"
+"C:\projects\freespace2_public\code\Math\Floating.cpp"
+"C:\projects\freespace2_public\code\Math\Fvi.cpp"
+"C:\projects\freespace2_public\code\Math\spline.cpp"
+"C:\projects\freespace2_public\code\Math\StaticRand.cpp"
+"C:\projects\freespace2_public\code\Math\VecMat.cpp"
+"C:\projects\freespace2_public\code\MenuUI\Barracks.cpp"
+"C:\projects\freespace2_public\code\MenuUI\Credits.cpp"
+"C:\projects\freespace2_public\code\MenuUI\fishtank.cpp"
+"C:\projects\freespace2_public\code\MenuUI\MainHallMenu.cpp"
+"C:\projects\freespace2_public\code\MenuUI\MainHallTemp.cpp"
+"C:\projects\freespace2_public\code\MenuUI\OptionsMenu.cpp"
+"C:\projects\freespace2_public\code\MenuUI\OptionsMenuMulti.cpp"
+"C:\projects\freespace2_public\code\MenuUI\PlayerMenu.cpp"
+"C:\projects\freespace2_public\code\MenuUI\ReadyRoom.cpp"
+"C:\projects\freespace2_public\code\MenuUI\SnazzyUI.cpp"
+"C:\projects\freespace2_public\code\MenuUI\TechMenu.cpp"
+"C:\projects\freespace2_public\code\MenuUI\TrainingMenu.cpp"
+"C:\projects\freespace2_public\code\Mission\MissionBriefCommon.cpp"
+"C:\projects\freespace2_public\code\Mission\MissionCampaign.cpp"
+"C:\projects\freespace2_public\code\Mission\MissionGoals.cpp"
+"C:\projects\freespace2_public\code\Mission\MissionGrid.cpp"
+"C:\projects\freespace2_public\code\Mission\MissionHotKey.cpp"
+"C:\projects\freespace2_public\code\Mission\MissionLoad.cpp"
+"C:\projects\freespace2_public\code\Mission\MissionLog.cpp"
+"C:\projects\freespace2_public\code\Mission\MissionMessage.cpp"
+"C:\projects\freespace2_public\code\Mission\MissionParse.cpp"
+"C:\projects\freespace2_public\code\Mission\MissionTraining.cpp"
+"C:\projects\freespace2_public\code\MissionUI\Chatbox.cpp"
+"C:\projects\freespace2_public\code\MissionUI\MissionBrief.cpp"
+"C:\projects\freespace2_public\code\MissionUI\MissionCmdBrief.cpp"
+"C:\projects\freespace2_public\code\MissionUI\MissionDebrief.cpp"
+"C:\projects\freespace2_public\code\MissionUI\MissionLoopBrief.cpp"
+"C:\projects\freespace2_public\code\MissionUI\MissionPause.cpp"
+"C:\projects\freespace2_public\code\MissionUI\MissionRecommend.cpp"
+"C:\projects\freespace2_public\code\MissionUI\MissionScreenCommon.cpp"
+"C:\projects\freespace2_public\code\MissionUI\MissionShipChoice.cpp"
+"C:\projects\freespace2_public\code\MissionUI\MissionStats.cpp"
+"C:\projects\freespace2_public\code\MissionUI\MissionWeaponChoice.cpp"
+"C:\projects\freespace2_public\code\MissionUI\RedAlert.cpp"
+"C:\projects\freespace2_public\code\Model\ModelCollide.cpp"
+"C:\projects\freespace2_public\code\Model\ModelInterp.cpp"
+"C:\projects\freespace2_public\code\Model\ModelOctant.cpp"
+"C:\projects\freespace2_public\code\Model\ModelRead.cpp"
+"C:\projects\freespace2_public\code\Object\CollideDebrisShip.cpp"
+"C:\projects\freespace2_public\code\Object\CollideDebrisWeapon.cpp"
+"C:\projects\freespace2_public\code\Object\CollideShipShip.cpp"
+"C:\projects\freespace2_public\code\Object\CollideShipWeapon.cpp"
+"C:\projects\freespace2_public\code\Object\CollideWeaponWeapon.cpp"
+"C:\projects\freespace2_public\code\Object\ObjCollide.cpp"
+"C:\projects\freespace2_public\code\Object\Object.cpp"
+"C:\projects\freespace2_public\code\Object\ObjectSnd.cpp"
+"C:\projects\freespace2_public\code\Object\ObjectSort.cpp"
+"C:\projects\freespace2_public\code\Observer\Observer.cpp"
+"C:\projects\freespace2_public\code\OsApi\OsApi.cpp"
+"C:\projects\freespace2_public\code\OsApi\OsRegistry.cpp"
+"C:\projects\freespace2_public\code\OsApi\OutWnd.cpp"
+"C:\projects\freespace2_public\code\Palman\PalMan.cpp"
+"C:\projects\freespace2_public\code\Parse\Encrypt.cpp"
+"C:\projects\freespace2_public\code\Parse\PARSELO.CPP"
+"C:\projects\freespace2_public\code\Parse\SEXP.CPP"
+"C:\projects\freespace2_public\code\Particle\Particle.cpp"
+"C:\projects\freespace2_public\code\PcxUtils\pcxutils.cpp"
+"C:\projects\freespace2_public\code\Physics\Physics.cpp"
+"C:\projects\freespace2_public\code\Playerman\ManagePilot.cpp"
+"C:\projects\freespace2_public\code\Playerman\PlayerControl.cpp"
+"C:\projects\freespace2_public\code\Popup\Popup.cpp"
+"C:\projects\freespace2_public\code\Popup\PopupDead.cpp"
+"C:\projects\freespace2_public\code\Radar\Radar.cpp"
+"C:\projects\freespace2_public\code\Render\3dClipper.cpp"
+"C:\projects\freespace2_public\code\Render\3ddraw.cpp"
+"C:\projects\freespace2_public\code\Render\3dLaser.cpp"
+"C:\projects\freespace2_public\code\Render\3dMath.cpp"
+"C:\projects\freespace2_public\code\Render\3dSetup.cpp"
+"C:\projects\freespace2_public\code\Ship\Afterburner.cpp"
+"C:\projects\freespace2_public\code\Ship\ai.cpp"
+"C:\projects\freespace2_public\code\Ship\AiBig.cpp"
+"C:\projects\freespace2_public\code\Ship\AiCode.cpp"
+"C:\projects\freespace2_public\code\Ship\AiGoals.cpp"
+"C:\projects\freespace2_public\code\Ship\AWACS.cpp"
+"C:\projects\freespace2_public\code\Ship\Shield.cpp"
+"C:\projects\freespace2_public\code\Ship\Ship.cpp"
+"C:\projects\freespace2_public\code\Ship\ShipContrails.cpp"
+"C:\projects\freespace2_public\code\Ship\ShipFX.cpp"
+"C:\projects\freespace2_public\code\Ship\ShipHit.cpp"
+"C:\projects\freespace2_public\code\Sound\acm.cpp"
+"C:\projects\freespace2_public\code\Sound\AudioStr.cpp"
+"C:\projects\freespace2_public\code\Sound\ds.cpp"
+"C:\projects\freespace2_public\code\Sound\ds3d.cpp"
+"C:\projects\freespace2_public\code\Sound\dscap.cpp"
+"C:\projects\freespace2_public\code\Sound\midifile.cpp"
+"C:\projects\freespace2_public\code\Sound\RBAudio.cpp"
+"C:\projects\freespace2_public\code\Sound\rtvoice.cpp"
+"C:\projects\freespace2_public\code\Sound\Sound.cpp"
+"C:\projects\freespace2_public\code\Sound\WinMIDI.cpp"
+"C:\projects\freespace2_public\code\Sound\winmidi_base.cpp"
+"C:\projects\freespace2_public\code\Starfield\Nebula.cpp"
+"C:\projects\freespace2_public\code\Starfield\StarField.cpp"
+"C:\projects\freespace2_public\code\Starfield\Supernova.cpp"
+"C:\projects\freespace2_public\code\Stats\Medals.cpp"
+"C:\projects\freespace2_public\code\Stats\Scoring.cpp"
+"C:\projects\freespace2_public\code\Stats\Stats.cpp"
+"C:\projects\freespace2_public\code\UI\BUTTON.cpp"
+"C:\projects\freespace2_public\code\UI\CHECKBOX.cpp"
+"C:\projects\freespace2_public\code\UI\GADGET.cpp"
+"C:\projects\freespace2_public\code\UI\icon.cpp"
+"C:\projects\freespace2_public\code\UI\INPUTBOX.cpp"
+"C:\projects\freespace2_public\code\UI\KEYTRAP.cpp"
+"C:\projects\freespace2_public\code\UI\LISTBOX.cpp"
+"C:\projects\freespace2_public\code\UI\RADIO.cpp"
+"C:\projects\freespace2_public\code\UI\SCROLL.cpp"
+"C:\projects\freespace2_public\code\UI\slider.cpp"
+"C:\projects\freespace2_public\code\Ui\SLIDER2.cpp"
+"C:\projects\freespace2_public\code\UI\UIDRAW.cpp"
+"C:\projects\freespace2_public\code\UI\UIMOUSE.cpp"
+"C:\projects\freespace2_public\code\UI\WINDOW.cpp"
+"C:\projects\freespace2_public\code\VCodec\CODEC1.CPP"
+"C:\projects\freespace2_public\code\Weapon\Beam.cpp"
+"C:\projects\freespace2_public\code\Weapon\Corkscrew.cpp"
+"C:\projects\freespace2_public\code\Weapon\Emp.cpp"
+"C:\projects\freespace2_public\code\Weapon\Flak.cpp"
+"C:\projects\freespace2_public\code\Weapon\MuzzleFlash.cpp"
+"C:\projects\freespace2_public\code\Weapon\Shockwave.cpp"
+"C:\projects\freespace2_public\code\Weapon\Swarm.cpp"
+"C:\projects\freespace2_public\code\Weapon\Trails.cpp"
+"C:\projects\freespace2_public\code\Weapon\Weapons.cpp"
+"C:\projects\freespace2_public\code\Nebula\Neb.cpp"
+"C:\projects\freespace2_public\code\Nebula\NebLightning.cpp"
+"C:\projects\freespace2_public\code\Localization\fhash.cpp"
+"C:\projects\freespace2_public\code\Localization\localize.cpp"
+"C:\projects\freespace2_public\code\TgaUtils\TgaUtils.cpp"
+"C:\projects\freespace2_public\code\Demo\Demo.cpp"
+"C:\projects\freespace2_public\code\Inetfile\CFtp.cpp"
+"C:\projects\freespace2_public\code\Inetfile\Chttpget.cpp"
+"C:\projects\freespace2_public\code\Inetfile\inetgetfile.cpp"
+"C:\projects\freespace2_public\code\ExceptionHandler\ExceptionHandler.cpp"
+"C:\projects\freespace2_public\code\Network\Multi.cpp"
+"C:\projects\freespace2_public\code\Network\multi_campaign.cpp"
+"C:\projects\freespace2_public\code\Network\multi_data.cpp"
+"C:\projects\freespace2_public\code\Network\multi_dogfight.cpp"
+"C:\projects\freespace2_public\code\Network\multi_endgame.cpp"
+"C:\projects\freespace2_public\code\Network\multi_ingame.cpp"
+"C:\projects\freespace2_public\code\Network\multi_kick.cpp"
+"C:\projects\freespace2_public\code\Network\multi_log.cpp"
+"C:\projects\freespace2_public\code\Network\multi_obj.cpp"
+"C:\projects\freespace2_public\code\Network\multi_observer.cpp"
+"C:\projects\freespace2_public\code\Network\multi_oo.cpp"
+"C:\projects\freespace2_public\code\Network\multi_options.cpp"
+"C:\projects\freespace2_public\code\Network\multi_pause.cpp"
+"C:\projects\freespace2_public\code\Network\multi_pinfo.cpp"
+"C:\projects\freespace2_public\code\Network\multi_ping.cpp"
+"C:\projects\freespace2_public\code\Network\multi_pmsg.cpp"
+"C:\projects\freespace2_public\code\Network\multi_rate.cpp"
+"C:\projects\freespace2_public\code\Network\multi_respawn.cpp"
+"C:\projects\freespace2_public\code\Network\multi_team.cpp"
+"C:\projects\freespace2_public\code\Network\multi_update.cpp"
+"C:\projects\freespace2_public\code\Network\multi_voice.cpp"
+"C:\projects\freespace2_public\code\Network\multi_xfer.cpp"
+"C:\projects\freespace2_public\code\Network\multilag.cpp"
+"C:\projects\freespace2_public\code\Network\MultiMsgs.cpp"
+"C:\projects\freespace2_public\code\Network\MultiTeamSelect.cpp"
+"C:\projects\freespace2_public\code\Network\MultiUI.cpp"
+"C:\projects\freespace2_public\code\Network\MultiUtil.cpp"
+"C:\projects\freespace2_public\code\Network\PsNet.cpp"
+"C:\projects\freespace2_public\code\Network\Psnet2.cpp"
+"C:\projects\freespace2_public\code\Network\stand_gui.cpp"
+]
+Creating command line "cwcl.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP3B4.tmp"
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP3B5.tmp" with contents
+[
+/nologo /out:"..\Debug\code.lib"
+\projects\freespace2_public\Debug\AnimPlay.obj
+\projects\freespace2_public\Debug\PackUnpack.obj
+\projects\freespace2_public\Debug\Asteroid.obj
+\projects\freespace2_public\Debug\BmpMan.obj
+\projects\freespace2_public\Debug\cfile.obj
+\projects\freespace2_public\Debug\CfileArchive.obj
+\projects\freespace2_public\Debug\CfileList.obj
+\projects\freespace2_public\Debug\CfileSystem.obj
+\projects\freespace2_public\Debug\cmdline.obj
+\projects\freespace2_public\Debug\CMeasure.obj
+\projects\freespace2_public\Debug\ControlsConfig.obj
+\projects\freespace2_public\Debug\ControlsConfigCommon.obj
+\projects\freespace2_public\Debug\Cutscenes.obj
+\projects\freespace2_public\Debug\Debris.obj
+\projects\freespace2_public\Debug\Console.obj
+\projects\freespace2_public\Debug\FireBalls.obj
+\projects\freespace2_public\Debug\WarpInEffect.obj
+\projects\freespace2_public\Debug\ContextHelp.obj
+\projects\freespace2_public\Debug\GameplayHelp.obj
+\projects\freespace2_public\Debug\GameSequence.obj
+\projects\freespace2_public\Debug\EventMusic.obj
+\projects\freespace2_public\Debug\GameSnd.obj
+\projects\freespace2_public\Debug\Glide.obj
+\projects\freespace2_public\Debug\AlphaColors.obj
+\projects\freespace2_public\Debug\crypt.obj
+\projects\freespace2_public\Debug\SystemVars.obj
+\projects\freespace2_public\Debug\version.obj
+\projects\freespace2_public\Debug\WinDebug.obj
+\projects\freespace2_public\Debug\2d.obj
+\projects\freespace2_public\Debug\aaline.obj
+\projects\freespace2_public\Debug\Bitblt.obj
+\projects\freespace2_public\Debug\Circle.obj
+\projects\freespace2_public\Debug\Colors.obj
+\projects\freespace2_public\Debug\Font.obj
+\projects\freespace2_public\Debug\Gradient.obj
+\projects\freespace2_public\Debug\GrD3D.obj
+\projects\freespace2_public\Debug\GrD3DRender.obj
+\projects\freespace2_public\Debug\GrD3DTexture.obj
+\projects\freespace2_public\Debug\GrDirectDraw.obj
+\projects\freespace2_public\Debug\GrGlide.obj
+\projects\freespace2_public\Debug\GrGlideTexture.obj
+\projects\freespace2_public\Debug\GrOpenGL.obj
+\projects\freespace2_public\Debug\GrSoft.obj
+\projects\freespace2_public\Debug\GrZbuffer.obj
+\projects\freespace2_public\Debug\Line.obj
+\projects\freespace2_public\Debug\Pixel.obj
+\projects\freespace2_public\Debug\Rect.obj
+\projects\freespace2_public\Debug\Scaler.obj
+\projects\freespace2_public\Debug\Shade.obj
+\projects\freespace2_public\Debug\TmapGenericScans.obj
+\projects\freespace2_public\Debug\Tmapper.obj
+\projects\freespace2_public\Debug\TmapScanline.obj
+\projects\freespace2_public\Debug\TmapScanTiled128x128.obj
+\projects\freespace2_public\Debug\TmapScanTiled16x16.obj
+\projects\freespace2_public\Debug\TmapScanTiled256x256.obj
+\projects\freespace2_public\Debug\TmapScanTiled32x32.obj
+\projects\freespace2_public\Debug\TmapScanTiled64x64.obj
+\projects\freespace2_public\Debug\HUD.obj
+\projects\freespace2_public\Debug\HudArtillery.obj
+\projects\freespace2_public\Debug\HUDbrackets.obj
+\projects\freespace2_public\Debug\HUDconfig.obj
+\projects\freespace2_public\Debug\HUDescort.obj
+\projects\freespace2_public\Debug\HUDets.obj
+\projects\freespace2_public\Debug\HUDlock.obj
+\projects\freespace2_public\Debug\HUDmessage.obj
+\projects\freespace2_public\Debug\HUDObserver.obj
+\projects\freespace2_public\Debug\HUDreticle.obj
+\projects\freespace2_public\Debug\HUDshield.obj
+\projects\freespace2_public\Debug\HUDsquadmsg.obj
+\projects\freespace2_public\Debug\HUDtarget.obj
+\projects\freespace2_public\Debug\HUDtargetbox.obj
+\projects\freespace2_public\Debug\HUDWingmanStatus.obj
+\projects\freespace2_public\Debug\Joy.obj
+\projects\freespace2_public\Debug\Joy_ff.obj
+\projects\freespace2_public\Debug\Key.obj
+\projects\freespace2_public\Debug\KeyControl.obj
+\projects\freespace2_public\Debug\Mouse.obj
+\projects\freespace2_public\Debug\swff_lib.obj
+\projects\freespace2_public\Debug\Timer.obj
+\projects\freespace2_public\Debug\JumpNode.obj
+\projects\freespace2_public\Debug\Lighting.obj
+\projects\freespace2_public\Debug\Fix.obj
+\projects\freespace2_public\Debug\Floating.obj
+\projects\freespace2_public\Debug\Fvi.obj
+\projects\freespace2_public\Debug\spline.obj
+\projects\freespace2_public\Debug\StaticRand.obj
+\projects\freespace2_public\Debug\VecMat.obj
+\projects\freespace2_public\Debug\Barracks.obj
+\projects\freespace2_public\Debug\Credits.obj
+\projects\freespace2_public\Debug\fishtank.obj
+\projects\freespace2_public\Debug\MainHallMenu.obj
+\projects\freespace2_public\Debug\MainHallTemp.obj
+\projects\freespace2_public\Debug\OptionsMenu.obj
+\projects\freespace2_public\Debug\OptionsMenuMulti.obj
+\projects\freespace2_public\Debug\PlayerMenu.obj
+\projects\freespace2_public\Debug\ReadyRoom.obj
+\projects\freespace2_public\Debug\SnazzyUI.obj
+\projects\freespace2_public\Debug\TechMenu.obj
+\projects\freespace2_public\Debug\TrainingMenu.obj
+\projects\freespace2_public\Debug\MissionBriefCommon.obj
+\projects\freespace2_public\Debug\MissionCampaign.obj
+\projects\freespace2_public\Debug\MissionGoals.obj
+\projects\freespace2_public\Debug\MissionGrid.obj
+\projects\freespace2_public\Debug\MissionHotKey.obj
+\projects\freespace2_public\Debug\MissionLoad.obj
+\projects\freespace2_public\Debug\MissionLog.obj
+\projects\freespace2_public\Debug\MissionMessage.obj
+\projects\freespace2_public\Debug\MissionParse.obj
+\projects\freespace2_public\Debug\MissionTraining.obj
+\projects\freespace2_public\Debug\Chatbox.obj
+\projects\freespace2_public\Debug\MissionBrief.obj
+\projects\freespace2_public\Debug\MissionCmdBrief.obj
+\projects\freespace2_public\Debug\MissionDebrief.obj
+\projects\freespace2_public\Debug\MissionLoopBrief.obj
+\projects\freespace2_public\Debug\MissionPause.obj
+\projects\freespace2_public\Debug\MissionRecommend.obj
+\projects\freespace2_public\Debug\MissionScreenCommon.obj
+\projects\freespace2_public\Debug\MissionShipChoice.obj
+\projects\freespace2_public\Debug\MissionStats.obj
+\projects\freespace2_public\Debug\MissionWeaponChoice.obj
+\projects\freespace2_public\Debug\RedAlert.obj
+\projects\freespace2_public\Debug\ModelCollide.obj
+\projects\freespace2_public\Debug\ModelInterp.obj
+\projects\freespace2_public\Debug\ModelOctant.obj
+\projects\freespace2_public\Debug\ModelRead.obj
+\projects\freespace2_public\Debug\CollideDebrisShip.obj
+\projects\freespace2_public\Debug\CollideDebrisWeapon.obj
+\projects\freespace2_public\Debug\CollideShipShip.obj
+\projects\freespace2_public\Debug\CollideShipWeapon.obj
+\projects\freespace2_public\Debug\CollideWeaponWeapon.obj
+\projects\freespace2_public\Debug\ObjCollide.obj
+\projects\freespace2_public\Debug\Object.obj
+\projects\freespace2_public\Debug\ObjectSnd.obj
+\projects\freespace2_public\Debug\ObjectSort.obj
+\projects\freespace2_public\Debug\Observer.obj
+\projects\freespace2_public\Debug\OsApi.obj
+\projects\freespace2_public\Debug\OsRegistry.obj
+\projects\freespace2_public\Debug\OutWnd.obj
+\projects\freespace2_public\Debug\PalMan.obj
+\projects\freespace2_public\Debug\Encrypt.obj
+\projects\freespace2_public\Debug\PARSELO.OBJ
+\projects\freespace2_public\Debug\SEXP.OBJ
+\projects\freespace2_public\Debug\Particle.obj
+\projects\freespace2_public\Debug\pcxutils.obj
+\projects\freespace2_public\Debug\Physics.obj
+\projects\freespace2_public\Debug\ManagePilot.obj
+\projects\freespace2_public\Debug\PlayerControl.obj
+\projects\freespace2_public\Debug\Popup.obj
+\projects\freespace2_public\Debug\PopupDead.obj
+\projects\freespace2_public\Debug\Radar.obj
+\projects\freespace2_public\Debug\3dClipper.obj
+\projects\freespace2_public\Debug\3ddraw.obj
+\projects\freespace2_public\Debug\3dLaser.obj
+\projects\freespace2_public\Debug\3dMath.obj
+\projects\freespace2_public\Debug\3dSetup.obj
+\projects\freespace2_public\Debug\Afterburner.obj
+\projects\freespace2_public\Debug\ai.obj
+\projects\freespace2_public\Debug\AiBig.obj
+\projects\freespace2_public\Debug\AiCode.obj
+\projects\freespace2_public\Debug\AiGoals.obj
+\projects\freespace2_public\Debug\AWACS.obj
+\projects\freespace2_public\Debug\Shield.obj
+\projects\freespace2_public\Debug\Ship.obj
+\projects\freespace2_public\Debug\ShipContrails.obj
+\projects\freespace2_public\Debug\ShipFX.obj
+\projects\freespace2_public\Debug\ShipHit.obj
+\projects\freespace2_public\Debug\acm.obj
+\projects\freespace2_public\Debug\AudioStr.obj
+\projects\freespace2_public\Debug\ds.obj
+\projects\freespace2_public\Debug\ds3d.obj
+\projects\freespace2_public\Debug\dscap.obj
+\projects\freespace2_public\Debug\midifile.obj
+\projects\freespace2_public\Debug\RBAudio.obj
+\projects\freespace2_public\Debug\rtvoice.obj
+\projects\freespace2_public\Debug\Sound.obj
+\projects\freespace2_public\Debug\WinMIDI.obj
+\projects\freespace2_public\Debug\winmidi_base.obj
+\projects\freespace2_public\Debug\Nebula.obj
+\projects\freespace2_public\Debug\StarField.obj
+\projects\freespace2_public\Debug\Supernova.obj
+\projects\freespace2_public\Debug\Medals.obj
+\projects\freespace2_public\Debug\Scoring.obj
+\projects\freespace2_public\Debug\Stats.obj
+\projects\freespace2_public\Debug\BUTTON.obj
+\projects\freespace2_public\Debug\CHECKBOX.obj
+\projects\freespace2_public\Debug\GADGET.obj
+\projects\freespace2_public\Debug\icon.obj
+\projects\freespace2_public\Debug\INPUTBOX.obj
+\projects\freespace2_public\Debug\KEYTRAP.obj
+\projects\freespace2_public\Debug\LISTBOX.obj
+\projects\freespace2_public\Debug\RADIO.obj
+\projects\freespace2_public\Debug\SCROLL.obj
+\projects\freespace2_public\Debug\slider.obj
+\projects\freespace2_public\Debug\SLIDER2.obj
+\projects\freespace2_public\Debug\UIDRAW.obj
+\projects\freespace2_public\Debug\UIMOUSE.obj
+\projects\freespace2_public\Debug\WINDOW.obj
+\projects\freespace2_public\Debug\CODEC1.OBJ
+\projects\freespace2_public\Debug\Beam.obj
+\projects\freespace2_public\Debug\Corkscrew.obj
+\projects\freespace2_public\Debug\Emp.obj
+\projects\freespace2_public\Debug\Flak.obj
+\projects\freespace2_public\Debug\MuzzleFlash.obj
+\projects\freespace2_public\Debug\Shockwave.obj
+\projects\freespace2_public\Debug\Swarm.obj
+\projects\freespace2_public\Debug\Trails.obj
+\projects\freespace2_public\Debug\Weapons.obj
+\projects\freespace2_public\Debug\Neb.obj
+\projects\freespace2_public\Debug\NebLightning.obj
+\projects\freespace2_public\Debug\fhash.obj
+\projects\freespace2_public\Debug\localize.obj
+\projects\freespace2_public\Debug\TgaUtils.obj
+\projects\freespace2_public\Debug\Demo.obj
+\projects\freespace2_public\Debug\CFtp.obj
+\projects\freespace2_public\Debug\Chttpget.obj
+\projects\freespace2_public\Debug\inetgetfile.obj
+\projects\freespace2_public\Debug\ExceptionHandler.obj
+\projects\freespace2_public\Debug\Multi.obj
+\projects\freespace2_public\Debug\multi_campaign.obj
+\projects\freespace2_public\Debug\multi_data.obj
+\projects\freespace2_public\Debug\multi_dogfight.obj
+\projects\freespace2_public\Debug\multi_endgame.obj
+\projects\freespace2_public\Debug\multi_ingame.obj
+\projects\freespace2_public\Debug\multi_kick.obj
+\projects\freespace2_public\Debug\multi_log.obj
+\projects\freespace2_public\Debug\multi_obj.obj
+\projects\freespace2_public\Debug\multi_observer.obj
+\projects\freespace2_public\Debug\multi_oo.obj
+\projects\freespace2_public\Debug\multi_options.obj
+\projects\freespace2_public\Debug\multi_pause.obj
+\projects\freespace2_public\Debug\multi_pinfo.obj
+\projects\freespace2_public\Debug\multi_ping.obj
+\projects\freespace2_public\Debug\multi_pmsg.obj
+\projects\freespace2_public\Debug\multi_rate.obj
+\projects\freespace2_public\Debug\multi_respawn.obj
+\projects\freespace2_public\Debug\multi_team.obj
+\projects\freespace2_public\Debug\multi_update.obj
+\projects\freespace2_public\Debug\multi_voice.obj
+\projects\freespace2_public\Debug\multi_xfer.obj
+\projects\freespace2_public\Debug\multilag.obj
+\projects\freespace2_public\Debug\MultiMsgs.obj
+\projects\freespace2_public\Debug\MultiTeamSelect.obj
+\projects\freespace2_public\Debug\MultiUI.obj
+\projects\freespace2_public\Debug\MultiUtil.obj
+\projects\freespace2_public\Debug\PsNet.obj
+\projects\freespace2_public\Debug\Psnet2.obj
+\projects\freespace2_public\Debug\stand_gui.obj
+.\DirectX\vDdraw.lib
+.\DirectX\vDinput.lib
+.\DirectX\vDsound.lib
+.\DirectX\vDxguid.lib
+]
+Creating command line "link.exe -lib @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP3B5.tmp"
+<h3>Output Window</h3>
+Compiling...
+AnimPlay.cpp
+PackUnpack.cpp
+Asteroid.cpp
+BmpMan.cpp
+cfile.cpp
+CfileArchive.cpp
+CfileList.cpp
+CfileSystem.cpp
+cmdline.cpp
+CMeasure.cpp
+ControlsConfig.cpp
+ControlsConfigCommon.cpp
+Cutscenes.cpp
+Debris.cpp
+Console.cpp
+FireBalls.cpp
+WarpInEffect.cpp
+ContextHelp.cpp
+GameplayHelp.cpp
+GameSequence.cpp
+EventMusic.cpp
+GameSnd.cpp
+Glide.cpp
+AlphaColors.cpp
+crypt.cpp
+SystemVars.cpp
+version.cpp
+WinDebug.cpp
+2d.cpp
+aaline.cpp
+Bitblt.cpp
+Circle.cpp
+Colors.cpp
+Font.cpp
+Gradient.cpp
+GrD3D.cpp
+GrD3DRender.cpp
+GrD3DTexture.cpp
+GrDirectDraw.cpp
+GrGlide.cpp
+GrGlideTexture.cpp
+GrOpenGL.cpp
+GrSoft.cpp
+GrZbuffer.cpp
+Line.cpp
+Pixel.cpp
+Rect.cpp
+Scaler.cpp
+Shade.cpp
+TmapGenericScans.cpp
+Tmapper.cpp
+TmapScanline.cpp
+TmapScanTiled128x128.cpp
+TmapScanTiled16x16.cpp
+TmapScanTiled256x256.cpp
+TmapScanTiled32x32.cpp
+TmapScanTiled64x64.cpp
+HUD.cpp
+HudArtillery.cpp
+HUDbrackets.cpp
+HUDconfig.cpp
+HUDescort.cpp
+HUDets.cpp
+HUDlock.cpp
+HUDmessage.cpp
+HUDObserver.cpp
+HUDreticle.cpp
+HUDshield.cpp
+HUDsquadmsg.cpp
+HUDtarget.cpp
+HUDtargetbox.cpp
+HUDWingmanStatus.cpp
+Joy.cpp
+Joy_ff.cpp
+Key.cpp
+KeyControl.cpp
+Mouse.cpp
+swff_lib.cpp
+Timer.cpp
+JumpNode.cpp
+Lighting.cpp
+Fix.cpp
+Floating.cpp
+Fvi.cpp
+spline.cpp
+StaticRand.cpp
+VecMat.cpp
+Barracks.cpp
+Credits.cpp
+fishtank.cpp
+MainHallMenu.cpp
+MainHallTemp.cpp
+OptionsMenu.cpp
+OptionsMenuMulti.cpp
+PlayerMenu.cpp
+ReadyRoom.cpp
+SnazzyUI.cpp
+TechMenu.cpp
+TrainingMenu.cpp
+MissionBriefCommon.cpp
+MissionCampaign.cpp
+MissionGoals.cpp
+MissionGrid.cpp
+MissionHotKey.cpp
+MissionLoad.cpp
+MissionLog.cpp
+MissionMessage.cpp
+MissionParse.cpp
+MissionTraining.cpp
+Chatbox.cpp
+MissionBrief.cpp
+MissionCmdBrief.cpp
+MissionDebrief.cpp
+MissionLoopBrief.cpp
+MissionPause.cpp
+MissionRecommend.cpp
+MissionScreenCommon.cpp
+MissionShipChoice.cpp
+MissionStats.cpp
+MissionWeaponChoice.cpp
+RedAlert.cpp
+ModelCollide.cpp
+ModelInterp.cpp
+ModelOctant.cpp
+ModelRead.cpp
+CollideDebrisShip.cpp
+CollideDebrisWeapon.cpp
+CollideShipShip.cpp
+CollideShipWeapon.cpp
+CollideWeaponWeapon.cpp
+ObjCollide.cpp
+Object.cpp
+ObjectSnd.cpp
+ObjectSort.cpp
+Observer.cpp
+OsApi.cpp
+OsRegistry.cpp
+OutWnd.cpp
+PalMan.cpp
+Encrypt.cpp
+PARSELO.CPP
+SEXP.CPP
+Particle.cpp
+pcxutils.cpp
+Physics.cpp
+ManagePilot.cpp
+PlayerControl.cpp
+Popup.cpp
+PopupDead.cpp
+Radar.cpp
+3dClipper.cpp
+3ddraw.cpp
+3dLaser.cpp
+3dMath.cpp
+3dSetup.cpp
+Afterburner.cpp
+ai.cpp
+AiBig.cpp
+AiCode.cpp
+AiGoals.cpp
+AWACS.cpp
+Shield.cpp
+Ship.cpp
+ShipContrails.cpp
+ShipFX.cpp
+ShipHit.cpp
+acm.cpp
+AudioStr.cpp
+ds.cpp
+ds3d.cpp
+dscap.cpp
+midifile.cpp
+RBAudio.cpp
+rtvoice.cpp
+Sound.cpp
+WinMIDI.cpp
+winmidi_base.cpp
+Nebula.cpp
+StarField.cpp
+Supernova.cpp
+Medals.cpp
+Scoring.cpp
+Stats.cpp
+BUTTON.cpp
+CHECKBOX.cpp
+GADGET.cpp
+icon.cpp
+INPUTBOX.cpp
+KEYTRAP.cpp
+LISTBOX.cpp
+RADIO.cpp
+SCROLL.cpp
+slider.cpp
+SLIDER2.cpp
+UIDRAW.cpp
+UIMOUSE.cpp
+WINDOW.cpp
+CODEC1.CPP
+Beam.cpp
+Corkscrew.cpp
+Emp.cpp
+Flak.cpp
+MuzzleFlash.cpp
+Shockwave.cpp
+Swarm.cpp
+Trails.cpp
+Weapons.cpp
+Neb.cpp
+NebLightning.cpp
+fhash.cpp
+localize.cpp
+TgaUtils.cpp
+Demo.cpp
+CFtp.cpp
+Chttpget.cpp
+inetgetfile.cpp
+ExceptionHandler.cpp
+Multi.cpp
+multi_campaign.cpp
+multi_data.cpp
+multi_dogfight.cpp
+multi_endgame.cpp
+multi_ingame.cpp
+multi_kick.cpp
+multi_log.cpp
+multi_obj.cpp
+multi_observer.cpp
+multi_oo.cpp
+multi_options.cpp
+multi_pause.cpp
+multi_pinfo.cpp
+multi_ping.cpp
+multi_pmsg.cpp
+multi_rate.cpp
+multi_respawn.cpp
+multi_team.cpp
+multi_update.cpp
+multi_voice.cpp
+multi_xfer.cpp
+multilag.cpp
+MultiMsgs.cpp
+MultiTeamSelect.cpp
+MultiUI.cpp
+MultiUtil.cpp
+PsNet.cpp
+Psnet2.cpp
+stand_gui.cpp
+Creating library...
+vDinput.lib(DINPUT.dll) : warning LNK4006: __NULL_IMPORT_DESCRIPTOR already defined in vDdraw.lib(DDRAW.dll); second definition ignored
+vDsound.lib(DSOUND.dll) : warning LNK4006: __NULL_IMPORT_DESCRIPTOR already defined in vDdraw.lib(DDRAW.dll); second definition ignored
+<h3>
+--------------------Configuration: Freespace2 - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating command line "rc.exe /l 0x409 /fo"Debug/FreeSpace.res" /i "code\FREESPACE2" /d "_DEBUG" "C:\projects\freespace2_public\code\FREESPACE2\FreeSpace.rc""
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP3B6.tmp" with contents
+[
+/nologo /G5 /MTd /W4 /Gm /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /I "code\demo" /I "code\inetfile" /I "code\ExceptionHandler" /I "code\3dnow" /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "NO_CD_CHECK" /U "NDEBUG" /Fr"Debug/" /Fp"Debug/Freespace2.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
+"C:\projects\freespace2_public\code\FREESPACE2\FreeSpace.cpp"
+"C:\projects\freespace2_public\code\FREESPACE2\LevelPaging.cpp"
+]
+Creating command line "cwcl.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP3B6.tmp"
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP3B7.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib winmm.lib vfw32.lib msacm32.lib comctl32.lib code.lib /nologo /subsystem:windows /incremental:no /pdb:"FS2.pdb" /debug /debugtype:both /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /out:"e:\games\freespace2\FS2.exe" /libpath:"debug"
+.\Debug\FreeSpace.obj
+.\Debug\LevelPaging.obj
+.\Debug\FreeSpace.res
+.\Debug\code.lib
+]
+Creating command line "cwlink.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP3B7.tmp"
+<h3>Output Window</h3>
+Compiling resources...
+Compiling...
+FreeSpace.cpp
+LevelPaging.cpp
+Linking...
+
+
+
+<h3>Results</h3>
+FS2.exe - 0 error(s), 2 warning(s)
+</pre>
+</body>
+</html>
diff --git a/HelpEd.dsp b/HelpEd.dsp
new file mode 100644
index 0000000..76d2934
--- /dev/null
+++ b/HelpEd.dsp
@@ -0,0 +1,167 @@
+# Microsoft Developer Studio Project File - Name="HelpEd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=HelpEd - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "HelpEd.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "HelpEd.mak" CFG="HelpEd - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "HelpEd - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "HelpEd - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Freespace2", WSSCAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "HelpEd - Win32 Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 /nologo /subsystem:windows /machine:I386
+
+!ELSEIF "$(CFG)" == "HelpEd - Win32 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "HelpEd___Win32_Debug"
+# PROP BASE Intermediate_Dir "HelpEd___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "HelpEdDebug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /G5 /MDd /W4 /Gm- /GX /Zi /Od /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 winmm.lib /nologo /subsystem:windows /incremental:no /debug /debugtype:both /machine:I386 /nodefaultlib:"libcd" /nodefaultlib:"libc" /pdbtype:sept /libpath:"debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "HelpEd - Win32 Release"
+# Name "HelpEd - Win32 Debug"
+# Begin Group "res"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\code\HelpEd\res\HelpEd.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\res\HelpEd.rc2
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\res\HelpEdDoc.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\res\Toolbar.bmp
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\code\HelpEd\HelpEd.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\HelpEd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\HelpEd.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\HelpEdDoc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\HelpEdDoc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\HelpEdLine.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\HelpEdLine.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\HelpEdView.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\HelpEdView.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\MainFrm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\MainFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\StdAfx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\HelpEd\StdAfx.h
+# End Source File
+# End Target
+# End Project
diff --git a/HelpEd.exe b/HelpEd.exe
new file mode 100644
index 0000000..a72bf0b
--- /dev/null
+++ b/HelpEd.exe
Binary files differ
diff --git a/HelpEd.plg b/HelpEd.plg
new file mode 100644
index 0000000..863c64a
--- /dev/null
+++ b/HelpEd.plg
@@ -0,0 +1,52 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: HelpEd - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating command line "rc.exe /l 0x409 /fo"HelpEdDebug/HelpEd.res" /i "code\HelpEd" /d "_DEBUG" /d "_AFXDLL" "C:\projects\freespace2_public\code\HelpEd\HelpEd.rc""
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP34B.tmp" with contents
+[
+/nologo /G5 /MDd /W4 /GX /Zi /Od /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Fo"HelpEdDebug/" /Fd"HelpEdDebug/" /FD /GZ /c
+"C:\projects\freespace2_public\code\HelpEd\HelpEd.cpp"
+"C:\projects\freespace2_public\code\HelpEd\HelpEdDoc.cpp"
+"C:\projects\freespace2_public\code\HelpEd\HelpEdLine.cpp"
+"C:\projects\freespace2_public\code\HelpEd\HelpEdView.cpp"
+"C:\projects\freespace2_public\code\HelpEd\MainFrm.cpp"
+"C:\projects\freespace2_public\code\HelpEd\StdAfx.cpp"
+]
+Creating command line "cwcl.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP34B.tmp"
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP34C.tmp" with contents
+[
+winmm.lib /nologo /subsystem:windows /incremental:no /pdb:"HelpEd.pdb" /debug /debugtype:both /machine:I386 /nodefaultlib:"libcd" /nodefaultlib:"libc" /out:"HelpEd.exe" /pdbtype:sept /libpath:"debug"
+.\HelpEdDebug\HelpEd.obj
+.\HelpEdDebug\HelpEdDoc.obj
+.\HelpEdDebug\HelpEdLine.obj
+.\HelpEdDebug\HelpEdView.obj
+.\HelpEdDebug\MainFrm.obj
+.\HelpEdDebug\StdAfx.obj
+.\HelpEdDebug\HelpEd.res
+.\Debug\code.lib
+]
+Creating command line "cwlink.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP34C.tmp"
+<h3>Output Window</h3>
+Compiling resources...
+Compiling...
+HelpEd.cpp
+HelpEdDoc.cpp
+HelpEdLine.cpp
+HelpEdView.cpp
+MainFrm.cpp
+StdAfx.cpp
+Generating Code...
+Linking...
+
+
+
+<h3>Results</h3>
+HelpEd.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
diff --git a/Nebedit.dsp b/Nebedit.dsp
new file mode 100644
index 0000000..4c6a795
--- /dev/null
+++ b/Nebedit.dsp
@@ -0,0 +1,99 @@
+# Microsoft Developer Studio Project File - Name="Nebedit" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=Nebedit - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Nebedit.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Nebedit.mak" CFG="Nebedit - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Nebedit - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "Nebedit - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Freespace2", RQCCAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Nebedit - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "NebeditRelease"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /U "_DEBUG" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /libpath:"release"
+
+!ELSEIF "$(CFG)" == "Nebedit - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Nebedit___Win32_Debug"
+# PROP BASE Intermediate_Dir "Nebedit___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "NebEditDebug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G5 /MTd /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "NEBEDIT" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib msacm32.lib comctl32.lib wsock32.lib code.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /out:"E:\games\freespace2\Nebedit.exe" /pdbtype:sept /libpath:"debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Nebedit - Win32 Release"
+# Name "Nebedit - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\code\nebedit\NebEdit.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\nebedit\Nebstubs.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/Nebedit.plg b/Nebedit.plg
new file mode 100644
index 0000000..b5ad67a
--- /dev/null
+++ b/Nebedit.plg
@@ -0,0 +1,37 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: Nebedit - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP34E.tmp" with contents
+[
+/nologo /G5 /MTd /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "NEBEDIT" /Fo"NebEditDebug/" /Fd"NebEditDebug/" /FD /GZ /c
+"C:\projects\freespace2_public\code\nebedit\NebEdit.cpp"
+"C:\projects\freespace2_public\code\nebedit\Nebstubs.cpp"
+]
+Creating command line "cwcl.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP34E.tmp"
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP34F.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib msacm32.lib comctl32.lib wsock32.lib code.lib /nologo /subsystem:windows /incremental:yes /pdb:"Nebedit.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /out:"E:\games\freespace2\Nebedit.exe" /pdbtype:sept /libpath:"debug"
+.\NebEditDebug\NebEdit.obj
+.\NebEditDebug\Nebstubs.obj
+.\Debug\code.lib
+]
+Creating command line "cwlink.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP34F.tmp"
+<h3>Output Window</h3>
+Compiling...
+NebEdit.cpp
+Nebstubs.cpp
+Generating Code...
+Linking...
+
+
+
+<h3>Results</h3>
+Nebedit.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
diff --git a/Pofview.dsp b/Pofview.dsp
new file mode 100644
index 0000000..0fd1922
--- /dev/null
+++ b/Pofview.dsp
@@ -0,0 +1,179 @@
+# Microsoft Developer Studio Project File - Name="Pofview" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=Pofview - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Pofview.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Pofview.mak" CFG="Pofview - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Pofview - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "Pofview - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Freespace2", ARCCAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Pofview - Win32 Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "PofViewRelease"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /U "_DEBUG" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 winmm.lib msacm32.lib comctl32.lib wsock32.lib code.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmtd.lib" /libpath:"release"
+
+!ELSEIF "$(CFG)" == "Pofview - Win32 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Pofview___Win32_Debug"
+# PROP BASE Intermediate_Dir "Pofview___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "PofViewDebug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /G5 /MDd /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\fred2" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_AFXDLL" /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 winmm.lib msacm32.lib comctl32.lib wsock32.lib code.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmtd.lib" /out:"E:\games\freespace2\Pofview.exe" /pdbtype:sept /libpath:"debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Pofview - Win32 Release"
+# Name "Pofview - Win32 Debug"
+# Begin Group "res"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\code\pofview\res\PofView.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\res\PofView.rc2
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\res\PofViewDoc.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\res\Toolbar.bmp
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\code\pofview\ChildFrm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\ChildFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\MainFrm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\MainFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\ObjectTree.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\ObjectTree.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\PofView.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\PofView.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\PofView.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\PofViewDoc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\PofViewDoc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\PofViewStubs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\PofViewView.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\PofViewView.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\StdAfx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\pofview\StdAfx.h
+# End Source File
+# End Target
+# End Project
diff --git a/Pofview.plg b/Pofview.plg
new file mode 100644
index 0000000..f17481e
--- /dev/null
+++ b/Pofview.plg
@@ -0,0 +1,58 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: Pofview - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating command line "rc.exe /l 0x409 /fo"PofViewDebug/PofView.res" /i "code\pofview" /d "_DEBUG" /d "_AFXDLL" "C:\projects\freespace2_public\code\pofview\PofView.rc""
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP351.tmp" with contents
+[
+/nologo /G5 /MDd /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\fred2" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_AFXDLL" /Fo"PofViewDebug/" /Fd"PofViewDebug/" /FD /GZ /c
+"C:\projects\freespace2_public\code\pofview\ChildFrm.cpp"
+"C:\projects\freespace2_public\code\pofview\MainFrm.cpp"
+"C:\projects\freespace2_public\code\pofview\ObjectTree.cpp"
+"C:\projects\freespace2_public\code\pofview\PofView.cpp"
+"C:\projects\freespace2_public\code\pofview\PofViewDoc.cpp"
+"C:\projects\freespace2_public\code\pofview\PofViewStubs.cpp"
+"C:\projects\freespace2_public\code\pofview\PofViewView.cpp"
+"C:\projects\freespace2_public\code\pofview\StdAfx.cpp"
+]
+Creating command line "cwcl.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP351.tmp"
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP352.tmp" with contents
+[
+winmm.lib msacm32.lib comctl32.lib wsock32.lib code.lib /nologo /subsystem:windows /incremental:yes /pdb:"Pofview.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmtd.lib" /out:"E:\games\freespace2\Pofview.exe" /pdbtype:sept /libpath:"debug"
+.\PofViewDebug\ChildFrm.obj
+.\PofViewDebug\MainFrm.obj
+.\PofViewDebug\ObjectTree.obj
+.\PofViewDebug\PofView.obj
+.\PofViewDebug\PofViewDoc.obj
+.\PofViewDebug\PofViewStubs.obj
+.\PofViewDebug\PofViewView.obj
+.\PofViewDebug\StdAfx.obj
+.\PofViewDebug\PofView.res
+.\Debug\code.lib
+]
+Creating command line "cwlink.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP352.tmp"
+<h3>Output Window</h3>
+Compiling resources...
+Compiling...
+ChildFrm.cpp
+MainFrm.cpp
+ObjectTree.cpp
+PofView.cpp
+PofViewDoc.cpp
+PofViewStubs.cpp
+PofViewView.cpp
+StdAfx.cpp
+Generating Code...
+Linking...
+
+
+
+<h3>Results</h3>
+Pofview.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
diff --git a/Scramble.dsp b/Scramble.dsp
new file mode 100644
index 0000000..32a8a81
--- /dev/null
+++ b/Scramble.dsp
@@ -0,0 +1,94 @@
+# Microsoft Developer Studio Project File - Name="Scramble" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Scramble - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Scramble.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Scramble.mak" CFG="Scramble - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Scramble - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Scramble - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Freespace2", XSCCAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Scramble - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "ScrambleRelease"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /I "code\nebula" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /U "_DEBUG" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /libpath:"release"
+
+!ELSEIF "$(CFG)" == "Scramble - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Scramble___Win32_Debug"
+# PROP BASE Intermediate_Dir "Scramble___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "ScrambleDebug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G5 /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib msacm32.lib comctl32.lib wsock32.lib code.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /pdbtype:sept /libpath:"debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Scramble - Win32 Release"
+# Name "Scramble - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\code\Scramble\scramble.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\code\Scramble\scramble.h
+# End Source File
+# End Target
+# End Project
diff --git a/Scramble.plg b/Scramble.plg
new file mode 100644
index 0000000..86f6032
--- /dev/null
+++ b/Scramble.plg
@@ -0,0 +1,33 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: Scramble - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP354.tmp" with contents
+[
+/nologo /G5 /MLd /W4 /GX /Zi /Od /Ob2 /I "code\anim" /I "code\asteroid" /I "code\bmpman" /I "code\cfile" /I "code\cmdline" /I "code\cmeasure" /I "code\controlconfig" /I "code\cutscene" /I "code\debris" /I "code\debugconsole" /I "code\directx" /I "code\fireball" /I "code\gamehelp" /I "code\freespace2" /I "code\fs2launch" /I "code\fred" /I "code\gamesequence" /I "code\gamesnd" /I "code\glide" /I "code\globalincs" /I "code\graphics" /I "code\hud" /I "code\io" /I "code\jumpnode" /I "code\lighting" /I "code\math" /I "code\menuui" /I "code\mission" /I "code\missionui" /I "code\model" /I "code\movie" /I "code\network" /I "code\object" /I "code\observer" /I "code\osapi" /I "code\palman" /I "code\parse" /I "code\particle" /I "code\pcxutils" /I "code\physics" /I "code\playerman" /I "code\popup" /I "code\radar" /I "code\render" /I "code\ship" /I "code\sndman" /I "code\sound" /I "code\starfield" /I "code\stats" /I "code\testcode" /I "code\ui" /I "code\vcodec" /I "code\weapon" /I "code\localization" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"ScrambleDebug/" /Fd"ScrambleDebug/" /FD /GZ /c
+"C:\projects\freespace2_public\code\Scramble\scramble.cpp"
+]
+Creating command line "cwcl.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP354.tmp"
+Creating temporary file "C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP355.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib msacm32.lib comctl32.lib wsock32.lib code.lib /nologo /subsystem:console /incremental:yes /pdb:"Scramble.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /out:"Scramble.exe" /pdbtype:sept /libpath:"debug"
+.\ScrambleDebug\scramble.obj
+.\Debug\code.lib
+]
+Creating command line "cwlink.exe @C:\DOCUME~1\daveb\LOCALS~1\Temp\RSP355.tmp"
+<h3>Output Window</h3>
+Compiling...
+scramble.cpp
+Linking...
+
+
+
+<h3>Results</h3>
+Scramble.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
diff --git a/code/AC/ac.cpp b/code/AC/ac.cpp
new file mode 100644
index 0000000..b16d4da
--- /dev/null
+++ b/code/AC/ac.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/AC/ac.cpp $
+ * $Revision: 2 $
+ * $Date: 10/23/98 6:03p $
+ * $Author: Dave $
+ *
+ * C module for console version of anim converter
+ *
+ * $Log: /Freespace2/code/AC/ac.cpp $
+ *
+ * 2 10/23/98 6:03p Dave
+ *
+ * 12 6/24/98 10:43a Hoffoss
+ * Changed default to 15 FPS instead of 30 FPS.
+ *
+ * 11 6/23/98 4:18p Hoffoss
+ * Fixed some bugs with AC release build.
+ *
+ * 10 7/20/97 6:59p Lawrance
+ * added new -i and -x switches
+ *
+ * 9 5/21/97 11:06a Lawrance
+ * enabling a user-defined transparent value
+ *
+ * 8 5/19/97 3:21p Lawrance
+ * add fps parm, version num to anim header
+ *
+ * 7 2/25/97 5:18p Lawrance
+ * add carriage return after finished, so DOS prompt at a new line
+ *
+ * 6 2/20/97 3:03p Lawrance
+ * initialize force_key_frame global to -1
+ *
+ * 5 2/20/97 1:59p Lawrance
+ * sourcesafe sucks
+ *
+ * 4 2/20/97 1:58p Adam
+ *
+ * 2 2/19/97 9:26p Lawrance
+ * console version of converter working
+ *
+ * 1 2/19/97 7:26p Lawrance
+ *
+ * $NoKeywords: $
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "convert.h"
+#include "ac.h"
+#include "AnimPlay.h"
+#include "PackUnpack.h"
+
+#ifdef NDEBUG
+char *help_text = "AC ANI Converter Copyright (C) 1998, Volition, Inc. All Rights Reserved.\n"
+ "For exclusive use in FreeSpace missions only.\n\n"
+ "Usage: ac [-fps n] [-v] filename\n\n" \
+ "-i => display information and statistics about the ani file\n" \
+ "-x => extract pcx files from ani (named filename0000.pcx etc)\n" \
+ "-fps n => n frames per second (default 15)\n" \
+ "-v => display the version number\n" \
+ "filename => a Microsoft RLE AVI || PCX file in form nameXXXX.pcx\n\n" \
+ "Examples:\n" \
+ "ac test.avi => converts test.avi to test.ani\n" \
+ "ac test0000.pcx => converts test0000.pcx up to highest testxxxx.pcx to test.ani\n";
+
+#else
+char *help_text = "Usage: ac [-c n] [-k n] [-ke n] [-fps n] [-to] [-v] filename\n\n" \
+ "-c n => which kind of compression to use (default is 1):\n" \
+ " -c 0 => compression using up to 255 count, takes 3 bytes for a run\n" \
+ " -c 1 => compression using up to 127 count, takes 2 bytes for a run\n" \
+ "-i => display information and statistics about the ani file\n" \
+ "-x => extract pcx files from ani (named filename0000.pcx etc)\n" \
+ "-k n => keyframe at frame n\n" \
+ "-ke n => keyframe every n frames\n" \
+ "-fps n => n frames per second (default 15)\n" \
+ "-to => transparent override. Use pixel in top-left corner of first frame as transparent color. Otherwise RGB value 0.255.0 is used.\n" \
+ "-v => display the version number\n" \
+ "filename => a Microsoft RLE AVI || PCX file in form nameXXXX.pcx\n\n" \
+ "Examples:\n" \
+ "ac test.avi => converts test.avi to test.ani with no keyframes\n" \
+ "ac -k 10 test.avi => converts test.avi to test.ani with keyframe at 10th frame\n" \
+ "ac -ke 10 test.avi => every 10th frame (frame 1, 10, 20 etc) is a keyframe\n" \
+ "ac test0000.pcx => converts test0000.pcx up to highest testxxxx.pcx to test.ani\n"\
+ "ac -k 10 test0000.pcx => same as above, but test009.pcx is a keyframe\n" \
+ "ac -ke 5 test0000.pcx => makes test0004.pcx, test0009.pcx, etc a keyframe\n";
+#endif
+
+// Global to file
+static char buffer[255];
+
+// Internal function prototypes
+void ac_error(char *msg);
+void start_convert_with(char* filename);
+
+int main(int argc, char *argv[])
+{
+ int i;
+
+ key_frame_rate = 0; // assume no regular keyframes
+ force_key_frame = -1; // assume no force key frame
+
+ Default_fps = ANIM_DEFAULT_FPS; // assume default fps value
+ Use_custom_xparent_color = 0; // assume xparent RGB is 0.255.0
+
+ Compression_type = CUSTOM_DELTA_RLE;
+
+ vm_init(16*1024*1024);
+
+ if ( argc <= 1 ) {
+ printf(help_text);
+ exit(0);
+ }
+
+ for ( i = 1; i < argc; i++ ) {
+ if ( !stricmp(argv[i], "-h" ) ) {
+ printf(help_text);
+ exit(0);
+
+#ifndef NDEBUG
+ } else if ( !stricmp(argv[i], "-c" ) ) {
+ int mode;
+ if ( i+1 >= argc ) ac_error("-c switch requires a parameter\n");
+ mode = atoi(argv[i+1]);
+ i++;
+ switch ( mode ) {
+ case 0:
+ Compression_type = CUSTOM_DELTA_RLE;
+ break;
+ case 1:
+ Compression_type = STD_DELTA_RLE;
+ break;
+ default:
+ ac_error("-c only supports compression types 0 and 1\n");
+ break;
+ } // end switch
+
+ } else if ( !stricmp(argv[i], "-k" ) ) {
+ if ( i+1 >= argc ) ac_error("-k switch requires a parameter\n");
+ force_key_frame = atoi(argv[i+1]);
+ i++;
+
+ } else if ( !stricmp(argv[i], "-ke" ) ) {
+ if ( i+1 >= argc ) ac_error("-ke switch requires a parameter\n");
+ key_frame_rate = atoi(argv[i+1]);
+ i++;
+
+ } else if ( !stricmp(argv[i], "-to" ) ) {
+ Use_custom_xparent_color = 1;
+#endif
+
+ } else if ( !stricmp(argv[i], "-fps" ) ) {
+ if ( i+1 >= argc ) ac_error("-fps switch requires a parameter\n");
+ Default_fps = atoi(argv[i+1]);
+ i++;
+
+ } else if ( !stricmp(argv[i], "-v" ) ) {
+ printf("AC version: %.2f\n", float(ANIM_VERSION));
+
+ } else if ( !stricmp(argv[i], "-i" ) ) {
+ if ( i+1 >= argc ) ac_error("-i switch requires filename of ani\n");
+ anim_display_info(argv[i+1]);
+ exit(0);
+
+ } else if ( !stricmp(argv[i], "-x" ) ) {
+ if ( i+1 >= argc ) ac_error("-x switch requires filename of ani\n");
+ anim_write_frames_out(argv[i+1]);
+ exit(0);
+
+ } else {
+ start_convert_with(argv[i]);
+ }
+
+ }
+
+ return 0;
+}
+
+void ac_error(char *msg)
+{
+ fprintf(stderr, msg);
+ exit(1);
+}
+
+
+void start_convert_with(char* filename)
+{
+ char *extension;
+ int rc;
+
+ if (strlen(filename) < 4 || filename[strlen(filename) - 4] != '.')
+ ac_error("Extension must be specified for file to convert");
+
+ extension = filename + strlen(filename) - 3;
+ if (!stricmp(extension, "avi")) {
+ if ( key_frame_rate > 0 )
+ key_frame_rate--;
+ rc = convert_avi_to_anim(filename);
+ if (rc) {
+ sprintf(buffer,"Could not convert %s to ani format\n", filename);
+ ac_error(buffer);
+ }
+ }
+ else if (!stricmp(extension, "pcx")) {
+ rc = convert_frames_to_anim(filename);
+ if (rc) {
+ sprintf(buffer,"Could not convert %s to ani format\n", filename);
+ ac_error(buffer);
+ }
+ }
+ else
+ ac_error("Type of file to convert is not supported");
+} \ No newline at end of file
diff --git a/code/AC/ac.h b/code/AC/ac.h
new file mode 100644
index 0000000..5f8931d
--- /dev/null
+++ b/code/AC/ac.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/AC/ac.h $
+ * $Revision: 2 $
+ * $Date: 10/23/98 6:03p $
+ * $Author: Dave $
+ *
+ * Header file for console version of anim converter
+ *
+ * $Log: /Freespace2/code/AC/ac.h $
+ *
+ * 2 10/23/98 6:03p Dave
+ *
+ * 1 10/23/98 5:04p Dave
+ *
+ * 1 10/23/98 4:32p Dave
+ *
+ * 1 2/19/97 7:26p Lawrance
+ *
+ * $NoKeywords: $
+ */
+
+
+#ifndef __AC_H__
+#define __AC_H__
+
+
+#endif /* __AC_H__ */ \ No newline at end of file
diff --git a/code/AC/ac_stubs.cpp b/code/AC/ac_stubs.cpp
new file mode 100644
index 0000000..1384a84
--- /dev/null
+++ b/code/AC/ac_stubs.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/ac/ac_stubs.cpp $
+ * $Revision: 7 $
+ * $Date: 6/21/99 10:24a $
+ * $Author: Andsager $
+ *
+ * Stubs to allow compiling of AC project
+ *
+ * $Log: /Freespace2/code/ac/ac_stubs.cpp $
+ *
+ * 7 6/21/99 10:24a Andsager
+ * Fix stubs.
+ *
+ * 6 3/19/99 9:52a Dave
+ * Checkin to repair massive source safe crash. Also added support for
+ * pof-style nebulae, and some new weapons code.
+ *
+ * 5 2/17/99 2:17p Dave
+ * a few new stubs
+ *
+ * 4 1/08/99 2:08p Dave
+ * Fixed software mode for pofview.
+ *
+ * 3 1/06/99 2:24p Dave
+ * Stub fixes.
+ *
+ * 2 10/23/98 6:03p Dave
+ *
+ * 1 10/23/98 5:04p Dave
+ *
+ * 1 10/23/98 4:32p Dave
+ *
+ * 6 6/23/98 2:52p Hoffoss
+ * Changed code so AC compiles once again.
+ *
+ * 5 7/20/97 6:59p Lawrance
+ * added new -i and -x switches
+ *
+ * 4 5/19/97 3:21p Lawrance
+ * add fps parm, version num to anim header
+ *
+ * 3 4/18/97 9:20a Lawrance
+ * added os_force_windowed() stub
+ *
+ * 2 2/19/97 9:26p Lawrance
+ * console version of converter working
+ *
+ * $NoKeywords: $
+ */
+
+#include "pstypes.h"
+
+struct bitmap;
+
+void gr_palette_load(unsigned char*)
+{
+}
+
+void os_force_windowed()
+{
+}
+
+void gr_set_palette(char *, unsigned char *)
+{
+}
+
+int tga_read_bitmap( char *, bitmap *) { return 0; };
+int tga_read_header(char *, bitmap *, unsigned char *) { return 0; }
+long fixdiv(long, long) { return 0; }
+int game_cd_changed() { return 0; }
+int Font1;
+void freespace_menu_background() {}
+int Fred_running;
+int Pofview_running = 0;
+char *Game_CDROM_dir;
+void game_stop_looped_sounds() {}
+void game_enter_state(int, int){}
+void game_leave_state(int, int){}
+void game_do_state(int){}
+int set_cdrom_path(int){return 0;}
+int find_freespace_cd(char*){return 0;}
+void game_flush(){}
+void game_process_event(int, int);
+int Game_skill_level;
+float flFrametime;
+int game_check_key(){return 0;}
+void game_stop_time(){}
+void game_do_state_common(int, int){}
+void game_start_time(){}
+void game_set_frametime(int){}
+int Test_begin;
+long Game_time_compression;
+int Framerate_delay;
+int game_poll() {return 0;}
+char *Game_current_mission_filename;
+void game_process_event(int, int){}
+void game_increase_skill_level(){}
+int Warpout_forced;
+float Warpout_time;
+int game_start_mission(){return 0;}
+void game_level_close(){}
+void game_whack_apply(float, float){}
+void game_flash(float, float, float){}
+int game_do_cd_check(char*){return 0;}
+struct fs_builtin_mission *game_find_builtin_mission(char*){return 0;}
+int Game_do_state_should_skip;
+int Show_target_weapons;
+int Show_target_debug_info;
+int Game_subspace_effect;
+void game_load_palette(){}
+void game_format_time(long, char*){}
+int game_get_default_skill_level(){return 0;}
+float Freespace_gamma;
+void get_version_string(char*){}
+int Sun_drew;
+int Interface_framerate;
+void game_set_view_clip(){}
+float Viewer_zoom;
+int Game_weapons_tbl_valid;
+int Game_ships_tbl_valid;
+vector Camera_pos;
+vector Dead_player_last_vel;
+int Debug_octant;
+void game_shudder_apply(int, float){}
+int game_hacked_data() {return 0;}
+int game_single_step;
+int last_single_step;
+int Nebedit_running;
+void game_tst_mark(struct object*, struct ship*){}
+int game_do_cd_mission_check(char*){return 0;}
+int Player_multi_died_check;
+int tst; \ No newline at end of file
diff --git a/code/AC/convert.cpp b/code/AC/convert.cpp
new file mode 100644
index 0000000..728b644
--- /dev/null
+++ b/code/AC/convert.cpp
@@ -0,0 +1,788 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/AC/convert.cpp $
+ * $Revision: 2 $
+ * $Date: 10/23/98 6:03p $
+ * $Author: Dave $
+ *
+ * C module for the conversion of standard animation files to our own ANIM format.
+ * This is where all the real code for this application is located really.
+ *
+ * $Log: /Freespace2/code/AC/convert.cpp $
+ *
+ * 2 10/23/98 6:03p Dave
+ *
+ * 1 10/23/98 5:34p Dave
+ *
+ * 3 10/22/98 6:14p Dave
+ * Optimized some #includes in Anim folder. Put in the beginnings of
+ * parse/localization support for externalized strings and tstrings.tbl
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 12 6/23/98 2:52p Hoffoss
+ * Changed code so AC compiles once again.
+ *
+ * 11 7/20/97 6:57p Lawrance
+ * supporting new RLE format
+ *
+ * 10 6/25/97 11:57a Lawrance
+ * forgot linefeed
+ *
+ * 9 6/25/97 11:49a Lawrance
+ * don't assert if PCX read fails, print warning
+ *
+ * 8 5/21/97 2:26p Lawrance
+ * bug fix: not using correct header size
+ *
+ * 7 5/21/97 11:06a Lawrance
+ * enabling a user-defined transparent value
+ *
+ * 6 5/19/97 3:21p Lawrance
+ * add fps parm, version num to anim header
+ *
+ * 5 2/25/97 5:18p Lawrance
+ * force_key_frame now numbering from 1 for PCXs as well as AVIs
+ *
+ * 4 2/20/97 1:47p Lawrance
+ * adding dots when making frames
+ *
+ * 3 2/20/97 10:30a Hoffoss
+ * Added in support for forcing a key frame.
+ *
+ * 2 2/19/97 9:26p Lawrance
+ * added force_key_frame global
+ *
+ * 1 2/19/97 7:14p Lawrance
+ *
+ * 14 2/19/97 4:21p Lawrance
+ * took out unnecessary #include BmpMan.h
+ *
+ * 13 2/19/97 3:59p Lawrance
+ * using pcxutils to load bitmaps, not bmpman
+ *
+ * 12 2/17/97 2:59p Lawrance
+ * integrating into game
+ *
+ * 11 2/17/97 3:02p Hoffoss
+ * Added headers to files, and implemented key frame dialog stuff.
+ *
+ * 10 2/14/97 10:38p Lawrance
+ * fixing bugs
+ *
+ * 9 2/14/97 9:47p Hoffoss
+ * fixed bugs.
+ *
+ * 8 2/14/97 8:44p Lawrance
+ * fixed bug with saving header
+ *
+ * 7 2/14/97 8:04p Hoffoss
+ * Fixed bug.
+ *
+ * 6 2/14/97 7:44p Lawrance
+ * fixed some bugs in loading an AVI
+ *
+ * 5 2/14/97 7:33p Lawrance
+ * added convert_avi_to_anim() function
+ *
+ * 4 2/14/97 5:38p Hoffoss
+ * Changes to get AnimCoverter project to compile and link.
+ *
+ * 3 2/14/97 3:28p Hoffoss
+ * Wrote functions to save an anim file.
+ *
+ * 2 2/13/97 5:55p Lawrance
+ * reading AVI / decompressing AVI functions in
+ *
+ * $NoKeywords: $
+ */
+
+#pragma warning(disable: 4201)
+
+#include <wtypes.h>
+#include <vfw.h> /* Video For Windows header file */
+#include "PsTypes.h"
+#include "convert.h"
+#include "pcxutils.h"
+#include "AnimPlay.h"
+#include "PackUnPack.h"
+
+#define AVI_STREAM_F_USED ( 1 << 0 )
+
+typedef struct AVI_STREAM_TYPE {
+ PAVISTREAM pstream;
+ PAVIFILE pfile;
+ int num_frames;
+ int current_frame;
+ int w,h,bpp;
+ int min_compressed_buffer_size;
+ ubyte palette[768];
+ char filename[255];
+ //ubyte pal_translation[256]; // palette translation look-up table
+ int flags;
+} AVI_STREAM_TYPE;
+
+// Internal function prototypes
+int AVI_stream_open(char* filename);
+void AVI_stream_close();
+int AVI_stream_get_frame(ubyte* buffer, int frame_number);
+void AVI_decompress_RLE8(ubyte* src, ubyte* dest, int w, int h);
+
+// Global to file
+static AVI_STREAM_TYPE AVI_stream;
+static int AVI_stream_inited = 0;
+
+// Globals
+char *anim_save_filename;
+ubyte *cur_frame, *last_frame;
+ubyte anim_buffer[ANIM_BUFFER_MAX];
+int key_frame_rate;
+int force_key_frame;
+int total_key_frames;
+int anim_offset;
+int cur_frame_num;
+int Default_fps;
+int Use_custom_xparent_color;
+rgb_triple Xparent_color;
+
+int Compression_type; // what kind of RLE compression is going to be used
+int Key_frame_compression, Regular_frame_compression;
+
+key_frame *first_frame;
+FILE *anim_fp = NULL;
+anim Anim;
+
+// AVI_stream_init() is called only to clear USED flag of the AVI_stream structure
+// and reset the current frame.
+//
+// This does not need to be called explicity, since it will be called by AVI_stream_open()
+// anyways.
+//
+void AVI_stream_init()
+{
+ AVI_stream.flags &= ~AVI_STREAM_F_USED;
+ AVI_stream.current_frame = 0;
+ AVI_stream_inited = 1;
+
+ AVIFileInit(); // opens AVIFile library
+}
+
+// AVI_stream_open() will open the AVI file and prepare it for reading, but will not
+// store any of the frame data.
+//
+// returns: 0 ==> success
+// !0 ==> could not open the AVI stream
+//
+// The filename is expected to be an absolute pathname (or file in the current working directory)
+//
+int AVI_stream_open(char* filename)
+{
+ if ( !AVI_stream_inited )
+ AVI_stream_init();
+
+ int hr;
+ PAVIFILE pfile;
+ PAVISTREAM pstream;
+ AVISTREAMINFO avi_stream_info;
+
+ Assert( !(AVI_stream.flags & AVI_STREAM_F_USED) );
+
+ // Open the AVI file
+ hr = AVIFileOpen(&pfile, filename, OF_SHARE_DENY_WRITE, 0);
+ if (hr != 0){
+// nprintf(("Warning", "AVI ==> Unable to open %s", filename));
+ return -1;
+ }
+
+ strcpy(AVI_stream.filename, filename);
+
+ // Get a handle to the video stream within the AVI file
+ hr = AVIFileGetStream(pfile, &pstream, streamtypeVIDEO, 0);
+ if (hr != 0){
+ //nprintf(("Warning", "AVI ==> Unable to open video stream in %s", filename));
+ return -1;
+ }
+
+ // Store the pointer to stream, since we'll need it later to read from disk
+ AVI_stream.pstream = pstream;
+ AVI_stream.pfile = pfile;
+
+ // Get information on the stream
+ hr = AVIStreamInfo( pstream, &avi_stream_info, sizeof(AVISTREAMINFO) );
+ if (hr != 0){
+ //nprintf(("Warning", "AVI ==> Unable to retreive stream info in %s", filename));
+ return -1;
+ }
+
+
+ int buffer_size;
+
+ int start_sample = AVIStreamStart(pstream);
+ Assert( start_sample == 0 );
+
+ int end_sample = AVIStreamEnd(pstream);
+ Assert( end_sample >= start_sample );
+
+ // store the number of frames in the AVI_info[] structure
+ AVI_stream.num_frames = end_sample; // start sample must be 0
+ Assert(AVI_stream.num_frames == AVIStreamLength(pstream) );
+
+
+ // Get information on the stream
+ hr = AVIStreamInfo( pstream, &avi_stream_info, sizeof(AVISTREAMINFO) );
+ if (hr != 0){
+ //nprintf(("Warning", "AVI ==> Unable to retreive stream info in %s", filename));
+ return -1;
+ }
+
+ buffer_size = avi_stream_info.dwSuggestedBufferSize;
+ Assert( buffer_size > 0 );
+ AVI_stream.min_compressed_buffer_size = buffer_size;
+
+ // determine the format of the AVI image data
+ ubyte* format_buffer;
+ long format_buffer_size;
+ BITMAPINFO* bitmap_info;
+
+ hr = AVIStreamFormatSize(pstream, 0, &format_buffer_size);
+ Assert( format_buffer_size > 0 );
+
+ format_buffer = (ubyte*) malloc(format_buffer_size);
+ Assert(format_buffer != NULL); // format_buffer is free'ed when AVI is free'ed, since memory is used by b_info member in AVI_info[] structure
+
+ hr = AVIStreamReadFormat(pstream, 0, format_buffer, &format_buffer_size);
+ bitmap_info = (BITMAPINFO*)format_buffer;
+
+
+ switch ( bitmap_info->bmiHeader.biCompression ) {
+ case BI_RLE8:
+ break;
+
+ default:
+ Assert(0);
+ break;
+ }
+
+ AVI_stream.w = bitmap_info->bmiHeader.biWidth;
+ AVI_stream.h = bitmap_info->bmiHeader.biHeight;
+ AVI_stream.bpp = bitmap_info->bmiHeader.biBitCount;
+
+ // create the palette translation look-up table
+ //
+ // Transparency: If the palette color is full green, then treat as transparent
+ //
+ RGBQUAD* pal;
+ pal = (RGBQUAD*)(bitmap_info->bmiColors);
+
+ // Store the palette in the AVI stream structure
+ for ( int i = 0; i < 256; i++ ) {
+ AVI_stream.palette[i*3] = pal[i].rgbRed;
+ AVI_stream.palette[i*3+1] = pal[i].rgbGreen;
+ AVI_stream.palette[i*3+2] = pal[i].rgbBlue;
+ }
+
+
+ // memcpy(AVI_stream.palette, pal, 256*3);
+
+/*
+ int transparent_found = 0;
+ for ( i = 0; i < 256; i++ ) {
+
+ //nprintf(("AVI", "AVI ==> R: %d G: %d B: %d\n", pal[i].rgbRed, pal[i].rgbGreen, pal[i].rgbBlue));
+ if ( pal[i].rgbRed < 5 && pal[i].rgbGreen > 250 && pal[i].rgbBlue < 5 ) {
+ avi_stream->pal_translation[i] = TRANSPARENT_INDEX;
+ break; // found transparent, continue in j for loop, since don't need check any more
+ }
+ else
+ avi_stream->pal_translation[i] = palette_find( pal[i].rgbRed, pal[i].rgbGreen, pal[i].rgbBlue );
+ }
+
+ for ( j = i+1; j < 256; j++ ) {
+ avi_stream->pal_translation[j] = palette_find( pal[j].rgbRed, pal[j].rgbGreen, pal[j].rgbBlue );
+ }
+*/
+
+ free(format_buffer);
+
+ // set the flag to used, so to make sure we only process one AVI stream at a time
+ AVI_stream.flags |= AVI_STREAM_F_USED;
+
+
+ return 0;
+}
+
+
+// AVI_stream_close() should be called when you are finished reading all the frames of an AVI
+//
+void AVI_stream_close()
+{
+// Assert( AVI_stream.flags & AVI_STREAM_F_USED);
+
+ AVIStreamRelease(AVI_stream.pstream); // closes the video stream
+ AVIFileRelease(AVI_stream.pfile); // closes the file
+ AVI_stream.flags &= ~AVI_STREAM_F_USED; // clear the used flag
+
+ AVIFileExit(); // releases AVIFile library
+ AVI_stream_inited = 0;
+
+}
+
+
+
+
+// AVI_stream_get_next_frame() will take the next RLE'd AVI frame and return the
+// uncompressed data in the buffer pointer supplied as a parameter. The caller is
+// responsible for allocating the memory before-hand (the memory required is easily
+// calculated by looking at the w and h members in AVI_stream).
+//
+// returns: 0 ==> success
+// !0 ==> error
+//
+int AVI_stream_get_frame(ubyte* buffer, int frame_number)
+{
+ if ( frame_number > AVI_stream.num_frames ) {
+ buffer = NULL;
+ return -1;
+ }
+
+ Assert( (frame_number - 1) >= 0 );
+
+ ubyte* compressed_frame = (ubyte*)malloc(AVI_stream.min_compressed_buffer_size);
+ Assert( compressed_frame != NULL );
+
+ long num_bytes_used;
+ long num_samples_used;
+
+ AVIStreamRead( AVI_stream.pstream, frame_number-1, 1, compressed_frame, AVI_stream.min_compressed_buffer_size, &num_bytes_used, &num_samples_used);
+ Assert(num_samples_used == 1);
+
+ AVI_decompress_RLE8(compressed_frame, buffer, AVI_stream.w, AVI_stream.h);
+
+ free( compressed_frame );
+ return 0;
+
+}
+
+
+
+// -------------------------------------------------------------------------------------------------
+// AVI_decompress_RLE8() will decompress the data pointed to by src, and store in dest.
+//
+// NOTE: 1. memory for dest must be already allocated before calling function
+//
+
+void AVI_decompress_RLE8(ubyte* src, ubyte* dest, int w, int h)
+{
+ int src_index = 0;
+ int dest_index = 0;
+ int i;
+
+ Assert( src != NULL);
+ Assert( dest != NULL);
+ Assert( w > 0 );
+ Assert( h > 0 );
+
+ ubyte count;
+ ubyte run;
+ ubyte control_code;
+
+ int size_src = w * h + 1;
+
+ int scan_line = h-1;
+ int height_offset = scan_line * w;
+
+ while ( src_index < size_src ) {
+
+ count = src[src_index];
+
+ if ( count == 0 ) { // control code follows
+ src_index++;
+ control_code = src[src_index];
+ if ( control_code == 1 ) {
+ src_index++;
+// nprintf(("AVI","AVI ==> Reached end of compressed image\n"));
+ break;
+ }
+ else if ( control_code == 0 ) {
+ src_index++;
+ scan_line--;
+ height_offset = scan_line * w; // only need to calc once per scanline
+ dest_index = 0;
+ //nprintf(("AVI","AVI ==> Reached end of line in compressed image\n"));
+ }
+ else if ( control_code == 2 ) {
+ Assert(0);
+ }
+ else {
+ // in absolute mode
+ src_index++;
+ for ( i = 0; i < control_code; i++ ) {
+
+ dest[height_offset + dest_index] = src[src_index];
+ dest_index++;
+ src_index++;
+ }
+ // run must end on a word boundry
+ if ( control_code & 1 )
+ src_index++;
+ }
+ }
+ else {
+ src_index++;
+ run = src[src_index];
+ // nprintf(("AVI","AVI ==> Got %d pixel run of %d\n", src[src_index], count));
+ memset( &dest[height_offset + dest_index], run, count );
+ dest_index += count;
+ src_index++;
+ }
+ } // end while
+
+}
+
+int save_anim_header()
+{
+ int i, new_format_id = 0;
+
+ Assert(anim_fp);
+ fclose(anim_fp);
+ anim_fp = fopen(anim_save_filename, "r+b");
+
+ if (!fwrite(&new_format_id, 2, 1, anim_fp))
+ return -1;
+ if (!fwrite(&Anim.version, 2, 1, anim_fp))
+ return -1;
+ if (!fwrite(&Anim.fps, 2, 1, anim_fp))
+ return -1;
+ if (!fwrite(&Anim.xparent_r, 1, 1, anim_fp))
+ return -1;
+ if (!fwrite(&Anim.xparent_g, 1, 1, anim_fp))
+ return -1;
+ if (!fwrite(&Anim.xparent_b, 1, 1, anim_fp))
+ return -1;
+ if (!fwrite(&Anim.width, 2, 1, anim_fp))
+ return -1;
+ if (!fwrite(&Anim.height, 2, 1, anim_fp))
+ return -1;
+ if (!fwrite(&Anim.total_frames, 2, 1, anim_fp))
+ return -1;
+ if (!fwrite(&Anim.packer_code, 1, 1, anim_fp))
+ return -1;
+ if (fwrite(&Anim.palette, 3, 256, anim_fp) != 256)
+ return -1;
+ if (!fwrite(&total_key_frames, 2, 1, anim_fp))
+ return -1;
+
+ for (i=0; i<Anim.num_keys; i++) {
+ if (!fwrite(&Anim.keys[i].frame_num, 2, 1, anim_fp))
+ return -1;
+
+ if (!fwrite(&Anim.keys[i].offset, 4, 1, anim_fp))
+ return -1;
+ }
+
+ if (!fwrite(&anim_offset, 4, 1, anim_fp))
+ return -1;
+
+ return 0;
+}
+
+// This function allocates a linked list of key frame headers.
+// It is responsible for determining which frames in an anim
+// should be key frames.
+int allocate_key_frames(int total_frames)
+{
+ int count = 0, frame = 1, rate = key_frame_rate, last_frame;
+
+ if (!rate)
+ rate = total_frames;
+
+ while (frame <= total_frames) {
+ count++;
+ frame += rate;
+ }
+
+ if (force_key_frame >= 0)
+ count++;
+
+ if (count)
+ Anim.keys = (key_frame *) malloc(count * sizeof(key_frame));
+
+ count = 0;
+ frame = last_frame = 1;
+ while (frame <= total_frames) {
+ if ((force_key_frame > last_frame) && (force_key_frame < frame))
+ Anim.keys[count++].frame_num = force_key_frame;
+
+ Anim.keys[count++].frame_num = frame;
+ frame += rate;
+ }
+
+ if (force_key_frame > last_frame)
+ Anim.keys[count++].frame_num = force_key_frame;
+
+ Anim.num_keys = count;
+ return count; // number of key frames
+}
+
+int anim_save_init(char *file, int width, int height, int frames)
+{
+ Assert(file);
+ anim_save_filename = file;
+ anim_fp = fopen(file, "wb");
+ if (!anim_fp)
+ return -1;
+
+ Anim.version = ANIM_VERSION;
+ Anim.fps = Default_fps;
+ Anim.width = width;
+ Anim.height = height;
+ Anim.packer_code = PACKER_CODE;
+ Anim.xparent_r = Xparent_color.r;
+ Anim.xparent_g = Xparent_color.g;
+ Anim.xparent_b = Xparent_color.b;
+ Anim.total_frames = frames;
+ anim_offset = 0;
+ cur_frame_num = 0;
+ total_key_frames = allocate_key_frames(frames);
+ fseek(anim_fp, ANIM_HEADER_SIZE + total_key_frames * 6, SEEK_SET);
+
+ switch ( Compression_type ) {
+ case CUSTOM_DELTA_RLE:
+ Key_frame_compression = PACKING_METHOD_RLE_KEY;
+ Regular_frame_compression = PACKING_METHOD_RLE;
+ break;
+
+ case STD_DELTA_RLE:
+ Key_frame_compression = PACKING_METHOD_STD_RLE_KEY;
+ Regular_frame_compression = PACKING_METHOD_STD_RLE;
+ break;
+
+ default:
+ Int3();
+ return -1;
+ break;
+ } // end switch
+
+ return 0;
+}
+
+int anim_save_frame()
+{
+ ubyte *temp;
+ int i, size;
+ key_frame *keyp = NULL;
+
+ Assert(anim_fp);
+ cur_frame_num++;
+ Assert(cur_frame_num <= Anim.total_frames);
+
+ for (i=0; i<Anim.num_keys; i++)
+ if (Anim.keys[i].frame_num == cur_frame_num) {
+ keyp = &Anim.keys[i];
+ break;
+ }
+
+ if (keyp) {
+ fprintf(stdout, "*");
+ fflush(stdout);
+ keyp->offset = anim_offset;
+ size = pack_key_frame(cur_frame, anim_buffer, Anim.width * Anim.height, ANIM_BUFFER_MAX, Key_frame_compression);
+
+ } else {
+ fprintf(stdout, ".");
+ fflush(stdout);
+ size = pack_frame(cur_frame, last_frame, anim_buffer, Anim.width * Anim.height, ANIM_BUFFER_MAX, Regular_frame_compression);
+ }
+
+ if (size < 0)
+ return -1;
+
+ if ((int) fwrite(anim_buffer, 1, size, anim_fp) != size)
+ return -1;
+
+ anim_offset += size;
+ temp = cur_frame;
+ cur_frame = last_frame;
+ last_frame = temp;
+ return 0;
+}
+
+
+// converts an avi file to an anim file
+//
+// returns: 0 ==> success
+// !0 ==> failure
+//
+int convert_avi_to_anim(char* filename)
+{
+ char ani_filename[255];
+ int ret = 1;
+ int rc, i, xparent_pal_index;
+ int avi_stream_opened = 0;
+
+ rc = AVI_stream_open(filename);
+ if ( rc != 0 ) {
+ // could not open the AVI stream
+ goto Finish;
+ }
+ avi_stream_opened = 1;
+
+ Assert(AVI_stream.bpp == 8);
+ cur_frame = (ubyte*) malloc(AVI_stream.w * AVI_stream.h);
+ last_frame = (ubyte*) malloc(AVI_stream.w * AVI_stream.h);
+ Assert(cur_frame && last_frame);
+
+ strcpy(ani_filename, AVI_stream.filename);
+ strcpy(ani_filename + strlen(ani_filename) - 3, "ani");
+
+ memcpy(Anim.palette, AVI_stream.palette, 768);
+
+ if (Use_custom_xparent_color) {
+ // Need to look at pixel in top-left
+ rc = AVI_stream_get_frame(cur_frame, 1);
+ xparent_pal_index = cur_frame[0];
+ Xparent_color.r = Anim.palette[xparent_pal_index * 3];
+ Xparent_color.g = Anim.palette[xparent_pal_index * 3 + 1];
+ Xparent_color.b = Anim.palette[xparent_pal_index * 3 + 2];
+
+ } else {
+ Xparent_color.r = 0;
+ Xparent_color.g = 255;
+ Xparent_color.b = 0;
+ }
+
+ rc = anim_save_init(ani_filename, AVI_stream.w, AVI_stream.h, AVI_stream.num_frames);
+ if (rc == -1)
+ goto Finish;
+
+ for ( i=1; i <= AVI_stream.num_frames; i++ ) {
+ // get uncompressed frame from the AVI
+ rc = AVI_stream_get_frame(cur_frame, i);
+ if ( rc != 0 )
+ goto Finish;
+
+ // pass to the anim compression
+ rc = anim_save_frame();
+ if ( rc != 0 )
+ goto Finish;
+ }
+
+ rc = save_anim_header();
+ if ( rc != 0 )
+ goto Finish;
+
+ ret = 0;
+
+ Finish:
+ // done with the AVI.. close the stream
+ if ( avi_stream_opened )
+ AVI_stream_close();
+
+ if ( anim_fp )
+ fclose(anim_fp);
+
+ free(cur_frame);
+ free(last_frame);
+ fprintf(stdout,"\n");
+ fflush(stdout);
+ return ret;
+}
+
+int convert_frames_to_anim(char *filename)
+{
+ int first_frame, frame, pos, width, height, xparent_pal_index, r = -1;
+ char ani_filename[255], name[255], temp[8];
+ int rc;
+ FILE *fp;
+
+ Assert(strlen(filename) < 254);
+ strcpy(name, filename);
+ strcpy(ani_filename, filename);
+ strcpy(ani_filename + strlen(ani_filename) - 8, ".ani");
+ pos = strlen(name) - 8;
+ frame = first_frame = atoi(&name[pos]);
+ force_key_frame -= frame;
+
+ // first file
+ fp = fopen(name, "rb");
+ if(fp != NULL){
+ do {
+ fclose(fp);
+ frame++;
+ sprintf(temp, "%04.4d", frame);
+ strncpy(&name[pos], temp, 4);
+
+ // next file
+ fp = fopen(name, "rb");
+ } while(fp != NULL);
+ }
+
+ rc = pcx_read_header(filename, &width, &height, NULL);
+ if (rc != PCX_ERROR_NONE) {
+ fprintf(stdout, "An error reading the PCX file %s. It may not exist.\n", filename);
+ return -1;
+ }
+
+ cur_frame = (ubyte *) malloc(width * height);
+ last_frame = (ubyte *) malloc(width * height);
+
+ rc = pcx_read_bitmap_8bpp(filename, cur_frame, Anim.palette);
+ if (rc != PCX_ERROR_NONE) {
+ fprintf(stdout, "An error reading the PCX file %s. It may not exist.\n", filename);
+ return -1;
+ }
+
+ if (Use_custom_xparent_color) {
+ // Need to look at pixel in top-left
+ xparent_pal_index = ((ubyte *) cur_frame)[0];
+ Xparent_color.r = Anim.palette[xparent_pal_index * 3];
+ Xparent_color.g = Anim.palette[xparent_pal_index * 3 + 1];
+ Xparent_color.b = Anim.palette[xparent_pal_index * 3 + 2];
+
+ } else {
+ Xparent_color.r = 0;
+ Xparent_color.g = 255;
+ Xparent_color.b = 0;
+ }
+
+ if (anim_save_init(ani_filename, width, height, frame - first_frame))
+ goto done;
+
+ while (first_frame < frame) {
+ sprintf(temp, "%04.4d", first_frame);
+ strncpy(&name[pos], temp, 4);
+ rc = pcx_read_bitmap_8bpp(name, cur_frame, Anim.palette);
+ if (rc != PCX_ERROR_NONE)
+ goto done;
+
+ if (anim_save_frame())
+ goto done;
+
+ first_frame++;
+ }
+
+ if (save_anim_header())
+ goto done;
+
+ r = 0;
+
+done:
+ fclose(anim_fp);
+ free(cur_frame);
+ free(last_frame);
+ fprintf(stdout, "\n");
+ fflush(stdout);
+ return r;
+}
+
diff --git a/code/AC/convert.h b/code/AC/convert.h
new file mode 100644
index 0000000..35afcfa
--- /dev/null
+++ b/code/AC/convert.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/AC/convert.h $
+ * $Revision: 2 $
+ * $Date: 10/23/98 6:03p $
+ * $Author: Dave $
+ *
+ * Header file for the conversion of standard animation files to our own ANIM format
+ *
+ * $Log: /Freespace2/code/AC/convert.h $
+ *
+ * 2 10/23/98 6:03p Dave
+ *
+ * 1 10/23/98 5:34p Dave
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 7 6/24/98 10:43a Hoffoss
+ * Changed default to 15 FPS instead of 30 FPS.
+ *
+ * 6 4/10/98 5:20p John
+ * Changed RGB in lighting structure to be ubytes. Removed old
+ * not-necessary 24 bpp software stuff.
+ *
+ * 5 7/20/97 6:58p Lawrance
+ * supporting new RLE format
+ *
+ * 4 5/21/97 11:06a Lawrance
+ * enabling a user-defined transparent value
+ *
+ * 3 5/19/97 3:21p Lawrance
+ * add fps parm, version num to anim header
+ *
+ * 2 2/19/97 9:26p Lawrance
+ * added force_key_frame global
+ *
+ * 1 2/19/97 7:14p Lawrance
+ *
+ * 5 2/17/97 3:02p Hoffoss
+ * Added headers to files, and implemented key frame dialog stuff.
+ *
+ * 4 2/14/97 7:33p Lawrance
+ * added convert_avi_to_anim() function
+ *
+ * 3 2/14/97 3:28p Hoffoss
+ * Wrote functions to save an anim file.
+ *
+ * 2 2/13/97 5:55p Lawrance
+ * reading AVI / decompressing AVI functions in
+ *
+ * $NoKeywords: $
+ */
+
+#include "pstypes.h"
+
+#ifndef __CONVERT_H__
+#define __CONVERT_H__
+
+// !!IMPORTANT!!
+// ANIM_HEADER_SIZE is the size (in bytes) of the header. If the header format changes, you
+// must update this number.
+#define ANIM_HEADER_SIZE 790
+
+#define ANIM_BUFFER_MAX 400000
+#define ANIM_VERSION 2 // update this when save format changes
+
+#define ANIM_DEFAULT_FPS 15
+
+// specify the different types of compression that can be used (Compression_type is assigned one of these values)
+#define CUSTOM_DELTA_RLE 0
+#define STD_DELTA_RLE 1
+
+int convert_avi_to_anim(char* filename);
+int convert_frames_to_anim(char *filename);
+
+typedef struct rgb_triple {
+ ubyte r, g, b;
+} rgb_triple;
+
+extern int key_frame_rate;
+extern int force_key_frame;
+extern int Default_fps;
+extern rgb_triple Xparent_color;
+extern int Use_custom_xparent_color;
+extern int Compression_type;
+
+
+#endif /* __CONVERT_H__ */ \ No newline at end of file
diff --git a/code/Anim/AnimPlay.cpp b/code/Anim/AnimPlay.cpp
new file mode 100644
index 0000000..d5e3c1f
--- /dev/null
+++ b/code/Anim/AnimPlay.cpp
@@ -0,0 +1,1312 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/Anim/AnimPlay.cpp $
+ * $Revision: 9 $
+ * $Date: 9/13/99 11:26p $
+ * $Author: Andsager $
+ *
+ * C module for playing back anim files
+ *
+ * $Log: /Freespace2/code/Anim/AnimPlay.cpp $
+ *
+ * 9 9/13/99 11:26p Andsager
+ * Add debug code to check for poorly sized anis
+ *
+ * 8 8/26/99 9:45a Dave
+ * First pass at easter eggs and cheats.
+ *
+ * 7 7/16/99 1:49p Dave
+ * 8 bit aabitmaps. yay.
+ *
+ * 6 7/13/99 1:15p Dave
+ * 32 bit support. Whee!
+ *
+ * 5 6/10/99 10:34a Dave
+ * Removed unnecessary assert.
+ *
+ * 4 11/30/98 1:07p Dave
+ * 16 bit conversion, first run.
+ *
+ * 3 10/22/98 6:14p Dave
+ * Optimized some #includes in Anim folder. Put in the beginnings of
+ * parse/localization support for externalized strings and tstrings.tbl
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 38 6/23/98 4:18p Hoffoss
+ * Fixed some bugs with AC release build.
+ *
+ * 37 5/18/98 5:59p Hoffoss
+ * Made command briefing advanced now once the speech stops and animation
+ * has fully played once, whichever is longer.
+ *
+ * 36 5/14/98 6:29p Hoffoss
+ * Fixed some warnings a release rebuild all turned up.
+ *
+ * 35 5/07/98 3:11a Lawrance
+ * Implement custom streaming code
+ *
+ * 34 4/27/98 3:36p Dave
+ *
+ * 33 3/25/98 8:43p Hoffoss
+ * Changed anim_play() to not be so damn complex when you try and call it.
+ *
+ * 32 2/05/98 9:21p John
+ * Some new Direct3D code. Added code to monitor a ton of stuff in the
+ * game.
+ *
+ * 31 1/19/98 11:37p Lawrance
+ * Fixing Optimization build warnings
+ *
+ * 30 1/19/98 3:09p Hoffoss
+ * Only free an anim instance if it is actually playing.
+ *
+ * 29 1/14/98 6:43p Lawrance
+ * Add ref_count to anim struct, so we don't free multiple times
+ *
+ * 28 12/30/97 6:44p John
+ * Made g3_Draw_bitmap functions account for aspect of bitmap.
+ *
+ * 27 12/27/97 2:35p John
+ * Restructed some code so that if the memory-mapped file open fails, it
+ * will still read it the old-fashioned, non-memory mapped way.
+ *
+ * 26 12/24/97 9:10p Lawrance
+ * take out some debugging statements
+ *
+ * 25 12/24/97 8:57p Lawrance
+ * Added anim_ignore_next_frametime()
+ *
+ * 24 12/07/97 2:06p Dave
+ * Removed some debug frame-checking code.
+ *
+ * 23 12/06/97 2:55p Dave
+ *
+ * 22 11/29/97 2:05p John
+ * made g3_draw_bitmap and g3_draw_rotated bitmap take w&h, not w/2 & h/2,
+ * like they used to incorrectly assume. Added code to model to read in
+ * thruster radius's.
+ *
+ * 21 11/20/97 5:36p Dave
+ * Hooked in a bunch of main hall changes (including sound). Made it
+ * possible to reposition (rewind/ffwd)
+ * sound buffer pointers. Fixed animation direction change framerate
+ * problem.
+ *
+ * 20 11/20/97 4:33p Sandeep
+ * ALAN: ensure instance->paused gets initialized
+ *
+ * 19 11/20/97 4:12p Lawrance
+ * when paused, don't increment time_elapsed
+ *
+ * 18 11/19/97 8:28p Dave
+ * Hooked in Main Hall screen. Put in Anim support for ping ponging
+ * animations as well as general reversal of anim direction.
+ *
+ * 17 9/11/97 4:17p Allender
+ * use _MAX_PATH instead of MAX_FILENAME_LENGTH for anim_play since it is
+ * called from MoviePlayer with full path
+ *
+ * 16 9/11/97 10:49a Lawrance
+ * improve anim_show_next_frame()
+ *
+ * 15 9/10/97 4:59p Lawrance
+ * improve comments to anim_play() function
+ *
+ * 14 9/03/97 4:19p John
+ * changed bmpman to only accept ani and pcx's. made passing .pcx or .ani
+ * to bm_load functions not needed. Made bmpman keep track of palettes
+ * for bitmaps not mapped into game palettes.
+ *
+ * 13 8/30/97 2:11p Lawrance
+ * allow animations to loop
+ *
+ * 12 8/25/97 11:13p Lawrance
+ * support framerate independent playback with the option of now advancing
+ * more than one frame at a time
+ *
+ * 11 8/22/97 8:20a Lawrance
+ * display scrolling text properly, with indicator that text exitsts to be
+ * scrolled
+ *
+ * 10 8/21/97 5:11p Lawrance
+ * frame numbering for ANI's now is from 0 -> total_frames-1.
+ *
+ * 9 8/19/97 9:30a Lawrance
+ * print out reason if file doesn't open right
+ *
+ * 8 7/28/97 10:42p Lawrance
+ * re-did interface to unpack_frame() to make more general
+ *
+ * 7 7/21/97 11:41a Lawrance
+ * make playback time of .ani files keyed of frametime
+ *
+ * 6 7/20/97 6:57p Lawrance
+ * supporting new RLE format
+ *
+ * 5 7/11/97 11:54a John
+ * added rotated 3d bitmaps.
+ *
+ * 4 6/27/97 4:36p Lawrance
+ * update pal translation table when gr_screen.signature changes
+ *
+ * 3 6/26/97 3:00p Lawrance
+ * fix bug with playing 3d anims
+ *
+ * 2 6/26/97 12:12a Lawrance
+ * supporting anti-aliased bitmap animations
+ *
+ * 1 6/23/97 5:09p Lawrance
+ *
+ * 24 6/03/97 5:53p Lawrance
+ * don't unload bitmap after bm_create
+ *
+ * $NoKeywords: $
+ */
+
+#include "AnimPlay.h"
+#include "LinkList.h"
+#include "Timer.h"
+#include "Bmpman.h"
+#include "2D.h"
+#include "3d.h"
+#include "grinternal.h"
+#include "PCXUtils.h"
+#include "PackUnPack.h"
+#include "cfile.h"
+
+static color Color_xparent;
+
+anim *first_anim = NULL;
+anim_instance anim_free_list;
+anim_instance anim_render_list;
+
+#define MAX_ANIM_INSTANCES 25
+anim_instance anim_render_instance[MAX_ANIM_INSTANCES];
+
+int Anim_paused; // global variable to pause the playing back of anims
+int Anim_inited = FALSE;
+
+fix t1,t2;
+
+int Anim_ignore_frametime=0; // flag used to ignore frametime... useful when need to avoid saturated frametimes
+
+// -------------------------------------------------------------------------------------------------
+// anim_init() will queue all the anim_render_instance[] elements onto the anim_free_list
+//
+void anim_init()
+{
+ int i;
+
+ if ( Anim_inited == TRUE )
+ return;
+
+ list_init( &anim_free_list );
+ list_init( &anim_render_list );
+
+ // Link all anim render slots into the free list
+ for (i=1; i < MAX_ANIM_INSTANCES; i++) {
+ list_append(&anim_free_list, &anim_render_instance[i]);
+ }
+
+ Anim_paused = 0;
+ Anim_inited = TRUE;
+}
+
+// -------------------------------------------------------------------------------------------------
+// anim_render_all() will display the frames for the currently playing anims
+//
+void anim_render_all(int screen_id, float frametime)
+{
+ anim_instance* A;
+ anim_instance* temp;
+
+ A = GET_FIRST(&anim_render_list);
+ while( A !=END_OF_LIST(&anim_render_list) ) {
+ temp = GET_NEXT(A);
+ if ( A->screen_id == screen_id ) {
+ if ( Anim_ignore_frametime ) {
+ frametime = 0.0f;
+ Anim_ignore_frametime=0;
+ }
+ if ( anim_show_next_frame(A, frametime) == -1 ) {
+ A->data = NULL;
+ anim_release_render_instance(A);
+ }
+ }
+ A = temp;
+ }
+}
+
+// -------------------------------------------------------------------------------------------------
+// anim_render_one() will display the frames for the passed animation, it will ignore animations which
+// do not have the same id as the passed screen_id
+//
+void anim_render_one(int screen_id, anim_instance *ani, float frametime)
+{
+ // make sure this guy's screen id matches the passed one
+ if(screen_id != ani->screen_id){
+ return;
+ }
+
+ // otherwise render it
+ if ( Anim_ignore_frametime ) {
+ frametime = 0.0f;
+ Anim_ignore_frametime=0;
+ }
+ if ( anim_show_next_frame(ani, frametime) == -1 ) {
+ ani->data = NULL;
+ anim_release_render_instance(ani);
+ }
+}
+
+MONITOR(NumANIPlayed);
+
+// Setup an anim_play_struct for passing into anim_play(). Will fill in default values, which you
+// can then change before calling anim_play().
+//
+void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y)
+{
+ aps->anim_info = a_info;
+ aps->x = x;
+ aps->y = y;
+ aps->start_at = 0;
+ aps->stop_at = a_info->total_frames - 1;
+ aps->screen_id = 0;
+ aps->world_pos = NULL;
+ aps->radius = 0.0f;
+ aps->framerate_independent = 0;
+ aps->color = NULL;
+ aps->skip_frames = 1;
+ aps->looped = 0;
+ aps->ping_pong = 0;
+}
+
+// -------------------------------------------------------------------------------------------------
+// anim_play() will add an anim instance to the anim_render_list. This will cause the
+// anim to be played at the x,y position specified in the parameter list.
+//
+// input:
+//
+// anim_info => the compressed animation that we should make an instance from
+// x => x position of animation to play at (top left corner)
+// y => y position of animation to play at ( top left corner)
+// start_at => frame number to start at (note: numbering is from 0->num_frames-1)
+// stop_at => frame number to stop at (note: numbering is from 0->num_frames-1)
+// screen_id => OPTIONAL (default value 0): screen signature so animation only plays when
+// anim_render_all() called with that same signature
+// world_pos => OPTIONAL (default value NULL): only give a world pos when you want to
+// play the animation at a 3D location. You must specify radius when
+// this is non-null.
+// radius => OPTIONAL (default value 0): only needed when the animation is playing
+// as a 3D animation (this is only when world_pos in not NULL).
+// fi => OPTIONAL (default value 0): framerate indepentdent flag, when set TRUE
+// the animation will skip frames if necessary to maintain the fps value
+// associated with the animation
+// color => OPTIONAL (default value NULL) address of an alpha color struct. Only
+// required when the animation should be drawn with an alpha color.
+// skip_frames => OPTIONAL (default value 1) should anim skip frames when doing framerate
+// independent playback
+// looped => OPTIONAL (default value 0) should anim play looped (ie forever)
+//
+// returns:
+//
+// pointer to instance => success
+// NULL => if anim anim could not be played
+//
+anim_instance *anim_play(anim_play_struct *aps)
+{
+ Assert( aps->anim_info != NULL );
+ Assert( aps->start_at >= 0 );
+ Assert( aps->stop_at < aps->anim_info->total_frames );
+ // Assert( aps->stop_at >= aps->start_at );
+ Assert( !(aps->looped && aps->ping_pong) ); // shouldn't have these both set at once
+
+ MONITOR_INC(NumANIPlayed, 1);
+
+ // if (aps->ping_pong && !(aps->anim_info->flags & ANF_ALL_KEYFRAMES));
+
+ anim_instance *instance;
+
+ // Find next free anim instance slot on queue
+ instance = GET_FIRST(&anim_free_list);
+ Assert( instance != &anim_free_list ); // shouldn't have the dummy element
+
+ // remove instance from the free list
+ list_remove( &anim_free_list, instance );
+
+ // insert instance onto the end of anim_render_list
+ list_append( &anim_render_list, instance );
+
+ aps->anim_info->instance_count++;
+ instance->frame_num = -1;
+ instance->last_frame_num = -99;
+ instance->parent = aps->anim_info;
+ instance->data = aps->anim_info->data;
+ if ( anim_instance_is_streamed(instance) ) {
+ instance->file_offset = instance->parent->file_offset;
+ }
+ instance->frame = (ubyte *) malloc(instance->parent->width * instance->parent->height * 2);
+ Assert( instance->frame != NULL );
+ instance->time_elapsed = 0.0f;
+ instance->stop_at = aps->stop_at;
+ instance->x = aps->x;
+ instance->y = aps->y;
+ instance->world_pos = aps->world_pos;
+ instance->radius = aps->radius;
+ instance->framerate_independent = aps->framerate_independent;
+ instance->last_bitmap = -1;
+ instance->stop_now = FALSE;
+ instance->screen_id = aps->screen_id;
+ instance->aa_color = aps->color;
+ instance->skip_frames = aps->skip_frames;
+ instance->looped = aps->looped;
+ instance->ping_pong = aps->ping_pong;
+ instance->direction = ANIM_DIRECT_FORWARD;
+ instance->paused = 0;
+ instance->loop_count = 0;
+ if ( aps->color == NULL ){
+ instance->xlate_pal = 1;
+ } else {
+ instance->xlate_pal = 0;
+ }
+
+ // determining the start_at frame is more complicated, since it must be a key-frame.
+ // Futhermore, need to subtract 1 from key-frame number, since frame number is always
+ // incremented the first time anim_show_next_frame() is called
+
+ instance->start_at = aps->start_at;
+
+ if ( aps->start_at > 0 ) {
+ key_frame *keyp;
+ int idx;
+ int key = 0;
+ int offset = 0;
+ int frame_num = aps->start_at;
+
+ keyp = instance->parent->keys;
+ idx = 0;
+ while (idx < instance->parent->num_keys) {
+ if (key == frame_num)
+ break;
+
+ key = keyp[idx].frame_num - 1;
+ offset = keyp[idx].offset;
+
+ idx++;
+ }
+ /*while (keyp) {
+ if (( (keyp->frame_num-1) <= frame_num) && ( (keyp->frame_num-1) > key)) { // find closest key
+ key = keyp->frame_num-1;
+ offset = keyp->offset;
+ if ( key == frame_num )
+ break;
+ }
+
+ keyp = keyp->next;
+ }*/
+
+ if (key > instance->frame_num) { // best key is closer than current position
+ instance->frame_num = key;
+ if ( anim_instance_is_streamed(instance) ) {
+ instance->file_offset = instance->parent->file_offset + offset;
+ } else {
+ instance->data = instance->parent->data + offset;
+ }
+
+ }
+
+ instance->frame_num--; // required
+ }
+
+ return instance;
+}
+
+// -----------------------------------------------------------------------------
+// anim_show_next_frame()
+//
+// This function is called to blit the next frame of an anim instance to the
+// screen. This is normally called by the anim_render_all() function.
+//
+// input: instance => pointer to animation instance
+// frametime => time elapsed since last call, in seconds
+//
+int anim_show_next_frame(anim_instance *instance, float frametime)
+{
+ int bitmap_id, bitmap_flags=0, new_frame_num, frame_diff=0, i, n_frames=0,frame_save;
+ float percent_through, decompress_time, render_time, time;
+ vertex image_vertex;
+ int aabitmap = 0;
+ int bpp = 16;
+
+ Assert( instance != NULL );
+
+ instance->time_elapsed += frametime;
+
+ // Advance to the next frame, if we determine enough time has elapsed.
+ if(instance->direction == ANIM_DIRECT_FORWARD)
+ n_frames = instance->stop_at - instance->start_at + 1;
+ else if(instance->direction == ANIM_DIRECT_REVERSE)
+ n_frames = instance->start_at - instance->stop_at + 1;
+ time = n_frames / i2fl(instance->parent->fps);
+
+ percent_through = instance->time_elapsed / time;
+
+ if(instance->direction == ANIM_DIRECT_FORWARD)
+ new_frame_num = instance->start_at - 1 + fl2i(percent_through * n_frames + 0.5f);
+ else
+ new_frame_num = instance->start_at - 1 - fl2i(percent_through * n_frames + 0.5f);
+
+ frame_save = instance->frame_num;
+
+ // If framerate independent, use the new_frame_num... unless instance->skip_frames is
+ // FALSE, then only advance a maximum of one frame (this is needed since some big animations
+ // should just play slower rather than taking the hit of decompressing multiple frames and
+ // creating an even greater slowdown
+ if (instance->framerate_independent) {
+ if(instance->direction == ANIM_DIRECT_FORWARD){
+ if ( new_frame_num > instance->last_frame_num) {
+ if ( instance->skip_frames )
+ instance->frame_num = new_frame_num;
+ else
+ instance->frame_num++;
+ }
+ } else if(instance->direction == ANIM_DIRECT_REVERSE){
+ if( new_frame_num < instance->last_frame_num) {
+ if ( instance->skip_frames )
+ instance->frame_num = new_frame_num;
+ else
+ instance->frame_num--;
+ }
+ }
+ }
+ else {
+ if(instance->direction == ANIM_DIRECT_FORWARD){
+ if ( new_frame_num > instance->last_frame_num) {
+ instance->frame_num++;
+ }
+ } else if(instance->direction == ANIM_DIRECT_REVERSE){
+ if ( new_frame_num < instance->last_frame_num) {
+ instance->frame_num--;
+ }
+ }
+ }
+
+ if(instance->direction == ANIM_DIRECT_FORWARD){
+ if ( instance->frame_num < instance->start_at ) {
+ instance->frame_num = instance->start_at;
+ }
+ } else if(instance->direction == ANIM_DIRECT_REVERSE){
+ if ( instance->frame_num > instance->start_at ) {
+ instance->frame_num = instance->start_at;
+ }
+ }
+
+ if ( instance->stop_now == TRUE ) {
+ return -1;
+ }
+
+ // If past the last frame, clamp to the last frame and then set the stop_now flag in the
+ // anim instance. The next iteration, the animation will stop.
+ if(instance->direction == ANIM_DIRECT_FORWARD){
+ if (instance->frame_num >= instance->stop_at ) {
+ if (instance->looped) { // looped animations
+ instance->frame_num = instance->stop_at;
+ instance->time_elapsed = 0.0f;
+ } else if(instance->ping_pong) { // pingponged animations
+ instance->frame_num = instance->stop_at;
+ // instance->time_elapsed = 0.0f;
+ anim_reverse_direction(instance);
+ } else { // one-shot animations
+ instance->frame_num = instance->stop_at;
+ instance->last_frame_num = instance->frame_num;
+ instance->stop_now = TRUE;
+ }
+ }
+ } else if(instance->direction == ANIM_DIRECT_REVERSE){
+ if (instance->frame_num <= instance->stop_at ) {
+ if (instance->looped) { // looped animations
+ instance->frame_num = instance->stop_at;
+ instance->time_elapsed = 0.0f;
+ } else if(instance->ping_pong) { // pingponged animations
+ instance->frame_num = instance->stop_at;
+ // instance->time_elapsed = 0.0f;
+ anim_reverse_direction(instance);
+ } else { // one-shot animations
+ instance->frame_num = instance->stop_at+1;
+ instance->last_frame_num = instance->frame_num;
+ instance->stop_now = TRUE;
+ }
+ }
+ }
+
+ if(instance->direction == ANIM_DIRECT_FORWARD){
+ if( instance->last_frame_num >= instance->start_at ) {
+ frame_diff = instance->frame_num - instance->last_frame_num;
+ } else {
+ frame_diff = 1;
+ }
+ } else if(instance->direction == ANIM_DIRECT_REVERSE){
+ if( instance->last_frame_num <= instance->start_at ) {
+ frame_diff = instance->last_frame_num - instance->frame_num;
+ } else {
+ frame_diff = 1;
+ }
+ }
+ Assert(frame_diff >= 0);
+ // nprintf(("Alan","FRAME DIFF: %d\n",frame_diff));
+ Assert( instance->frame_num >= 0 && instance->frame_num < instance->parent->total_frames );
+
+ // if the anim is paused, ignore all the above changes and still display this frame
+ if(instance->paused || Anim_paused){
+ instance->frame_num = frame_save;
+ instance->time_elapsed -= frametime;
+ frame_diff = 0;
+ }
+
+ if (instance->parent->flags & ANF_XPARENT){
+ // bitmap_flags = BMP_XPARENT;
+ bitmap_flags = 0;
+ }
+ bpp = 16;
+ if(instance->aa_color != NULL){
+ bitmap_flags |= BMP_AABITMAP;
+ aabitmap = 1;
+ bpp = 8;
+ }
+
+ if ( frame_diff > 0 ) {
+ instance->last_frame_num = instance->frame_num;
+
+ t1 = timer_get_fixed_seconds();
+ for ( i = 0; i < frame_diff; i++ ) {
+ anim_check_for_palette_change(instance);
+
+ // if we're playing backwards, every frame must be a keyframe and we set the data ptr here
+ if(instance->direction == ANIM_DIRECT_REVERSE){
+ if ( anim_instance_is_streamed(instance) ) {
+ instance->file_offset = instance->parent->file_offset + instance->parent->keys[instance->frame_num-1].offset;
+ } else {
+ instance->data = instance->parent->data + instance->parent->keys[instance->frame_num-1].offset;
+ }
+ }
+
+ ubyte *temp = NULL;
+ int temp_file_offset = 0;
+
+ // if we're using bitmap polys
+ if(Gr_bitmap_poly){
+ BM_SELECT_TEX_FORMAT();
+ }
+
+ if ( anim_instance_is_streamed(instance) ) {
+ if ( instance->xlate_pal ){
+ temp_file_offset = unpack_frame_from_file(instance, instance->frame, instance->parent->width*instance->parent->height, instance->parent->palette_translation, aabitmap, bpp);
+ } else {
+ temp_file_offset = unpack_frame_from_file(instance, instance->frame, instance->parent->width*instance->parent->height, NULL, aabitmap, bpp);
+ }
+ } else {
+ if ( instance->xlate_pal ){
+ temp = unpack_frame(instance, instance->data, instance->frame, instance->parent->width*instance->parent->height, instance->parent->palette_translation, aabitmap, bpp);
+ } else {
+ temp = unpack_frame(instance, instance->data, instance->frame, instance->parent->width*instance->parent->height, NULL, aabitmap, bpp);
+ }
+ }
+
+ // always go back to screen format
+ BM_SELECT_SCREEN_FORMAT();
+
+ if(instance->direction == ANIM_DIRECT_FORWARD){
+ if ( anim_instance_is_streamed(instance) ) {
+ instance->file_offset = temp_file_offset;
+ } else {
+ instance->data = temp;
+ }
+ }
+ }
+ t2 = timer_get_fixed_seconds();
+ }
+ else {
+ t2=t1=0;
+ }
+
+ // this only happens when the anim is being looped, we need to reset the last_frame_num
+ if ( (instance->time_elapsed == 0) && (instance->looped) ) {
+ instance->last_frame_num = -1;
+ instance->frame_num = -1;
+ instance->data = instance->parent->data;
+ instance->file_offset = instance->parent->file_offset;
+ instance->loop_count++;
+ }
+
+ decompress_time = f2fl(t2-t1);
+
+ t1 = timer_get_fixed_seconds();
+ if ( frame_diff == 0 && instance->last_bitmap != -1 ) {
+ bitmap_id = instance->last_bitmap;
+ }
+ else {
+ if ( instance->last_bitmap != -1 ){
+ bm_release(instance->last_bitmap);
+ }
+ bitmap_id = bm_create(16, instance->parent->width, instance->parent->height, instance->frame, bitmap_flags);
+ }
+
+ if ( bitmap_id == -1 ) {
+ // anim has finsished playing, free the instance frame data
+ anim_release_render_instance(instance);
+ return -1;
+
+ // NOTE: there is no need to free the instance, since it was pre-allocated as
+ // part of the anim_free_list
+ }
+ else {
+ gr_set_bitmap(bitmap_id);
+
+ // determine x,y to display the bitmap at
+ if ( instance->world_pos == NULL ) {
+ if ( instance->aa_color == NULL ) {
+ gr_bitmap(instance->x, instance->y);
+ }
+ else {
+ gr_set_color_fast( (color*)instance->aa_color );
+ gr_aabitmap(instance->x, instance->y);
+ }
+ }
+ else {
+ g3_rotate_vertex(&image_vertex,instance->world_pos);
+ Assert(instance->radius != 0.0f);
+ g3_draw_bitmap(&image_vertex, 0, instance->radius*1.5f, TMAP_FLAG_TEXTURED );
+ }
+
+ //bm_release(bitmap_id);
+ instance->last_bitmap = bitmap_id;
+ }
+
+ t2 = timer_get_fixed_seconds();
+ render_time = f2fl(t2-t1);
+
+// nprintf(("Alan","DECOMPRESS: %.3fms RENDER: %.3fms\n", decompress_time*1000, render_time*1000));
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+// anim_stop_playing()
+//
+// Stop an anim instance that is on the anim_render_list from playing
+//
+int anim_stop_playing(anim_instance* instance)
+{
+ Assert(instance != NULL);
+
+ if ( anim_playing(instance) ) {
+ anim_release_render_instance(instance);
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+// anim_release_render_instance()
+//
+// Free a particular animation instance that is on the anim_render_list. Do
+// not call this function to free an animation instance in general (use
+// free_anim_instance() for that), only when you want to free an instance
+// that is on the anim_render_list
+//
+void anim_release_render_instance(anim_instance* instance)
+{
+ Assert( instance != NULL );
+ Assert(instance->frame);
+ free(instance->frame);
+ instance->frame = NULL;
+ instance->parent->instance_count--;
+
+ if ( instance->last_bitmap != -1 ) {
+ bm_release(instance->last_bitmap);
+ instance->last_bitmap = -1;
+ }
+
+ // remove instance from anim_render_list
+ list_remove( &anim_render_list, instance );
+
+ // insert instance into the anim_free_list
+ list_append( &anim_free_list, instance );
+}
+
+// -----------------------------------------------------------------------------
+// anim_release_all_instances()
+//
+// Free all anim instances that are on the anim_render_list.
+//
+// input: screen_id => optional parameter that lets you only free a subset
+// of the anim instances. A screen_id of 0 is the default
+// value, and this is used for animations that always play
+// when they are placed on the aim_render_list.
+//
+void anim_release_all_instances(int screen_id)
+{
+ anim_instance* A;
+ anim_instance* temp;
+
+ if ( Anim_inited == FALSE )
+ return;
+
+ A = GET_FIRST(&anim_render_list);
+ while( A !=END_OF_LIST(&anim_render_list) ) {
+ temp = GET_NEXT(A);
+ if ( A->screen_id == screen_id || screen_id == 0 ) {
+ anim_release_render_instance(A);
+ }
+ A = temp;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// anim_read_header()
+//
+// Read the header of a .ani file. Below is the format of a .ani header
+//
+// #bytes | description
+// 2 | obsolete, kept for compatibility with old versions
+// 2 | version number
+// 2 | fps
+// 1 | transparent red value
+// 1 | transparent green value
+// 1 | transparent blue value
+// 2 | width
+// 2 | height
+// 2 | number of frames
+// 2 | packer code
+// 763 | palette
+// 2 | number of key frames
+// 2 | key frame number } repeats
+// 4 | key frame offset } repeats
+// 4 | compressed data length
+//
+void anim_read_header(anim *ptr, CFILE *fp)
+{
+ ptr->width = cfread_short(fp);
+ // If first 2 bytes are zero, this means we are using a new format, which includes
+ // a version, and fps values. This is only done since a version number was not included
+ // in the original header.
+
+ // default
+ Color_xparent.red = 0;
+ Color_xparent.green = 255;
+ Color_xparent.blue = 0;
+
+ if ( ptr->width == 0 ) {
+ ptr->version = cfread_short(fp);
+ ptr->fps = cfread_short(fp);
+
+ // version 2 added a custom transparency color
+ if ( ptr->version >= 2 ) {
+ cfread(&Color_xparent.red, 1, 1, fp);
+ cfread(&Color_xparent.green, 1, 1, fp);
+ cfread(&Color_xparent.blue, 1, 1, fp);
+ }
+
+ ptr->width = cfread_short(fp);
+ }
+ else {
+ ptr->version = 0;
+ ptr->fps = 30;
+ }
+
+ ptr->height = cfread_short(fp);
+
+#ifndef NDEBUG
+ // get size of ani compared to power of 2
+ int r, floor_pow;
+ r = ptr->height;
+ floor_pow = 0;
+
+ while(r >= 2) {
+ r /= 2;
+ floor_pow++;
+ }
+
+ int floor_size = (int) pow(2, floor_pow);
+ int diff = ptr->height - floor_size;
+ float waste = 100.0f * float((floor_size - diff))/(2.0f *(float)floor_size);
+
+ if (diff != 0) {
+ if (ptr->height > 16) {
+ mprintf(("ANI %s with size %dx%d (%.1f%% wasted)\n", ptr->name, ptr->height, ptr->height, waste));
+ }
+ }
+#endif
+
+ ptr->total_frames = cfread_short(fp);
+ cfread(&ptr->packer_code, 1, 1, fp);
+ cfread(&ptr->palette, 256, 3, fp);
+ ptr->num_keys = cfread_short(fp);
+
+ // store xparent colors
+ ptr->xparent_r = Color_xparent.red;
+ ptr->xparent_g = Color_xparent.green;
+ ptr->xparent_b = Color_xparent.blue;
+
+ if(ptr->total_frames == ptr->num_keys){
+ ptr->flags |= ANF_ALL_KEYFRAMES;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// anim_load()
+//
+// Load an animation. This stores the compressed data, which instances
+// of the animation can reference. Must be free'ed later with anim_free()
+//
+// input: name => filename of animation
+// file_mapped => boolean, whether to use memory-mapped file or not.
+// Memory-mapped files will page in the animation from disk
+// as it is needed, but performance is not as good
+//
+// returns: pointer to anim that is loaded => sucess
+// NULL => failure
+//
+anim *anim_load(char *real_filename, int file_mapped)
+{
+ anim *ptr;
+ CFILE *fp;
+ int count,idx;
+ char name[_MAX_PATH];
+
+// file_mapped = 0;
+
+ Assert ( real_filename != NULL );
+
+ strcpy( name, real_filename );
+ char *p = strchr( name, '.' );
+ if ( p ) {
+ *p = 0;
+ }
+ strcat( name, ".ani" );
+
+ ptr = first_anim;
+ while (ptr) {
+ if (!stricmp(name, ptr->name))
+ break;
+
+ ptr = ptr->next;
+ }
+
+ if (!ptr) {
+ fp = cfopen(name, "rb");
+ if ( !fp )
+ return NULL;
+
+ ptr = (anim *) malloc(sizeof(anim));
+ Assert(ptr);
+
+ ptr->flags = 0;
+ ptr->next = first_anim;
+ first_anim = ptr;
+ Assert(strlen(name) < _MAX_PATH - 1);
+ strcpy(ptr->name, name);
+ ptr->instance_count = 0;
+ ptr->width = 0;
+ ptr->height = 0;
+ ptr->total_frames = 0;
+ ptr->keys = NULL;
+ ptr->ref_count=0;
+
+ anim_read_header(ptr, fp);
+
+ if(ptr->num_keys > 0){
+ ptr->keys = (key_frame*)malloc(sizeof(key_frame) * ptr->num_keys);
+ Assert(ptr->keys != NULL);
+ }
+
+ // store how long the anim should take on playback (in seconds)
+ ptr->time = i2fl(ptr->total_frames)/ptr->fps;
+
+ for(idx=0;idx<ptr->num_keys;idx++){
+ ptr->keys[idx].frame_num = 0;
+ cfread(&ptr->keys[idx].frame_num, 2, 1, fp);
+ cfread(&ptr->keys[idx].offset, 4, 1, fp);
+ }
+
+ /*prev_keyp = &ptr->keys;
+ count = ptr->num_keys;
+ while (count--) {
+ keyp = (key_frame *) malloc(sizeof(key_frame));
+ keyp->next = *prev_keyp;
+ *prev_keyp = keyp;
+ prev_keyp = &keyp->next;
+
+ keyp->frame_num = 0;
+ cfread(&keyp->frame_num, 2, 1, fp);
+ cfread(&keyp->offset, 4, 1, fp);
+ }*/
+ cfread(&count, 4, 1, fp); // size of compressed data
+
+ ptr->cfile_ptr = NULL;
+
+ if ( file_mapped ) {
+ // Try mapping the file to memory
+ ptr->flags |= ANF_MEM_MAPPED;
+ ptr->cfile_ptr = cfopen(name, "rb", CFILE_MEMORY_MAPPED);
+ }
+
+ // couldn't memory-map file... must be in a packfile, so stream manually
+ if ( file_mapped && !ptr->cfile_ptr ) {
+ ptr->flags &= ~ANF_MEM_MAPPED;
+ ptr->flags |= ANF_STREAMED;
+ ptr->cfile_ptr = cfopen(name, "rb");
+ }
+
+ ptr->cache = NULL;
+
+ // If it opened properly as mem-mapped (or streamed)
+ if (ptr->cfile_ptr != NULL) {
+ // VERY IMPORTANT STEP
+ // Set the data pointer to the compressed data (which is not at the start of the
+ // file). Use ftell() to find out how far we've already parsed into the file
+ //
+ int offset;
+ offset = cftell(fp);
+ ptr->file_offset = offset;
+ if ( ptr->flags & ANF_STREAMED ) {
+ ptr->data = NULL;
+ ptr->cache_file_offset = ptr->file_offset;
+ ptr->cache = (ubyte*)malloc(ANI_STREAM_CACHE_SIZE+2);
+ Assert(ptr->cache);
+ cfseek(ptr->cfile_ptr, offset, CF_SEEK_SET);
+ cfread(ptr->cache, ANI_STREAM_CACHE_SIZE, 1, ptr->cfile_ptr);
+ } else {
+ ptr->data = (ubyte*)cf_returndata(ptr->cfile_ptr) + offset;
+ }
+ } else {
+ // Not a memory mapped file (or streamed)
+ ptr->flags &= ~ANF_MEM_MAPPED;
+ ptr->flags &= ~ANF_STREAMED;
+ ptr->data = (ubyte *) malloc(count);
+ ptr->file_offset = -1;
+ cfread(ptr->data, count, 1, fp);
+ }
+
+ cfclose(fp);
+
+ // store screen signature, so we can tell if palette changes
+ ptr->screen_sig = gr_screen.signature;
+
+ anim_set_palette(ptr);
+ }
+
+ ptr->ref_count++;
+ return ptr;
+}
+
+// ---------------------------------------------------
+// anim_free()
+//
+// Free an animation that was loaded with anim_load(). All instances
+// referencing this animation must be free'ed or get an assert.
+//
+int anim_free(anim *ptr)
+{
+ Assert ( ptr != NULL );
+ anim *list, **prev_anim;
+
+ list = first_anim;
+ prev_anim = &first_anim;
+ while (list && (list != ptr)) {
+ prev_anim = &list->next;
+ list = list->next;
+ }
+
+ if ( !list )
+ return -1;
+
+ // only free when ref_count is 0
+ ptr->ref_count--;
+ if ( ptr->ref_count > 0 )
+ return -1;
+
+ // only free if there are no playing instances
+ if ( ptr->instance_count > 0 )
+ return -1;
+
+ if(ptr->keys != NULL){
+ free(ptr->keys);
+ ptr->keys = NULL;
+ }
+
+ if ( ptr->flags & (ANF_MEM_MAPPED|ANF_STREAMED) ) {
+ cfclose(ptr->cfile_ptr);
+ if ( ptr->cache ) {
+ free(ptr->cache);
+ }
+ }
+ else {
+ Assert(ptr->data);
+ free(ptr->data);
+ }
+
+ *prev_anim = ptr->next;
+ free(ptr);
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------
+// anim_playing()
+//
+// Return if an anim is playing or not.
+//
+int anim_playing(anim_instance *ai)
+{
+ Assert(ai != NULL);
+ if ( ai->frame == NULL )
+ return 0;
+ else
+ return 1;
+}
+
+
+// ---------------------------------------------------------------------
+// anim_level_init()
+//
+// Called at the beginning of a mission to initialize any mission dependent
+// anim data.
+//
+void anim_level_init()
+{
+}
+
+// ---------------------------------------------------------------------
+// anim_level_close()
+//
+// Called after the end of a mission to clean up any mission dependent
+// anim data.
+//
+void anim_level_close()
+{
+ anim_release_all_instances();
+}
+
+// ---------------------------------------------------
+// anim_write_frames_out()
+//
+// Write the frames of a .ani file out to disk as .pcx files.
+// Use naming convention: filename0000.pcx, filename0001.pcx etc.
+//
+// return: 0 => success
+// -1 => failed
+//
+int anim_write_frames_out(char *filename)
+{
+ anim *source_anim;
+ anim_instance *ai;
+ char root_name[256], pcxname[256];
+ char buf[64];
+ int i,j;
+ ubyte **row_data;
+
+ strcpy(root_name, filename);
+ root_name[strlen(filename)-4] = 0;
+
+ source_anim = anim_load(filename);
+ if ( source_anim == NULL )
+ return -1;
+
+ ai = init_anim_instance(source_anim, 16);
+
+ row_data = (ubyte**)malloc((source_anim->height+1) * 4);
+
+ for ( i = 0; i < source_anim->total_frames; i++ ) {
+ anim_get_next_raw_buffer(ai, 0, 0, 16);
+ strcpy(pcxname, root_name);
+ sprintf(buf,"%04d",i);
+ strcat(pcxname, buf);
+
+ for ( j = 0; j < source_anim->height; j++ ) {
+ row_data[j] = &ai->frame[j*source_anim->width];
+ }
+
+
+ pcx_write_bitmap( pcxname,
+ source_anim->width,
+ source_anim->height,
+ row_data,
+ source_anim->palette);
+
+ printf(".");
+
+ }
+ printf("\n");
+ free(row_data);
+ return 0;
+}
+
+// ---------------------------------------------------
+// anim_display_info()
+//
+// Display information and statistics about a .ani file.
+// This is called when -i switch is on when running ac.exe
+//
+void anim_display_info(char *real_filename)
+{
+ CFILE *fp;
+ anim A;
+ float percent;
+ int i, uncompressed, compressed, *key_frame_nums=NULL, tmp;
+ char filename[MAX_FILENAME_LEN];
+
+ strcpy( filename, real_filename );
+ char *p = strchr( filename, '.' );
+ if ( p ) {
+ *p = 0;
+ }
+ strcat( filename, ".ani" );
+
+ fp = cfopen(filename, "rb");
+ if ( !fp ) {
+ printf("Fatal error opening %s", filename);
+ return;
+ }
+
+ anim_read_header(&A, fp);
+ // read the keyframe frame nums and offsets
+ key_frame_nums = (int*)malloc(sizeof(int)*A.num_keys);
+ Assert(key_frame_nums != NULL);
+ for ( i = 0; i < A.num_keys; i++ ) {
+ key_frame_nums[i] = 0;
+ cfread(&key_frame_nums[i], 2, 1, fp);
+ cfread(&tmp, 4, 1, fp);
+//printf("key frame num: %d,%d\n", key_frame_nums[i],tmp);
+ }
+
+ cfread(&compressed, 4, 1, fp);
+
+ uncompressed = A.width * A.height * A.total_frames; // 8 bits per pixel
+ percent = i2fl(compressed) / uncompressed * 100.0f;
+
+ printf("%% of uncompressed size: %.0f%%\n", percent);
+ printf("Width: %d\n", A.width);
+ printf("Height: %d\n", A.height);
+ printf("Total Frames: %d\n", A.total_frames);
+
+#ifndef NDEBUG
+ printf("Key Frames: %d\n", A.num_keys);
+ if ( A.num_keys > 1 && (A.total_frames != A.num_keys) ) {
+ printf("key list: (");
+ for ( i = 0; i < A.num_keys; i++ ) {
+ if ( i < A.num_keys-1 )
+ printf("%d, ", key_frame_nums[i]);
+ else
+ printf("%d)\n", key_frame_nums[i]);
+ }
+ }
+#endif
+
+ printf("FPS: %d\n", A.fps);
+
+#ifndef NDEBUG
+ printf("Transparent RGB: (%d,%d,%d)\n", A.xparent_r, A.xparent_g, A.xparent_b);
+#endif
+
+ printf("ac version: %d\n", A.version);
+
+ if ( key_frame_nums != NULL ) {
+ free(key_frame_nums);
+ }
+
+ cfclose(fp);
+}
+
+void anim_reverse_direction(anim_instance *ai)
+{
+ int temp;
+
+ if(!(ai->parent->flags & ANF_ALL_KEYFRAMES)){
+ // you're not allowed to call anim_reverse_direction(...) unless every frame is a keyframe!!!!
+ // The God of Delta-RLE demands it be thus.
+ Int3();
+ }
+
+ // flip the animation direction
+ if(ai->direction == ANIM_DIRECT_FORWARD){
+ ai->direction = ANIM_DIRECT_REVERSE;
+ } else if(ai->direction == ANIM_DIRECT_REVERSE){
+ ai->direction = ANIM_DIRECT_FORWARD;
+ }
+
+ // flip frame_num and last_frame_num
+ temp = ai->frame_num;
+ ai->frame_num = ai->last_frame_num;
+ ai->last_frame_num = temp;
+
+ // flip the start and stop at frames
+ temp = ai->stop_at;
+ ai->stop_at = ai->start_at;
+ ai->start_at = temp;
+
+ // make sure to sync up the time correctly
+ if(ai->direction == ANIM_DIRECT_FORWARD){
+ ai->time_elapsed = ((float)ai->frame_num - (float)ai->start_at - 1.0f) / (float)ai->parent->fps;
+ } else if(ai->direction == ANIM_DIRECT_REVERSE) {
+ ai->time_elapsed = ((float)ai->start_at - (float)ai->frame_num - 1.0f) / (float)ai->parent->fps;
+ }
+}
+
+void anim_pause(anim_instance *ai)
+{
+ ai->paused = 1;
+}
+
+void anim_unpause(anim_instance *ai)
+{
+ ai->paused = 0;
+}
+
+void anim_ignore_next_frametime()
+{
+ Anim_ignore_frametime=1;
+}
+
+int anim_instance_is_streamed(anim_instance *ai)
+{
+ Assert(ai);
+ return ( ai->parent->flags & ANF_STREAMED );
+}
+
+unsigned char anim_instance_get_byte(anim_instance *ai, int offset)
+{
+ int absolute_offset;
+ anim *parent;
+
+ Assert(ai);
+ Assert(ai->parent->cfile_ptr);
+ Assert(ai->parent->flags & ANF_STREAMED);
+
+ parent = ai->parent;
+ absolute_offset = ai->file_offset + offset;
+
+ // maybe in cache?
+ int cache_offset;
+ cache_offset = absolute_offset - parent->cache_file_offset;
+ if ( (cache_offset >= 0) && (cache_offset < ANI_STREAM_CACHE_SIZE) ) {
+ return parent->cache[cache_offset];
+ } else {
+ // fill cache
+ cfseek(parent->cfile_ptr, absolute_offset, CF_SEEK_SET);
+ cfread(parent->cache, ANI_STREAM_CACHE_SIZE, 1, parent->cfile_ptr);
+ parent->cache_file_offset = absolute_offset;
+ return parent->cache[0];
+ }
+}
diff --git a/code/Anim/AnimPlay.h b/code/Anim/AnimPlay.h
new file mode 100644
index 0000000..4f793be
--- /dev/null
+++ b/code/Anim/AnimPlay.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/Anim/AnimPlay.h $
+ * $Revision: 3 $
+ * $Date: 10/22/98 6:14p $
+ * $Author: Dave $
+ *
+ * Header file for playing back anim files
+ *
+ * $Log: /Freespace2/code/Anim/AnimPlay.h $
+ *
+ * 3 10/22/98 6:14p Dave
+ * Optimized some #includes in Anim folder. Put in the beginnings of
+ * parse/localization support for externalized strings and tstrings.tbl
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 11 5/07/98 3:11a Lawrance
+ * Implement custom streaming code
+ *
+ * 10 4/27/98 3:36p Dave
+ *
+ * 9 3/25/98 8:43p Hoffoss
+ * Changed anim_play() to not be so damn complex when you try and call it.
+ *
+ * 8 12/24/97 8:57p Lawrance
+ * Added anim_ignore_next_frametime()
+ *
+ * 7 11/19/97 8:28p Dave
+ * Hooked in Main Hall screen. Put in Anim support for ping ponging
+ * animations as well as general reversal of anim direction.
+ *
+ * 6 8/30/97 2:11p Lawrance
+ * allow animations to loop
+ *
+ * 5 8/25/97 11:13p Lawrance
+ * support framerate independent playback with the option of now advancing
+ * more than one frame at a time
+ *
+ * 4 7/21/97 11:41a Lawrance
+ * make playback time of .ani files keyed of frametime
+ *
+ * 3 7/20/97 6:57p Lawrance
+ * supporting new RLE format
+ *
+ * 2 6/26/97 12:12a Lawrance
+ * supporting anti-aliased bitmap animations
+ *
+ * 1 6/23/97 5:09p Lawrance
+ *
+ * 10 5/19/97 2:28p Lawrance
+ * changes some variables to flags
+ *
+ * 9 5/15/97 5:58p Lawrance
+ * fix some bugs that were present with animations when playing multiple
+ * missions
+ *
+ * 8 5/15/97 4:42p Lawrance
+ * suporting anims in-game
+ *
+ * 7 5/15/97 11:46a Lawrance
+ * add function to check if an anim is playing
+ *
+ * 6 2/28/97 12:17p Lawrance
+ * supporting mapping file to memory
+ *
+ * 5 2/25/97 11:06a Lawrance
+ * moved some higher level functions to from PackUnpack to AnimPlay
+ *
+ * 4 2/19/97 9:27p Lawrance
+ * added pause capability to anim playback
+ *
+ * 3 2/17/97 4:19p Lawrance
+ * using frame numbers instead of percentages for accessing keyframes
+ *
+ * 2 2/17/97 3:01p Lawrance
+ * code for playing back an anim
+ *
+ * $NoKeywords: $
+ */
+
+#ifndef __ANIMPLAY_H__
+#define __ANIMPLAY_H__
+
+struct anim;
+struct anim_info;
+struct anim_instance;
+struct CFILE;
+
+// structure passed in when playing an anim. Talk about overkill..
+typedef struct {
+ anim *anim_info;
+ int x;
+ int y;
+ int start_at;
+ int stop_at;
+ int screen_id;
+ vector *world_pos;
+ float radius;
+ int framerate_independent;
+ void *color;
+ int skip_frames;
+ int looped;
+ int ping_pong;
+} anim_play_struct;
+
+extern int Anim_paused;
+
+void anim_init();
+void anim_level_init();
+void anim_level_close();
+void anim_render_all(int screen_id, float frametime);
+void anim_render_one(int screen_id, anim_instance *ani, float frametime);
+void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y);
+anim_instance *anim_play(anim_play_struct *aps);
+void anim_ignore_next_frametime();
+int anim_stop_playing(anim_instance* anim_instance);
+int anim_show_next_frame(anim_instance *instance, float frametime);
+void anim_release_all_instances(int screen_id = 0);
+void anim_release_render_instance(anim_instance* instance);
+anim *anim_load(char *name, int file_mapped = 0);
+int anim_free(anim *ptr);
+int anim_playing(anim_instance *ai);
+int anim_write_frames_out(char *filename);
+void anim_display_info(char *filename);
+void anim_read_header(anim *ptr, CFILE *fp);
+void anim_reverse_direction(anim_instance *ai); // called automatically for ping-ponging, and can also be called externally
+void anim_pause(anim_instance *ai);
+void anim_unpause(anim_instance *ai);
+
+int anim_instance_is_streamed(anim_instance *ai);
+unsigned char anim_instance_get_byte(anim_instance *ai, int offset);
+
+#endif /* __ANIMPLAY_H__ */ \ No newline at end of file
diff --git a/code/Anim/PackUnpack.cpp b/code/Anim/PackUnpack.cpp
new file mode 100644
index 0000000..9fdea08
--- /dev/null
+++ b/code/Anim/PackUnpack.cpp
@@ -0,0 +1,1275 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/Anim/PackUnpack.cpp $
+ * $Revision: 12 $
+ * $Date: 7/30/99 10:10p $
+ * $Author: Dave $
+ *
+ * Code for handling packing and unpacking in Hoffoss's RLE format, used for
+ * Anim files. Also handles Anim loading, creating Anim instances (for
+ * utilizing an Anim), and getting getting frames of the Anim.
+ *
+ * $Log: /Freespace2/code/Anim/PackUnpack.cpp $
+ *
+ * 12 7/30/99 10:10p Dave
+ * Fixed loading bar in 32 bit mode.
+ *
+ * 11 7/18/99 1:59p Johnson
+ * Fixed potential anim locking problem.
+ *
+ * 10 7/16/99 1:49p Dave
+ * 8 bit aabitmaps. yay.
+ *
+ * 9 7/13/99 1:15p Dave
+ * 32 bit support. Whee!
+ *
+ * 8 4/09/99 2:21p Dave
+ * Multiplayer beta stuff. CD checking.
+ *
+ * 7 1/14/99 12:48a Dave
+ * Todo list bug fixes. Made a pass at putting briefing icons back into
+ * FRED. Sort of works :(
+ *
+ * 6 12/01/98 5:53p Dave
+ * Simplified the way pixel data is swizzled. Fixed tga bitmaps to work
+ * properly in D3D and Glide.
+ *
+ * 5 12/01/98 8:06a Dave
+ * Temporary checkin to fix some texture transparency problems in d3d.
+ *
+ * 4 11/30/98 1:07p Dave
+ * 16 bit conversion, first run.
+ *
+ * 3 10/22/98 6:14p Dave
+ * Optimized some #includes in Anim folder. Put in the beginnings of
+ * parse/localization support for externalized strings and tstrings.tbl
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 30 5/14/98 3:38p John
+ * Added in more non-darkening colors for Adam. Had to fix some bugs in
+ * BmpMan and Ani stuff to get this to work.
+ *
+ * 29 5/07/98 3:11a Lawrance
+ * Implement custom streaming code
+ *
+ * 28 11/19/97 8:28p Dave
+ * Hooked in Main Hall screen. Put in Anim support for ping ponging
+ * animations as well as general reversal of anim direction.
+ *
+ * 27 9/09/97 3:39p Sandeep
+ * warning level 4 bugs
+ *
+ * 26 8/22/97 8:21a Lawrance
+ * short circuit key frame check if keyframe matches frame we are
+ * searching for
+ *
+ * 25 8/21/97 5:11p Lawrance
+ * frame numbering for ANI's now is from 0 -> total_frames-1.
+ *
+ * 24 8/19/97 10:59a Lawrance
+ * fix problem with accessing key frames
+ *
+ * 23 7/28/97 10:42p Lawrance
+ * re-did interface to unpack_frame() to make more general
+ *
+ * 22 7/28/97 10:52a Lawrance
+ * correctly set bitmap flags in anim_get_frame()
+ *
+ * 21 7/21/97 5:10p Lawrance
+ * fix problem that was causing infinite recursion
+ *
+ * 20 7/20/97 6:57p Lawrance
+ * supporting new RLE format
+ *
+ * 19 6/27/97 4:36p Lawrance
+ * update pal translation table when gr_screen.signature changes
+ *
+ * 18 6/26/97 12:12a Lawrance
+ * supporting anti-aliased bitmap animations
+ *
+ * 17 6/25/97 3:03p Lawrance
+ * fix palette translation problem with anti-alised bitmaps
+ *
+ * 16 5/19/97 2:28p Lawrance
+ * changes some variables to flags
+ *
+ * 15 5/15/97 4:42p Lawrance
+ * supporting animations in-game
+ *
+ * 14 2/25/97 11:06a Lawrance
+ * moved some higher level functions to from PackUnpack to AnimPlay
+ *
+ * 13 2/19/97 9:51p Lawrance
+ * made keyframe decompression more effecient, moved
+ * default anim FPS to header file
+ *
+ * 12 2/19/97 4:00p Lawrance
+ * don't assert when cannot find anim filename, return a NULL instead
+ *
+ * 11 2/17/97 4:17p Hoffoss
+ * modified packing internal format and added random access function to an
+ * Anim frame.
+ *
+ * 10 2/17/97 2:59p Lawrance
+ * integrating into game
+ *
+ * 9 2/14/97 11:27p Lawrance
+ * optimized unpacking some more (Jason)
+ *
+ * 8 2/14/97 11:09p Hoffoss
+ * Made optimizations.
+ *
+ * 7 2/14/97 10:48p Hoffoss
+ * fixed bug.
+ *
+ * 6 2/14/97 10:38p Lawrance
+ * fixing bugs
+ *
+ * 5 2/14/97 5:38p Hoffoss
+ * Changes to get AnimCoverter project to compile and link.
+ *
+ * 4 2/14/97 3:29p Hoffoss
+ * Added header for MSDEV to fill in.
+ *
+ * $NoKeywords: $
+ */
+
+#include "GrInternal.h"
+#include "BmpMan.h"
+#include "Palman.h"
+#include "2d.h"
+#include "AnimPlay.h"
+#include "PackUnPack.h"
+
+int packer_code = PACKER_CODE;
+int transparent_code = 254;
+
+void anim_check_for_palette_change(anim_instance *instance) {
+ if ( instance->parent->screen_sig != gr_screen.signature ) {
+ instance->parent->screen_sig = gr_screen.signature;
+ anim_set_palette(instance->parent);
+ }
+}
+
+anim_instance *init_anim_instance(anim *ptr, int bpp)
+{
+ anim_instance *inst;
+
+ if (!ptr) {
+ Int3();
+ return NULL;
+ }
+
+ if ( ptr->flags & ANF_STREAMED ) {
+ if ( ptr->file_offset < 0 ) {
+ Int3();
+ return NULL;
+ }
+ } else {
+ if ( !ptr->data ) {
+ Int3();
+ return NULL;
+ }
+ }
+
+ ptr->instance_count++;
+ inst = (anim_instance *) malloc(sizeof(anim_instance));
+ Assert(inst);
+ inst->frame_num = -1;
+ inst->last_frame_num = -1;
+ inst->parent = ptr;
+ inst->data = ptr->data;
+ inst->file_offset = ptr->file_offset;
+ inst->stop_now = FALSE;
+ inst->aa_color = NULL;
+
+ if(bpp == 16){
+ inst->frame = (ubyte *) malloc(inst->parent->width * inst->parent->height * 2);
+ } else {
+ inst->frame = (ubyte *) malloc(inst->parent->width * inst->parent->height);
+ }
+ return inst;
+}
+
+void free_anim_instance(anim_instance *inst)
+{
+ Assert(inst->frame);
+ free(inst->frame);
+ inst->frame = NULL;
+ inst->parent->instance_count--;
+ inst->parent = NULL;
+ inst->data = NULL;
+ inst->file_offset = -1;
+
+ free(inst);
+}
+
+int anim_get_next_frame(anim_instance *inst)
+{
+ int bm, bitmap_flags;
+ int aabitmap = 0;
+ int bpp = 16;
+
+ if ( anim_instance_is_streamed(inst) ) {
+ if ( inst->file_offset <= 0 ) {
+ return -1;
+ }
+ } else {
+ if (!inst->data)
+ return -1;
+ }
+
+ inst->frame_num++;
+ if (inst->frame_num >= inst->parent->total_frames) {
+ inst->data = NULL;
+ inst->file_offset = inst->parent->file_offset;
+ return -1;
+ }
+
+ if (inst->parent->flags & ANF_XPARENT) {
+ // bitmap_flags = BMP_XPARENT;
+ bitmap_flags = 0;
+ } else {
+ bitmap_flags = 0;
+ }
+
+ bpp = 16;
+ if(inst->aa_color != NULL){
+ bitmap_flags |= BMP_AABITMAP;
+ aabitmap = 1;
+ bpp = 8;
+ }
+
+ anim_check_for_palette_change(inst);
+
+ // if we're using bitmap polys
+ if(Gr_bitmap_poly){
+ BM_SELECT_TEX_FORMAT();
+ }
+
+ if ( anim_instance_is_streamed(inst) ) {
+ inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
+ } else {
+ inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
+ }
+
+ bm = bm_create(bpp, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
+ bm_unload(bm);
+ return bm;
+}
+
+ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp)
+{
+ if ( anim_instance_is_streamed(inst) ) {
+ if ( inst->file_offset < 0 ) {
+ return NULL;
+ }
+ } else {
+ if (!inst->data){
+ return NULL;
+ }
+ }
+
+ inst->frame_num++;
+ if (inst->frame_num >= inst->parent->total_frames) {
+ inst->data = NULL;
+ inst->file_offset = inst->parent->file_offset;
+ return NULL;
+ }
+
+ anim_check_for_palette_change(inst);
+
+ if ( anim_instance_is_streamed(inst) ) {
+ if ( xlate_pal ){
+ inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
+ } else {
+ inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL, aabitmap, bpp);
+ }
+ } else {
+ if ( xlate_pal ){
+ inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
+ } else {
+ inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL, aabitmap, bpp);
+ }
+ }
+
+ return inst->frame;
+}
+
+// --------------------------------------------------------------------
+// anim_get_frame()
+//
+// Get a bitmap id from the anim_instance for the specified frame_num
+//
+// input: *inst => pointer to anim instance
+// frame_num => frame number to get (first frame is 0)
+// xlate_pal => DEFAULT PARM (value 1): whether to translate the palette
+// to the current game palette
+//
+int anim_get_frame(anim_instance *inst, int frame_num, int xlate_pal)
+{
+ /*
+ int bm, bitmap_flags, key = 0, offset = 0;
+ int idx;
+
+ if ((frame_num < 0) || (frame_num >= inst->parent->total_frames)) // illegal frame number
+ return -1;
+
+ int need_reset = 0;
+ if ( anim_instance_is_streamed(inst) ) {
+ if ( inst->file_offset < 0 ) {
+ need_reset = 1;
+ }
+ } else {
+ if ( !inst->data ) {
+ need_reset = 1;
+ }
+ }
+
+ if (need_reset || (inst->frame_num >= inst->parent->total_frames)) { // reset to valid info
+ inst->data = inst->parent->data;
+ inst->file_offset = inst->parent->file_offset;
+ inst->frame_num = 0;
+ }
+
+ bitmap_flags = 0;
+ if (inst->parent->flags & ANF_XPARENT) {
+ // bitmap_flags = BMP_XPARENT;
+ bitmap_flags = 0;
+ }
+
+ if ( inst->frame_num == frame_num ) {
+ bm = bm_create(16, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
+ bm_unload(bm);
+ return bm;
+ }
+
+ if (inst->parent->flags & ANF_XPARENT){
+ // bitmap_flags = BMP_XPARENT;
+ bitmap_flags = 0;
+ } else {
+ bitmap_flags = 0;
+ }
+
+ idx = 0;
+ key = 0;
+ while(idx < inst->parent->num_keys){
+ if (( (inst->parent->keys[idx].frame_num-1) <= frame_num) && ( (inst->parent->keys[idx].frame_num-1) > key)) { // find closest key
+ key = inst->parent->keys[idx].frame_num - 1;
+ offset = inst->parent->keys[idx].offset;
+
+ if ( key == frame_num )
+ break;
+ }
+ idx++;
+ }
+
+ if ( key == frame_num ) {
+ inst->frame_num = key;
+
+ if ( anim_instance_is_streamed(inst) ) {
+ inst->file_offset = inst->parent->file_offset + offset;
+ } else {
+ inst->data = inst->parent->data + offset;
+ }
+
+ anim_check_for_palette_change(inst);
+
+ if ( anim_instance_is_streamed(inst) ) {
+ if ( xlate_pal ){
+ inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
+ } else {
+ inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
+ }
+ } else {
+ if ( xlate_pal ){
+ inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
+ } else {
+ inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
+ }
+ }
+
+ goto create_bitmap;
+ }
+
+ if (key > inst->frame_num) // best key is closer than current position
+ {
+ inst->frame_num = key;
+
+ if ( anim_instance_is_streamed(inst) ) {
+ inst->file_offset = inst->parent->file_offset + offset;
+ } else {
+ inst->data = inst->parent->data + offset;
+ }
+
+ anim_check_for_palette_change(inst);
+
+ if ( anim_instance_is_streamed(inst) ) {
+ if ( xlate_pal )
+ inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
+ else
+ inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
+ } else {
+ if ( xlate_pal )
+ inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
+ else
+ inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
+ }
+ }
+
+ while (inst->frame_num != frame_num) {
+ anim_check_for_palette_change(inst);
+
+ if ( anim_instance_is_streamed(inst) ) {
+ if ( xlate_pal )
+ inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
+ else
+ inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
+ } else {
+ if ( xlate_pal )
+ inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
+ else
+ inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
+ }
+ inst->frame_num++;
+ }
+
+ create_bitmap:
+
+ bm = bm_create(16, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
+ bm_unload(bm);
+ return bm;
+ */
+ Int3();
+ return -1;
+}
+
+// frame = frame pixel data to pack
+// save = memory to store packed data to
+// size = number of bytes to pack
+// max = maximum number of packed bytes (size of buffer)
+// returns: actual number of bytes data packed to or -1 if error
+int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type)
+{
+ int last = -32768, count = 0;
+ long packed_size = 1;
+
+ switch ( compress_type ) {
+ case PACKING_METHOD_RLE_KEY:
+ *save++ = PACKING_METHOD_RLE_KEY;
+ while (size--) {
+ if (*frame != last || count > 255) {
+ if (packed_size + 3 >= max)
+ return -1;
+
+ if (count < 3) {
+ if (last == packer_code) {
+ *save++ = (ubyte)packer_code;
+ *save++ = (ubyte)(count - 1);
+ packed_size += 2;
+
+ } else
+ while (count--) {
+ *save++ = (ubyte)last;
+ packed_size++;
+ }
+
+ } else {
+ *save++ = (ubyte)packer_code;
+ *save++ = (ubyte)(count - 1);
+ *save++ = (ubyte)last;
+ packed_size += 3;
+ }
+
+ count = 0;
+ last = *frame;
+ }
+
+ count++;
+ frame++;
+ }
+
+ if (packed_size + 3 >= max)
+ return -1;
+
+ if (count < 3) {
+ if (last == packer_code) {
+ *save++ = (ubyte)packer_code;
+ *save++ = (ubyte)(count - 1);
+ packed_size += 2;
+
+ } else
+ while (count--) {
+ *save++ = (ubyte)last;
+ packed_size++;
+ }
+
+ } else {
+ *save++ = (ubyte)packer_code;
+ *save++ = (ubyte)(count - 1);
+ *save++ = (ubyte)last;
+ packed_size += 3;
+ }
+ break;
+
+ case PACKING_METHOD_STD_RLE_KEY: {
+ ubyte *dest_start;
+ int i;
+
+ dest_start = save;
+ count = 1;
+
+ last = *frame++;
+ *save++ = PACKING_METHOD_STD_RLE_KEY;
+ for (i=1; i < size; i++ ) {
+
+ if ( *frame != last ) {
+ if ( count ) {
+
+ if (packed_size + 2 >= max)
+ return -1;
+
+ if ( (count == 1) && !(last & STD_RLE_CODE) ) {
+ *save++ = (ubyte)last;
+ packed_size++;
+ Assert( last != STD_RLE_CODE );
+// printf("Just packed %d 1 times, since pixel change, no count included\n",last);
+ }
+ else {
+ count |= STD_RLE_CODE;
+ *save++ = (ubyte)count;
+ *save++ = (ubyte)last;
+ packed_size += 2;
+// printf("Just packed %d %d times, since pixel change\n",last,count);
+ }
+ }
+
+ last = *frame;
+ count = 0;
+ }
+
+ count++;
+ frame++;
+
+ if ( count == 127 ) {
+ count |= STD_RLE_CODE;
+ *save++ = (ubyte)count;
+ *save++ = (ubyte)last;
+ packed_size += 2;
+ count = 0;
+// printf("Just packed %d %d times, since count overflow\n",last,count);
+
+ }
+ } // end for
+
+ if (count) {
+
+ if (packed_size + 2 >= max)
+ return -1;
+
+ if ( (count == 1) && !(last & STD_RLE_CODE) ) {
+ *save++ = (ubyte)last;
+ packed_size++;
+// printf("Just packed %d 1 times, at end since single pixel, no count\n",last);
+ Assert( last != STD_RLE_CODE );
+ }
+ else {
+ count |= STD_RLE_CODE;
+ *save++ = (ubyte)count;
+ *save++ = (ubyte)last;
+ packed_size += 2;
+// printf("Just packed %d %d times, at end since pixel change\n",last,count);
+ }
+ }
+
+ Assert(packed_size == (save-dest_start) );
+ return packed_size;
+ break;
+ }
+
+ default:
+ Assert(0);
+ return -1;
+ break;
+ } // end switch
+
+ return packed_size;
+}
+
+// frame = frame pixel data to pack
+// frame2 = previous frame's pixel data
+// save = memory to store packed data to
+// size = number of bytes to pack
+// max = maximum number of packed bytes (size of buffer)
+// returns: actual number of bytes data packed to or -1 if error
+int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type)
+{
+ int pixel, last = -32768, count = 0, i;
+ long packed_size = 1;
+
+ switch ( compress_type ) {
+ case PACKING_METHOD_RLE: // Hoffoss RLE regular frame
+ *save++ = PACKING_METHOD_RLE;
+ while (size--) {
+ if (*frame != *frame2++)
+ pixel = *frame;
+ else
+ pixel = transparent_code;
+
+ if (pixel != last || count > 255) {
+ if (packed_size + 3 >= max)
+ return -1;
+
+ if (count < 3) {
+ if (last == packer_code) {
+ *save++ = (ubyte)packer_code;
+ *save++ = (ubyte)(count - 1);
+ packed_size += 2;
+
+ } else
+ while (count--) {
+ *save++ = (ubyte)last;
+ packed_size++;
+ }
+
+ } else {
+ *save++ = (ubyte)packer_code;
+ *save++ = (ubyte)(count - 1);
+ *save++ = (ubyte)last;
+ packed_size += 3;
+ }
+
+ count = 0;
+ last = pixel;
+ }
+
+ frame++;
+ count++;
+ }
+
+ if (packed_size + 3 >= max)
+ return -1;
+
+ if (count < 3) {
+ if (last == packer_code) {
+ *save++ = (ubyte)packer_code;
+ *save++ = (ubyte)(count - 1);
+ packed_size += 2;
+
+ } else
+ while (count--) {
+ *save++ = (ubyte)last;
+ packed_size++;
+ }
+
+ } else {
+ *save++ = (ubyte)(packer_code);
+ *save++ = (ubyte)(count - 1);
+ *save++ = (ubyte)(last);
+ packed_size += 3;
+ }
+ break;
+
+ case PACKING_METHOD_STD_RLE: { // high bit count regular RLE frame
+
+ ubyte *dest_start;
+
+ dest_start = save;
+ count = 1;
+
+ if (*frame++ != *frame2++)
+ last = *frame;
+ else
+ last = transparent_code;
+
+ *save++ = PACKING_METHOD_STD_RLE;
+ for (i=1; i < size; i++ ) {
+
+ if (*frame != *frame2++)
+ pixel = *frame;
+ else
+ pixel = transparent_code;
+
+ if ( pixel != last ) {
+ if ( count ) {
+
+ if (packed_size + 2 >= max)
+ return -1;
+
+ if ( (count == 1) && !(last & STD_RLE_CODE) ) {
+ *save++ = (ubyte)last;
+ packed_size++;
+ Assert( last != STD_RLE_CODE );
+ }
+ else {
+ count |= STD_RLE_CODE;
+ *save++ = (ubyte)count;
+ *save++ = (ubyte)last;
+ packed_size += 2;
+ }
+ }
+
+ last = pixel;
+ count = 0;
+ }
+
+ count++;
+ frame++;
+
+ if ( count == 127 ) {
+ count |= STD_RLE_CODE;
+ *save++ = (ubyte)count;
+ *save++ = (ubyte)last;
+ packed_size += 2;
+ count = 0;
+ }
+ } // end for
+
+ if (count) {
+
+ if (packed_size + 2 >= max)
+ return -1;
+
+ if ( (count == 1) && !(last & STD_RLE_CODE) ) {
+ *save++ = (ubyte)last;
+ packed_size++;
+ Assert( last != STD_RLE_CODE );
+ }
+ else {
+ count |= STD_RLE_CODE;
+ *save++ = (ubyte)count;
+ *save++ = (ubyte)last;
+ packed_size += 2;
+ }
+ }
+
+ Assert(packed_size == (save-dest_start) );
+ return packed_size;
+ break;
+ }
+
+ default:
+ Assert(0);
+ return -1;
+ break;
+ } // end switch
+
+ return packed_size;
+}
+
+// unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
+int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bpp)
+{
+ int bit_24;
+ ushort bit_16 = 0;
+ ubyte bit_8 = 0;
+ ubyte al = 0;
+ ubyte r, g, b;
+ anim *a = ai->parent;
+ Assert(a);
+
+ // if this is an aabitmap, don't run through the palette
+ if(aabitmap){
+ switch(bpp){
+ case 16 :
+ bit_16 = (ushort)pix;
+ break;
+ case 8:
+ bit_8 = pix;
+ break;
+ default:
+ Int3();
+ }
+ } else {
+ // if the pixel value is 255, or is the xparent color, make it so
+ if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
+ r = b = 0;
+ g = 255;
+ bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
+ } else {
+ // stuff the 24 bit value
+ memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
+
+ // convert to 16 bit
+ bm_24_to_16(bit_24, &bit_16);
+ }
+ }
+
+ // stuff the pixel
+ switch(bpp){
+ case 16 :
+ memcpy(data, &bit_16, sizeof(ushort));
+ return sizeof(ushort);
+
+ case 8 :
+ *data = bit_8;
+ return sizeof(ubyte);
+ }
+
+ Int3();
+ return 0;
+}
+
+// unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
+int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count, int aabitmap, int bpp)
+{
+ int bit_24;
+ int idx;
+ ubyte al = 0;
+ ushort bit_16 = 0;
+ ubyte bit_8 = 0;
+ anim *a = ai->parent;
+ ubyte r, g, b;
+ Assert(a);
+
+ // if this is an aabitmap, don't run through the palette
+ if(aabitmap){
+ switch(bpp){
+ case 16 :
+ bit_16 = (ushort)pix;
+ break;
+ case 8 :
+ bit_8 = pix;
+ break;
+ default :
+ Int3();
+ }
+ } else {
+ // if the pixel value is 255, or is the xparent color, make it so
+ if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
+ r = b = 0;
+ g = 255;
+ bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
+ } else {
+ // stuff the 24 bit value
+ memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
+
+ // convert to 16 bit
+ bm_24_to_16(bit_24, &bit_16);
+ }
+ }
+
+ // stuff the pixel
+ for(idx=0; idx<count; idx++){
+ switch(bpp){
+ case 16 :
+ memcpy(data + (idx*2), &bit_16, sizeof(ushort));
+ break;
+ case 8 :
+ *(data + idx) = bit_8;
+ break;
+ }
+ }
+
+ if(bpp == 16){
+ return sizeof(ushort) * count;
+ }
+ return sizeof(ubyte) * count;
+}
+
+// ptr = packed data to unpack
+// frame = where to store unpacked data to
+// size = total number of unpacked pixels requested
+// pal_translate = color translation lookup table (NULL if no palette translation desired)
+ubyte *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
+{
+ int xlate_pal, value, count = 0;
+ int stuffed;
+ int pixel_size = (bpp == 16) ? 2 : 1;
+
+ if ( pal_translate == NULL ) {
+ xlate_pal = 0;
+ }
+ else {
+ xlate_pal = 1;
+ }
+
+ if (*ptr == PACKING_METHOD_RLE_KEY) { // key frame, Hoffoss's RLE format
+ ptr++;
+ while (size > 0) {
+ value = *ptr++;
+ if (value != packer_code) {
+ if ( xlate_pal ){
+ stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
+ }
+ frame += stuffed;
+ size--;
+ } else {
+ count = *ptr++;
+ if (count < 2){
+ value = packer_code;
+ } else {
+ value = *ptr++;
+ }
+
+ if (++count > size){
+ count = size;
+ }
+
+ if ( xlate_pal ){
+ stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
+ }
+
+ frame += stuffed;
+ size -= count;
+ }
+ }
+ }
+ else if ( *ptr == PACKING_METHOD_STD_RLE_KEY) { // key frame, with high bit as count
+ ptr++;
+ while (size > 0) {
+ value = *ptr++;
+ if ( !(value & STD_RLE_CODE) ) {
+ if ( xlate_pal ){
+ stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
+ }
+
+ frame += stuffed;
+ size--;
+ } else {
+ count = value & (~STD_RLE_CODE);
+ value = *ptr++;
+
+ size -= count;
+ Assert(size >= 0);
+
+ if ( xlate_pal ){
+ stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
+ }
+
+ frame += stuffed;
+ }
+ }
+ }
+ else if (*ptr == PACKING_METHOD_RLE) { // normal frame, Hoffoss's RLE format
+
+// test code, to show unused pixels
+// memset(frame, 255, size);
+
+ ptr++;
+ while (size > 0) {
+ value = *ptr++;
+ if (value != packer_code) {
+ if (value != transparent_code) {
+ if ( xlate_pal ){
+ stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
+ }
+ } else {
+ // temporary pixel
+ stuffed = pixel_size;
+ }
+
+ frame += stuffed;
+ size--;
+ } else {
+ count = *ptr++;
+ if (count < 2){
+ value = packer_code;
+ } else {
+ value = *ptr++;
+ }
+
+ if (++count > size){
+ count = size;
+ }
+
+ size -= count;
+ Assert(size >= 0);
+
+ if (value != transparent_code ) {
+ if ( xlate_pal ) {
+ stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
+ }
+ } else {
+ stuffed = count * pixel_size;
+ }
+
+ frame += stuffed;
+ }
+ }
+
+ }
+ else if ( *ptr == PACKING_METHOD_STD_RLE) { // normal frame, with high bit as count
+ ptr++;
+ while (size > 0) {
+ value = *ptr++;
+ if ( !(value & STD_RLE_CODE) ) {
+ if (value != transparent_code) {
+ if ( xlate_pal ){
+ stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
+ }
+ } else {
+ stuffed = pixel_size;
+ }
+
+ frame += stuffed;
+ size--;
+ } else {
+ count = value & (~STD_RLE_CODE);
+ value = *ptr++;
+
+ size -= count;
+ Assert(size >= 0);
+
+ if (value != transparent_code) {
+ if ( xlate_pal ){
+ stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
+ }
+ } else {
+ stuffed = pixel_size * count;
+ }
+
+ frame += stuffed;
+ }
+ }
+ }
+ else {
+ Assert(0); // unknown packing method
+ }
+
+ return ptr;
+}
+
+// ptr = packed data to unpack
+// frame = where to store unpacked data to
+// size = total number of unpacked pixels requested
+// pal_translate = color translation lookup table (NULL if no palette translation desired)
+int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
+{
+ int xlate_pal, value, count = 0;
+ int offset = 0;
+ int stuffed;
+ int pixel_size = (bpp == 16) ? 2 : 1;
+
+ if ( pal_translate == NULL ) {
+ xlate_pal = 0;
+ }
+ else {
+ xlate_pal = 1;
+ }
+
+ if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE_KEY) { // key frame, Hoffoss's RLE format
+ offset++;
+ while (size > 0) {
+ value = anim_instance_get_byte(ai,offset);
+ offset++;
+ if (value != packer_code) {
+ if ( xlate_pal ){
+ stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
+ }
+
+ frame += stuffed;
+ size--;
+ } else {
+ count = anim_instance_get_byte(ai,offset);
+ offset++;
+ if (count < 2) {
+ value = packer_code;
+ } else {
+ value = anim_instance_get_byte(ai,offset);
+ offset++;
+ }
+
+ if (++count > size){
+ count = size;
+ }
+
+ if ( xlate_pal ){
+ stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
+ }
+
+ frame += stuffed;
+ size -= count;
+ }
+ }
+ }
+ else if ( anim_instance_get_byte(ai,offset) == PACKING_METHOD_STD_RLE_KEY) { // key frame, with high bit as count
+ offset++;
+ while (size > 0) {
+ value = anim_instance_get_byte(ai,offset);
+ offset++;
+ if ( !(value & STD_RLE_CODE) ) {
+ if ( xlate_pal ){
+ stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
+ }
+
+ frame += stuffed;
+ size--;
+ } else {
+ count = value & (~STD_RLE_CODE);
+ value = anim_instance_get_byte(ai,offset);
+ offset++;
+
+ size -= count;
+ Assert(size >= 0);
+
+ if ( xlate_pal ){
+ stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
+ }
+
+ frame += stuffed;
+ }
+ }
+ }
+ else if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE) { // normal frame, Hoffoss's RLE format
+
+// test code, to show unused pixels
+// memset(frame, 255, size);
+
+ offset++;
+ while (size > 0) {
+ value = anim_instance_get_byte(ai,offset);
+ offset++;
+ if (value != packer_code) {
+ if (value != transparent_code) {
+ if ( xlate_pal ){
+ stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
+ }
+ } else {
+ stuffed = pixel_size;
+ }
+
+ frame += stuffed;
+ size--;
+ } else {
+ count = anim_instance_get_byte(ai,offset);
+ offset++;
+
+ if (count < 2) {
+ value = packer_code;
+ } else {
+ value = anim_instance_get_byte(ai,offset);
+ offset++;
+ }
+ if (++count > size){
+ count = size;
+ }
+
+ size -= count;
+ Assert(size >= 0);
+
+ if (value != transparent_code ) {
+ if ( xlate_pal ) {
+ stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
+ }
+ } else {
+ stuffed = pixel_size * count;
+ }
+
+ frame += stuffed;
+ }
+ }
+
+ }
+ else if ( anim_instance_get_byte(ai,offset) ) { // normal frame, with high bit as count
+ offset++;
+ while (size > 0) {
+ value = anim_instance_get_byte(ai,offset);
+ offset++;
+ if ( !(value & STD_RLE_CODE) ) {
+ if (value != transparent_code) {
+ if ( xlate_pal ){
+ stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
+ }
+ } else {
+ stuffed = pixel_size;
+ }
+
+ frame += stuffed;
+ size--;
+ } else {
+ count = value & (~STD_RLE_CODE);
+ value = anim_instance_get_byte(ai,offset);
+ offset++;
+
+ size -= count;
+ Assert(size >= 0);
+
+ if (value != transparent_code) {
+ if ( xlate_pal ){
+ stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
+ } else {
+ stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
+ }
+ } else {
+ stuffed = pixel_size * count;
+ }
+
+ frame += stuffed;
+ }
+ }
+ }
+ else {
+ Int3(); // unknown packing method
+ }
+
+ return ai->file_offset + offset;
+}
+
+
+// TODO: actually convert the frame data to correct palette at this point
+void anim_set_palette(anim *ptr)
+{
+ int i, xparent_found = 0;
+
+ // create the palette translation look-up table
+ for ( i = 0; i < 256; i++ ) {
+
+ //if ( (ptr->palette[i*3] == ptr->xparent_r) && (ptr->palette[i*3+1] == ptr->xparent_g) && (ptr->palette[i*3+2] == ptr->xparent_b) ) {
+ // ptr->palette_translation[i] = 255;
+ // xparent_found = 1;
+ //} else {
+ // ptr->palette_translation[i] = (ubyte)palette_find( ptr->palette[i*3], ptr->palette[i*3+1], ptr->palette[i*3+2] );
+ ptr->palette_translation[i] = (ubyte)i;
+ //}
+ }
+
+ if ( xparent_found ) {
+ ptr->flags |= ANF_XPARENT;
+ }
+ else {
+ ptr->flags &= ~ANF_XPARENT;
+ }
+} \ No newline at end of file
diff --git a/code/Anim/PackUnpack.h b/code/Anim/PackUnpack.h
new file mode 100644
index 0000000..0a7b990
--- /dev/null
+++ b/code/Anim/PackUnpack.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/Anim/PackUnpack.h $
+ * $Revision: 7 $
+ * $Date: 7/16/99 1:49p $
+ * $Author: Dave $
+ *
+ * Code for handling packing and unpacking in Hoffoss's RLE format, used for
+ * Anim files. Also handles Anim loading, creating Anim instances (for
+ * utilizing an Anim), and getting getting frames of the Anim.
+ *
+ * $Log: /Freespace2/code/Anim/PackUnpack.h $
+ *
+ * 7 7/16/99 1:49p Dave
+ * 8 bit aabitmaps. yay.
+ *
+ * 6 1/14/99 12:48a Dave
+ * Todo list bug fixes. Made a pass at putting briefing icons back into
+ * FRED. Sort of works :(
+ *
+ * 5 11/30/98 1:07p Dave
+ * 16 bit conversion, first run.
+ *
+ * 4 10/22/98 6:14p Dave
+ * Optimized some #includes in Anim folder. Put in the beginnings of
+ * parse/localization support for externalized strings and tstrings.tbl
+ *
+ * 3 10/16/98 3:42p Andsager
+ * increase MAX_WEAPONS and MAX_SHIPS and som header files
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 32 5/18/98 5:59p Hoffoss
+ * Made command briefing advanced now once the speech stops and animation
+ * has fully played once, whichever is longer.
+ *
+ * 31 5/07/98 3:11a Lawrance
+ * Implement custom streaming code
+ *
+ * 30 1/14/98 6:43p Lawrance
+ * Add ref_count to anim struct, so we don't free multiple times
+ *
+ * 29 11/19/97 8:28p Dave
+ * Hooked in Main Hall screen. Put in Anim support for ping ponging
+ * animations as well as general reversal of anim direction.
+ *
+ * 28 8/30/97 2:11p Lawrance
+ * allow animations to loop
+ *
+ * 27 8/25/97 11:13p Lawrance
+ * support framerate independent playback with the option of now advancing
+ * more than one frame at a time
+ *
+ * 26 8/21/97 5:11p Lawrance
+ * frame numbering for ANI's now is from 0 -> total_frames-1.
+ *
+ * 25 7/28/97 10:42p Lawrance
+ * re-did interface to unpack_frame() to make more general
+ *
+ * 24 7/21/97 11:41a Lawrance
+ * make playback time of .ani files keyed of frametime
+ *
+ * 23 7/20/97 6:57p Lawrance
+ * supporting new RLE format
+ *
+ * 22 6/27/97 4:36p Lawrance
+ * update pal translation table when gr_screen.signature changes
+ *
+ * 21 6/26/97 12:12a Lawrance
+ * supporting anti-aliased bitmap animations
+ *
+ * 20 6/25/97 3:03p Lawrance
+ * fix palette translation problem with anti-alised bitmaps
+ *
+ * 19 5/27/97 3:48p Lawrance
+ * don't re-create a bitmap if using the same frame of animation
+ *
+ * 18 5/21/97 11:06a Lawrance
+ * enabling a user-defined transparent value
+ *
+ * 17 5/19/97 3:21p Lawrance
+ * add fps parm, version num to anim header
+ *
+ * 16 5/19/97 2:28p Lawrance
+ * changes some variables to flags
+ *
+ * 15 5/15/97 4:42p Lawrance
+ * supporting animations in-game
+ *
+ * 14 3/01/97 2:08p Lawrance
+ * not using windows.h, since memory mapping details moved to cfile
+ *
+ * 13 2/28/97 12:17p Lawrance
+ * supporting mapping file to memory
+ *
+ * 12 2/25/97 11:06a Lawrance
+ * moved some higher level functions to from PackUnpack to AnimPlay
+ *
+ * 11 2/19/97 9:51p Lawrance
+ * made keyframe decompression more effecient, moved
+ * default anim FPS to header file
+ *
+ * 10 2/19/97 4:01p Lawrance
+ * load_anim returns int, not void
+ *
+ * 9 2/17/97 4:19p Lawrance
+ * changed stop and start to be actual frame numbers, not percentages
+ *
+ * 8 2/17/97 4:17p Hoffoss
+ * modified packing internal format and added random access function to an
+ * Anim frame.
+ *
+ * 7 2/17/97 2:59p Lawrance
+ * integrating into game
+ *
+ * 6 2/14/97 11:09p Hoffoss
+ * Made optimizations.
+ *
+ * 5 2/14/97 10:48p Hoffoss
+ * fixed bug.
+ *
+ * 4 2/14/97 10:38p Lawrance
+ * fixing bugs
+ *
+ * 3 2/14/97 3:29p Hoffoss
+ * Added header for MSDEV to fill in.
+ *
+ * $NoKeywords: $
+ */
+
+#ifndef __PACKUNPACK_H__
+#define __PACKUNPACK_H__
+
+#include "PsTypes.h"
+
+struct CFILE;
+
+#define ANI_STREAM_CACHE_SIZE 4096
+
+#define PACKER_CODE 0xEE // Use'd by PACKING_METHOD_RLE
+#define PACKING_METHOD_RLE 0 // Hoffoss's RLE format
+#define PACKING_METHOD_RLE_KEY 1 // Hoffoss's key frame RLE format
+#define PACKING_METHOD_STD_RLE 2 // Standard RLE format (high bit is count)
+#define PACKING_METHOD_STD_RLE_KEY 3 // Standard RLE format key frame
+
+#define STD_RLE_CODE 0x80
+
+typedef struct key_frame {
+ int frame_num; // which frame number this key frame is
+ int offset; // offset from the start of data block
+} key_frame;
+
+#define ANF_MEM_MAPPED (1<<0) // animation is memory-mapped file
+#define ANF_STREAMED (1<<1)
+#define ANF_XPARENT (1<<2) // animation has transparency
+#define ANF_ALL_KEYFRAMES (1<<3) // all the frames are keyframes (this is necessary if we want to play the file backwards)
+
+typedef struct anim {
+ anim *next;
+ char name[MAX_PATH_LEN];
+ ubyte packer_code;
+ int width;
+ int height;
+ int total_frames;
+ int instance_count; // number of instances that are currently playing
+ int ref_count; // number of times this anim has been loaded
+ float time; // playback time in seconds
+ int num_keys;
+ key_frame *keys;
+ ubyte palette[768];
+ ubyte palette_translation[256];
+ ubyte *data; // points to compressed data
+ CFILE* cfile_ptr;
+ int version;
+ int fps;
+ ubyte xparent_r; // red component for the transparent color in source image
+ ubyte xparent_g; // green component for the transparent color in source image
+ ubyte xparent_b; // blue component for the transparent color in source image
+ int flags;
+ uint screen_sig;
+ int file_offset; // file offset to start of frame data
+ int cache_file_offset;
+ ubyte *cache;
+} anim;
+
+// the direction to play the anim (forwards or backwards)
+#define ANIM_DIRECT_FORWARD 0
+#define ANIM_DIRECT_REVERSE 1
+
+typedef struct anim_instance {
+ anim_instance *next, *prev;
+ int x,y; // coordinates anim is played at (top left corner of anim)
+ vector *world_pos; // world (x,y,z) position of explosion
+ float radius; // radius of image, needed for scaling
+ int frame_num; // current frame, or last frame if between frames (first frame is 0)
+ int last_frame_num;// last frame rendered
+ anim *parent; // pointer to anim structure, which holds compressed data
+ ubyte *data; // pointer to next frame's compressed data
+ ubyte *frame; // uncompressed frame
+ float time_elapsed; // how long the anim has played for (in seconds)
+ int start_at; // frame anim playing should start
+ int stop_at; // frame anim playing should stop
+ int framerate_independent; // animation should play back in same amount of time, regardless
+ int skip_frames; // should anim skip frames during framerate independent playback
+ int looped; // should anim keep playing over and over...
+ int stop_now; // flag to indicate time to stop the animation
+ int last_bitmap; // id of last bitmap that was rendered out from animation
+ int screen_id; // 0 means all screens should render, otherwise screen specific
+ void *aa_color; // anti-aliased bitmap color
+ int xlate_pal;
+ int direction; // playing forwards or backwards ?
+ int ping_pong; // should be played ping-pong style
+ int paused; // pause the anim
+ int file_offset; // current offset into frame (like data, put offset into file)
+ int loop_count; // starts at 0, and is incremented each time it loops
+} anim_instance;
+
+extern int packer_code;
+
+int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type);
+int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type);
+
+ubyte *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp);
+int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp);
+
+void anim_init();
+anim_instance *init_anim_instance(anim *ptr, int bpp);
+void free_anim_instance(anim_instance *inst);
+int anim_get_next_frame(anim_instance *inst);
+int anim_get_frame(anim_instance *inst, int frame_num, int xlate_pal=1);
+ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp);
+void anim_set_palette(anim *a);
+void anim_check_for_palette_change(anim_instance *inst);
+
+
+#endif /* __PACKUNPACK_H__ */ \ No newline at end of file
diff --git a/code/Asteroid/Asteroid.cpp b/code/Asteroid/Asteroid.cpp
new file mode 100644
index 0000000..45f7c3a
--- /dev/null
+++ b/code/Asteroid/Asteroid.cpp
@@ -0,0 +1,2271 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/Asteroid/Asteroid.cpp $
+ * $Revision: 31 $
+ * $Date: 9/08/99 10:52a $
+ * $Author: Mikek $
+ *
+ * C module for asteroid code
+ *
+ * $Log: /Freespace2/code/Asteroid/Asteroid.cpp $
+ *
+ * 31 9/08/99 10:52a Mikek
+ * Reduce the number of asteroids that can be thrown at a target at
+ * Medium+.
+ *
+ * 30 9/06/99 12:46a Andsager
+ * Add weapon_explosion_ani LOD
+ *
+ * 29 9/05/99 3:13p Mikek
+ * Slightly decrease number of asteroids thrown at escorted ships.
+ *
+ * 28 8/26/99 8:51p Dave
+ * Gave multiplayer TvT messaging a heavy dose of sanity. Cheat codes.
+ *
+ * 27 7/30/99 7:01p Dave
+ * Dogfight escort gauge. Fixed up laser rendering in Glide.
+ *
+ * 26 7/19/99 8:58p Andsager
+ * Don't try to throw at objnum -1
+ *
+ * 25 7/15/99 9:20a Andsager
+ * FS2_DEMO initial checkin
+ *
+ * 24 7/09/99 5:54p Dave
+ * Seperated cruiser types into individual types. Added tons of new
+ * briefing icons. Campaign screen.
+ *
+ * 23 6/10/99 11:06a Andsager
+ * Mission designed selection of asteroid types.
+ *
+ * 22 6/09/99 2:55p Andsager
+ * Allow multiple asteroid subtypes (of large, medium, small) and follow
+ * family.
+ *
+ * 21 6/08/99 7:19p Dave
+ * Fixed asteroid lighting. Was because on non-darkening textures in Glide
+ * only. Dumb.
+ *
+ * 20 6/07/99 1:18p Andsager
+ * Make asteroids choose consistent texture from large to small. Modify
+ * fireball radius of dying asteroids.
+ *
+ * 19 5/03/99 10:50p Andsager
+ * Make Asteroid_obj_list. Change get_nearest_turret_objnum() to use
+ * Asteroid_obj_list, Ship_obj_list and Missile_obj_list vs.
+ * obj_used_list.
+ *
+ * 18 4/23/99 12:01p Johnson
+ * Added SIF_HUGE_SHIP
+ *
+ * 17 4/21/99 6:15p Dave
+ * Did some serious housecleaning in the beam code. Made it ready to go
+ * for anti-fighter "pulse" weapons. Fixed collision pair creation. Added
+ * a handy macro for recalculating collision pairs for a given object.
+ *
+ * 16 4/16/99 2:34p Andsager
+ * Second pass on debris fields
+ *
+ * 15 4/15/99 5:27p Andsager
+ * Fix explosion sound for Ships debris
+ *
+ * 14 4/15/99 5:00p Andsager
+ * Frist pass on Debris field
+ *
+ * 13 2/07/99 8:51p Andsager
+ * Add inner bound to asteroid field. Inner bound tries to stay astroid
+ * free. Wrap when within and don't throw at ships inside.
+ *
+ * 12 1/20/99 6:04p Dave
+ * Another bit of stuff for beam weapons. Ships will properly use them
+ * now, although they're really deadly.
+ *
+ * 11 1/06/99 2:24p Dave
+ * Stubs and release build fixes.
+ *
+ * 10 12/03/98 3:14p Andsager
+ * Check in code that checks rotating submodel actually has ship subsystem
+ *
+ * 9 11/19/98 11:07p Andsager
+ * Check in of physics and collision detection of rotating submodels
+ *
+ * 8 11/13/98 10:12a Andsager
+ * simplify collision code
+ *
+ * 7 11/05/98 5:55p Dave
+ * Big pass at reducing #includes
+ *
+ * 6 10/23/98 3:51p Dave
+ * Full support for tstrings.tbl and foreign languages. All that remains
+ * is to make it active in Fred.
+ *
+ * 5 10/23/98 1:11p Andsager
+ * Make ship sparks emit correctly from rotating structures.
+ *
+ * 4 10/16/98 1:22p Andsager
+ * clean up header files
+ *
+ * 3 10/13/98 9:28a Dave
+ * Started neatening up freespace.h. Many variables renamed and
+ * reorganized. Added AlphaColors.[h,cpp]
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 80 7/14/98 3:30p Dave
+ *
+ * 79 5/18/98 12:05p Mike
+ * Make sm1-06a a little harder.
+ *
+ * 78 5/06/98 12:36p Lawrance
+ * disable ambient asteroid sound for now
+ *
+ * 77 4/30/98 12:49a Allender
+ * deal with asteroid problems in multiplayer
+ *
+ * 76 4/27/98 1:46p Mike
+ * Make asteroid_density have no meaning.
+ *
+ * 75 4/24/98 11:59a Dan
+ * fix bug where a null vector would occur when death_hit_pos was assinged
+ * to asteroid_pos
+ *
+ * 74 4/23/98 4:43p Andsager
+ * Don't call asteroid_update_collide() on creating asteroids since it
+ * creates sets of collisions pairs. Pairs are created when objects are
+ * merged in obj_merge_created_list()
+ *
+ * 73 4/21/98 1:23a Mike
+ * Tone down difficulty in asteroid toss missions.
+ *
+ * 72 4/16/98 11:57a John
+ * Removed debug and unused registry values.
+ *
+ * 71 4/08/98 1:27a Lawrance
+ * Fix typo.
+ *
+ * 70 4/08/98 1:17a Lawrance
+ * Fix bug with red and white brackets being drawn on top of one another.
+ *
+ * 69 4/02/98 6:28p Lawrance
+ * remove asteroid code from demo
+ *
+ * 68 4/02/98 5:11p Mike
+ * Quick out of asteroid code if none present.
+ *
+ * 67 4/02/98 1:34p Mike
+ * Minor difficulty balance, made a bit easier.
+ *
+ * 66 4/02/98 1:29p Andsager
+ *
+ * 65 4/01/98 5:34p John
+ * Made only the used POFs page in for a level. Reduced some interp
+ * arrays. Made custom detail level work differently.
+ *
+ * 64 3/31/98 5:11p John
+ * Removed demo/save/restore. Made NDEBUG defined compile. Removed a
+ * bunch of debug stuff out of player file. Made model code be able to
+ * unload models and malloc out only however many models are needed.
+ *
+ * 63 3/30/98 4:02p John
+ * Made machines with < 32 MB of RAM use every other frame of certain
+ * bitmaps. Put in code to keep track of how much RAM we've malloc'd.
+ *
+ * 62 3/30/98 2:38p Mike
+ * Add asteroid_density to detail level support.
+ * No force explosion damage in training missions.
+ * Make cargo deathrolls shorter.
+ *
+ * 61 3/30/98 10:07a Lawrance
+ * Um, make asteroids work again.
+ *
+ * 60 3/29/98 12:55a Lawrance
+ * Get demo build working with limited set of data.
+ *
+ * 59 3/26/98 9:19a Lawrance
+ * Support multiple asteroid pofs
+ *
+ * 58 3/25/98 3:44p Andsager
+ * Fixed bug in asteroid_sub_create, where last_pos field was invalid in
+ * its creation frame but needed for collision in that frame.
+ *
+ * 57 3/25/98 2:03p Sandeep
+ * Remove "f" from top of file.
+ *
+ * 56 3/25/98 1:50p Mike
+ * Asteroid destruction (sm1-06a) balancing.
+ *
+ * 55 3/25/98 10:43a Andsager
+ * Hack for ship_asteroid collisions when erroneous relative_vel >150
+ *
+ * 54 3/23/98 12:20p Andsager
+ * Enable collision from rotation in ship_debris and ship_debris
+ * collisions.
+ *
+ * 53 3/22/98 4:09p Andsager
+ * Make moment of inertia based on model.
+ *
+ * 52 3/21/98 3:33p Lawrance
+ * When asteroid collides with an escort ship, make the sound carry
+ * farther
+ *
+ * 51 3/19/98 12:09p John
+ * Fixed a bug using 6 characters. r_heavy was using local coordinates
+ * instead of world so all asteroid-ship and debris-ship hitpos's were in
+ * the wrong spot. Ok, I rearreanged some code to make it clearer also.
+ *
+ * 50 3/17/98 5:55p Lawrance
+ * Support object linked sounds for asteroids.
+ *
+ * 49 3/17/98 3:44p Mike
+ * Make asteroids-thrown-at-target not only happen when an asteroid wraps.
+ *
+ * 48 3/17/98 9:53a Lawrance
+ * Asteroid area effect only affect ships
+ *
+ * 47 3/17/98 9:25a Allender
+ * some minor asteroid changes for multiplayer
+ *
+ * 46 3/17/98 12:16a Allender
+ * asteroids in multiplayer -- minor problems with position being correct
+ *
+ * 45 3/14/98 1:44p Mike
+ * Todolist items 3365..3368. Make child asteroids collide properly.
+ * Make asteroid throwing less bunchy, toss asteroids earlier, make
+ * facing-ness not break mission balance.
+ *
+ * 44 3/13/98 9:06a John
+ * Made missile thrusters use a different min dist for scaling. Made
+ * missilies not use lighting.
+ *
+ * 43 3/12/98 4:01p Lawrance
+ * Only show warning brackets for cruiser/capital ships on the same team
+ *
+ * $NoKeywords: $
+ */
+
+#include "Asteroid.h"
+#include "Object.h"
+#include "ObjCollide.h"
+#include "FreeSpace.h"
+#include "Timer.h"
+#include "3d.h"
+#include "Fireballs.h"
+#include "GameSnd.h"
+#include "Bmpman.h"
+#include "Particle.h"
+#include "LinkList.h"
+#include "HUDescort.h"
+#include "ShipHit.h"
+#include "MultiUtil.h"
+#include "StaticRand.h"
+#include "MultiMsgs.h"
+#include "SystemVars.h"
+#include "localize.h"
+#include "Multi.h"
+
+#ifndef FS2_DEMO
+
+#define ASTEROID_OBJ_USED (1<<0) // flag used in asteroid_obj struct
+#define MAX_ASTEROID_OBJS MAX_ASTEROIDS // max number of asteroids tracked in asteroid list
+asteroid_obj Asteroid_objs[MAX_ASTEROID_OBJS]; // array used to store asteroid object indexes
+asteroid_obj Asteroid_obj_list; // head of linked list of asteroid_obj structs
+
+// Asteroid editor requires first set of entries to be "None" and then "Asteroid XXX"
+// Any changes to this will require changes to the asteroid editor
+debris_struct Field_debris_info[] = {
+ -1, "None",
+ ASTEROID_TYPE_SMALL, "Asteroid Small",
+ ASTEROID_TYPE_MEDIUM, "Asteroid Medium",
+ ASTEROID_TYPE_BIG, "Asteroid Large",
+
+ DEBRIS_TERRAN_SMALL, "Terran Small",
+ DEBRIS_TERRAN_MEDIUM, "Terran Medium",
+ DEBRIS_TERRAN_LARGE, "Terran Large",
+
+ DEBRIS_VASUDAN_SMALL, "Vasudan Small",
+ DEBRIS_VASUDAN_MEDIUM, "Vasudan Medium",
+ DEBRIS_VASUDAN_LARGE, "Vasudan Large",
+
+ DEBRIS_SHIVAN_SMALL, "Shivan Small",
+ DEBRIS_SHIVAN_MEDIUM, "Shivan Medium",
+ DEBRIS_SHIVAN_LARGE, "Shivan Large"
+};
+
+// used for randomly generating debris type when there are multiple sizes.
+#define SMALL_DEBRIS_WEIGHT 8
+#define MEDIUM_DEBRIS_WEIGHT 4
+#define LARGE_DEBRIS_WEIGHT 1
+
+int Asteroids_enabled = 1;
+int Num_asteroid_types;
+int Num_asteroids = 0;
+int Asteroid_throw_objnum = -1; // Object index of ship to throw asteroids at.
+int Next_asteroid_throw;
+
+asteroid_info Asteroid_info[MAX_DEBRIS_TYPES];
+asteroid Asteroids[MAX_ASTEROIDS];
+asteroid_field Asteroid_field;
+
+static int Asteroid_impact_explosion_ani;
+static float Asteroid_impact_explosion_radius;
+
+#define ASTEROID_CHECK_WRAP_TIMESTAMP 2000 // how often an asteroid gets checked for wrapping
+#define ASTEROID_UPDATE_COLLIDE_TIMESTAMP 2000 // how often asteroid is checked for impending collisions with escort ships
+#define ASTEROID_MIN_COLLIDE_TIME 24 // time in seconds to check for asteroid colliding
+
+// Force updating of pair stuff for asteroid *objp.
+void asteroid_update_collide(object *objp)
+{
+ // Asteroid has wrapped, update collide objnum and flags
+ Asteroids[objp->instance].collide_objnum = -1;
+ Asteroids[objp->instance].collide_objsig = -1;
+ OBJ_RECALC_PAIRS(objp);
+}
+
+// Clear out the Asteroid_obj_list
+//
+void asteroid_obj_list_init()
+{
+ int i;
+
+ list_init(&Asteroid_obj_list);
+ for ( i = 0; i < MAX_ASTEROID_OBJS; i++ ) {
+ Asteroid_objs[i].flags = 0;
+ }
+}
+
+// ---------------------------------------------------
+// asteroid_obj_list_add()
+//
+// Function to add a node from the Asteroid_obj_list. Only
+// called from weapon_create()
+int asteroid_obj_list_add(int objnum)
+{
+ int index;
+
+ asteroid *cur_asteroid = &Asteroids[Objects[objnum].instance];
+ index = cur_asteroid - Asteroids;
+
+ Assert(index >= 0 && index < MAX_ASTEROID_OBJS);
+ Assert(!Asteroid_objs[index].flags & ASTEROID_OBJ_USED);
+
+ Asteroid_objs[index].flags = 0;
+ Asteroid_objs[index].objnum = objnum;
+ list_append(&Asteroid_obj_list, &Asteroid_objs[index]);
+ Asteroid_objs[index].flags |= ASTEROID_OBJ_USED;
+
+ return index;
+}
+
+// ---------------------------------------------------
+// missle_obj_list_remove()
+//
+// Function to remove a node from the Asteroid_obj_list. Only
+// called from weapon_delete()
+void asteroid_obj_list_remove(object * obj)
+{
+ int index = obj->instance;
+
+ Assert(index >= 0 && index < MAX_ASTEROID_OBJS);
+ Assert(Asteroid_objs[index].flags & ASTEROID_OBJ_USED);
+
+ list_remove(&Asteroid_obj_list, &Asteroid_objs[index]);
+ Asteroid_objs[index].flags = 0;
+}
+
+
+// Prevent speed from getting too huge so it's hard to catch up to an asteroid.
+float asteroid_cap_speed(int asteroid_info_index, float speed)
+{
+ float max, double_max;
+
+ max = Asteroid_info[asteroid_info_index].max_speed;
+ double_max = max * 2;
+
+ while (speed > double_max){
+ speed *= 0.5f;
+ }
+
+ if (speed > max){
+ speed *= 0.75f;
+ }
+
+ return speed;
+}
+
+// Returns whether position is inside inner bounding volume
+// sum together the following: 1 inside x, 2 inside y, 4 inside z
+// inside only when sum = 7
+int asteroid_in_inner_bound_with_axes(asteroid_field *asfieldp, vector *pos, float delta)
+{
+ Assert(asfieldp->has_inner_bound);
+
+ int rval = 0;
+ if ( (pos->x > asfieldp->inner_min_bound.x - delta) && (pos->x < asfieldp->inner_max_bound.x + delta) ) {
+ rval += 1;
+ }
+
+ if ( (pos->y > asfieldp->inner_min_bound.y - delta) && (pos->y < asfieldp->inner_max_bound.y + delta) ) {
+ rval += 2;
+ }
+
+ if ( (pos->z > asfieldp->inner_min_bound.z - delta) && (pos->z < asfieldp->inner_max_bound.z + delta) ) {
+ rval += 4;
+ }
+
+ return rval;
+}
+
+// check if asteroid is within inner bound
+// return 0 if not inside or no inner bound, 1 if inside inner bound
+int asteroid_in_inner_bound(asteroid_field *asfieldp, vector *pos, float delta) {
+
+ if (!asfieldp->has_inner_bound) {
+ return 0;
+ }
+
+ return (asteroid_in_inner_bound_with_axes(asfieldp, pos, delta) == 7);
+}
+
+// repositions asteroid outside the inner box on all 3 axes
+// moves to the other side of the inner box a distance delta from edge of box
+void inner_bound_pos_fixup(asteroid_field *asfieldp, vector *pos)
+{
+ if (!asteroid_in_inner_bound(asfieldp, pos, 0)) {
+ return;
+ }
+
+ float dist1, dist2;
+ int axis;
+
+ for (axis=0; axis<3; axis++) {
+ dist1 = pos->a1d[axis] - asfieldp->inner_min_bound.a1d[axis];
+ dist2 = asfieldp->inner_max_bound.a1d[axis] - pos->a1d[axis];
+ Assert(dist1 >= 0 && dist2 >= 0);
+
+ if (dist1 < dist2) {
+ pos->a1d[axis] = asfieldp->inner_max_bound.a1d[axis] + dist1;
+ } else {
+ pos->a1d[axis] = asfieldp->inner_min_bound.a1d[axis] - dist2;
+ }
+ }
+}
+
+
+// Create a single asteroid
+object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroid_subtype)
+{
+ int n, objnum;
+ matrix orient;
+ object *objp;
+ asteroid *asp;
+ asteroid_info *asip;
+ vector pos, delta_bound;
+ angles angs;
+ float radius;
+ ushort signature;
+ int rand_base;
+
+ // bogus
+ if(asfieldp == NULL){
+ return NULL;
+ }
+
+ for (n=0; n<MAX_ASTEROIDS; n++ ) {
+ if ( !(Asteroids[n].flags & AF_USED) ){
+ break;
+ }
+ }
+
+ if (n >= MAX_ASTEROIDS) {
+ nprintf(("Warning","Could not create asteroid, no more slots left\n"));
+ return NULL;
+ }
+
+ if((asteroid_type < 0) || (asteroid_type >= Num_asteroid_types)){
+ return NULL;
+ }
+
+ // HACK: multiplayer asteroid subtype always 0 to keep subtype in sync
+ if ( Game_mode & GM_MULTIPLAYER) {
+ asteroid_subtype = 0;
+ }
+
+ if( (asteroid_subtype < 0) || (asteroid_subtype >= MAX_ASTEROID_POFS)){
+ return NULL;
+ }
+
+ asip = &Asteroid_info[asteroid_type];
+
+ // bogus
+ if(asip->modelp[asteroid_subtype] == NULL){
+ return NULL;
+ }
+
+ asp = &Asteroids[n];
+ asp->type = asteroid_type;
+ asp->asteroid_subtype = asteroid_subtype;
+ asp->flags = 0;
+ asp->flags |= AF_USED;
+ asp->check_for_wrap = timestamp_rand(0, ASTEROID_CHECK_WRAP_TIMESTAMP);
+ asp->check_for_collide = timestamp_rand(0, ASTEROID_UPDATE_COLLIDE_TIMESTAMP);
+ asp->final_death_time = timestamp(-1);
+ asp->collide_objnum = -1;
+ asp->collide_objsig = -1;
+ asp->target_objnum = -1;
+
+ radius = model_get_radius(asip->model_num[asteroid_subtype]);
+
+ vm_vec_sub(&delta_bound, &asfieldp->max_bound, &asfieldp->min_bound);
+
+ // for multiplayer, we want to do a static_rand so that everything behaves the same on all machines
+ signature = 0;
+ rand_base = 0;
+ if ( Game_mode & GM_NORMAL ) {
+ pos.x = asfieldp->min_bound.x + delta_bound.x * frand();
+ pos.y = asfieldp->min_bound.y + delta_bound.y * frand();
+ pos.z = asfieldp->min_bound.z + delta_bound.z * frand();
+
+ inner_bound_pos_fixup(asfieldp, &pos);
+ // vm_set_identity(&orient);
+ angs.p = frand() * 2*PI;
+ angs.b = frand() * 2*PI;
+ angs.h = frand() * 2*PI;
+ } else {
+ signature = multi_assign_network_signature( MULTI_SIG_ASTEROID );
+ rand_base = signature;
+
+ pos.x = asfieldp->min_bound.x + delta_bound.x * static_randf( rand_base++ );
+ pos.y = asfieldp->min_bound.y + delta_bound.y * static_randf( rand_base++ );
+ pos.z = asfieldp->min_bound.z + delta_bound.z * static_randf( rand_base++ );
+
+ inner_bound_pos_fixup(asfieldp, &pos);
+ // vm_set_identity(&orient);
+ angs.p = static_randf( rand_base++ ) * 2*PI;
+ angs.b = static_randf( rand_base++ ) * 2*PI;
+ angs.h = static_randf( rand_base++ ) * 2*PI;
+ }
+
+ vm_angles_2_matrix(&orient, &angs);
+
+ objnum = obj_create( OBJ_ASTEROID, -1, n, &orient, &pos, radius, OF_RENDERS | OF_PHYSICS | OF_COLLIDES);
+ // mprintf(("Framecount: %d asteroid create: obj = %d\n", Framecount, objnum));
+
+ if ( (objnum == -1) || (objnum >= MAX_OBJECTS) ) {
+ mprintf(("Couldn't create asteroid -- out of object slots\n"));
+ return NULL;
+ }
+
+ asp->objnum = objnum;
+
+ // Add to Asteroid_used_list
+ asteroid_obj_list_add(objnum);
+
+ objp = &Objects[objnum];
+
+ if ( Game_mode & GM_MULTIPLAYER ){
+ objp->net_signature = signature;
+ }
+
+ Num_asteroids++;
+
+ if (radius < 1.0) {
+ radius = 1.0f;
+ }
+
+ vector rotvel;
+ if ( Game_mode & GM_NORMAL ) {
+ vm_vec_rand_vec_quick(&rotvel);
+ vm_vec_scale(&rotvel, frand()/4.0f + 0.1f);
+ objp->phys_info.rotvel = rotvel;
+ vm_vec_rand_vec_quick(&objp->phys_info.vel);
+ } else {
+ static_randvec( rand_base++, &rotvel );
+ vm_vec_scale(&rotvel, static_randf(rand_base++)/4.0f + 0.1f);
+ objp->phys_info.rotvel = rotvel;
+ static_randvec( rand_base++, &objp->phys_info.vel );
+ }
+
+
+ float speed;
+
+ if ( Game_mode & GM_NORMAL ) {
+ speed = asteroid_cap_speed(asteroid_type, asfieldp->speed*frand_range(0.5f + (float) Game_skill_level/NUM_SKILL_LEVELS, 2.0f + (float) (2*Game_skill_level)/NUM_SKILL_LEVELS));
+ } else {
+ speed = asteroid_cap_speed(asteroid_type, asfieldp->speed*static_randf_range(rand_base++, 0.5f + (float) Game_skill_level/NUM_SKILL_LEVELS, 2.0f + (float) (2*Game_skill_level)/NUM_SKILL_LEVELS));
+ }
+
+ vm_vec_scale(&objp->phys_info.vel, speed);
+ objp->phys_info.desired_vel = objp->phys_info.vel;
+
+ // blow out his reverse thrusters. Or drag, same thing.
+ objp->phys_info.rotdamp = 10000.0f;
+ objp->phys_info.side_slip_time_const = 10000.0f;
+ objp->phys_info.flags |= (PF_REDUCED_DAMP | PF_DEAD_DAMP); // set damping equal for all axis and not changable
+
+ // Fill in the max_vel field, so the collision pair stuff knows
+ // how fast this can move maximum in order to throw out collisions.
+ // This is in local coordinates, so Z is forward velocity.
+ objp->phys_info.max_vel.x = 0.0f;
+ objp->phys_info.max_vel.y = 0.0f;
+ objp->phys_info.max_vel.z = vm_vec_mag(&objp->phys_info.desired_vel);
+
+ objp->phys_info.mass = asip->modelp[asteroid_subtype]->rad * 700.0f;
+ objp->phys_info.I_body_inv.rvec.x = 1.0f / (objp->phys_info.mass*asip->modelp[asteroid_subtype]->rad);
+ objp->phys_info.I_body_inv.uvec.y = objp->phys_info.I_body_inv.rvec.x;
+ objp->phys_info.I_body_inv.fvec.z = objp->phys_info.I_body_inv.rvec.x;
+ objp->hull_strength = asip->initial_hull_strength * (0.8f + (float)Game_skill_level/NUM_SKILL_LEVELS)/2.0f;
+
+ // ensure vel is valid
+ Assert( !vm_is_vec_nan(&objp->phys_info.vel) );
+
+ // assign a persistant sound to the asteroid
+// obj_snd_assign(objnum, SND_ASTEROID);
+
+ return objp;
+}
+
+// Create asteroids when parent_objp blows up.
+void asteroid_sub_create(object *parent_objp, int asteroid_type, vector *relvec)
+{
+ object *new_objp;
+ float speed;
+
+ Assert(parent_objp->type == OBJ_ASTEROID);
+ int subtype = Asteroids[parent_objp->instance].asteroid_subtype;
+ new_objp = asteroid_create(&Asteroid_field, asteroid_type, subtype);
+
+ if (new_objp == NULL)
+ return;
+
+ if ( MULTIPLAYER_MASTER ){
+ send_asteroid_create( new_objp, parent_objp, asteroid_type, relvec );
+ }
+
+ // Now, bash some values.
+ vm_vec_scale_add(&new_objp->pos, &parent_objp->pos, relvec, 0.5f * parent_objp->radius);
+ float parent_speed = vm_vec_mag_quick(&parent_objp->phys_info.vel);
+
+ if ( parent_speed < 0.1f ) {
+ parent_speed = vm_vec_mag_quick(&Asteroid_field.vel);
+ }
+
+ new_objp->phys_info.vel = parent_objp->phys_info.vel;
+ if ( Game_mode & GM_NORMAL )
+ speed = asteroid_cap_speed(asteroid_type, (frand() + 2.0f) * parent_speed);
+ else
+ speed = asteroid_cap_speed(asteroid_type, (static_randf(new_objp->net_signature)+2.0f) * parent_speed);
+
+ vm_vec_scale_add2(&new_objp->phys_info.vel, relvec, speed);
+ if (vm_vec_mag_quick(&new_objp->phys_info.vel) > 80.0f)
+ vm_vec_scale(&new_objp->phys_info.vel, 0.5f);
+
+ new_objp->phys_info.desired_vel = new_objp->phys_info.vel;
+ vm_vec_scale_add(&new_objp->last_pos, &new_objp->pos, &new_objp->phys_info.vel, -flFrametime);
+ // DA: 4/22/98 We get next line for free when new object (in obj_create_list) is merged.
+ // this line gives too many collision pairs.
+ // asteroid_update_collide(new_objp);
+}
+
+// Load in an asteroid model
+void asteroid_load(int asteroid_info_index, int asteroid_subtype)
+{
+ asteroid_info *asip;
+// int pof_index;
+
+ asip = &Asteroid_info[asteroid_info_index];
+
+ // pick one of MAX_ASTEROID_POFS models
+ // LOAD ALL TEXTURES USED
+// static int asteroid_pof_index = rand() % MAX_ASTEROID_POFS;
+// if (Asteroid_field.debris_genre == DG_ASTEROID) {
+// pof_index = asteroid_pof_index;
+// } else {
+// // only 1 pof for ship debris type
+// pof_index = 0;
+// }
+
+ asip->model_num[asteroid_subtype] = model_load( asip->pof_files[asteroid_subtype], 0, NULL );
+
+ if (asip->model_num[asteroid_subtype] > -1) {
+ asip->modelp[asteroid_subtype] = model_get(asip->model_num[asteroid_subtype]);
+
+ // Stuff detail level distances.
+ for (int i = 0; i < asip->num_detail_levels; i++) {
+ asip->modelp[asteroid_subtype]->detail_depth[i] = i2fl(asip->detail_distance[i]);
+ }
+ }
+}
+
+// randomly choose a debris model within the current group
+int get_debris_from_same_group(int index) {
+ int group_base, group_offset;
+
+ group_base = (index / 3) * 3;
+ group_offset = index - group_base;
+
+ // group base + offset
+ // offset is formed by adding 1 or 2 (since 3 in model group) and mapping back in the 0-2 range
+ return group_base + ((group_offset + rand()%2 + 1) % 3);
+}
+
+// returns a weight that depends on asteroid size.
+// the weight is then used to determine the frequencty of different sizes of ship debris
+int get_debris_weight(int ship_debris_index)
+{
+ switch (ship_debris_index) {
+ case DEBRIS_TERRAN_SMALL:
+ case DEBRIS_VASUDAN_SMALL:
+ case DEBRIS_SHIVAN_SMALL:
+ return SMALL_DEBRIS_WEIGHT;
+ break;
+
+ case DEBRIS_TERRAN_MEDIUM:
+ case DEBRIS_VASUDAN_MEDIUM:
+ case DEBRIS_SHIVAN_MEDIUM:
+ return MEDIUM_DEBRIS_WEIGHT;
+ break;
+
+ case DEBRIS_TERRAN_LARGE:
+ case DEBRIS_VASUDAN_LARGE:
+ case DEBRIS_SHIVAN_LARGE:
+ return LARGE_DEBRIS_WEIGHT;
+ break;
+
+ default:
+ Int3();
+ return 1;
+ break;
+ }
+}
+
+// Create all the asteroids for the mission, called from
+void asteroid_create_all()
+{
+ int i, idx;
+
+ // ship_debris_odds_table keeps track of debris type of the next debris piece
+ // each different type (size) of debris piece has a diffenent weight, smaller weighted more heavily than larger.
+ // choose next type from table ship_debris_odds_table by rand()%max_weighted_range,
+ // the first column in ship_debris_odds_table random number *below* which the debris type in the second column is selected.
+ int ship_debris_odds_table[3][2];
+ int max_weighted_range = 0;
+
+ if (!Asteroids_enabled)
+ return;
+
+ if (Asteroid_field.num_initial_asteroids <= 0 ) {
+ return;
+ }
+
+ int max_asteroids = Asteroid_field.num_initial_asteroids; // * (1.0f - 0.1f*(MAX_DETAIL_LEVEL-Detail.asteroid_density)));
+
+ int num_debris_types = 0;
+
+ // get number of ship debris types
+ if (Asteroid_field.debris_genre == DG_SHIP) {
+ for (idx=0; idx<3; idx++) {
+ if (Asteroid_field.field_debris_type[idx] != -1) {
+ num_debris_types++;
+ }
+ }
+
+ // Calculate the odds table
+ for (idx=0; idx<num_debris_types; idx++) {
+ int debris_weight = get_debris_weight(Asteroid_field.field_debris_type[idx]);
+ ship_debris_odds_table[idx][0] = max_weighted_range + debris_weight;
+ ship_debris_odds_table[idx][1] = Asteroid_field.field_debris_type[idx];
+ max_weighted_range += debris_weight;
+ }
+ }
+
+ // Load Asteroid/ship models
+ if (Asteroid_field.debris_genre == DG_SHIP) {
+ for (idx=0; idx<num_debris_types; idx++) {
+ asteroid_load(Asteroid_field.field_debris_type[idx], 0);
+ }
+ } else {
+ if (Asteroid_field.field_debris_type[0] != -1) {
+ asteroid_load(ASTEROID_TYPE_SMALL, 0);
+ asteroid_load(ASTEROID_TYPE_MEDIUM, 0);
+ asteroid_load(ASTEROID_TYPE_BIG, 0);
+ }
+
+ if (Asteroid_field.field_debris_type[1] != -1) {
+ asteroid_load(ASTEROID_TYPE_SMALL, 1);
+ asteroid_load(ASTEROID_TYPE_MEDIUM, 1);
+ asteroid_load(ASTEROID_TYPE_BIG, 1);
+ }
+
+ if (Asteroid_field.field_debris_type[2] != -1) {
+ asteroid_load(ASTEROID_TYPE_SMALL, 2);
+ asteroid_load(ASTEROID_TYPE_MEDIUM, 2);
+ asteroid_load(ASTEROID_TYPE_BIG, 2);
+ }
+ }
+
+ // load all the asteroid/debris pieces
+ for (i=0; i<max_asteroids; i++) {
+ if (Asteroid_field.debris_genre == DG_ASTEROID) {
+ // For asteroid, load only large asteroids
+
+ // get a valid subtype
+ int subtype = rand() % 3;
+ while (Asteroid_field.field_debris_type[subtype] == -1) {
+ subtype = (subtype + 1) % 3;
+ }
+
+ asteroid_create(&Asteroid_field, ASTEROID_TYPE_BIG, subtype);
+ } else {
+ Assert(num_debris_types > 0);
+
+ int rand_choice = rand() % max_weighted_range;
+
+ for (idx=0; idx<3; idx++) {
+ // for ship debris, choose type according to odds table
+ if (rand_choice < ship_debris_odds_table[idx][0]) {
+ asteroid_create(&Asteroid_field, ship_debris_odds_table[idx][1], 0);
+ break;
+ }
+ }
+ }
+ }
+}
+
+// Init asteriod system for the level, called from game_level_init()
+void asteroid_level_init()
+{
+ Asteroid_field.num_initial_asteroids=0;
+ Num_asteroids = 0;
+ Next_asteroid_throw = timestamp(1);
+ asteroid_obj_list_init();
+}
+
+// return !0 if asteroid should be wrapped, 0 otherwise. Multiplayer clients will always return
+// 0 from this function. We will force a wrap on the clients when server tells us
+int asteroid_should_wrap(object *objp, asteroid_field *asfieldp)
+{
+ if ( MULTIPLAYER_CLIENT )
+ return 0;
+
+ if (objp->pos.x < asfieldp->min_bound.x) {
+ return 1;
+ }
+
+ if (objp->pos.y < asfieldp->min_bound.y) {
+ return 1;
+ }
+
+ if (objp->pos.z < asfieldp->min_bound.z) {
+ return 1;
+ }
+
+ if (objp->pos.x > asfieldp->max_bound.x) {
+ return 1;
+ }
+
+ if (objp->pos.y > asfieldp->max_bound.y) {
+ return 1;
+ }
+
+ if (objp->pos.z > asfieldp->max_bound.z) {
+ return 1;
+ }
+
+ // check against inner bound
+ if (asfieldp->has_inner_bound) {
+ if ( (objp->pos.x > asfieldp->inner_min_bound.x) && (objp->pos.x < asfieldp->inner_max_bound.x)
+ && (objp->pos.y > asfieldp->inner_min_bound.y) && (objp->pos.y < asfieldp->inner_max_bound.y)
+ && (objp->pos.z > asfieldp->inner_min_bound.z) && (objp->pos.z < asfieldp->inner_max_bound.z) ) {
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+// Wrap an asteroid from one end of the asteroid field to the other
+void asteroid_wrap_pos(object *objp, asteroid_field *asfieldp)
+{
+ if (objp->pos.x < asfieldp->min_bound.x) {
+ objp->pos.x = asfieldp->max_bound.x + (objp->pos.x - asfieldp->min_bound.x);
+ }
+
+ if (objp->pos.y < asfieldp->min_bound.y) {
+ objp->pos.y = asfieldp->max_bound.y + (objp->pos.y - asfieldp->min_bound.y);
+ }
+
+ if (objp->pos.z < asfieldp->min_bound.z) {
+ objp->pos.z = asfieldp->max_bound.z + (objp->pos.z - asfieldp->min_bound.z);
+ }
+
+ if (objp->pos.x > asfieldp->max_bound.x) {
+ objp->pos.x = asfieldp->min_bound.x + (objp->pos.x - asfieldp->max_bound.x);
+ }
+
+ if (objp->pos.y > asfieldp->max_bound.y) {
+ objp->pos.y = asfieldp->min_bound.y + (objp->pos.y - asfieldp->max_bound.y);
+ }
+
+ if (objp->pos.z > asfieldp->max_bound.z) {
+ objp->pos.z = asfieldp->min_bound.z + (objp->pos.z - asfieldp->max_bound.z);
+ }
+
+ // wrap on inner bound, check all 3 axes as needed, use of rand ok for multiplayer with send_asteroid_throw()
+ inner_bound_pos_fixup(asfieldp, &objp->pos);
+
+}
+
+
+// return !0 if this asteroid is a target for any ship, otherwise return 0
+int asteroid_is_targeted(object *objp)
+{
+ ship_obj *so;
+ object *ship_objp;
+ int asteroid_obj_index;
+
+ asteroid_obj_index=OBJ_INDEX(objp);
+
+ for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
+ ship_objp = &Objects[so->objnum];
+ if ( Ai_info[Ships[ship_objp->instance].ai_index].target_objnum == asteroid_obj_index ) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+// Create an asteroid that will hit object *objp in delta_time seconds
+void asteroid_aim_at_target(object *objp, object *asteroid_objp, float delta_time)
+{
+ vector predicted_center_pos;
+ vector rand_vec;
+ float speed;
+
+ vm_vec_scale_add(&predicted_center_pos, &objp->pos, &objp->phys_info.vel, delta_time);
+ vm_vec_rand_vec_quick(&rand_vec);
+ vm_vec_scale_add2(&predicted_center_pos, &rand_vec, objp->radius/2.0f);
+
+ vm_vec_add2(&rand_vec, &objp->orient.fvec);
+ if (vm_vec_mag_quick(&rand_vec) < 0.1f)
+ vm_vec_add2(&rand_vec, &objp->orient.rvec);
+ vm_vec_normalize(&rand_vec);
+
+ speed = Asteroid_info[0].max_speed * (frand()/2.0f + 0.5f);
+
+ vm_vec_copy_scale(&asteroid_objp->phys_info.vel, &rand_vec, -speed);
+ asteroid_objp->phys_info.desired_vel = asteroid_objp->phys_info.vel;
+ vm_vec_scale_add(&asteroid_objp->pos, &predicted_center_pos, &asteroid_objp->phys_info.vel, -delta_time);
+ vm_vec_scale_add(&asteroid_objp->last_pos, &asteroid_objp->pos, &asteroid_objp->phys_info.vel, -flFrametime);
+}
+
+int Max_incoming_asteroids[NUM_SKILL_LEVELS] = {3, 4, 5, 7, 10};
+
+// Call once per frame to maybe throw an asteroid at a ship.
+// "count" asteroids already targeted on
+void maybe_throw_asteroid(int count)
+{
+ if (!timestamp_elapsed(Next_asteroid_throw)) {
+ return;
+ }
+
+ if (Asteroid_throw_objnum == -1) {
+ return;
+ }
+
+ nprintf(("AI", "Incoming asteroids: %i\n", count));
+
+ if (count > Max_incoming_asteroids[Game_skill_level])
+ return;
+
+ Next_asteroid_throw = timestamp(1000 + 1200 * count/(Game_skill_level+1));
+
+ ship_obj *so;
+ for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
+ object *A = &Objects[so->objnum];
+ if (so->objnum == Asteroid_throw_objnum) {
+ int subtype = rand() % 3;
+ while (Asteroid_field.field_debris_type[subtype] == -1) {
+ subtype = (subtype + 1) % 3;
+ }
+ object *objp = asteroid_create(&Asteroid_field, ASTEROID_TYPE_BIG, subtype);
+ if (objp != NULL) {
+ asteroid_aim_at_target(A, objp, ASTEROID_MIN_COLLIDE_TIME + frand() * 20.0f);
+
+ // if asteroid is inside inner bound, kill it
+ if (asteroid_in_inner_bound(&Asteroid_field, &objp->pos, 0.0f)) {
+ objp->flags |= OF_SHOULD_BE_DEAD;
+ } else {
+ Asteroids[objp->instance].target_objnum = so->objnum;
+ // DA: 4/22/98 We get next line for free when new object (in obj_create_list) is merged.
+ // this line gives too many collision pairs.
+ // asteroid_update_collide(objp);
+
+ if ( MULTIPLAYER_MASTER ) {
+ send_asteroid_throw( objp );
+ }
+ }
+ }
+
+ return;
+ }
+ }
+
+}
+
+void asteroid_delete( object * obj )
+{
+ int num;
+ asteroid *asp;
+
+ num = obj->instance;
+ Assert( Asteroids[num].objnum == OBJ_INDEX(obj));
+
+ asp = &Asteroids[num];
+
+ Assert( Num_asteroids >= 0 );
+
+ asp->flags = 0;
+ Num_asteroids--;
+
+ // Delete asteroid from Asteroid_used_list
+ asteroid_obj_list_remove( obj );
+}
+
+// See if we should reposition the asteroid. Only reposition if oustide the bounding volume and
+// the player isn't looking towards the asteroid.
+void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
+{
+ // passive field does not wrap
+ if (asfieldp->field_type == FT_PASSIVE) {
+ return;
+ }
+
+ if ( asteroid_should_wrap(objp, asfieldp) ) {
+ vector vec_to_asteroid, old_asteroid_pos, old_vel;
+ float dot, dist;
+
+ old_asteroid_pos = objp->pos;
+ old_vel = objp->phys_info.vel;
+
+ //nprintf(("AI", "Frame %i, reposition #%i\n", Framecount, objp-Objects));
+
+ // don't wrap asteroid if it is a target of some ship
+ if ( !asteroid_is_targeted(objp) ) {
+
+ // only wrap if player won't see asteroid disappear/reverse direction
+ dist = vm_vec_normalized_dir(&vec_to_asteroid, &objp->pos, &Eye_position);
+ dot = vm_vec_dot(&Eye_matrix.fvec, &vec_to_asteroid);
+
+ if ((dot < 0.7f) || (dist > 3000.0f)) {
+ if (Num_asteroids > MAX_ASTEROIDS-10) {
+ objp->flags |= OF_SHOULD_BE_DEAD;
+ } else {
+ // check to ensure player won't see asteroid appear either
+ asteroid_wrap_pos(objp, asfieldp);
+ Asteroids[objp->instance].target_objnum = -1;
+
+ vm_vec_normalized_dir(&vec_to_asteroid, &objp->pos, &Eye_position);
+ dot = vm_vec_dot(&Eye_matrix.fvec, &vec_to_asteroid);
+ dist = vm_vec_dist_quick(&objp->pos, &Eye_position);
+
+ if (( dot > 0.7f) && (dist < 3000.0f)) {
+ // player would see asteroid pop out other side, so reverse velocity instead of wrapping
+ objp->pos = old_asteroid_pos;
+ vm_vec_copy_scale(&objp->phys_info.vel, &old_vel, -1.0f);
+ objp->phys_info.desired_vel = objp->phys_info.vel;
+ Asteroids[objp->instance].target_objnum = -1;
+ }
+
+ // update last pos (after vel is known)
+ vm_vec_scale_add(&objp->last_pos, &objp->pos, &objp->phys_info.vel, -flFrametime);
+
+ asteroid_update_collide(objp);
+
+ if ( MULTIPLAYER_MASTER )
+ send_asteroid_throw( objp );
+ }
+ }
+ }
+ }
+}
+
+void lerp(float *goal, float f1, float f2, float scale)
+{
+ *goal = (f2 - f1) * scale + f1;
+}
+
+void asteroid_process_pre( object *objp, float frame_time)
+{
+ if (Asteroids_enabled) {
+ vector *v, *vv;
+
+ v = &objp->phys_info.vel;
+ vv = &objp->phys_info.desired_vel;
+
+ //nprintf(("AI", "Frm %i: Obj #%2i: Hull: %5.1f Vel: %5.1f %5.1f %5.1f Des: %5.1f %5.1f %5.1f\n", Framecount, objp-Objects, objp->hull_strength, v->x, v->y, v->z, vv->x, vv->y, vv->z));
+
+ // Make vel chase desired_vel
+ lerp(&objp->phys_info.vel.x, objp->phys_info.vel.x, objp->phys_info.desired_vel.x, flFrametime);
+ lerp(&objp->phys_info.vel.y, objp->phys_info.vel.y, objp->phys_info.desired_vel.y, flFrametime);
+ lerp(&objp->phys_info.vel.z, objp->phys_info.vel.z, objp->phys_info.desired_vel.z, flFrametime);
+ }
+}
+
+#pragma warning ( push )
+#pragma warning ( disable : 4701 )
+int asteroid_check_collision(object *pasteroid, object *other_obj, vector *hitpos, collision_info_struct *asteroid_hit_info)
+{
+ if (!Asteroids_enabled) {
+ return 0;
+ }
+
+ mc_info mc;
+ int num, asteroid_subtype;
+
+ Assert( pasteroid->type == OBJ_ASTEROID );
+
+ num = pasteroid->instance;
+ Assert( num >= 0 );
+
+ Assert( Asteroids[num].objnum == OBJ_INDEX(pasteroid));
+ asteroid_subtype = Asteroids[num].asteroid_subtype;
+
+ // asteroid_hit_info NULL -- asteroid-weapon collision
+ if ( asteroid_hit_info == NULL ) {
+ // asteroid weapon collision
+ Assert( other_obj->type == OBJ_WEAPON );
+ mc.model_num = Asteroid_info[Asteroids[num].type].model_num[asteroid_subtype]; // Fill in the model to check
+ model_clear_instance( mc.model_num );
+ mc.orient = &pasteroid->orient; // The object's orient
+ mc.pos = &pasteroid->pos; // The object's position
+ mc.p0 = &other_obj->last_pos; // Point 1 of ray to check
+ mc.p1 = &other_obj->pos; // Point 2 of ray to check
+ mc.flags = (MC_CHECK_MODEL);
+
+ if (model_collide(&mc))
+ *hitpos = mc.hit_point_world;
+
+ return mc.num_hits;
+ }
+
+ // asteroid ship collision -- use asteroid_hit_info to calculate physics
+ object *ship_obj = other_obj;
+ Assert( ship_obj->type == OBJ_SHIP );
+
+ object* heavy = asteroid_hit_info->heavy;
+ object* light = asteroid_hit_info->light;
+ object *heavy_obj = heavy;
+ object *light_obj = light;
+
+ vector zero, p0, p1;
+ vm_vec_zero( &zero );
+ vm_vec_sub( &p0, &light->last_pos, &heavy->last_pos );
+ vm_vec_sub( &p1, &light->pos, &heavy->pos );
+
+ mc.pos = &zero; // The object's position
+ mc.p0 = &p0; // Point 1 of ray to check
+ mc.p1 = &p1; // Point 2 of ray to check
+
+ // find the light object's position in the heavy object's reference frame at last frame and also in this frame.
+ vector p0_temp, p0_rotated;
+
+ // Collision detection from rotation enabled if at rotaion is less than 30 degree in frame
+ // This should account for all ships
+ if ( (vm_vec_mag_squared( &heavy->phys_info.rotvel ) * flFrametime*flFrametime) < (PI*PI/36) ) {
+ // collide_rotate calculate (1) start position and (2) relative velocity
+ asteroid_hit_info->collide_rotate = 1;
+ vm_vec_rotate( &p0_temp, &p0, &heavy->last_orient );
+ vm_vec_unrotate( &p0_rotated, &p0_temp, &heavy->orient );
+ mc.p0 = &p0_rotated; // Point 1 of ray to check
+ vm_vec_sub( &asteroid_hit_info->light_rel_vel, &p1, &p0_rotated );
+ vm_vec_scale( &asteroid_hit_info->light_rel_vel, 1/flFrametime );
+ // HACK - this applies to big ships warping in/out of asteroid fields - not sure what it does
+ if (vm_vec_mag(&asteroid_hit_info->light_rel_vel) > 300) {
+ // nprintf(("Physics", "Asteroid type %d\n", Asteroids[asteroid_hit_info->light->instance].type));
+ asteroid_hit_info->collide_rotate = 0;
+ vm_vec_sub( &asteroid_hit_info->light_rel_vel, &light->phys_info.vel, &heavy->phys_info.vel );
+ }
+ } else {
+ asteroid_hit_info->collide_rotate = 0;
+ vm_vec_sub( &asteroid_hit_info->light_rel_vel, &light->phys_info.vel, &heavy->phys_info.vel );
+ }
+
+ int mc_ret_val = 0;
+
+ if ( asteroid_hit_info->heavy == ship_obj ) { // ship is heavier, so asteroid is sphere. Check sphere collision against ship poly model
+ mc.model_num = Ships[ship_obj->instance].modelnum; // Fill in the model to check
+ mc.orient = &ship_obj->orient; // The object's orient
+ mc.radius = pasteroid->radius;
+ mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
+
+ // copy important data
+ int copy_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
+ vector copy_p0, copy_p1;
+ copy_p0 = *mc.p0;
+ copy_p1 = *mc.p1;
+
+ // first test against the sphere - if this fails then don't do any submodel tests
+ mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
+
+ int submodel_list[MAX_ROTATING_SUBMODELS];
+ int num_rotating_submodels = 0;
+ polymodel *pm;
+
+ ship_model_start(ship_obj);
+
+ if (model_collide(&mc)) {
+
+ // Set earliest hit time
+ asteroid_hit_info->hit_time = FLT_MAX;
+
+ // Do collision the cool new way
+ if ( asteroid_hit_info->collide_rotate ) {
+ // We collide with the sphere, find the list of rotating submodels and test one at a time
+ model_get_rotating_submodel_list(submodel_list, &num_rotating_submodels, heavy_obj);
+
+ // Get polymodel and turn off all rotating submodels, collide against only 1 at a time.
+ pm = model_get(Ships[heavy_obj->instance].modelnum);
+
+ // turn off all rotating submodels and test for collision
+ for (int i=0; i<num_rotating_submodels; i++) {
+ pm->submodel[submodel_list[i]].blown_off = 1;
+ }
+
+ // reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
+ mc.flags = copy_flags | MC_SUBMODEL_INSTANCE;
+
+
+ // check each submodel in turn
+ for (i=0; i<num_rotating_submodels; i++) {
+ // turn on submodel for collision test
+ pm->submodel[submodel_list[i]].blown_off = 0;
+
+ // set angles for last frame (need to set to prev to get p0)
+ angles copy_angles = pm->submodel[submodel_list[i]].angs;
+
+ // find the start and end positions of the sphere in submodel RF
+ pm->submodel[submodel_list[i]].angs = pm->submodel[submodel_list[i]].sii->prev_angs;
+ world_find_model_point(&p0, &light_obj->last_pos, pm, submodel_list[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
+
+ pm->submodel[submodel_list[i]].angs = copy_angles;
+ world_find_model_point(&p1, &light_obj->pos, pm, submodel_list[i], &heavy_obj->orient, &heavy_obj->pos);
+
+ mc.p0 = &p0;
+ mc.p1 = &p1;
+ // mc.pos = zero // in submodel RF
+
+ mc.orient = &vmd_identity_matrix;
+ mc.submodel_num = submodel_list[i];
+
+ if ( model_collide(&mc) ) {
+ if ( mc.hit_dist < asteroid_hit_info->hit_time ) {
+ mc_ret_val = 1;
+
+ // set up asteroid_hit_info common
+ set_hit_struct_info(asteroid_hit_info, &mc, SUBMODEL_ROT_HIT);
+
+ // set up asteroid_hit_info for rotating submodel
+ if (asteroid_hit_info->edge_hit == 0) {
+ model_find_obj_dir(&asteroid_hit_info->collision_normal, &mc.hit_normal, heavy_obj, mc.hit_submodel);
+ }
+
+ // find position in submodel RF of light object at collison
+ vector int_light_pos, diff;
+ vm_vec_sub(&diff, mc.p1, mc.p0);
+ vm_vec_scale_add(&int_light_pos, mc.p0, &diff, mc.hit_dist);
+ model_find_world_point(&asteroid_hit_info->light_collision_cm_pos, &int_light_pos, mc.model_num, mc.hit_submodel, &heavy_obj->orient, &zero);
+ }
+ }
+ // Don't look at this submodel again
+ pm->submodel[submodel_list[i]].blown_off = 1;
+ }
+
+ }
+
+ // Recover and do usual ship_ship collision, but without rotating submodels
+ mc.flags = copy_flags;
+ *mc.p0 = copy_p0;
+ *mc.p1 = copy_p1;
+ mc.orient = &heavy_obj->orient;
+
+ // usual ship_ship collision test
+ if ( model_collide(&mc) ) {
+ // check if this is the earliest hit
+ if (mc.hit_dist < asteroid_hit_info->hit_time) {
+ mc_ret_val = 1;
+
+ set_hit_struct_info(asteroid_hit_info, &mc, SUBMODEL_NO_ROT_HIT);
+
+ // get collision normal if not edge hit
+ if (asteroid_hit_info->edge_hit == 0) {
+ model_find_obj_dir(&asteroid_hit_info->collision_normal, &mc.hit_normal, heavy_obj, mc.hit_submodel);
+ }
+
+ // find position in submodel RF of light object at collison
+ vector diff;
+ vm_vec_sub(&diff, mc.p1, mc.p0);
+ vm_vec_scale_add(&asteroid_hit_info->light_collision_cm_pos, mc.p0, &diff, mc.hit_dist);
+
+ }
+ }
+
+ ship_model_stop( ship_obj );
+ }
+
+ } else {
+ // Asteroid is heavier obj
+ mc.model_num = Asteroid_info[Asteroids[num].type].model_num[asteroid_subtype]; // Fill in the model to check
+ model_clear_instance( mc.model_num );
+ mc.orient = &pasteroid->orient; // The object's orient
+ mc.radius = model_get_core_radius( Ships[ship_obj->instance].modelnum );
+
+ // check for collision between asteroid model and ship sphere
+ mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
+
+ mc_ret_val = model_collide(&mc);
+
+ if (mc_ret_val) {
+ set_hit_struct_info(asteroid_hit_info, &mc, SUBMODEL_NO_ROT_HIT);
+
+ // set normal if not edge hit
+ if ( !asteroid_hit_info->edge_hit ) {
+ vm_vec_unrotate(&asteroid_hit_info->collision_normal, &mc.hit_normal, &heavy->orient);
+ }
+
+ // find position in submodel RF of light object at collison
+ vector diff;
+ vm_vec_sub(&diff, mc.p1, mc.p0);
+ vm_vec_scale_add(&asteroid_hit_info->light_collision_cm_pos, mc.p0, &diff, mc.hit_dist);
+
+ }
+ }
+
+
+ if ( mc_ret_val ) {
+
+ // SET PHYSICS PARAMETERS
+ // already have (hitpos - heavy) and light_cm_pos
+ // get heavy cm pos - already have light_cm_pos
+ asteroid_hit_info->heavy_collision_cm_pos = zero;
+
+ // get r_heavy and r_light
+ asteroid_hit_info->r_heavy = asteroid_hit_info->hit_pos;
+ vm_vec_sub(&asteroid_hit_info->r_light, &asteroid_hit_info->hit_pos, &asteroid_hit_info->light_collision_cm_pos);
+
+ // set normal for edge hit
+ if ( asteroid_hit_info->edge_hit ) {
+ vm_vec_copy_normalize(&asteroid_hit_info->collision_normal, &asteroid_hit_info->r_light);
+ vm_vec_negate(&asteroid_hit_info->collision_normal);
+ }
+
+ // get world hitpos
+ vm_vec_add(hitpos, &asteroid_hit_info->heavy->pos, &asteroid_hit_info->r_heavy);
+
+ return 1;
+ } else {
+ // no hit
+ return 0;
+ }
+}
+#pragma warning ( pop )
+
+
+void asteroid_render(object * obj)
+{
+ if (Asteroids_enabled) {
+ int num;
+ polymodel *pm;
+ asteroid *asp;
+
+ pm = NULL;
+ num = obj->instance;
+
+ Assert((num >= 0) && (num < MAX_ASTEROIDS));
+ asp = &Asteroids[num];
+
+ Assert( asp->flags & AF_USED );
+
+ model_clear_instance( Asteroid_info[asp->type].model_num[asp->asteroid_subtype]);
+ model_render(Asteroid_info[asp->type].model_num[asp->asteroid_subtype], &obj->orient, &obj->pos, MR_NORMAL|MR_IS_ASTEROID, OBJ_INDEX(obj) ); // Replace MR_NORMAL with 0x07 for big yellow blobs
+ }
+}
+
+// Create a normalized vector generally in the direction from *hitpos to other_obj->pos
+void asc_get_relvec(vector *relvec, object *other_obj, vector *hitpos)
+{
+ vector tvec, rand_vec;
+ int count = 0;
+
+ vm_vec_normalized_dir(&tvec, &other_obj->pos, hitpos);
+
+ // Try up to three times to get a good vector.
+ while (count++ < 3) {
+ vm_vec_rand_vec_quick(&rand_vec);
+ vm_vec_add(relvec, &tvec, &rand_vec);
+ float mag = vm_vec_mag_quick(relvec);
+ if ((mag > 0.2f) && (mag < 1.7f))
+ break;
+ }
+
+ vm_vec_normalize_quick(relvec);
+}
+
+// return multiplier on asteroid radius for fireball
+float asteroid_get_fireball_scale_multiplier(int num)
+{
+ if (Asteroids[num].flags & AF_USED) {
+
+ switch(Asteroids[num].type) {
+ case ASTEROID_TYPE_BIG:
+ return 1.5f;
+ break;
+
+ default:
+ return 1.0f;
+ break;
+ }
+ }
+
+ Int3(); // this should not happen. asteroid should be used.
+ return 1.0f;
+}
+
+
+// create asteroid explosion
+// exit: expected time for explosion anim to last, in seconds
+float asteroid_create_explosion(object *objp)
+{
+ int fireball_objnum;
+ float explosion_life, fireball_scale_multiplier;
+
+ fireball_scale_multiplier = asteroid_get_fireball_scale_multiplier(objp->instance);
+
+ fireball_objnum = fireball_create( &objp->pos, FIREBALL_ASTEROID, OBJ_INDEX(objp), objp->radius*fireball_scale_multiplier, 0, &objp->phys_info.vel );
+ if ( fireball_objnum > -1 ) {
+ explosion_life = fireball_lifeleft(&Objects[fireball_objnum]);
+ } else {
+ explosion_life = 0.0f;
+ }
+
+ return explosion_life;
+}
+
+// play sound when asteroid explodes
+void asteriod_explode_sound(object *objp, int type, int play_loud)
+{
+ int sound_index = -1;
+ float range_factor = 1.0f; // how many times sound should traver farther than normal
+
+ switch (type) {
+ case ASTEROID_TYPE_SMALL:
+ case ASTEROID_TYPE_MEDIUM:
+ case DEBRIS_TERRAN_SMALL:
+ case DEBRIS_TERRAN_MEDIUM:
+ case DEBRIS_VASUDAN_SMALL:
+ case DEBRIS_VASUDAN_MEDIUM:
+ case DEBRIS_SHIVAN_SMALL:
+ case DEBRIS_SHIVAN_MEDIUM:
+ sound_index = SND_ASTEROID_EXPLODE_SMALL;
+ range_factor = 5.0f;
+ break;
+
+ case ASTEROID_TYPE_BIG:
+ case DEBRIS_TERRAN_LARGE:
+ case DEBRIS_VASUDAN_LARGE:
+ case DEBRIS_SHIVAN_LARGE:
+ sound_index = SND_ASTEROID_EXPLODE_BIG;
+ range_factor = 10.0f;
+ break;
+
+ default:
+ Int3();
+ return;
+ }
+
+ Assert(sound_index != -1);
+
+ if ( !play_loud ) {
+ range_factor = 1.0f;
+ }
+
+ snd_play_3d( &Snds[sound_index], &objp->pos, &Eye_position, objp->radius, NULL, 0, 1.0f, SND_PRIORITY_MUST_PLAY, NULL, range_factor );
+}
+
+// asteroid_do_area_effect()
+//
+// Do the area effect for an asteroid exploding
+//
+// input: asteroid_objp => object pointer to asteriod causing explosion
+void asteroid_do_area_effect(object *asteroid_objp)
+{
+ object *ship_objp;
+ float damage, blast;
+ ship_obj *so;
+ asteroid *asp;
+ asteroid_info *asip;
+
+ asp = &Asteroids[asteroid_objp->instance];
+ asip = &Asteroid_info[asp->type];
+
+ if ( asip->damage <= 0 ) { // do a quick out if there is no damage to apply
+ return;
+ }
+
+ for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
+ ship_objp = &Objects[so->objnum];
+
+ // don't blast navbuoys
+ if ( ship_get_SIF(ship_objp->instance) & SIF_NAVBUOY ) {
+ continue;
+ }
+
+ if ( weapon_area_calc_damage(ship_objp, &asteroid_objp->pos, asip->inner_rad, asip->outer_rad, asip->blast, asip->damage, &blast, &damage, asip->outer_rad) == -1 )
+ continue;
+
+ ship_apply_global_damage(ship_objp, asteroid_objp, &asteroid_objp->pos, damage );
+ weapon_area_apply_blast(NULL, ship_objp, &asteroid_objp->pos, blast, 0);
+ } // end for
+}
+
+// Asteroid asteroid_obj was hit.
+// Apply damage. Maybe make it break into smaller asteroids.
+// input: asteroid_obj => pointer to asteroid object getting hit
+// other_obj => object that hit asteroid, can be NULL if asteroid hit by area effect
+// hitpos => world position asteroid was hit, can be NULL if hit by area effect
+// damage => amount of damage to apply to asteroid
+void asteroid_hit( object * asteroid_obj, object * other_obj, vector * hitpos, float damage )
+{
+ float explosion_life;
+ asteroid *asp;
+
+ asp = &Asteroids[asteroid_obj->instance];
+
+ if (asteroid_obj->flags & OF_SHOULD_BE_DEAD){
+ return;
+ }
+
+ if ( MULTIPLAYER_MASTER ){
+ send_asteroid_hit( asteroid_obj, other_obj, hitpos, damage );
+ }
+
+ asteroid_obj->hull_strength -= damage;
+
+ //nprintf(("AI", "Asteroid collided with %s, hull = %.2f\n", Object_type_names[other_obj->type], asteroid_obj->hull_strength));
+
+ if (asteroid_obj->hull_strength < 0.0f) {
+ if ( asp->final_death_time <= 0 ) {
+ int play_loud_collision = 0;
+
+ explosion_life = asteroid_create_explosion(asteroid_obj);
+ if ( asp->collide_objnum == OBJ_INDEX(other_obj) ) {
+// play_loud_collision = 1;
+ }
+ asteriod_explode_sound(asteroid_obj, asp->type, play_loud_collision);
+ asteroid_do_area_effect(asteroid_obj);
+
+ asp->final_death_time = timestamp( fl2i(explosion_life*1000.0f)/5 ); // Wait till 30% of vclip time before breaking the asteroid up.
+ if ( hitpos ) {
+ asp->death_hit_pos = *hitpos;
+ } else {
+ asp->death_hit_pos = asteroid_obj->pos;
+ // randomize hit pos a bit, otherwise we will get a NULL vector when trying to find direction to toss child asteroids
+ vector rand_vec;
+ vm_vec_rand_vec_quick(&rand_vec);
+ vm_vec_add2(&asp->death_hit_pos, &rand_vec);
+ }
+ }
+ } else if ( other_obj ) {
+ if ( other_obj->type == OBJ_WEAPON ) {
+ weapon_info *wip;
+ wip = &Weapon_info[Weapons[other_obj->instance].weapon_info_index];
+ // If the weapon didn't play any impact animation, play custom asteroid impact animation
+ if ( wip->impact_weapon_expl_index < 0 ) {
+ particle_create( hitpos, &vmd_zero_vector, 0.0f, Asteroid_impact_explosion_radius, PARTICLE_BITMAP, Asteroid_impact_explosion_ani );
+ }
+ }
+ }
+
+ // evaluate any relevant player scoring implications
+ scoring_eval_hit(asteroid_obj,other_obj);
+}
+
+// De-init asteroids, called from game_level_close()
+void asteroid_level_close()
+{
+ int i;
+
+ for (i=0; i<MAX_ASTEROIDS; i++) {
+ if (Asteroids[i].flags & AF_USED) {
+ Asteroids[i].flags &= ~AF_USED;
+ Assert(Asteroids[i].objnum >=0 && Asteroids[i].objnum < MAX_OBJECTS);
+ Objects[Asteroids[i].objnum].flags |= OF_SHOULD_BE_DEAD;
+ }
+ }
+
+ Asteroid_field.num_initial_asteroids=0;
+}
+
+DCF(asteroids,"Turns asteroids on/off")
+{
+ if ( Dc_command ) {
+ dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
+ if ( Dc_arg_type & ARG_TRUE )
+ Asteroids_enabled = 1;
+ else if ( Dc_arg_type & ARG_FALSE )
+ Asteroids_enabled = 0;
+ else if ( Dc_arg_type & ARG_NONE )
+ Asteroids_enabled ^= 1;
+ }
+ if ( Dc_help )
+ dc_printf( "Usage: asteroids [bool]\nTurns asteroid system on/off. If nothing passed, then toggles it.\n" );
+
+ if ( Dc_status )
+ dc_printf( "asteroids are %s\n", (Asteroids_enabled?"ON":"OFF") );
+
+/*
+ if ((old_asteroids_enabled == 0) && (Asteroids_enabled == 1)) {
+ asteroid_init();
+ } else if ((old_asteroids_enabled == 1) && (Asteroids_enabled == 0)) {
+ asteroid_uninit();
+ }
+*/
+}
+
+void hud_target_asteroid()
+{
+ int i;
+ int start_index = 0, end_index = MAX_ASTEROIDS;
+
+ if (Player_ai->target_objnum != -1) {
+ if (Objects[Player_ai->target_objnum].type == OBJ_ASTEROID) {
+ start_index = Objects[Player_ai->target_objnum].instance+1;
+ end_index = start_index-1;
+ if (end_index < 0)
+ end_index = MAX_ASTEROIDS;
+ }
+ }
+
+ i = start_index;
+ while (i != end_index) {
+ if (i == MAX_ASTEROIDS)
+ i = 0;
+
+ if (Asteroids[i].flags & AF_USED) {
+ Assert(Objects[Asteroids[i].objnum].type == OBJ_ASTEROID);
+ set_target_objnum( Player_ai, Asteroids[i].objnum);
+ break;
+ }
+
+ i++;
+ }
+}
+
+// Return the number of active asteroids
+int asteroid_count()
+{
+ return Num_asteroids;
+}
+
+// See if asteroid should split up. We delay splitting up to allow the explosion animation
+// to play for a bit.
+void asteroid_maybe_break_up(object *asteroid_obj)
+{
+ asteroid *asp;
+
+ asp = &Asteroids[asteroid_obj->instance];
+
+ if ( timestamp_elapsed(asp->final_death_time) ) {
+ vector relvec, vfh, tvec;
+
+ asteroid_obj->flags |= OF_SHOULD_BE_DEAD;
+
+ // multiplayer clients won't go through the following code. asteroid_sub_create will send
+ // a create packet to the client in the above named function
+ if ( !MULTIPLAYER_CLIENT ) {
+
+ switch (asp->type) {
+ case ASTEROID_TYPE_SMALL:
+ break;
+ case ASTEROID_TYPE_MEDIUM:
+ asc_get_relvec(&relvec, asteroid_obj, &asp->death_hit_pos);
+ asteroid_sub_create(asteroid_obj, ASTEROID_TYPE_SMALL, &relvec);
+
+ vm_vec_normalized_dir(&vfh, &asteroid_obj->pos, &asp->death_hit_pos);
+ vm_vec_copy_scale(&tvec, &vfh, 2.0f);
+ vm_vec_sub2(&tvec, &relvec);
+ asteroid_sub_create(asteroid_obj, ASTEROID_TYPE_SMALL, &tvec);
+
+ break;
+ case ASTEROID_TYPE_BIG:
+ asc_get_relvec(&relvec, asteroid_obj, &asp->death_hit_pos);
+ asteroid_sub_create(asteroid_obj, ASTEROID_TYPE_MEDIUM, &relvec);
+
+ vm_vec_normalized_dir(&vfh, &asteroid_obj->pos, &asp->death_hit_pos);
+ vm_vec_copy_scale(&tvec, &vfh, 2.0f);
+ vm_vec_sub2(&tvec, &relvec);
+ asteroid_sub_create(asteroid_obj, ASTEROID_TYPE_MEDIUM, &tvec);
+
+ while (frand() > 0.6f) {
+ vector rvec, tvec2;
+ vm_vec_rand_vec_quick(&rvec);
+ vm_vec_scale_add(&tvec2, &vfh, &rvec, 0.75f);
+ asteroid_sub_create(asteroid_obj, ASTEROID_TYPE_SMALL, &tvec2);
+ }
+
+ break;
+
+ // ship debris does not break up
+ case DEBRIS_TERRAN_SMALL:
+ case DEBRIS_TERRAN_MEDIUM:
+ case DEBRIS_TERRAN_LARGE:
+ case DEBRIS_VASUDAN_SMALL:
+ case DEBRIS_VASUDAN_MEDIUM:
+ case DEBRIS_VASUDAN_LARGE:
+ case DEBRIS_SHIVAN_SMALL:
+ case DEBRIS_SHIVAN_MEDIUM:
+ case DEBRIS_SHIVAN_LARGE:
+ break;
+
+ default:
+ Int3();
+ }
+ }
+
+ asp->final_death_time = timestamp(-1);
+ }
+}
+
+int asteroid_get_random_in_cone(vector *pos, vector *dir, float ang, int danger)
+{
+ int idx;
+ vector asteroid_dir;
+
+ // just pick the first asteroid which satisfies our condition
+ for(idx=0; idx<Num_asteroids; idx++){
+ vm_vec_sub(&asteroid_dir, &Objects[Asteroids[idx].objnum].pos, pos);
+ vm_vec_normalize_quick(&asteroid_dir);
+
+ // if it satisfies the condition
+ if(vm_vec_dot(dir, &asteroid_dir) >= ang){
+ return idx;
+ }
+ }
+
+ return -1;
+}
+
+void asteroid_test_collide(object *asteroid_obj, object *ship_obj, mc_info *mc)
+{
+ float asteroid_ray_dist;
+ vector asteroid_fvec, terminus;
+
+ // See if ray from asteroid intersects bounding box of escort ship
+ asteroid_ray_dist = vm_vec_mag_quick(&asteroid_obj->phys_info.desired_vel) * ASTEROID_MIN_COLLIDE_TIME;
+ asteroid_fvec = asteroid_obj->phys_info.desired_vel;
+
+ if(IS_VEC_NULL(&asteroid_fvec)){
+ terminus = asteroid_obj->pos;
+ } else {
+ vm_vec_normalize(&asteroid_fvec);
+ vm_vec_scale_add(&terminus, &asteroid_obj->pos, &asteroid_fvec, asteroid_ray_dist);
+ }
+
+ Assert(ship_obj->type == OBJ_SHIP);
+
+ ship_model_start(ship_obj);
+
+ mc->model_num = Ships[ship_obj->instance].modelnum; // Fill in the model to check
+ mc->orient = &ship_obj->orient; // The object's orientation
+ mc->pos = &ship_obj->pos; // The object's position
+ mc->p0 = &asteroid_obj->pos; // Point 1 of ray to check
+ mc->p1 = &terminus; // Point 2 of ray to check
+// mc->flags = MC_CHECK_MODEL | MC_ONLY_BOUND_BOX;
+ mc->flags = MC_CHECK_MODEL | MC_CHECK_SPHERELINE;
+ mc->radius = asteroid_obj->radius;
+
+ model_collide(mc);
+
+ ship_model_stop(ship_obj);
+}
+
+// Return !0 is the asteroid will collide with the escort ship within ASTEROID_MIN_COLLIDE_TIME
+// seconds
+int asteroid_will_collide(object *asteroid_obj, object *escort_objp)
+{
+ mc_info mc;
+
+ asteroid_test_collide(asteroid_obj, escort_objp, &mc);
+
+ if ( !mc.num_hits ) {
+ return 0;
+ }
+
+ return 1;
+}
+
+// return !0 if we should warn about asteroid hitting ship, otherwise return 0
+int asteroid_valid_ship_to_warn_collide(ship *shipp)
+{
+ if ( !(Ship_info[shipp->ship_info_index].flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) ) {
+ return 0;
+ }
+
+ if ( shipp->flags & (SF_DYING|SF_DEPART_WARP) ) {
+ return 0;
+ }
+
+ if ( (shipp->team != Player_ship->team) || (Player_ship->team == TEAM_TRAITOR) ) {
+ return 0;
+ }
+
+ return 1;
+}
+
+// See if asteroid will collide with a large ship on the escort list in the next
+// ASTEROID_MIN_COLLIDE_TIME seconds.
+void asteroid_update_collide_flag(object *asteroid_objp)
+{
+ int i, num_escorts, escort_objnum, will_collide=0;
+ ship *escort_shipp;
+ asteroid *asp;
+
+ asp = &Asteroids[asteroid_objp->instance];
+ asp->collide_objnum = -1;
+ asp->collide_objsig = -1;
+
+ // multiplayer dogfight
+ if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
+ return;
+ }
+
+ num_escorts = hud_escort_num_ships_on_list();
+
+ if ( num_escorts <= 0 ) {
+ return;
+ }
+
+ for ( i = 0; i < num_escorts; i++ ) {
+ escort_objnum = hud_escort_return_objnum(i);
+ if ( escort_objnum >= 0 ) {
+ escort_shipp = &Ships[Objects[escort_objnum].instance];
+ if ( asteroid_valid_ship_to_warn_collide(escort_shipp) ) {
+ will_collide = asteroid_will_collide(asteroid_objp, &Objects[escort_objnum]);
+ if ( will_collide ) {
+ asp->collide_objnum = escort_objnum;
+ asp->collide_objsig = Objects[escort_objnum].signature;
+ }
+ }
+ }
+ }
+}
+
+// ensure that the collide objnum for the asteroid is still valid
+void asteroid_verify_collide_objnum(asteroid *asp)
+{
+ if ( asp->collide_objnum >= 0 ) {
+ if ( Objects[asp->collide_objnum].signature != asp->collide_objsig ) {
+ asp->collide_objnum = -1;
+ asp->collide_objsig = -1;
+ }
+ }
+}
+
+void asteroid_process_post(object * obj, float frame_time)
+{
+ if (Asteroids_enabled) {
+ int num;
+ num = obj->instance;
+
+ //Assert( Asteroids[num].objnum == objnum );
+ asteroid *asp = &Asteroids[num];
+
+ // Only wrap if active field
+ if (Asteroid_field.field_type == FT_ACTIVE) {
+ if ( timestamp_elapsed(asp->check_for_wrap) ) {
+ asteroid_maybe_reposition(obj, &Asteroid_field);
+ asp->check_for_wrap = timestamp(ASTEROID_CHECK_WRAP_TIMESTAMP);
+ }
+ }
+
+ asteroid_verify_collide_objnum(asp);
+
+ if ( timestamp_elapsed(asp->check_for_collide) ) {
+ asteroid_update_collide_flag(obj);
+ asp->check_for_collide = timestamp(ASTEROID_UPDATE_COLLIDE_TIMESTAMP);
+ }
+
+ asteroid_maybe_break_up(obj);
+ }
+}
+
+// return the object number that the asteroid is about to impact
+int asteroid_collide_objnum(object *asteroid_objp)
+{
+ return Asteroids[asteroid_objp->instance].collide_objnum;
+}
+
+// return the time until the asteroid will impact its collide_objnum
+float asteroid_time_to_impact(object *asteroid_objp)
+{
+ float time=-1.0f, total_dist, speed;
+ asteroid *asp;
+ mc_info mc;
+
+ asp = &Asteroids[asteroid_objp->instance];
+
+ if ( asp->collide_objnum < 0 ) {
+ return time;
+ }
+
+ asteroid_test_collide(asteroid_objp, &Objects[asp->collide_objnum], &mc);
+
+ if ( mc.num_hits ) {
+ total_dist = vm_vec_dist(&mc.hit_point_world, &asteroid_objp->pos) - asteroid_objp->radius;
+ if ( total_dist < 0 ) {
+ total_dist = 0.0f;
+ }
+ speed = vm_vec_mag(&asteroid_objp->phys_info.vel);
+ time = total_dist/speed;
+ }
+
+ return time;
+}
+
+// read in a single asteroid section from asteroid.tbl
+void asteroid_parse_section()
+{
+ asteroid_info *asip;
+
+ asip = &Asteroid_info[Num_asteroid_types];
+
+ required_string("$Name:");
+ stuff_string(asip->name, F_NAME, NULL);
+
+ required_string( "$POF file1:" );
+ stuff_string_white( asip->pof_files[0] );
+
+ required_string( "$POF file2:" );
+ stuff_string_white( asip->pof_files[1] );
+
+ if ( (strstr(asip->name,"Asteroid") != NULL) || (strstr(asip->name, "asteroid") != NULL) ) {
+ required_string( "$POF file3:" );
+ stuff_string_white( asip->pof_files[2] );
+ }
+
+ asip->num_detail_levels = 0;
+
+ required_string("$Detail distance:");
+ asip->num_detail_levels = stuff_int_list(asip->detail_distance, MAX_SHIP_DETAIL_LEVELS, RAW_INTEGER_TYPE);
+
+ required_string("$Max Speed:");
+ stuff_float(&asip->max_speed);
+
+ required_string("$Expl inner rad:");
+ stuff_float(&asip->inner_rad);
+
+ required_string("$Expl outer rad:");
+ stuff_float(&asip->outer_rad);
+
+ required_string("$Expl damage:");
+ stuff_float(&asip->damage);
+
+ required_string("$Expl blast:");
+ stuff_float(&asip->blast);
+
+ required_string("$Hitpoints:");
+ stuff_float(&asip->initial_hull_strength);
+}
+
+// read in data from asteroid.tbl into Asteroid_info[] array
+void asteroid_parse_tbl()
+{
+ char impact_ani_file[FILESPEC_LENGTH];
+
+ Num_asteroid_types = 0;
+
+ // open localization
+ lcl_ext_open();
+
+ read_file_text("asteroid.tbl");
+ reset_parse();
+
+ required_string("#Asteroid Types");
+
+ while (required_string_either("#End","$Name:")) {
+ Assert( Num_asteroid_types < MAX_DEBRIS_TYPES );
+ asteroid_parse_section();
+ Num_asteroid_types++;
+ }
+
+ required_string("#End");
+
+ // check all read in
+ Assert(Num_asteroid_types == MAX_DEBRIS_TYPES);
+
+ Asteroid_impact_explosion_ani = -1;
+ required_string("$Impact Explosion:");
+ stuff_string(impact_ani_file, F_NAME, NULL);
+ if ( stricmp(impact_ani_file,NOX("none"))) {
+ int num_frames;
+ Asteroid_impact_explosion_ani = bm_load_animation( impact_ani_file, &num_frames, NULL, 1);
+ }
+
+ required_string("$Impact Explosion Radius:");
+ stuff_float(&Asteroid_impact_explosion_radius);
+
+ // close localization
+ lcl_ext_close();
+}
+
+// Return number of asteroids expected to collide with a ship.
+int count_incident_asteroids()
+{
+ object *asteroid_objp;
+ int count;
+
+ count = 0;
+
+ for ( asteroid_objp = GET_FIRST(&obj_used_list); asteroid_objp !=END_OF_LIST(&obj_used_list); asteroid_objp = GET_NEXT(asteroid_objp) ) {
+ if (asteroid_objp->type == OBJ_ASTEROID ) {
+ asteroid *asp = &Asteroids[asteroid_objp->instance];
+
+ if ( asp->target_objnum >= 0 ) {
+ count++;
+ }
+ }
+ }
+
+ return count;
+}
+
+// Pick object to throw asteroids at.
+// Pick any capital or big ship inside the bounds of the asteroid field.
+int set_asteroid_throw_objnum()
+{
+ if (Asteroid_field.num_initial_asteroids < 1)
+ return -1;
+
+ ship_obj *so;
+ object *ship_objp;
+
+ for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
+ ship_objp = &Objects[so->objnum];
+ float radius = ship_objp->radius*2.0f;
+
+ if (Ship_info[Ships[ship_objp->instance].ship_info_index].flags & (SIF_HUGE_SHIP | SIF_BIG_SHIP)) {
+ if (ship_objp->pos.x + radius > Asteroid_field.min_bound.x)
+ if (ship_objp->pos.y + radius > Asteroid_field.min_bound.y)
+ if (ship_objp->pos.z + radius > Asteroid_field.min_bound.z)
+ if (ship_objp->pos.x - radius < Asteroid_field.max_bound.x)
+ if (ship_objp->pos.y - radius < Asteroid_field.max_bound.y)
+ if (ship_objp->pos.z - radius < Asteroid_field.max_bound.z)
+ if (!asteroid_in_inner_bound(&Asteroid_field, &ship_objp->pos, radius))
+ return so->objnum;
+ }
+ }
+ return -1;
+
+}
+
+void asteroid_frame()
+{
+ if (Num_asteroids < 1)
+ return;
+
+ // Only throw if active field
+ if (Asteroid_field.field_type == FT_PASSIVE) {
+ return;
+ }
+
+ Asteroid_throw_objnum = set_asteroid_throw_objnum();
+
+ maybe_throw_asteroid(count_incident_asteroids());
+}
+
+// Called once, at game start. Do any one-time initializations here
+void asteroid_init()
+{
+ asteroid_parse_tbl();
+}
+
+// Draw brackets around on-screen asteroids that are about to collide, otherwise draw an offscreen indicator
+void asteroid_show_brackets()
+{
+ vertex asteroid_vertex;
+ object *asteroid_objp, *player_target;
+ asteroid *asp;
+
+ // get pointer to player target, so we don't need to take OBJ_INDEX() of asteroid_objp to compare to target_objnum
+ if ( Player_ai->target_objnum >= 0 ) {
+ player_target = &Objects[Player_ai->target_objnum];
+ } else {
+ player_target = NULL;
+ }
+
+ for ( asteroid_objp = GET_FIRST(&obj_used_list); asteroid_objp !=END_OF_LIST(&obj_used_list); asteroid_objp = GET_NEXT(asteroid_objp) ) {
+ if (asteroid_objp->type != OBJ_ASTEROID ) {
+ continue;
+ }
+
+ asp = &Asteroids[asteroid_objp->instance];
+
+ if ( asp->collide_objnum < 0 ) {
+ continue;
+ }
+
+ if ( asteroid_objp == player_target ) {
+ continue;
+ }
+
+ g3_rotate_vertex(&asteroid_vertex,&asteroid_objp->pos);
+ g3_project_vertex(&asteroid_vertex);
+
+ if (!(asteroid_vertex.flags & PF_OVERFLOW)) {
+ gr_set_color_fast(&IFF_colors[IFF_COLOR_SELECTION][1]);
+ hud_show_brackets(asteroid_objp, &asteroid_vertex);
+ }
+
+ // if asteroid is not on screen, draw an offscreen indicator
+ if ( hud_gauge_active(HUD_OFFSCREEN_INDICATOR) ) {
+ if (asteroid_vertex.codes != 0) {
+ float dist;
+// dist = vm_vec_dist_quick(&Player_obj->pos, &asteroid_objp->pos);
+ dist = hud_find_target_distance( asteroid_objp, Player_obj );
+ gr_set_color_fast(&IFF_colors[IFF_COLOR_SELECTION][1]);
+ hud_draw_offscreen_indicator(&asteroid_vertex, &asteroid_objp->pos, dist);
+ }
+ }
+ }
+}
+
+// target the closest danger asteroid to the player
+void asteroid_target_closest_danger()
+{
+ object *asteroid_objp, *closest_asteroid_objp = NULL;
+ asteroid *asp;
+ float dist, closest_dist = 999999.0f;
+
+ for ( asteroid_objp = GET_FIRST(&obj_used_list); asteroid_objp !=END_OF_LIST(&obj_used_list); asteroid_objp = GET_NEXT(asteroid_objp) ) {
+ if (asteroid_objp->type != OBJ_ASTEROID ) {
+ continue;
+ }
+
+ asp = &Asteroids[asteroid_objp->instance];
+
+ if ( asp->collide_objnum < 0 ) {
+ continue;
+ }
+
+ dist = vm_vec_dist_quick(&Player_obj->pos, &asteroid_objp->pos);
+
+ if ( dist < closest_dist ) {
+ closest_dist = dist;
+ closest_asteroid_objp = asteroid_objp;
+ }
+ }
+
+ if ( closest_asteroid_objp ) {
+ set_target_objnum( Player_ai, OBJ_INDEX(closest_asteroid_objp) );
+ }
+}
+
+void asteroid_page_in()
+{
+ if (Asteroid_field.num_initial_asteroids > 0 ) {
+ int i, j, k;
+
+ nprintf(( "Paging", "Paging in asteroids\n" ));
+
+
+ // max of 3 possible debris field models
+ for (i=0; i<3; i++) {
+ asteroid_info *asip;
+
+ if (Asteroid_field.debris_genre == DG_ASTEROID) {
+ // asteroid
+ asip = &Asteroid_info[i];
+ } else {
+ // ship debris - always full until empty
+ if (Asteroid_field.field_debris_type[i] != -1) {
+ asip = &Asteroid_info[Asteroid_field.field_debris_type[i]];
+ } else {
+ break;
+ }
+ }
+
+
+ for (k=0; k<3; k++) {
+
+ // SHIP DEBRIS - use subtype 0
+ if (Asteroid_field.debris_genre == DG_SHIP) {
+ if (k > 0) {
+ break;
+ }
+ } else {
+ // ASTEROID DEBRIS - use subtype (Asteroid_field.field_debris_type[] != -1)
+ if (Asteroid_field.field_debris_type[k] == -1) {
+ continue;
+ }
+ }
+
+ asip->modelp[k] = model_get(asip->model_num[k]);
+
+ // Page in textures
+ for (j=0; j<asip->modelp[k]->n_textures; j++ ) {
+ int bitmap_num = asip->modelp[k]->original_textures[j];
+
+
+ // if we're in Glide (and maybe later with D3D), use nondarkening textures
+ if ( bitmap_num > -1 ) {
+ if(gr_screen.mode == GR_GLIDE){
+ bm_page_in_nondarkening_texture( bitmap_num );
+ } else {
+ bm_page_in_texture( bitmap_num );
+ }
+ }
+ }
+
+ }
+ }
+ }
+}
+
+#else
+
+// stubbed out functions not used in the demo
+void asteroid_init() {}
+void asteroid_level_init() {}
+void asteroid_level_close() {}
+void asteroid_create_all() {}
+void asteroid_render( object *asteroid_objp ) {}
+void asteroid_delete( object *asteroid_objp ) {}
+void asteroid_process_pre( object *asteroid_objp, float frame_time) {}
+void asteroid_process_post( object *asteroid_objp, float frame_time) {}
+int asteroid_check_collision( object *asteroid_objp, object * other_obj, vector * hitpos, collision_info_struct *asteroid_hit_info ) {return 0;}
+void asteroid_hit( object *asteroid_objp, object *other_objp, vector *hitpos, float damage ) {}
+void asteroid_save_restore(CFILE *fp) {}
+int asteroid_count() {return 0;}
+int asteroid_collide_objnum(object *asteroid_objp) {return 0;}
+float asteroid_time_to_impact(object *asteroid_objp) {return 0.0f;}
+void asteroid_show_brackets() {}
+void asteroid_target_closest_danger() {}
+void asteroid_page_in() {}
+void asteroid_sub_create(object *parent_objp, int asteroid_type, vector *relvec) {}
+void asteroid_frame() {}
+
+
+#endif \ No newline at end of file
diff --git a/code/Asteroid/Asteroid.h b/code/Asteroid/Asteroid.h
new file mode 100644
index 0000000..fbc60c8
--- /dev/null
+++ b/code/Asteroid/Asteroid.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/Asteroid/Asteroid.h $
+ * $Revision: 12 $
+ * $Date: 6/09/99 2:55p $
+ * $Author: Andsager $
+ *
+ * Header file for asteroids
+ *
+ * $Log: /Freespace2/code/Asteroid/Asteroid.h $
+ *
+ * 12 6/09/99 2:55p Andsager
+ * Allow multiple asteroid subtypes (of large, medium, small) and follow
+ * family.
+ *
+ * 11 6/07/99 1:18p Andsager
+ * Make asteroids choose consistent texture from large to small. Modify
+ * fireball radius of dying asteroids.
+ *
+ * 10 5/03/99 10:50p Andsager
+ * Make Asteroid_obj_list. Change get_nearest_turret_objnum() to use
+ * Asteroid_obj_list, Ship_obj_list and Missile_obj_list vs.
+ * obj_used_list.
+ *
+ * 9 4/16/99 2:34p Andsager
+ * Second pass on debris fields
+ *
+ * 8 4/15/99 5:00p Andsager
+ * Frist pass on Debris field
+ *
+ * 7 3/31/99 9:51a Andsager
+ * Add for generalization to debris field
+ *
+ * 6 2/07/99 8:51p Andsager
+ * Add inner bound to asteroid field. Inner bound tries to stay astroid
+ * free. Wrap when within and don't throw at ships inside.
+ *
+ * 5 1/20/99 6:04p Dave
+ * Another bit of stuff for beam weapons. Ships will properly use them
+ * now, although they're really deadly.
+ *
+ * 4 11/05/98 5:55p Dave
+ * Big pass at reducing #includes
+ *
+ * 3 10/16/98 1:22p Andsager
+ * clean up header files
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 17 3/26/98 9:19a Lawrance
+ * Support multiple asteroid pofs
+ *
+ * 16 3/17/98 12:16a Allender
+ * asteroids in multiplayer -- minor problems with position being correct
+ *
+ * 15 3/14/98 1:44p Mike
+ * Todolist items 3365..3368. Make child asteroids collide properly.
+ * Make asteroid throwing less bunchy, toss asteroids earlier, make
+ * facing-ness not break mission balance.
+ *
+ * 14 3/11/98 12:13a Lawrance
+ * Auto-target asteroids if no hostile ships present
+ *
+ * 13 3/08/98 4:16p Hoffoss
+ *
+ * 12 3/07/98 3:48p Lawrance
+ * Show offscreen indicators for asteroids
+ *
+ * 11 3/04/98 11:59p Lawrance
+ * create an asteroid.tbl, read all asteroid data from there
+ *
+ * 10 3/04/98 4:11p Lawrance
+ * Have area effects affect asteroids, have asteroids cast an area effect,
+ * fix ship shockwaves
+ *
+ * 9 3/03/98 12:48a Lawrance
+ * Ensure collide_objnum is still valid each frame.
+ *
+ * 8 3/02/98 11:35p Lawrance
+ * Keep track of asteroids that will impact ships on the escort view.
+ *
+ * 7 2/26/98 10:07p Hoffoss
+ * Rewrote state saving and restoring to fix bugs and simplify the code.
+ *
+ * 6 2/26/98 4:22p Lawrance
+ * Change wrapping behavior, make vel random
+ *
+ * 5 2/20/98 8:31p Lawrance
+ * delay creation of sub-asteroids
+ *
+ * 4 2/19/98 4:33p Lawrance
+ * hook in new sounds and custom explosion animation
+ *
+ * 3 2/19/98 12:46a Lawrance
+ * Further work on asteroids.
+ *
+ * 2 2/10/98 6:43p Lawrance
+ * Moved asteroid code to a separate lib.
+ *
+ * 1 2/10/98 6:05p Lawrance
+ *
+ * $NoKeywords: $
+ */
+
+#ifndef __ASTEROID_H__
+#define __ASTEROID_H__
+
+#include "ship.h"
+#include "parselo.h" // for NAME_LENGTH
+
+struct object;
+struct polymodel;
+struct collision_info_struct;
+
+#define MAX_ASTEROIDS 256
+
+// DEBRIS TYPES
+#define MAX_DEBRIS_TYPES 12
+#define ASTEROID_TYPE_SMALL 0
+#define ASTEROID_TYPE_MEDIUM 1
+#define ASTEROID_TYPE_BIG 2
+//
+#define DEBRIS_TERRAN_SMALL 3
+#define DEBRIS_TERRAN_MEDIUM 4
+#define DEBRIS_TERRAN_LARGE 5
+//
+#define DEBRIS_VASUDAN_SMALL 6
+#define DEBRIS_VASUDAN_MEDIUM 7
+#define DEBRIS_VASUDAN_LARGE 8
+//
+#define DEBRIS_SHIVAN_SMALL 9
+#define DEBRIS_SHIVAN_MEDIUM 10
+#define DEBRIS_SHIVAN_LARGE 11
+// END DEBRIS TYPES
+
+typedef struct debris_struct {
+ int index;
+ char *name;
+} debris_struct;
+
+// Data structure to track the active asteroids
+typedef struct asteroid_obj {
+ asteroid_obj *next, *prev;
+ int flags, objnum;
+} asteroid_obj;
+extern asteroid_obj Asteroid_obj_list;
+
+
+extern debris_struct Field_debris_info[];
+
+#define MAX_ASTEROID_POFS 3 // Max number of POFs per asteroid type
+
+#define AF_USED (1<<0) // Set means used.
+
+typedef struct asteroid_info {
+ char name[NAME_LENGTH]; // name for the asteroid
+ char pof_files[MAX_ASTEROID_POFS][NAME_LENGTH]; // POF files to load/associate with ship
+ int num_detail_levels; // number of detail levels for this ship
+ int detail_distance[MAX_SHIP_DETAIL_LEVELS]; // distance to change detail levels at
+ float max_speed; // cap on speed for asteroid
+ float inner_rad; // radius within which maximum area effect damage is applied
+ float outer_rad; // radius at which no area effect damage is applied
+ float damage; // maximum damage applied from area effect explosion
+ float blast; // maximum blast impulse from area effect explosion
+ float initial_hull_strength; // starting strength of asteroid
+ polymodel *modelp[MAX_ASTEROID_POFS];
+ int model_num[MAX_ASTEROID_POFS];
+} asteroid_info;
+
+typedef struct asteroid {
+ int flags;
+ int objnum;
+ int type; // In 0..Num_asteroid_types
+ int asteroid_subtype; // Which index into asteroid_info for modelnum and modelp
+ int check_for_wrap; // timestamp to check for asteroid wrapping around field
+ int check_for_collide; // timestamp to check for asteroid colliding with escort ships
+ int final_death_time; // timestamp to swap in new models after explosion starts
+ int collide_objnum; // set to objnum that asteroid will be impacting soon
+ int collide_objsig; // object signature corresponding to collide_objnum
+ vector death_hit_pos; // hit pos that caused death
+ int target_objnum; // Yes, hah! Asteroids can have targets. See asteroid_aim_at_target().
+} asteroid;
+
+// TYPEDEF FOR SPECIES OF DEBRIS - BITFIELD
+#define DS_TERRAN 0x01
+#define DS_VASUDAN 0x02
+#define DS_SHIVAN 0x04
+
+// TYPEDEF FOR DEBRIS TYPE
+typedef enum {
+ DG_ASTEROID,
+ DG_SHIP
+} debris_genre;
+
+// TYPEDEF FOR FIELD TYPE
+typedef enum {
+ FT_ACTIVE,
+ FT_PASSIVE
+} field_type;
+
+#define MAX_ACTIVE_DEBRIS_TYPES 3
+
+typedef struct asteroid_field {
+ vector min_bound; // Minimum range of field.
+ vector max_bound; // Maximum range of field.
+ int has_inner_bound;
+ vector inner_min_bound;
+ vector inner_max_bound;
+ vector vel; // Average asteroid moves at this velocity.
+ float speed; // Average speed of field
+ int num_initial_asteroids; // Number of asteroids at creation.
+ field_type field_type; // active throws and wraps, passive does not
+ debris_genre debris_genre; // type of debris (ship or asteroid) [generic type]
+ int field_debris_type[MAX_ACTIVE_DEBRIS_TYPES]; // one of the debris type defines above
+} asteroid_field;
+
+extern asteroid_info Asteroid_info[MAX_DEBRIS_TYPES];
+extern asteroid Asteroids[MAX_ASTEROIDS];
+extern asteroid_field Asteroid_field;
+
+extern int Num_asteroid_types;
+extern int Num_asteroids;
+extern int Asteroids_enabled;
+
+void asteroid_init();
+void asteroid_level_init();
+void asteroid_level_close();
+void asteroid_create_all();
+void asteroid_render( object *asteroid_objp );
+void asteroid_delete( object *asteroid_objp );
+void asteroid_process_pre( object *asteroid_objp, float frame_time);
+void asteroid_process_post( object *asteroid_objp, float frame_time);
+int asteroid_check_collision( object *asteroid_objp, object * other_obj, vector * hitpos, collision_info_struct *asteroid_hit_info=NULL );
+void asteroid_hit( object *asteroid_objp, object *other_objp, vector *hitpos, float damage );
+int asteroid_count();
+int asteroid_collide_objnum(object *asteroid_objp);
+float asteroid_time_to_impact(object *asteroid_objp);
+void asteroid_show_brackets();
+void asteroid_target_closest_danger();
+int asteroid_get_random_in_cone(vector *pos, vector *dir, float ang, int danger = 0);
+
+// need to extern for multiplayer
+void asteroid_sub_create(object *parent_objp, int asteroid_type, vector *relvec);
+
+void asteroid_frame();
+
+#endif // __ASTEROID_H__
diff --git a/code/Bmpman/BmpMan.cpp b/code/Bmpman/BmpMan.cpp
new file mode 100644
index 0000000..a9f7e61
--- /dev/null
+++ b/code/Bmpman/BmpMan.cpp
@@ -0,0 +1,2561 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/Bmpman/BmpMan.cpp $
+ * $Revision: 37 $
+ * $Date: 9/13/99 11:26p $
+ * $Author: Andsager $
+ *
+ * Code to load and manage all bitmaps for the game
+ *
+ * $Log: /Freespace2/code/Bmpman/BmpMan.cpp $
+ *
+ * 37 9/13/99 11:26p Andsager
+ * Add debug code to check for poorly sized anis
+ *
+ * 36 9/05/99 11:19p Dave
+ * Made d3d texture cache much more safe. Fixed training scoring bug where
+ * it would backout scores without ever having applied them in the first
+ * place.
+ *
+ * 35 8/20/99 2:09p Dave
+ * PXO banner cycling.
+ *
+ * 34 8/10/99 6:54p Dave
+ * Mad optimizations. Added paging to the nebula effect.
+ *
+ * 33 8/06/99 1:52p Dave
+ * Bumped up MAX_BITMAPS for the demo.
+ *
+ * 32 8/02/99 1:49p Dave
+ * Fixed low-mem animation problem. Whee!
+ *
+ * 31 7/16/99 1:49p Dave
+ * 8 bit aabitmaps. yay.
+ *
+ * 30 7/13/99 1:15p Dave
+ * 32 bit support. Whee!
+ *
+ * 29 6/29/99 10:35a Dave
+ * Interface polygon bitmaps! Whee!
+ *
+ * 28 6/16/99 4:06p Dave
+ * New pilot info popup. Added new draw-bitmap-as-poly function.
+ *
+ * 27 5/05/99 9:02p Dave
+ * Fixed D3D aabitmap rendering. Spiffed up nebula effect a bit (added
+ * rotations, tweaked values, made bitmap selection more random). Fixed
+ * D3D beam weapon clipping problem. Added D3d frame dumping.
+ *
+ * 26 4/27/99 12:16a Dave
+ * Fixed beam weapon muzzle glow problem. Fixed premature timeout on the
+ * pxo server list screen. Fixed secondary firing for hosts on a
+ * standalone. Fixed wacky multiplayer weapon "shuddering" problem.
+ *
+ * 25 4/09/99 2:21p Dave
+ * Multiplayer beta stuff. CD checking.
+ *
+ * 24 4/08/99 10:42a Johnson
+ * Don't try to swizzle a texture to transparent in Fred.
+ *
+ * 23 3/31/99 8:24p Dave
+ * Beefed up all kinds of stuff, incluging beam weapons, nebula effects
+ * and background nebulae. Added per-ship non-dimming pixel colors.
+ *
+ * 22 3/20/99 3:46p Dave
+ * Added support for model-based background nebulae. Added 3 new
+ * sexpressions.
+ *
+ * 21 2/11/99 3:08p Dave
+ * PXO refresh button. Very preliminary squad war support.
+ *
+ * 20 2/08/99 5:07p Dave
+ * FS2 chat server support. FS2 specific validated missions.
+ *
+ * 19 2/05/99 12:52p Dave
+ * Fixed Glide nondarkening textures.
+ *
+ * 18 2/04/99 6:29p Dave
+ * First full working rev of FS2 PXO support. Fixed Glide lighting
+ * problems.
+ *
+ * 17 2/03/99 11:44a Dave
+ * Fixed d3d transparent textures.
+ *
+ * 16 1/15/99 11:29a Neilk
+ * Fixed D3D screen/texture pixel formatting problem.
+ *
+ * 15 1/14/99 12:48a Dave
+ * Todo list bug fixes. Made a pass at putting briefing icons back into
+ * FRED. Sort of works :(
+ *
+ * 14 1/12/99 12:53a Dave
+ * More work on beam weapons - made collision detection very efficient -
+ * collide against all object types properly - made 3 movement types
+ * smooth. Put in test code to check for possible non-darkening pixels on
+ * object textures.
+ *
+ * 13 1/08/99 2:08p Dave
+ * Fixed software rendering for pofview. Super early support for AWACS and
+ * beam weapons.
+ *
+ * 12 1/06/99 2:24p Dave
+ * Stubs and release build fixes.
+ *
+ * 11 12/14/98 4:01p Dave
+ * Got multi_data stuff working well with new xfer stuff.
+ *
+ * 10 12/06/98 2:36p Dave
+ * Drastically improved nebula fogging.
+ *
+ * 9 12/01/98 5:53p Dave
+ * Simplified the way pixel data is swizzled. Fixed tga bitmaps to work
+ * properly in D3D and Glide.
+ *
+ * 8 12/01/98 4:46p Dave
+ * Put in targa bitmap support (16 bit).
+ *
+ * 7 12/01/98 10:32a Johnson
+ * Fixed direct3d font problems. Fixed sun bitmap problem. Fixed direct3d
+ * starfield problem.
+ *
+ * 6 12/01/98 8:06a Dave
+ * Temporary checkin to fix some texture transparency problems in d3d.
+ *
+ * 5 11/30/98 5:31p Dave
+ * Fixed up Fred support for software mode.
+ *
+ * 4 11/30/98 1:07p Dave
+ * 16 bit conversion, first run.
+ *
+ * 3 10/22/98 6:14p Dave
+ * Optimized some #includes in Anim folder. Put in the beginnings of
+ * parse/localization support for externalized strings and tstrings.tbl
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 106 5/23/98 4:43p John
+ * Took out debugging sleep
+ *
+ * 105 5/23/98 4:14p John
+ * Added code to preload textures to video card for AGP. Added in code
+ * to page in some bitmaps that weren't getting paged in at level start.
+ *
+ * 104 5/20/98 12:59p John
+ * Turned optimizations on for debug builds. Also turning on automatic
+ * function inlining. Turned off the unreachable code warning.
+ *
+ * 103 5/20/98 10:20a Hoffoss
+ * Fixed warning in the code.
+ *
+ * 102 5/19/98 3:45p John
+ * fixed bug causing lowmem to drop half of the frames. Also halved fps
+ * during lowmem.
+ *
+ * 101 5/14/98 3:38p John
+ * Added in more non-darkening colors for Adam. Had to fix some bugs in
+ * BmpMan and Ani stuff to get this to work.
+ *
+ * 100 4/22/98 9:13p John
+ * Added code to replace frames of animations in vram if so desired.
+ *
+ * 99 4/17/98 6:56a John
+ * Fixed bug where RLE'd user bitmaps caused data to not get freed.
+ * (Turned off RLE for use bitmaps). Made lossy animations reduce
+ * resolution by a factor of 2 in low memory conditions.
+ *
+ * 98 4/16/98 6:31p Hoffoss
+ * Added function to get filename of a bitmap handle, which we don't have
+ * yet and I need.
+ *
+ * 97 4/01/98 9:27p John
+ * Fixed debug info in bmpman.
+ *
+ * 96 4/01/98 5:34p John
+ * Made only the used POFs page in for a level. Reduced some interp
+ * arrays. Made custom detail level work differently.
+ *
+ * 95 3/31/98 9:55a Lawrance
+ * JOHN: get xparency working for user bitmaps
+ *
+ * 94 3/30/98 4:02p John
+ * Made machines with < 32 MB of RAM use every other frame of certain
+ * bitmaps. Put in code to keep track of how much RAM we've malloc'd.
+ *
+ * 93 3/29/98 4:05p John
+ * New paging code that loads everything necessary at level startup.
+ *
+ * 92 3/27/98 11:20a John
+ * commented back in some debug code.
+ *
+ * 91 3/26/98 5:21p John
+ * Added new code to preload all bitmaps at the start of a level.
+ * Commented it out, though.
+ *
+ * 90 3/26/98 4:56p Jasen
+ * AL: Allow find_block_of() to allocate a series of bitmaps from index 0
+ *
+ * 89 3/26/98 10:21a John
+ * Made no palette-mapped bitmaps use 0,255,0 as transparent.
+ *
+ * 88 3/24/98 5:39p John
+ * Added debug code to show bitmap fragmentation. Made user bitmaps
+ * allocate from top of array.
+ *
+ * 87 3/22/98 3:28p John
+ * Added in stippled alpha for lower details. Made medium detail use
+ * engine glow.
+ *
+ * 86 3/11/98 1:55p John
+ * Fixed warnings
+ *
+ * 85 3/06/98 4:09p John
+ * Changed the way we do bitmap RLE'ing... this speds up HUD bitmaps by
+ * about 2x
+ *
+ * 84 3/02/98 6:00p John
+ * Moved MAX_BITMAPS into BmpMan.h so the stuff in the graphics code that
+ * is dependent on it won't break if it changes. Made ModelCache slots
+ * be equal to MAX_OBJECTS which is what it is.
+ *
+ * 83 3/02/98 9:51a John
+ * Added code to print the number of bitmap slots in use between levels.
+ *
+ * 82 2/16/98 3:54p John
+ * Changed a bunch of mprintfs to catagorize to BmpInfo
+ *
+ * 81 2/13/98 5:00p John
+ * Made user bitmaps not get wrote to level cache file.
+ *
+ * 80 2/06/98 8:25p John
+ * Added code for new bitmaps since last frame
+ *
+ * 79 2/06/98 8:10p John
+ * Added code to show amout of texture usage each frame.
+ *
+ * 78 2/05/98 9:21p John
+ * Some new Direct3D code. Added code to monitor a ton of stuff in the
+ * game.
+ *
+ * 77 1/29/98 11:48a John
+ * Added new counter measure rendering as model code. Made weapons be
+ * able to have impact explosion.
+ *
+ * 76 1/28/98 6:19p Dave
+ * Reduced standalone memory usage ~8 megs. Put in support for handling
+ * multiplayer submenu handling for endgame, etc.
+ *
+ * 75 1/17/98 12:55p John
+ * Fixed bug that I just created that loaded all ani frames.
+ *
+ * 74 1/17/98 12:33p John
+ * Made the game_busy function be called a constant amount of times per
+ * level load, making the bar prediction easier.
+ *
+ * 73 1/17/98 12:14p John
+ * Added loading... bar to freespace.
+ *
+ * 72 1/11/98 3:20p John
+ * Made so that if no .clt exists, it will load all the bitmaps
+ *
+ * 71 1/11/98 3:06p John
+ * Made bitmap loading stop when cache gets full.
+ *
+ * 70 1/11/98 2:45p John
+ * Changed .lst to .clt
+ *
+ * 69 1/11/98 2:14p John
+ * Changed a lot of stuff that had to do with bitmap loading. Made cfile
+ * not do callbacks, I put that in global code. Made only bitmaps that
+ * need to load for a level load.
+ *
+ * 67 1/09/98 4:07p John
+ * Made all bitmap functions return a bitmap "Handle" not number. This
+ * helps to find bm_release errors.
+ *
+ * 66 1/09/98 1:38p John
+ * Fixed some bugs from previous comment
+ *
+ * 65 1/09/98 1:32p John
+ * Added some debugging code to track down a weird error. Namely I fill
+ * in the be structure with bogus values when someone frees it.
+ *
+ * 64 12/28/97 2:00p John
+ * put in another assert checking for invalid lock/unlock sequencing
+ *
+ * 63 12/24/97 2:02p John
+ * Changed palette translation to be a little faster for unoptimized
+ * builds
+ *
+ * 62 12/18/97 8:59p Dave
+ * Finished putting in basic support for weapon select and ship select in
+ * multiplayer.
+ *
+ * 61 12/15/97 10:27p John
+ * fixed bug where 2 bm_loads of same file both open the header.
+ *
+ * 60 12/08/97 2:17p John
+ * fixed bug with bmpman and cf_callback.
+ * made cf_callback in Freespace set small font back when done.
+ *
+ * 59 12/03/97 5:01p Lawrance
+ * bump up MAX_BITMAPS to 1500. People have reached 1000 bitmaps while
+ * playing multiple missions.
+ *
+ * 58 12/02/97 3:59p John
+ * Added first rev of thruster glow, along with variable levels of
+ * translucency, which retquired some restructing of palman.
+ *
+ * 57 11/30/97 3:57p John
+ * Made fixed 32-bpp translucency. Made BmpMan always map translucent
+ * color into 255 even if you aren't supposed to remap and make it's
+ * palette black.
+ *
+ * 56 10/05/97 10:39a John
+ * fixed bug with palette on unmapped bitmaps. Made unmapped bitmaps get
+ * marked with xparent.
+ *
+ * 55 9/23/97 11:46a Lawrance
+ * fixed bug with rle'ing with spans get big
+ *
+ * 54 9/23/97 10:45a John
+ * made so you can tell bitblt code to rle a bitmap by passing flag to
+ * gr_set_bitmap
+ *
+ * 53 9/19/97 10:18a John
+ * fixed bug with aa animations being re-rle'd every
+ * frame.
+ *
+ *
+ * 52 9/09/97 10:08a Sandeep
+ * Fixed Compiler Level 4 warnings
+ *
+ * 51 9/08/97 2:02p John
+ * fixed typo in nprintf
+ *
+ * 50 9/08/97 1:56p John
+ * fixed some memory housekeeping bugs
+ *
+ * 49 9/03/97 4:19p John
+ * changed bmpman to only accept ani and pcx's. made passing .pcx or .ani
+ * to bm_load functions not needed. Made bmpman keep track of palettes
+ * for bitmaps not mapped into game palettes.
+ *
+ * 48 8/29/97 7:35p Lawrance
+ * check if .ani animation is already loaded in bm_load_animation()
+ *
+ * 47 8/25/97 11:14p Lawrance
+ * added support for .ani files in bm_load_animation()
+ *
+ * 46 8/17/97 2:42p Lawrance
+ * only flag PCX files as xparent if they have xparent pixels in them
+ *
+ * 45 8/15/97 9:57a Lawrance
+ * support multiple xparent entries for PCX files
+ *
+ * 44 8/05/97 10:18a Lawrance
+ * my_rand() being used temporarily instead of rand()
+ *
+ * 43 8/01/97 4:30p John
+ *
+ * 42 7/29/97 8:34a John
+ * took out png stuff
+ *
+ * 41 7/18/97 3:27p Lawrance
+ * have pcx files use (0,255,0) for transparency
+ *
+ * 40 7/16/97 3:07p John
+ *
+ * 39 7/10/97 8:34a John
+ * Added code to read TGA files.
+ *
+ * 38 6/20/97 1:50p John
+ * added rle code to bmpman. made gr8_aabitmap use it.
+ *
+ * 37 6/18/97 12:07p John
+ * fixed some color bugs
+ *
+ * 36 6/17/97 8:58p Lawrance
+ * fixed bug with not nulling bm.data with USER bitmaps
+ *
+ * 35 6/12/97 2:44a Lawrance
+ * changed bm_unlock() to take an index into bm_bitmaps(). Added
+ * ref_count to bitmap_entry struct
+ *
+ * 34 5/20/97 10:36a John
+ * Fixed problem with user bitmaps and direct3d caching.
+ *
+ * 33 5/14/97 1:59p John
+ * fixed a palette bug with vclips.
+ *
+ * 32 3/24/97 4:43p John
+ * speed up chunked collision detection by only checking cubes the vector
+ * goes through.
+ *
+ * 31 3/24/97 3:25p John
+ * Cleaned up and restructured model_collide code and fvi code. In fvi
+ * made code that finds uvs work.. Added bm_get_pixel to BmpMan.
+ *
+ * 30 3/11/97 2:49p Allender
+ *
+ * 29 2/18/97 9:43a Lawrance
+ * added Assert() in bm_release
+ *
+ * 28 1/22/97 4:29p John
+ * maybe fixed bug with code that counts total bytes of texture ram used.
+ *
+ * 27 1/22/97 4:19p Lawrance
+ * added flags to bm_create to allow transparency
+ *
+ * 26 1/21/97 5:24p John
+ * fixed another bug with bm_release.
+ *
+ * 25 1/21/97 5:12p John
+ * fixed bug with case
+ *
+ * 24 1/21/97 5:02p John
+ * Added code for 8bpp user bitmaps.
+ *
+ * 23 1/09/97 11:35a John
+ * Added some 2d functions to get/put screen images.
+ *
+ * 22 11/26/96 6:50p John
+ * Added some more hicolor primitives. Made windowed mode run as current
+ * bpp, if bpp is 8,16,or 32.
+ *
+ * 21 11/26/96 9:44a Allender
+ * Allow for use of different bitmap palettes
+ *
+ * 20 11/25/96 10:36a Allender
+ * started working on 32 bpp support. Added 15 bpp.
+ *
+ * 19 11/18/96 1:51p Allender
+ * fix up manager code to reread bitmaps if needed in newer bit depth
+ *
+ * 18 11/15/96 4:24p Allender
+ * more bmpman stuff -- only free bitmap slots when releasing copied
+ * texture -- otherwise, only release the data for the bitmap
+ *
+ * 17 11/15/96 3:33p Allender
+ * added support for converting to 16 bit textures when requested with
+ * bm_load. Added some other management functions
+ *
+ * 16 11/13/96 4:51p Allender
+ * started overhaul of bitmap manager. bm_load no longer actually load
+ * the data, only the info for the bitmap. Locking the bitmap now forces
+ * load when no data present (or will if bpp changes)
+ *
+ * $NoKeywords: $
+ */
+
+#include "pstypes.h"
+#include "PcxUtils.h"
+#include "BmpMan.h"
+#include "PalMan.h"
+#include "2d.h"
+#include "AnimPlay.h"
+#include "Timer.h"
+#include "SystemVars.h"
+#include "Key.h"
+#include "PackUnPack.h"
+#include "cfile.h"
+#include "GrInternal.h"
+#include "TgaUtils.h"
+#include "Ship.h"
+
+#ifndef NDEBUG
+#define BMPMAN_NDEBUG
+#endif
+
+// keep this defined to use per-ship nondarkening pixels
+#define BMPMAN_SPECIAL_NONDARK
+
+int bm_inited = 0;
+
+#define BM_TYPE_NONE 0
+#define BM_TYPE_PCX 1
+#define BM_TYPE_USER 2
+#define BM_TYPE_ANI 3 // in-house ANI format
+#define BM_TYPE_TGA 4 // 16 bit targa
+
+typedef union bm_extra_info {
+ struct {
+ // Stuff needed for animations
+ int first_frame; // used for animations -- points to index of first frame
+ ubyte num_frames; // used for animation -- number of frames in the animation
+ ubyte fps; // used for animation -- frames per second
+ } ani;
+ struct {
+ // Stuff needed for user bitmaps
+ void *data; // For user bitmaps, this is where the data comes from
+ ubyte bpp; // For user bitmaps, this is what format the data is
+ ubyte flags; // Flags passed to bm_create
+ } user;
+} bm_extra_info;
+
+typedef struct bitmap_entry {
+ // identification
+ char filename[MAX_FILENAME_LEN]; // filename for this bitmap
+
+ uint signature; // a unique signature identifying the data
+ uint palette_checksum; // checksum used to be sure bitmap is in current palette
+ int handle; // Handle = id*MAX_BITMAPS + bitmapnum
+ int last_used; // When this bitmap was last used
+
+ ubyte type; // PCX, USER, ANI, etc
+ signed char ref_count; // Number of locks on bitmap. Can't unload unless ref_count is 0.
+
+ // Stuff to keep track of usage
+ ubyte preloaded; // If set, then this was loaded from the lst file
+ ubyte used_flags; // What flags it was accessed thru
+
+ // Bitmap info
+ bitmap bm;
+
+ // Data for animations and user bitmaps
+ bm_extra_info info;
+
+#ifdef BMPMAN_NDEBUG
+ // bookeeping
+ ubyte used_last_frame; // If set, then it was used last frame
+ ubyte used_this_frame; // If set, then it was used this frame
+ int data_size; // How much data this bitmap uses
+ int used_count; // How many times it was accessed
+#endif
+} bitmap_entry;
+
+uint Bm_next_signature = 0x1234;
+
+bitmap_entry bm_bitmaps[MAX_BITMAPS];
+
+int bm_texture_ram = 0;
+
+// Bm_max_ram - How much RAM bmpman can use for textures.
+// Set to <1 to make it use all it wants.
+int Bm_max_ram = 0; //16*1024*1024; // Only use 16 MB for textures
+
+int bm_next_handle = 1;
+
+int Bm_paging = 0;
+
+static int Bm_low_mem = 0;
+
+// 16 bit pixel formats
+int Bm_pixel_format = BM_PIXEL_FORMAT_ARGB;
+
+// get and put functions for 16 bit pixels - neat bit slinging, huh?
+#define BM_SET_R_ARGB(p, r) { p[1] &= ~(0x7c); p[1] |= ((r & 0x1f) << 2); }
+#define BM_SET_G_ARGB(p, g) { p[0] &= ~(0xe0); p[1] &= ~(0x03); p[0] |= ((g & 0x07) << 5); p[1] |= ((g & 0x18) >> 3); }
+#define BM_SET_B_ARGB(p, b) { p[0] &= ~(0x1f); p[0] |= b & 0x1f; }
+#define BM_SET_A_ARGB(p, a) { p[1] &= ~(0x80); p[1] |= ((a & 0x01) << 7); }
+
+#define BM_SET_R_D3D(p, r) { *p |= (ushort)(( (int)r / Gr_current_red->scale ) << Gr_current_red->shift); }
+#define BM_SET_G_D3D(p, g) { *p |= (ushort)(( (int)g / Gr_current_green->scale ) << Gr_current_green->shift); }
+#define BM_SET_B_D3D(p, b) { *p |= (ushort)(( (int)b / Gr_current_blue->scale ) << Gr_current_blue->shift); }
+#define BM_SET_A_D3D(p, a) { if(a == 0){ *p = (ushort)Gr_current_green->mask; } }
+
+#define BM_SET_R(p, r) { switch(Bm_pixel_format){ case BM_PIXEL_FORMAT_ARGB: BM_SET_R_ARGB(((char*)p), r); break; case BM_PIXEL_FORMAT_D3D: BM_SET_R_D3D(p, r); break; default: Int3(); } }
+#define BM_SET_G(p, g) { switch(Bm_pixel_format){ case BM_PIXEL_FORMAT_ARGB: BM_SET_G_ARGB(((char*)p), g); break; case BM_PIXEL_FORMAT_D3D: BM_SET_G_D3D(p, g); break; default: Int3(); } }
+#define BM_SET_B(p, b) { switch(Bm_pixel_format){ case BM_PIXEL_FORMAT_ARGB: BM_SET_B_ARGB(((char*)p), b); break; case BM_PIXEL_FORMAT_D3D: BM_SET_B_D3D(p, b); break; default: Int3(); } }
+#define BM_SET_A(p, a) { switch(Bm_pixel_format){ case BM_PIXEL_FORMAT_ARGB: BM_SET_A_ARGB(((char*)p), a); break; case BM_PIXEL_FORMAT_D3D: BM_SET_A_D3D(p, a); break; default: Int3(); } }
+
+// ===========================================
+// Mode: 0 = High memory
+// 1 = Low memory ( every other frame of ani's)
+// 2 = Debug low memory ( only use first frame of each ani )
+void bm_set_low_mem( int mode )
+{
+ Assert( (mode >= 0) && (mode<=2 ));
+ Bm_low_mem = mode;
+}
+
+
+static int bm_get_next_handle()
+{
+ int n = bm_next_handle;
+ bm_next_handle++;
+ if ( bm_next_handle > 30000 ) {
+ bm_next_handle = 1;
+ }
+ return n;
+}
+
+// Frees a bitmaps data if it should, and
+// Returns true if bitmap n can free it's data.
+static void bm_free_data(int n)
+{
+ bitmap_entry *be;
+ bitmap *bmp;
+
+ Assert( n >= 0 && n < MAX_BITMAPS );
+
+ be = &bm_bitmaps[n];
+ bmp = &be->bm;
+
+ // If there isn't a bitmap in this structure, don't
+ // do anything but clear out the bitmap info
+ if ( be->type==BM_TYPE_NONE)
+ goto SkipFree;
+
+ // If this bitmap doesn't have any data to free, skip
+ // the freeing it part of this.
+ if ( bmp->data == 0 )
+ goto SkipFree;
+
+ // Don't free up memory for user defined bitmaps, since
+ // BmpMan isn't the one in charge of allocating/deallocing them.
+ if ( ( be->type==BM_TYPE_USER ) )
+ goto SkipFree;
+
+ // Free up the data now!
+
+ // mprintf(( "Bitmap %d freed %d bytes\n", n, bm_bitmaps[n].data_size ));
+ #ifdef BMPMAN_NDEBUG
+ bm_texture_ram -= be->data_size;
+ #endif
+ free((void *)bmp->data);
+
+SkipFree:
+
+ // Clear out & reset the bitmap data structure
+ bmp->flags = 0;
+ bmp->bpp = 0;
+ bmp->data = 0;
+ bmp->palette = NULL;
+ #ifdef BMPMAN_NDEBUG
+ be->data_size = 0;
+ #endif
+ be->signature = Bm_next_signature++;
+}
+
+
+#ifdef BMPMAN_NDEBUG
+
+int Bm_ram_freed = 0;
+
+static void bm_free_some_ram( int n, int size )
+{
+/*
+ if ( Bm_max_ram < 1 ) return;
+ if ( bm_texture_ram + size < Bm_max_ram ) return;
+
+ int current_time = timer_get_milliseconds();
+
+ while( bm_texture_ram + size > Bm_max_ram ) {
+ Bm_ram_freed++;
+
+ // Need to free some RAM up!
+ int i, oldest=-1, best_val=0;
+ for (i = 0; i < MAX_BITMAPS; i++) {
+ if ( (bm_bitmaps[i].type != BM_TYPE_NONE) && (bm_bitmaps[i].first_frame!=bm_bitmaps[n].first_frame) && (bm_bitmaps[i].ref_count==0) && (bm_bitmaps[i].data_size>0) ) {
+ int page_func = ( current_time-bm_bitmaps[i].last_used)*bm_bitmaps[i].data_size;
+ if ( (oldest==-1) || (page_func>best_val) ) {
+ oldest=i;
+ best_val = page_func;
+ }
+ }
+ }
+
+ if ( oldest > -1 ) {
+ //mprintf(( "Freeing bitmap '%s'\n", bm_bitmaps[oldest].filename ));
+ for (i=0; i<bm_bitmaps[oldest].num_frames; i++ ) {
+ bm_free_data(bm_bitmaps[oldest].first_frame+i);
+ }
+ } else {
+ //mprintf(( "Couldn't free enough! %d\n", bm_texture_ram ));
+ break;
+ }
+ }
+*/
+}
+
+#endif
+
+static void *bm_malloc( int n, int size )
+{
+ Assert( n >= 0 && n < MAX_BITMAPS );
+// mprintf(( "Bitmap %d allocated %d bytes\n", n, size ));
+ #ifdef BMPMAN_NDEBUG
+ bm_free_some_ram( n, size );
+ Assert( bm_bitmaps[n].data_size == 0 );
+ bm_bitmaps[n].data_size += size;
+ bm_texture_ram += size;
+ #endif
+ return malloc(size);
+}
+
+void bm_close()
+{
+ int i;
+ if ( bm_inited ) {
+ for (i=0; i<MAX_BITMAPS; i++ ) {
+ bm_free_data(i); // clears flags, bbp, data, etc
+ }
+ bm_inited = 0;
+ }
+}
+
+
+void bm_init()
+{
+ int i;
+
+ mprintf(( "Size of bitmap info = %d KB\n", sizeof( bm_bitmaps )/1024 ));
+ mprintf(( "Size of bitmap extra info = %d bytes\n", sizeof( bm_extra_info ) ));
+
+ if (!bm_inited) {
+ bm_inited = 1;
+ atexit(bm_close);
+ }
+
+ for (i=0; i<MAX_BITMAPS; i++ ) {
+ bm_bitmaps[i].filename[0] = '\0';
+ bm_bitmaps[i].type = BM_TYPE_NONE;
+ bm_bitmaps[i].info.user.data = NULL;
+ bm_bitmaps[i].bm.data = 0;
+ bm_bitmaps[i].bm.palette = NULL;
+ #ifdef BMPMAN_NDEBUG
+ bm_bitmaps[i].data_size = 0;
+ bm_bitmaps[i].used_count = 0;
+ bm_bitmaps[i].used_last_frame = 0;
+ bm_bitmaps[i].used_this_frame = 0;
+ #endif
+ bm_free_data(i); // clears flags, bbp, data, etc
+ }
+
+
+}
+
+#ifdef BMPMAN_NDEBUG
+
+// Returns number of bytes of bitmaps locked this frame
+// ntotal = number of bytes of bitmaps locked this frame
+// nnew = number of bytes of bitmaps locked this frame that weren't locked last frame
+void bm_get_frame_usage(int *ntotal, int *nnew)
+{
+ int i;
+
+ *ntotal = 0;
+ *nnew = 0;
+
+ for (i=0; i<MAX_BITMAPS; i++ ) {
+ if ( (bm_bitmaps[i].type != BM_TYPE_NONE) && (bm_bitmaps[i].used_this_frame)) {
+ if ( !bm_bitmaps[i].used_last_frame ) {
+ *nnew += bm_bitmaps[i].bm.w*bm_bitmaps[i].bm.h;
+ }
+ *ntotal += bm_bitmaps[i].bm.w*bm_bitmaps[i].bm.h;
+ }
+ bm_bitmaps[i].used_last_frame = bm_bitmaps[i].used_this_frame;
+ bm_bitmaps[i].used_this_frame = 0;
+ }
+
+}
+#else
+void bm_get_frame_usage(int *ntotal, int *nnew)
+{
+}
+#endif
+
+// given a loaded bitmap with valid info, calculate sections
+void bm_calc_sections(bitmap *be)
+{
+ int idx;
+
+ // number of x and y sections
+ be->sections.num_x = (ubyte)(be->w / MAX_BMAP_SECTION_SIZE);
+ if((be->sections.num_x * MAX_BMAP_SECTION_SIZE) < be->w){
+ be->sections.num_x++;
+ }
+ be->sections.num_y = (ubyte)(be->h / MAX_BMAP_SECTION_SIZE);
+ if((be->sections.num_y * MAX_BMAP_SECTION_SIZE) < be->h){
+ be->sections.num_y++;
+ }
+
+ // calculate the offsets for each section
+ for(idx=0; idx<be->sections.num_x; idx++){
+ be->sections.sx[idx] = (ushort)(MAX_BMAP_SECTION_SIZE * idx);
+ }
+ for(idx=0; idx<be->sections.num_y; idx++){
+ be->sections.sy[idx] = (ushort)(MAX_BMAP_SECTION_SIZE * idx);
+ }
+}
+
+// Creates a bitmap that exists in RAM somewhere, instead
+// of coming from a disk file. You pass in a pointer to a
+// block of 32 (or 8)-bit-per-pixel data. Right now, the only
+// bpp you can pass in is 32 or 8. On success, it returns the
+// bitmap number. You cannot free that RAM until bm_release
+// is called on that bitmap.
+int bm_create( int bpp, int w, int h, void * data, int flags )
+{
+ int i, n, first_slot = MAX_BITMAPS;
+
+ // Assert((bpp==32)||(bpp==8));
+ if(bpp != 16){
+ Assert(flags & BMP_AABITMAP);
+ } else {
+ Assert(bpp == 16);
+ }
+
+ if ( !bm_inited ) bm_init();
+
+ for (i = MAX_BITMAPS-1; i >= 0; i-- ) {
+ if ( bm_bitmaps[i].type == BM_TYPE_NONE ) {
+ first_slot = i;
+ break;
+ }
+ }
+
+ n = first_slot;
+ Assert( n > -1 );
+
+ // Out of bitmap slots
+ if ( n == -1 ) return -1;
+
+ memset( &bm_bitmaps[n], 0, sizeof(bitmap_entry) );
+
+ sprintf( bm_bitmaps[n].filename, "TMP%dx%d", w, h );
+ bm_bitmaps[n].type = BM_TYPE_USER;
+ bm_bitmaps[n].palette_checksum = 0;
+
+ bm_bitmaps[n].bm.w = short(w);
+ bm_bitmaps[n].bm.h = short(h);
+ bm_bitmaps[n].bm.rowsize = short(w);
+ bm_bitmaps[n].bm.bpp = unsigned char(bpp);
+ bm_bitmaps[n].bm.flags = 0;
+ bm_bitmaps[n].bm.flags |= flags;
+ bm_bitmaps[n].bm.data = 0;
+ bm_bitmaps[n].bm.palette = NULL;
+
+ bm_bitmaps[n].info.user.bpp = ubyte(bpp);
+ bm_bitmaps[n].info.user.data = data;
+ bm_bitmaps[n].info.user.flags = ubyte(flags);
+
+ bm_bitmaps[n].signature = Bm_next_signature++;
+
+ bm_bitmaps[n].handle = bm_get_next_handle()*MAX_BITMAPS + n;
+ bm_bitmaps[n].last_used = -1;
+
+ // fill in section info
+ bm_calc_sections(&bm_bitmaps[n].bm);
+
+ return bm_bitmaps[n].handle;
+}
+
+// sub helper function. Given a raw filename and an extension, try and find the bitmap
+// returns -1 if it could not be found
+// 0 if it was found as a file
+// 1 if it already exists, fills in handle
+int Bm_ignore_duplicates = 0;
+int bm_load_sub(char *real_filename, char *ext, int *handle)
+{
+ int i;
+ char filename[MAX_FILENAME_LEN] = "";
+
+ strcpy( filename, real_filename );
+ strcat( filename, ext );
+ for (i=0; i<(int)strlen(filename); i++ ){
+ filename[i] = char(tolower(filename[i]));
+ }
+
+ // try to find given filename to see if it has been loaded before
+ if(!Bm_ignore_duplicates){
+ for (i = 0; i < MAX_BITMAPS; i++) {
+ if ( (bm_bitmaps[i].type != BM_TYPE_NONE) && !stricmp(filename, bm_bitmaps[i].filename) ) {
+ nprintf (("BmpMan", "Found bitmap %s -- number %d\n", filename, i));
+ *handle = bm_bitmaps[i].handle;
+ return 1;
+ }
+ }
+ }
+
+ // try and find the file
+ /*
+ CFILE *test = cfopen(filename, "rb");
+ if(test != NULL){
+ cfclose(test);
+ return 0;
+ }
+ */
+
+ // could not be found
+ return 0;
+}
+
+// This loads a bitmap so we can draw with it later.
+// It returns a negative number if it couldn't load
+// the bitmap. On success, it returns the bitmap
+// number. Function doesn't acutally load the data, only
+// width, height, and possibly flags.
+int bm_load( char * real_filename )
+{
+ int i, n, first_slot = MAX_BITMAPS;
+ int w, h, bpp;
+ char filename[MAX_FILENAME_LEN];
+ int tga = 0;
+ int handle;
+ int found = 0;
+
+ if ( !bm_inited ) bm_init();
+
+ // nice little trick for keeping standalone memory usage way low - always return a bogus bitmap
+ if(Game_mode & GM_STANDALONE_SERVER){
+ strcpy(filename,"test128");
+ }
+
+ // make sure no one passed an extension
+ strcpy( filename, real_filename );
+ char *p = strchr( filename, '.' );
+ if ( p ) {
+ mprintf(( "Someone passed an extension to bm_load for file '%s'\n", real_filename ));
+ //Int3();
+ *p = 0;
+ }
+
+ // try and find the pcx file
+ switch(bm_load_sub(filename, ".pcx", &handle)){
+ // error
+ case -1:
+ break;
+
+ // found as a file
+ case 0:
+ found = 1;
+ strcat(filename, ".pcx");
+ break;
+
+ // found as pre-existing
+ case 1:
+ found = 1;
+ return handle;
+ }
+
+ if(!found){
+ // try and find the tga file
+ switch(bm_load_sub(filename, ".tga", &handle)){
+ // error
+ case -1:
+ return -1;
+ break;
+
+ // found as a file
+ case 0:
+ strcat(filename, ".tga");
+ tga = 1;
+ break;
+
+ // found as pre-existing
+ case 1:
+ return handle;
+ }
+ }
+
+ // if its a tga file
+ if(tga){
+ int tga_error=targa_read_header( filename, &w, &h, &bpp, NULL );
+ if ( tga_error != TARGA_ERROR_NONE ) {
+ mprintf(( "Couldn't open '%s'\n", filename ));
+ return -1;
+ }
+ }
+ // if its a pcx file
+ else {
+ int pcx_error=pcx_read_header( filename, &w, &h, NULL );
+ if ( pcx_error != PCX_ERROR_NONE ) {
+ mprintf(( "Couldn't open '%s'\n", filename ));
+ return -1;
+ }
+ }
+
+ // Error( LOCATION, "Unknown bitmap type %s\n", filename );
+
+ // Find an open slot
+ for (i = 0; i < MAX_BITMAPS; i++) {
+ if ( (bm_bitmaps[i].type == BM_TYPE_NONE) && (first_slot == MAX_BITMAPS) ){
+ first_slot = i;
+ }
+ }
+
+ n = first_slot;
+ Assert( n < MAX_BITMAPS );
+
+ if ( n == MAX_BITMAPS ) return -1;
+
+ // ensure fields are cleared out from previous bitmap
+// Assert(bm_bitmaps[n].bm.data == 0);
+// Assert(bm_bitmaps[n].bm.palette == NULL);
+// Assert(bm_bitmaps[n].ref_count == 0 );
+// Assert(bm_bitmaps[n].user_data == NULL);
+ memset( &bm_bitmaps[n], 0, sizeof(bitmap_entry) );
+
+ // Mark the slot as filled, because cf_read might load a new bitmap
+ // into this slot.
+ bm_bitmaps[n].type = tga ? (ubyte)BM_TYPE_TGA : (ubyte)BM_TYPE_PCX;
+ bm_bitmaps[n].signature = Bm_next_signature++;
+ Assert ( strlen(filename) < MAX_FILENAME_LEN );
+ strncpy(bm_bitmaps[n].filename, filename, MAX_FILENAME_LEN-1 );
+ bm_bitmaps[n].bm.w = short(w);
+ bm_bitmaps[n].bm.rowsize = short(w);
+ bm_bitmaps[n].bm.h = short(h);
+ bm_bitmaps[n].bm.bpp = 0;
+ bm_bitmaps[n].bm.flags = 0;
+ bm_bitmaps[n].bm.data = 0;
+ bm_bitmaps[n].bm.palette = NULL;
+
+ bm_bitmaps[n].palette_checksum = 0;
+ bm_bitmaps[n].handle = bm_get_next_handle()*MAX_BITMAPS + n;
+ bm_bitmaps[n].last_used = -1;
+
+ // fill in section info
+ bm_calc_sections(&bm_bitmaps[n].bm);
+
+ return bm_bitmaps[n].handle;
+}
+
+// special load function. basically allows you to load a bitmap which already exists (by filename).
+// this is useful because in some cases we need to have a bitmap which is locked in screen format
+// _and_ texture format, such as pilot pics and squad logos
+int bm_load_duplicate(char *filename)
+{
+ int ret;
+
+ // ignore duplicates
+ Bm_ignore_duplicates = 1;
+
+ // load
+ ret = bm_load(filename);
+
+ // back to normal
+ Bm_ignore_duplicates = 0;
+
+ return ret;
+}
+
+DCF(bm_frag,"Shows BmpMan fragmentation")
+{
+ if ( Dc_command ) {
+
+ gr_clear();
+
+ int x=0, y=0;
+ int xs=2, ys=2;
+ int w=4, h=4;
+
+ for (int i=0; i<MAX_BITMAPS; i++ ) {
+ switch( bm_bitmaps[i].type ) {
+ case BM_TYPE_NONE:
+ gr_set_color(128,128,128);
+ break;
+ case BM_TYPE_PCX:
+ gr_set_color(255,0,0);
+ break;
+ case BM_TYPE_USER:
+ gr_set_color(0,255,0);
+ break;
+ case BM_TYPE_ANI:
+ gr_set_color(0,0,255);
+ break;
+ }
+
+ gr_rect( x+xs, y+ys, w, h );
+ x += w+xs+xs;
+ if ( x > 639 ) {
+ x = 0;
+ y += h + ys + ys;
+ }
+
+ }
+
+ gr_flip();
+ key_getch();
+ }
+}
+
+static int find_block_of(int n)
+{
+ int i, cnt, nstart;
+
+ cnt=0;
+ nstart = 0;
+ for (i=0; i<MAX_BITMAPS; i++ ) {
+ if ( bm_bitmaps[i].type == BM_TYPE_NONE ) {
+ if (cnt==0) nstart = i;
+ cnt++;
+ } else
+ cnt=0;
+ if ( cnt == n ) return nstart;
+ }
+
+ // Error( LOCATION, "Couldn't find block of %d frames\n", n );
+ return -1;
+}
+
+// ------------------------------------------------------------------
+// bm_load_animation()
+//
+// input: filename => filename of animation
+// nframes => OUTPUT parameter: number of frames in the animation
+// fps => OUTPUT/OPTIONAL parameter: intended fps for the animation
+//
+// returns: bitmap number of first frame in the animation
+//
+int bm_load_animation( char *real_filename, int *nframes, int *fps, int can_drop_frames)
+{
+ int i, n;
+ anim the_anim;
+ CFILE *fp;
+ char filename[MAX_FILENAME_LEN];
+
+ if ( !bm_inited ) bm_init();
+
+ strcpy( filename, real_filename );
+ char *p = strchr( filename, '.' );
+ if ( p ) {
+ mprintf(( "Someone passed an extension to bm_load_animation for file '%s'\n", real_filename ));
+ //Int3();
+ *p = 0;
+ }
+ strcat( filename, ".ani" );
+
+ if ( (fp = cfopen(filename, "rb")) == NULL ) {
+// Error(LOCATION,"Could not open filename %s in bm_load_ani()\n", filename);
+ return -1;
+ }
+
+ int reduced = 0;
+#ifndef NDEBUG
+ // for debug of ANI sizes
+ strcpy(the_anim.name, real_filename);
+#endif
+ anim_read_header(&the_anim, fp);
+ if ( can_drop_frames ) {
+ if ( Bm_low_mem == 1 ) {
+ reduced = 1;
+ the_anim.total_frames = ( the_anim.total_frames+1)/2;
+ } else if ( Bm_low_mem == 2 ) {
+ the_anim.total_frames = 1;
+ }
+ }
+ cfclose(fp);
+
+ *nframes = the_anim.total_frames;
+ if ( fps != NULL ) {
+ if ( reduced ) {
+ *fps = the_anim.fps / 2;
+ } else {
+ *fps = the_anim.fps;
+ }
+ }
+
+ // first check to see if this ani already has it's frames loaded
+ for (i = 0; i < MAX_BITMAPS; i++) {
+ if ( (bm_bitmaps[i].type == BM_TYPE_ANI) && !stricmp(filename, bm_bitmaps[i].filename) ) {
+ break;
+ }
+ }
+
+ if ( i < MAX_BITMAPS ) {
+ // in low memory modes this can happen
+ if(!Bm_low_mem){
+ Assert(bm_bitmaps[i].info.ani.num_frames == *nframes);
+ }
+ return bm_bitmaps[i].handle;
+ }
+
+ n = find_block_of(*nframes);
+ if(n < 0){
+ return -1;
+ }
+ // Assert( n >= 0 );
+
+ int first_handle = bm_get_next_handle();
+
+ Assert ( strlen(filename) < MAX_FILENAME_LEN );
+ for ( i = 0; i < *nframes; i++ ) {
+ memset( &bm_bitmaps[n+i], 0, sizeof(bitmap_entry) );
+ bm_bitmaps[n+i].info.ani.first_frame = n;
+ bm_bitmaps[n+i].info.ani.num_frames = ubyte(the_anim.total_frames);
+ bm_bitmaps[n+i].info.ani.fps = ubyte(the_anim.fps);
+ bm_bitmaps[n+i].bm.w = short(the_anim.width);
+ bm_bitmaps[n+i].bm.rowsize = short(the_anim.width);
+ bm_bitmaps[n+i].bm.h = short(the_anim.height);
+ if ( reduced ) {
+ bm_bitmaps[n+i].bm.w /= 2;
+ bm_bitmaps[n+i].bm.rowsize /= 2;
+ bm_bitmaps[n+i].bm.h /= 2;
+ }
+ bm_bitmaps[n+i].bm.flags = 0;
+ bm_bitmaps[n+i].bm.bpp = 0;
+ bm_bitmaps[n+i].bm.data = 0;
+ bm_bitmaps[n+i].bm.palette = NULL;
+ bm_bitmaps[n+i].type = BM_TYPE_ANI;
+ bm_bitmaps[n+i].palette_checksum = 0;
+ bm_bitmaps[n+i].signature = Bm_next_signature++;
+ bm_bitmaps[n+i].handle = first_handle*MAX_BITMAPS + n+i;
+ bm_bitmaps[n+i].last_used = -1;
+
+ // fill in section info
+ bm_calc_sections(&bm_bitmaps[n+i].bm);
+
+ if ( i == 0 ) {
+ sprintf( bm_bitmaps[n+i].filename, "%s", filename );
+ } else {
+ sprintf( bm_bitmaps[n+i].filename, "%s[%d]", filename, i );
+ }
+ }
+
+ return bm_bitmaps[n].handle;
+}
+
+// Gets info. w,h,or flags,nframes or fps can be NULL if you don't care.
+void bm_get_info( int handle, int *w, int * h, ubyte * flags, int *nframes, int *fps, bitmap_section_info **sections )
+{
+ bitmap * bmp;
+
+ if ( !bm_inited ) return;
+
+ int bitmapnum = handle % MAX_BITMAPS;
+ Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE!
+
+ if ( (bm_bitmaps[bitmapnum].type == BM_TYPE_NONE) || (bm_bitmaps[bitmapnum].handle != handle) ) {
+ if (w) *w = 0;
+ if (h) *h = 0;
+ if (flags) *flags = 0;
+ if (nframes) *nframes=0;
+ if (fps) *fps=0;
+ if (sections != NULL) *sections = NULL;
+ return;
+ }
+
+ bmp = &(bm_bitmaps[bitmapnum].bm);
+
+ if (w) *w = bmp->w;
+ if (h) *h = bmp->h;
+ if (flags) *flags = bmp->flags;
+ if ( bm_bitmaps[bitmapnum].type == BM_TYPE_ANI ) {
+ if (nframes) {
+ *nframes = bm_bitmaps[bitmapnum].info.ani.num_frames;
+ }
+ if (fps) {
+ *fps= bm_bitmaps[bitmapnum].info.ani.fps;
+ }
+ } else {
+ if (nframes) {
+ *nframes = 1;
+ }
+ if (fps) {
+ *fps= 0;
+ }
+ }
+ if(sections != NULL){
+ *sections = &bm_bitmaps[bitmapnum].bm.sections;
+ }
+}
+
+uint bm_get_signature( int handle )
+{
+ if ( !bm_inited ) bm_init();
+
+ int bitmapnum = handle % MAX_BITMAPS;
+ Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE
+
+ return bm_bitmaps[bitmapnum].signature;
+}
+
+extern int palman_is_nondarkening(int r,int g, int b);
+static void bm_convert_format( int bitmapnum, bitmap *bmp, ubyte bpp, ubyte flags )
+{
+ int idx;
+ int r, g, b, a;
+
+ if(Fred_running || Pofview_running || Is_standalone){
+ Assert(bmp->bpp == 8);
+
+ return;
+ } else {
+ if(flags & BMP_AABITMAP){
+ Assert(bmp->bpp == 8);
+ } else {
+ Assert(bmp->bpp == 16);
+ }
+ }
+
+ // maybe swizzle to be an xparent texture
+ if(!(bmp->flags & BMP_TEX_XPARENT) && (flags & BMP_TEX_XPARENT)){
+ for(idx=0; idx<bmp->w*bmp->h; idx++){
+
+ // if the pixel is transparent
+ if ( ((ushort*)bmp->data)[idx] == Gr_t_green.mask) {
+ switch(Bm_pixel_format){
+ // 1555, all we need to do is zero the whole thing
+ case BM_PIXEL_FORMAT_ARGB:
+ case BM_PIXEL_FORMAT_ARGB_D3D:
+ ((ushort*)bmp->data)[idx] = 0;
+ break;
+ // d3d format
+ case BM_PIXEL_FORMAT_D3D:
+ r = g = b = a = 0;
+ r /= Gr_t_red.scale;
+ g /= Gr_t_green.scale;
+ b /= Gr_t_blue.scale;
+ a /= Gr_t_alpha.scale;
+ ((ushort*)bmp->data)[idx] = unsigned short((a<<Gr_t_alpha.shift) | (r << Gr_t_red.shift) | (g << Gr_t_green.shift) | (b << Gr_t_blue.shift));
+ break;
+ default:
+ Int3();
+ }
+ }
+ }
+
+ bmp->flags |= BMP_TEX_XPARENT;
+ }
+}
+
+// basically, map the bitmap into the current palette. used to be done for all pcx's, now just for
+// Fred, since its the only thing that uses the software tmapper
+void bm_swizzle_8bit_for_fred(bitmap_entry *be, bitmap *bmp, ubyte *data, ubyte *palette)
+{
+ int pcx_xparent_index = -1;
+ int i;
+ int r, g, b;
+ ubyte palxlat[256];
+
+ for (i=0; i<256; i++ ) {
+ r = palette[i*3];
+ g = palette[i*3+1];
+ b = palette[i*3+2];
+ if ( g == 255 && r == 0 && b == 0 ) {
+ palxlat[i] = 255;
+ pcx_xparent_index = i;
+ } else {
+ palxlat[i] = (ubyte)(palette_find( r, g, b ));
+ }
+ }
+ for (i=0; i<bmp->w * bmp->h; i++ ) {
+ ubyte c = palxlat[data[i]];
+ data[i] = c;
+ }
+ be->palette_checksum = gr_palette_checksum;
+}
+
+void bm_lock_pcx( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags )
+{
+ ubyte *data, *palette;
+ ubyte pal[768];
+ palette = NULL;
+
+ // Unload any existing data
+ bm_free_data( bitmapnum );
+
+ // allocate bitmap data
+ if(bpp == 8){
+ // Assert(Fred_running || Pofview_running || Is_standalone);
+ data = (ubyte *)bm_malloc(bitmapnum, bmp->w * bmp->h );
+ #ifdef BMPMAN_NDEBUG
+ Assert( be->data_size == bmp->w * bmp->h );
+ #endif
+ palette = pal;
+ bmp->data = (uint)data;
+ bmp->bpp = 8;
+ bmp->palette = gr_palette;
+ memset( data, 0, bmp->w * bmp->h);
+ } else {
+ data = (ubyte*)bm_malloc(bitmapnum, bmp->w * bmp->h * 2);
+ bmp->bpp = 16;
+ bmp->data = (uint)data;
+ bmp->palette = NULL;
+ memset( data, 0, bmp->w * bmp->h * 2);
+ }
+
+ Assert( &be->bm == bmp );
+ #ifdef BMPMAN_NDEBUG
+ Assert( be->data_size > 0 );
+ #endif
+
+ // some sanity checks on flags
+ Assert(!((flags & BMP_AABITMAP) && (flags & BMP_TEX_ANY))); // no aabitmap textures
+ Assert(!((flags & BMP_TEX_XPARENT) && (flags & BMP_TEX_NONDARK))); // can't be a transparent texture and a nondarkening texture
+ Assert(!((flags & BMP_TEX_NONDARK) && (gr_screen.mode == GR_DIRECT3D))); // D3D should never be trying to get nondarkening textures
+
+ if(bpp == 8){
+ int pcx_error=pcx_read_bitmap_8bpp( be->filename, data, palette );
+ if ( pcx_error != PCX_ERROR_NONE ) {
+ // Error( LOCATION, "Couldn't open '%s'\n", be->filename );
+ //Error( LOCATION, "Couldn't open '%s'\n", filename );
+ //return -1;
+ }
+
+ // now swizzle the thing into the proper format
+ if(Fred_running || Pofview_running){
+ bm_swizzle_8bit_for_fred(be, bmp, data, palette);
+ }
+ } else {
+ int pcx_error;
+
+ // load types
+ if(flags & BMP_AABITMAP){
+ pcx_error = pcx_read_bitmap_16bpp_aabitmap( be->filename, data );
+ } else if(flags & BMP_TEX_NONDARK){
+ pcx_error = pcx_read_bitmap_16bpp_nondark( be->filename, data );
+ } else {
+ pcx_error = pcx_read_bitmap_16bpp( be->filename, data );
+ }
+ if ( pcx_error != PCX_ERROR_NONE ) {
+ // Error( LOCATION, "Couldn't open '%s'\n", be->filename );
+ //Error( LOCATION, "Couldn't open '%s'\n", filename );
+ //return -1;
+ }
+ }
+
+ #ifdef BMPMAN_NDEBUG
+ Assert( be->data_size > 0 );
+ #endif
+
+ bmp->flags = 0;
+ bm_convert_format( bitmapnum, bmp, bpp, flags );
+}
+
+void bm_lock_ani( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags )
+{
+ anim *the_anim;
+ anim_instance *the_anim_instance;
+ bitmap *bm;
+ ubyte *frame_data;
+ int size, i;
+ int first_frame, nframes;
+
+ first_frame = be->info.ani.first_frame;
+ nframes = bm_bitmaps[first_frame].info.ani.num_frames;
+
+ if ( (the_anim = anim_load(bm_bitmaps[first_frame].filename)) == NULL ) {
+ // Error(LOCATION, "Error opening %s in bm_lock\n", be->filename);
+ }
+
+ if ( (the_anim_instance = init_anim_instance(the_anim, bpp)) == NULL ) {
+ // Error(LOCATION, "Error opening %s in bm_lock\n", be->filename);
+ anim_free(the_anim);
+ }
+
+ int can_drop_frames = 0;
+
+ if ( the_anim->total_frames != bm_bitmaps[first_frame].info.ani.num_frames ) {
+ can_drop_frames = 1;
+ }
+ bm = &bm_bitmaps[first_frame].bm;
+ if(bpp == 16){
+ size = bm->w * bm->h * 2;
+ } else {
+ size = bm->w * bm->h;
+ }
+
+ for ( i=0; i<nframes; i++ ) {
+ be = &bm_bitmaps[first_frame+i];
+ bm = &bm_bitmaps[first_frame+i].bm;
+
+ // Unload any existing data
+ bm_free_data( first_frame+i );
+
+ bm->flags = 0;
+ // briefing editor in Fred2 uses aabitmaps (ani's) - force to 8 bit
+ if(Fred_running || Is_standalone){
+ bm->bpp = 8;
+ } else {
+ bm->bpp = bpp;
+ }
+ bm->data = (uint)bm_malloc(first_frame + i, size);
+
+ frame_data = anim_get_next_raw_buffer(the_anim_instance, 0 ,flags & BMP_AABITMAP ? 1 : 0, bm->bpp);
+
+ if ( frame_data == NULL ) {
+ // Error(LOCATION,"Fatal error locking .ani file: %s\n", be->filename);
+ }
+
+ ubyte *dptr, *sptr;
+
+ sptr = frame_data;
+ dptr = (ubyte *)bm->data;
+
+ if ( (bm->w!=the_anim->width) || (bm->h!=the_anim->height) ) {
+ // Scale it down
+ // Int3(); // not ready yet - should only be ingame
+
+ // 8 bit
+ if(bpp == 8){
+ int w,h;
+ fix u, utmp, v, du, dv;
+
+ u = v = 0;
+
+ du = ( the_anim->width*F1_0 ) / bm->w;
+ dv = ( the_anim->height*F1_0 ) / bm->h;
+
+ for (h = 0; h < bm->h; h++) {
+ ubyte *drow = &dptr[bm->w * h];
+ ubyte *srow = &sptr[f2i(v)*the_anim->width];
+
+ utmp = u;
+
+ for (w = 0; w < bm->w; w++) {
+ *drow++ = srow[f2i(utmp)];
+ utmp += du;
+ }
+ v += dv;
+ }
+ }
+ // 16 bpp
+ else {
+ int w,h;
+ fix u, utmp, v, du, dv;
+
+ u = v = 0;
+
+ du = ( the_anim->width*F1_0 ) / bm->w;
+ dv = ( the_anim->height*F1_0 ) / bm->h;
+
+ for (h = 0; h < bm->h; h++) {
+ ushort *drow = &((ushort*)dptr)[bm->w * h];
+ ushort *srow = &((ushort*)sptr)[f2i(v)*the_anim->width];
+
+ utmp = u;
+
+ for (w = 0; w < bm->w; w++) {
+ *drow++ = srow[f2i(utmp)];
+ utmp += du;
+ }
+ v += dv;
+ }
+ }
+ } else {
+ // 1-to-1 mapping
+ memcpy(dptr, sptr, size);
+ }
+
+ bm_convert_format( first_frame+i, bm, bpp, flags );
+
+ // Skip a frame
+ if ( (i < nframes-1) && can_drop_frames ) {
+ frame_data = anim_get_next_raw_buffer(the_anim_instance, 0, flags & BMP_AABITMAP ? 1 : 0, bm->bpp);
+ }
+
+ //mprintf(( "Checksum = %d\n", be->palette_checksum ));
+ }
+
+ free_anim_instance(the_anim_instance);
+ anim_free(the_anim);
+}
+
+
+void bm_lock_user( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags )
+{
+ // int idx;
+ // ushort bit_16;
+
+ // Unload any existing data
+ bm_free_data( bitmapnum );
+
+ switch( be->info.user.bpp ) {
+ case 16: // user 16 bit bitmap
+ bmp->bpp = bpp;
+ bmp->flags = be->info.user.flags;
+ bmp->data = (uint)be->info.user.data;
+ break;
+
+ case 8: // Going from 8 bpp to something (probably only for aabitmaps)
+ /*
+ Assert(flags & BMP_AABITMAP);
+ bmp->bpp = 16;
+ bmp->data = (uint)malloc(bmp->w * bmp->h * 2);
+ bmp->flags = be->info.user.flags;
+ bmp->palette = NULL;
+
+ // go through and map the pixels
+ for(idx=0; idx<bmp->w * bmp->h; idx++){
+ bit_16 = (ushort)((ubyte*)be->info.user.data)[idx];
+ Assert(bit_16 <= 255);
+
+ // stuff the final result
+ memcpy((char*)bmp->data + (idx * 2), &bit_16, sizeof(ushort));
+ }
+ */
+ Assert(flags & BMP_AABITMAP);
+ bmp->bpp = bpp;
+ bmp->flags = be->info.user.flags;
+ bmp->data = (uint)be->info.user.data;
+ break;
+
+ // default:
+ // Error( LOCATION, "Unhandled user bitmap conversion from %d to %d bpp", be->info.user.bpp, bmp->bpp );
+ }
+
+ bm_convert_format( bitmapnum, bmp, bpp, flags );
+}
+
+void bm_lock_tga( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags )
+{
+ ubyte *data;
+
+ // Unload any existing data
+ bm_free_data( bitmapnum );
+
+ if(Fred_running || Is_standalone){
+ Assert(bpp == 8);
+ } else {
+ Assert(bpp == 16);
+ }
+
+ // should never try to make an aabitmap out of a targa
+ Assert(!(flags & BMP_AABITMAP));
+
+ // allocate bitmap data
+ if(bpp == 16){
+ data = (ubyte*)bm_malloc(bitmapnum, bmp->w * bmp->h * 2);
+ } else {
+ data = (ubyte*)bm_malloc(bitmapnum, bmp->w * bmp->h);
+ }
+ bmp->bpp = bpp;
+ bmp->data = (uint)data;
+ bmp->palette = NULL;
+ if(bpp == 16){
+ memset( data, 0, bmp->w * bmp->h * 2);
+ } else {
+ memset( data, 0, bmp->w * bmp->h );
+ }
+
+ Assert( &be->bm == bmp );
+ #ifdef BMPMAN_NDEBUG
+ Assert( be->data_size > 0 );
+ #endif
+
+ int tga_error=targa_read_bitmap( be->filename, data, NULL, (bpp == 16) ? 2 : 1);
+ if ( tga_error != TARGA_ERROR_NONE ) {
+ // Error( LOCATION, "Couldn't open '%s'\n", be->filename );
+ //Error( LOCATION, "Couldn't open '%s'\n", filename );
+ //return -1;
+ }
+
+ #ifdef BMPMAN_NDEBUG
+ Assert( be->data_size > 0 );
+ #endif
+
+ bmp->flags = 0;
+ bm_convert_format( bitmapnum, bmp, bpp, flags );
+}
+
+MONITOR( NumBitmapPage );
+MONITOR( SizeBitmapPage );
+
+// This locks down a bitmap and returns a pointer to a bitmap
+// that can be accessed until you call bm_unlock. Only lock
+// a bitmap when you need it! This will convert it into the
+// appropriate format also.
+bitmap * bm_lock( int handle, ubyte bpp, ubyte flags )
+{
+ bitmap *bmp;
+ bitmap_entry *be;
+
+
+ if ( !bm_inited ) bm_init();
+
+ int bitmapnum = handle % MAX_BITMAPS;
+ Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE
+
+// flags &= (~BMP_RLE);
+
+ // if we're on a standalone server, aways for it to lock to 8 bits
+ if(Is_standalone){
+ bpp = 8;
+ flags = 0;
+ }
+ // otherwise do it as normal
+ else {
+ if(Fred_running || Pofview_running){
+ Assert( bpp == 8 );
+ Assert( (bm_bitmaps[bitmapnum].type == BM_TYPE_PCX) || (bm_bitmaps[bitmapnum].type == BM_TYPE_ANI) || (bm_bitmaps[bitmapnum].type == BM_TYPE_TGA));
+ } else {
+ if(flags & BMP_AABITMAP){
+ Assert( bpp == 8 );
+ } else {
+ Assert( bpp == 16 );
+ }
+ }
+ }
+
+ be = &bm_bitmaps[bitmapnum];
+ bmp = &be->bm;
+
+ // If you hit this assert, chances are that someone freed the
+ // wrong bitmap and now someone is trying to use that bitmap.
+ // See John.
+ Assert( be->type != BM_TYPE_NONE );
+
+ // Increment ref count for bitmap since lock was made on it.
+ Assert(be->ref_count >= 0);
+ be->ref_count++; // Lock it before we page in data; this prevents a callback from freeing this
+ // as it gets read in
+
+ // Mark this bitmap as used this frame
+ #ifdef BMPMAN_NDEBUG
+ if ( be->used_this_frame < 255 ) {
+ be->used_this_frame++;
+ }
+ #endif
+
+ // if bitmap hasn't been loaded yet, then load it from disk
+ // reread the bitmap from disk under certain conditions
+ int pal_changed = 0;
+ int rle_changed = 0;
+ int fake_xparent_changed = 0;
+ if ( (bmp->data == NULL) || (bpp != bmp->bpp) || pal_changed || rle_changed || fake_xparent_changed ) {
+ Assert(be->ref_count == 1);
+
+ if ( be->type != BM_TYPE_USER ) {
+ if ( bmp->data == NULL ) {
+ nprintf (("BmpMan","Loading %s for the first time.\n", be->filename));
+ } else if ( bpp != bmp->bpp ) {
+ nprintf (("BmpMan","Reloading %s from bitdepth %d to bitdepth %d\n", be->filename, bmp->bpp, bpp));
+ } else if ( pal_changed ) {
+ nprintf (("BmpMan","Reloading %s to remap palette\n", be->filename));
+ } else if ( rle_changed ) {
+ nprintf (("BmpMan","Reloading %s to change RLE.\n", be->filename));
+ } else if ( fake_xparent_changed ) {
+ nprintf (("BmpMan","Reloading %s to change fake xparency.\n", be->filename));
+ }
+ }
+
+ MONITOR_INC( NumBitmapPage, 1 );
+ MONITOR_INC( SizeBitmapPage, bmp->w*bmp->h );
+
+ if ( !Bm_paging ) {
+ if ( be->type != BM_TYPE_USER ) {
+ char flag_text[64];
+ strcpy( flag_text, "--" );
+ nprintf(( "Paging", "Loading %s (%dx%dx%dx%s)\n", be->filename, bmp->w, bmp->h, bpp, flag_text ));
+ }
+ }
+
+ // select proper format
+ if(flags & BMP_AABITMAP){
+ BM_SELECT_ALPHA_TEX_FORMAT();
+ } else if(flags & BMP_TEX_ANY){
+ BM_SELECT_TEX_FORMAT();
+ } else {
+ BM_SELECT_SCREEN_FORMAT();
+ }
+
+ switch ( be->type ) {
+ case BM_TYPE_PCX:
+ bm_lock_pcx( handle, bitmapnum, be, bmp, bpp, flags );
+ break;
+
+ case BM_TYPE_ANI:
+ bm_lock_ani( handle, bitmapnum, be, bmp, bpp, flags );
+ break;
+
+ case BM_TYPE_USER:
+ bm_lock_user( handle, bitmapnum, be, bmp, bpp, flags );
+ break;
+
+ case BM_TYPE_TGA:
+ bm_lock_tga( handle, bitmapnum, be, bmp, bpp, flags );
+ break;
+
+ default:
+ Warning(LOCATION, "Unsupported type in bm_lock -- %d\n", be->type );
+ return NULL;
+ }
+
+ // always go back to screen format
+ BM_SELECT_SCREEN_FORMAT();
+ }
+
+ if ( be->type == BM_TYPE_ANI ) {
+ int i,first = bm_bitmaps[bitmapnum].info.ani.first_frame;
+
+ for ( i=0; i< bm_bitmaps[first].info.ani.num_frames; i++ ) {
+ // Mark all the bitmaps in this bitmap or animation as recently used
+ bm_bitmaps[first+i].last_used = timer_get_milliseconds();
+
+ // Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
+ #ifdef BMPMAN_NDEBUG
+ bm_bitmaps[first+i].used_count++;
+ #endif
+ bm_bitmaps[first+i].used_flags = flags;
+ }
+ } else {
+ // Mark all the bitmaps in this bitmap or animation as recently used
+ be->last_used = timer_get_milliseconds();
+
+ // Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
+ #ifdef BMPMAN_NDEBUG
+ be->used_count++;
+ #endif
+ be->used_flags = flags;
+ }
+
+ return bmp;
+}
+
+// Unlocks a bitmap
+//
+// Decrements the ref_count member of the bitmap_entry struct. A bitmap can only be unloaded
+// when the ref_count is 0.
+//
+void bm_unlock( int handle )
+{
+ bitmap_entry *be;
+ bitmap *bmp;
+
+ int bitmapnum = handle % MAX_BITMAPS;
+ Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE
+
+ Assert(bitmapnum >= 0 && bitmapnum < MAX_BITMAPS);
+ if ( !bm_inited ) bm_init();
+
+ be = &bm_bitmaps[bitmapnum];
+ bmp = &be->bm;
+
+ be->ref_count--;
+ Assert(be->ref_count >= 0); // Trying to unlock data more times than lock was called!!!
+
+}
+
+
+void bm_update()
+{
+}
+
+char *bm_get_filename(int handle)
+{
+ int n;
+
+ n = handle % MAX_BITMAPS;
+ Assert(bm_bitmaps[n].handle == handle); // INVALID BITMAP HANDLE
+ return bm_bitmaps[n].filename;
+}
+
+void bm_get_palette(int handle, ubyte *pal, char *name)
+{
+ char *filename;
+ int w,h;
+
+ int n= handle % MAX_BITMAPS;
+ Assert( bm_bitmaps[n].handle == handle ); // INVALID BITMAP HANDLE
+
+ filename = bm_bitmaps[n].filename;
+
+ if (name) {
+ strcpy( name, filename );
+ }
+
+ int pcx_error=pcx_read_header( filename, &w, &h, pal );
+ if ( pcx_error != PCX_ERROR_NONE ){
+ // Error(LOCATION, "Couldn't open '%s'\n", filename );
+ }
+}
+
+// --------------------------------------------------------------------------------------
+// bm_release() - unloads the bitmap's data and entire slot, so bitmap 'n' won't be valid anymore
+//
+// parameters: n => index into bm_bitmaps ( index returned from bm_load() or bm_create() )
+//
+// returns: nothing
+
+void bm_release(int handle)
+{
+ bitmap_entry *be;
+
+ int n = handle % MAX_BITMAPS;
+
+ Assert(n >= 0 && n < MAX_BITMAPS);
+ be = &bm_bitmaps[n];
+
+ if ( bm_bitmaps[n].type == BM_TYPE_NONE ) {
+ return; // Already been released?
+ }
+
+ if ( bm_bitmaps[n].type != BM_TYPE_USER ) {
+ return;
+ }
+
+ Assert( be->handle == handle ); // INVALID BITMAP HANDLE
+
+ // If it is locked, cannot free it.
+ if (be->ref_count != 0) {
+ nprintf(("BmpMan", "tried to unload %s that has a lock count of %d.. not unloading\n", be->filename, be->ref_count));
+ return;
+ }
+
+ bm_free_data(n);
+
+ if ( bm_bitmaps[n].type == BM_TYPE_USER ) {
+ bm_bitmaps[n].info.user.data = NULL;
+ bm_bitmaps[n].info.user.bpp = 0;
+ }
+
+
+ bm_bitmaps[n].type = BM_TYPE_NONE;
+
+ // Fill in bogus structures!
+
+ // For debugging:
+ strcpy( bm_bitmaps[n].filename, "IVE_BEEN_RELEASED!" );
+ bm_bitmaps[n].signature = 0xDEADBEEF; // a unique signature identifying the data
+ bm_bitmaps[n].palette_checksum = 0xDEADBEEF; // checksum used to be sure bitmap is in current palette
+
+ // bookeeping
+ #ifdef BMPMAN_NDEBUG
+ bm_bitmaps[n].data_size = -1; // How much data this bitmap uses
+ #endif
+ bm_bitmaps[n].ref_count = -1; // Number of locks on bitmap. Can't unload unless ref_count is 0.
+
+ // Bitmap info
+ bm_bitmaps[n].bm.w = bm_bitmaps[n].bm.h = -1;
+
+ // Stuff needed for animations
+ // Stuff needed for user bitmaps
+ memset( &bm_bitmaps[n].info, 0, sizeof(bm_extra_info) );
+
+ bm_bitmaps[n].handle = -1;
+}
+
+
+
+
+
+
+// --------------------------------------------------------------------------------------
+// bm_unload() - unloads the data, but not the bitmap info.
+//
+// parameters: n => index into bm_bitmaps ( index returned from bm_load() or bm_create() )
+//
+// returns: 0 => unload failed
+// 1 => unload successful
+//
+int bm_unload( int handle )
+{
+ bitmap_entry *be;
+ bitmap *bmp;
+
+ int n = handle % MAX_BITMAPS;
+
+ Assert(n >= 0 && n < MAX_BITMAPS);
+ be = &bm_bitmaps[n];
+ bmp = &be->bm;
+
+ if ( be->type == BM_TYPE_NONE ) {
+ return 0; // Already been released
+ }
+
+ Assert( be->handle == handle ); // INVALID BITMAP HANDLE!
+
+ // If it is locked, cannot free it.
+ if (be->ref_count != 0) {
+ nprintf(("BmpMan", "tried to unload %s that has a lock count of %d.. not unloading\n", be->filename, be->ref_count));
+ return 0;
+ }
+
+ nprintf(("BmpMan", "unloading %s. %dx%dx%d\n", be->filename, bmp->w, bmp->h, bmp->bpp));
+ bm_free_data(n); // clears flags, bbp, data, etc
+
+ return 1;
+}
+
+
+// unload all used bitmaps
+void bm_unload_all()
+{
+ int i;
+
+ for (i = 0; i < MAX_BITMAPS; i++) {
+ if ( bm_bitmaps[i].type != BM_TYPE_NONE ) {
+ bm_unload(bm_bitmaps[i].handle);
+ }
+ }
+}
+
+
+DCF(bmpman,"Shows/changes bitmap caching parameters and usage")
+{
+ if ( Dc_command ) {
+ dc_get_arg(ARG_STRING);
+ if ( !strcmp( Dc_arg, "flush" )) {
+ dc_printf( "Total RAM usage before flush: %d bytes\n", bm_texture_ram );
+ int i;
+ for (i = 0; i < MAX_BITMAPS; i++) {
+ if ( bm_bitmaps[i].type != BM_TYPE_NONE ) {
+ bm_free_data(i);
+ }
+ }
+ dc_printf( "Total RAM after flush: %d bytes\n", bm_texture_ram );
+ } else if ( !strcmp( Dc_arg, "ram" )) {
+ dc_get_arg(ARG_INT);
+ Bm_max_ram = Dc_arg_int*1024*1024;
+ } else {
+ // print usage, not stats
+ Dc_help = 1;
+ }
+ }
+
+ if ( Dc_help ) {
+ dc_printf( "Usage: BmpMan keyword\nWhere keyword can be in the following forms:\n" );
+ dc_printf( "BmpMan flush Unloads all bitmaps.\n" );
+ dc_printf( "BmpMan ram x Sets max mem usage to x MB. (Set to 0 to have no limit.)\n" );
+ dc_printf( "\nUse '? BmpMan' to see status of Bitmap manager.\n" );
+ Dc_status = 0; // don't print status if help is printed. Too messy.
+ }
+
+ if ( Dc_status ) {
+ dc_printf( "Total RAM usage: %d bytes\n", bm_texture_ram );
+
+
+ if ( Bm_max_ram > 1024*1024 )
+ dc_printf( "Max RAM allowed: %.1f MB\n", i2fl(Bm_max_ram)/(1024.0f*1024.0f) );
+ else if ( Bm_max_ram > 1024 )
+ dc_printf( "Max RAM allowed: %.1f KB\n", i2fl(Bm_max_ram)/(1024.0f) );
+ else if ( Bm_max_ram > 0 )
+ dc_printf( "Max RAM allowed: %d bytes\n", Bm_max_ram );
+ else
+ dc_printf( "No RAM limit\n" );
+
+
+ }
+}
+
+// Marks a texture as being used for this level
+void bm_page_in_texture( int bitmapnum, int nframes )
+{
+ int i;
+ for (i=0; i<nframes;i++ ) {
+ int n = bitmapnum % MAX_BITMAPS;
+
+ bm_bitmaps[n+i].preloaded = 1;
+
+ if ( D3D_enabled ) {
+ bm_bitmaps[n+i].used_flags = BMP_TEX_OTHER;
+ } else {
+ bm_bitmaps[n+i].used_flags = 0;
+ }
+ }
+}
+
+// Marks a texture as being used for this level
+// If num_frames is passed, assume this is an animation
+void bm_page_in_nondarkening_texture( int bitmapnum, int nframes )
+{
+ int i;
+ for (i=0; i<nframes;i++ ) {
+ int n = bitmapnum % MAX_BITMAPS;
+
+ bm_bitmaps[n+i].preloaded = 4;
+
+ if ( D3D_enabled ) {
+ bm_bitmaps[n+i].used_flags = BMP_TEX_NONDARK;
+ } else {
+ bm_bitmaps[n+i].used_flags = 0;
+ }
+ }
+}
+
+// marks a texture as being a transparent textyre used for this level
+// Marks a texture as being used for this level
+// If num_frames is passed, assume this is an animation
+void bm_page_in_xparent_texture( int bitmapnum, int nframes)
+{
+ int i;
+ for (i=0; i<nframes;i++ ) {
+ int n = bitmapnum % MAX_BITMAPS;
+
+ bm_bitmaps[n+i].preloaded = 3;
+
+ if ( D3D_enabled ) {
+ // bm_bitmaps[n+i].used_flags = BMP_NO_PALETTE_MAP;
+ bm_bitmaps[n+i].used_flags = BMP_TEX_XPARENT;
+ } else {
+ bm_bitmaps[n+i].used_flags = 0;
+ }
+ }
+}
+
+// Marks an aabitmap as being used for this level
+void bm_page_in_aabitmap( int bitmapnum, int nframes )
+{
+ int i;
+
+ for (i=0; i<nframes;i++ ) {
+ int n = bitmapnum % MAX_BITMAPS;
+
+ bm_bitmaps[n+i].preloaded = 2;
+
+ if ( D3D_enabled ) {
+ bm_bitmaps[n+i].used_flags = BMP_AABITMAP;
+ } else {
+ bm_bitmaps[n+i].used_flags = 0;
+ }
+ }
+}
+
+
+
+// Tell the bitmap manager to start keeping track of what bitmaps are used where.
+void bm_page_in_start()
+{
+ int i;
+
+ Bm_paging = 1;
+
+ // Mark all as inited
+ for (i = 0; i < MAX_BITMAPS; i++) {
+ if ( bm_bitmaps[i].type != BM_TYPE_NONE ) {
+ bm_unload(bm_bitmaps[i].handle);
+ }
+ bm_bitmaps[i].preloaded = 0;
+ #ifdef BMPMAN_NDEBUG
+ bm_bitmaps[i].used_count = 0;
+ #endif
+ bm_bitmaps[i].used_flags = 0;
+ }
+
+}
+
+extern void gr_d3d_preload_init();
+extern int gr_d3d_preload(int bitmap_num, int is_aabitmap );
+
+void bm_page_in_stop()
+{
+ int i;
+ int ship_info_index;
+
+ nprintf(( "BmpInfo","BMPMAN: Loading all used bitmaps.\n" ));
+
+ // Load all the ones that are supposed to be loaded for this level.
+ int n = 0;
+
+ #ifdef BMPMAN_NDEBUG
+ Bm_ram_freed = 0;
+ #endif
+
+ int d3d_preloading = 1;
+
+ gr_d3d_preload_init();
+
+ for (i = 0; i < MAX_BITMAPS; i++) {
+ if ( bm_bitmaps[i].type != BM_TYPE_NONE ) {
+ if ( bm_bitmaps[i].preloaded ) {
+#ifdef BMPMAN_SPECIAL_NONDARK
+ // if this is a texture, check to see if a ship uses it
+ ship_info_index = ship_get_texture(bm_bitmaps[i].handle);
+ // use the colors from this ship
+ if((ship_info_index >= 0) && (Ship_info[ship_info_index].num_nondark_colors > 0)){
+ // mprintf(("Using custom pixels for %s\n", Ship_info[ship_info_index].name));
+ palman_set_nondarkening(Ship_info[ship_info_index].nondark_colors, Ship_info[ship_info_index].num_nondark_colors);
+ }
+ // use the colors from the default table
+ else {
+ // mprintf(("Using default pixels\n"));
+ palman_set_nondarkening(Palman_non_darkening_default, Palman_num_nondarkening_default);
+ }
+#endif
+
+ // if preloaded == 3, load it as an xparent texture
+ if(bm_bitmaps[i].used_flags == BMP_AABITMAP){
+ bm_lock( bm_bitmaps[i].handle, 8, bm_bitmaps[i].used_flags );
+ } else {
+ bm_lock( bm_bitmaps[i].handle, 16, bm_bitmaps[i].used_flags );
+ }
+ bm_unlock( bm_bitmaps[i].handle );
+
+ if ( d3d_preloading ) {
+ if ( !gr_d3d_preload(bm_bitmaps[i].handle, (bm_bitmaps[i].preloaded==2) ) ) {
+ mprintf(( "Out of VRAM. Done preloading.\n" ));
+ d3d_preloading = 0;
+ }
+ }
+
+ n++;
+ #ifdef BMPMAN_NDEBUG
+ if ( Bm_ram_freed ) {
+ nprintf(( "BmpInfo","BMPMAN: Not enough cache memory to load all level bitmaps\n" ));
+ break;
+ }
+ #endif
+ }
+ }
+ game_busy();
+ }
+ nprintf(( "BmpInfo","BMPMAN: Loaded %d bitmaps that are marked as used for this level.\n", n ));
+
+ int total_bitmaps = 0;
+ for (i = 0; i < MAX_BITMAPS; i++) {
+ if ( bm_bitmaps[i].type != BM_TYPE_NONE ) {
+ total_bitmaps++;
+ }
+ if ( bm_bitmaps[i].type == BM_TYPE_USER ) {
+ mprintf(( "User bitmap '%s'\n", bm_bitmaps[i].filename ));
+ }
+ }
+
+ mprintf(( "Bmpman: %d/%d bitmap slots in use.\n", total_bitmaps, MAX_BITMAPS ));
+ //mprintf(( "Bmpman: Usage went from %d KB to %d KB.\n", usage_before/1024, usage_after/1024 ));
+
+ Bm_paging = 0;
+}
+
+int bm_get_cache_slot( int bitmap_id, int separate_ani_frames )
+{
+ int n = bitmap_id % MAX_BITMAPS;
+
+ Assert( bm_bitmaps[n].handle == bitmap_id ); // INVALID BITMAP HANDLE
+
+ bitmap_entry *be = &bm_bitmaps[n];
+
+ if ( (!separate_ani_frames) && (be->type == BM_TYPE_ANI) ) {
+ return be->info.ani.first_frame;
+ }
+
+ return n;
+
+}
+
+// convert a 24 bit value to a 16 bit value
+void bm_24_to_16(int bit_24, ushort *bit_16)
+{
+ ubyte *pixel = (ubyte*)&bit_24;
+ ubyte alpha = 1;
+
+ bm_set_components((ubyte*)bit_16, (ubyte*)&pixel[0], (ubyte*)&pixel[1], (ubyte*)&pixel[2], &alpha);
+}
+
+extern int D3D_32bit;
+
+void (*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
+
+void bm_set_components_argb(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av)
+{
+ // rgba
+ *((ushort*)pixel) |= (ushort)(( (int)*rv / Gr_current_red->scale ) << Gr_current_red->shift);
+ *((ushort*)pixel) |= (ushort)(( (int)*gv / Gr_current_green->scale ) << Gr_current_green->shift);
+ *((ushort*)pixel) |= (ushort)(( (int)*bv / Gr_current_blue->scale ) << Gr_current_blue->shift);
+ *((ushort*)pixel) &= ~(0x8000);
+ if(*av){
+ *((ushort*)pixel) |= 0x8000;
+ }
+}
+
+void bm_set_components_d3d(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av)
+{
+ // rgba
+ *((ushort*)pixel) |= (ushort)(( (int)*rv / Gr_current_red->scale ) << Gr_current_red->shift);
+ *((ushort*)pixel) |= (ushort)(( (int)*gv / Gr_current_green->scale ) << Gr_current_green->shift);
+ *((ushort*)pixel) |= (ushort)(( (int)*bv / Gr_current_blue->scale ) << Gr_current_blue->shift);
+ if(*av == 0){
+ *((ushort*)pixel) = (ushort)Gr_current_green->mask;
+ }
+}
+
+void bm_set_components_argb_d3d_16_screen(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av)
+{
+ *((ushort*)pixel) |= (ushort)(( (int)*rv / Gr_current_red->scale ) << Gr_current_red->shift);
+ *((ushort*)pixel) |= (ushort)(( (int)*gv / Gr_current_green->scale ) << Gr_current_green->shift);
+ *((ushort*)pixel) |= (ushort)(( (int)*bv / Gr_current_blue->scale ) << Gr_current_blue->shift);
+ if(*av == 0){
+ *((ushort*)pixel) = (ushort)Gr_current_green->mask;
+ }
+}
+
+void bm_set_components_argb_d3d_32_screen(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av)
+{
+ *((uint*)pixel) |= (uint)(( (int)*rv / Gr_current_red->scale ) << Gr_current_red->shift);
+ *((uint*)pixel) |= (uint)(( (int)*gv / Gr_current_green->scale ) << Gr_current_green->shift);
+ *((uint*)pixel) |= (uint)(( (int)*bv / Gr_current_blue->scale ) << Gr_current_blue->shift);
+ if(*av == 0){
+ *((uint*)pixel) = (uint)Gr_current_green->mask;
+ }
+}
+
+void bm_set_components_argb_d3d_16_tex(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av)
+{
+ *((ushort*)pixel) |= (ushort)(( (int)*rv / Gr_current_red->scale ) << Gr_current_red->shift);
+ *((ushort*)pixel) |= (ushort)(( (int)*gv / Gr_current_green->scale ) << Gr_current_green->shift);
+ *((ushort*)pixel) |= (ushort)(( (int)*bv / Gr_current_blue->scale ) << Gr_current_blue->shift);
+ *((ushort*)pixel) &= ~(Gr_current_alpha->mask);
+ if(*av){
+ *((ushort*)pixel) |= (ushort)(Gr_current_alpha->mask);
+ } else {
+ *((ushort*)pixel) = 0;
+ }
+}
+
+void bm_set_components_argb_d3d_32_tex(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av)
+{
+ *((ushort*)pixel) |= (ushort)(( (int)*rv / Gr_current_red->scale ) << Gr_current_red->shift);
+ *((ushort*)pixel) |= (ushort)(( (int)*gv / Gr_current_green->scale ) << Gr_current_green->shift);
+ *((ushort*)pixel) |= (ushort)(( (int)*bv / Gr_current_blue->scale ) << Gr_current_blue->shift);
+ *((ushort*)pixel) &= ~(Gr_current_alpha->mask);
+ if(*av){
+ *((ushort*)pixel) |= (ushort)(Gr_current_alpha->mask);
+ } else {
+ *((ushort*)pixel) = 0;
+ }
+}
+
+// for selecting pixel formats
+void BM_SELECT_SCREEN_FORMAT()
+{
+ Gr_current_red = &Gr_red;
+ Gr_current_green = &Gr_green;
+ Gr_current_blue = &Gr_blue;
+ Gr_current_alpha = &Gr_alpha;
+
+ // setup pointers
+ if(gr_screen.mode == GR_GLIDE){
+ bm_set_components = bm_set_components_argb;
+ } else if(gr_screen.mode == GR_DIRECT3D){
+ if(Bm_pixel_format == BM_PIXEL_FORMAT_D3D){
+ bm_set_components = bm_set_components_d3d;
+ } else {
+ if(D3D_32bit){
+ bm_set_components = bm_set_components_argb_d3d_32_screen;
+ } else {
+ bm_set_components = bm_set_components_argb_d3d_16_screen;
+ }
+ }
+ }
+}
+
+void BM_SELECT_TEX_FORMAT()
+{
+ Gr_current_red = &Gr_t_red;
+ Gr_current_green = &Gr_t_green;
+ Gr_current_blue = &Gr_t_blue;
+ Gr_current_alpha = &Gr_t_alpha;
+
+ // setup pointers
+ if(gr_screen.mode == GR_GLIDE){
+ bm_set_components = bm_set_components_argb;
+ } else if(gr_screen.mode == GR_DIRECT3D){
+ if(Bm_pixel_format == BM_PIXEL_FORMAT_D3D){
+ bm_set_components = bm_set_components_d3d;
+ } else {
+ if(D3D_32bit){
+ bm_set_components = bm_set_components_argb_d3d_32_tex;
+ } else {
+ bm_set_components = bm_set_components_argb_d3d_16_tex;
+ }
+ }
+ }
+}
+
+void BM_SELECT_ALPHA_TEX_FORMAT()
+{
+ Gr_current_red = &Gr_ta_red;
+ Gr_current_green = &Gr_ta_green;
+ Gr_current_blue = &Gr_ta_blue;
+ Gr_current_alpha = &Gr_ta_alpha;
+
+ // setup pointers
+ if(gr_screen.mode == GR_GLIDE){
+ bm_set_components = bm_set_components_argb;
+ } else if(gr_screen.mode == GR_DIRECT3D){
+ if(Bm_pixel_format == BM_PIXEL_FORMAT_D3D){
+ bm_set_components = bm_set_components_d3d;
+ } else {
+ if(D3D_32bit){
+ bm_set_components = bm_set_components_argb_d3d_32_tex;
+ } else {
+ bm_set_components = bm_set_components_argb_d3d_16_tex;
+ }
+ }
+ }
+}
+
+// set the rgba components of a pixel, any of the parameters can be -1
+/*
+void bm_set_components(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av)
+{
+ int bit_32 = 0;
+
+ // pick a byte size - 32 bits only if 32 bit mode d3d and screen format
+ if(D3D_32bit && (Gr_current_red == &Gr_red)){
+ bit_32 = 1;
+ }
+
+ if(bit_32){
+ *((uint*)pixel) |= (uint)(( (int)*rv / Gr_current_red->scale ) << Gr_current_red->shift);
+ } else {
+ *((ushort*)pixel) |= (ushort)(( (int)*rv / Gr_current_red->scale ) << Gr_current_red->shift);
+ }
+ if(bit_32){
+ *((uint*)pixel) |= (uint)(( (int)*gv / Gr_current_green->scale ) << Gr_current_green->shift);
+ } else {
+ *((ushort*)pixel) |= (ushort)(( (int)*gv / Gr_current_green->scale ) << Gr_current_green->shift);
+ }
+ if(bit_32){
+ *((uint*)pixel) |= (uint)(( (int)*bv / Gr_current_blue->scale ) << Gr_current_blue->shift);
+ } else {
+ *((ushort*)pixel) |= (ushort)(( (int)*bv / Gr_current_blue->scale ) << Gr_current_blue->shift);
+ }
+
+ // NOTE - this is a semi-hack. For direct3d we don't use an alpha bit, so if *av == 0, we just set the whole pixel to be Gr_green.mask
+ // ergo, we need to do this _last_
+ switch(Bm_pixel_format){
+ // glide has an alpha channel so we have to unset ir or set it each time
+ case BM_PIXEL_FORMAT_ARGB:
+ Assert(!bit_32);
+ *((ushort*)pixel) &= ~(0x8000);
+ if(*av){
+ *((ushort*)pixel) |= 0x8000;
+ }
+ break;
+
+ // this d3d format has no alpha channel, so only make it "transparent", never make it "non-transparent"
+ case BM_PIXEL_FORMAT_D3D:
+ Assert(!bit_32);
+ if(*av == 0){
+ *((ushort*)pixel) = (ushort)Gr_current_green->mask;
+ }
+ break;
+
+ // nice 1555 texture format
+ case BM_PIXEL_FORMAT_ARGB_D3D:
+ // if we're writing to normal texture format
+ if(Gr_current_red == &Gr_t_red){
+ Assert(!bit_32);
+ *((ushort*)pixel) &= ~(Gr_current_alpha->mask);
+ if(*av){
+ *((ushort*)pixel) |= (ushort)(Gr_current_alpha->mask);
+ } else {
+ *((ushort*)pixel) = 0;
+ }
+ }
+ // otherwise if we're writing to screen format, still do it the green mask way
+ else {
+ if(*av == 0){
+ if(bit_32){
+ *((uint*)pixel) = (uint)Gr_current_green->mask;
+ } else {
+ *((ushort*)pixel) = (ushort)Gr_current_green->mask;
+ }
+ }
+ }
+ break;
+ }
+}
+*/
+
+// get the rgba components of a pixel, any of the parameters can be NULL
+void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a)
+{
+ int bit_32 = 0;
+
+ // pick a byte size - 32 bits only if 32 bit mode d3d and screen format
+ if(D3D_32bit && (Gr_current_red == &Gr_red)){
+ bit_32 = 1;
+ }
+
+ if(r != NULL){
+ if(bit_32){
+ *r = ubyte(( (*((uint*)pixel) & Gr_current_red->mask)>>Gr_current_red->shift)*Gr_current_red->scale);
+ } else {
+ *r = ubyte(( ( ((ushort*)pixel)[0] & Gr_current_red->mask)>>Gr_current_red->shift)*Gr_current_red->scale);
+ }
+ }
+ if(g != NULL){
+ if(bit_32){
+ *g = ubyte(( (*((uint*)pixel) & Gr_current_green->mask) >>Gr_current_green->shift)*Gr_current_green->scale);
+ } else {
+ *g = ubyte(( ( ((ushort*)pixel)[0] & Gr_current_green->mask) >>Gr_current_green->shift)*Gr_current_green->scale);
+ }
+ }
+ if(b != NULL){
+ if(bit_32){
+ *b = ubyte(( (*((uint*)pixel) & Gr_current_blue->mask)>>Gr_current_blue->shift)*Gr_current_blue->scale);
+ } else {
+ *b = ubyte(( ( ((ushort*)pixel)[0] & Gr_current_blue->mask)>>Gr_current_blue->shift)*Gr_current_blue->scale);
+ }
+ }
+
+ // get the alpha value
+ if(a != NULL){
+ *a = 1;
+
+ switch(Bm_pixel_format){
+ // glide has an alpha channel so we have to unset ir or set it each time
+ case BM_PIXEL_FORMAT_ARGB:
+ Assert(!bit_32);
+ if(!( ((ushort*)pixel)[0] & 0x8000)){
+ *a = 0;
+ }
+ break;
+
+ // this d3d format has no alpha channel, so only make it "transparent", never make it "non-transparent"
+ case BM_PIXEL_FORMAT_D3D:
+ Assert(!bit_32);
+ if( *((ushort*)pixel) == Gr_current_green->mask){
+ *a = 0;
+ }
+ break;
+
+ // nice 1555 texture format mode
+ case BM_PIXEL_FORMAT_ARGB_D3D:
+ // if we're writing to a normal texture, use nice alpha bits
+ if(Gr_current_red == &Gr_t_red){
+ Assert(!bit_32);
+
+ if(!(*((ushort*)pixel) & Gr_current_alpha->mask)){
+ *a = 0;
+ }
+ }
+ // otherwise do it as normal
+ else {
+ if(bit_32){
+ if(*((int*)pixel) == Gr_current_green->mask){
+ *a = 0;
+ }
+ } else {
+ if(*((ushort*)pixel) == Gr_current_green->mask){
+ *a = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+// get filename
+void bm_get_filename(int bitmapnum, char *filename)
+{
+ int n = bitmapnum % MAX_BITMAPS;
+
+ // return filename
+ strcpy(filename, bm_bitmaps[n].filename);
+}
+
+// given a bitmap and a section, return the size (w, h)
+void bm_get_section_size(int bitmapnum, int sx, int sy, int *w, int *h)
+{
+ int bw, bh;
+ bitmap_section_info *sections;
+
+ // bogus input?
+ Assert((w != NULL) && (h != NULL));
+ if((w == NULL) || (h == NULL)){
+ return;
+ }
+
+ // get bitmap info
+ bm_get_info(bitmapnum, &bw, &bh, NULL, NULL, NULL, &sections);
+
+ // determine the width and height of this section
+ *w = sx < (sections->num_x - 1) ? MAX_BMAP_SECTION_SIZE : bw - sections->sx[sx];
+ *h = sy < (sections->num_y - 1) ? MAX_BMAP_SECTION_SIZE : bh - sections->sy[sy];
+} \ No newline at end of file
diff --git a/code/Bmpman/BmpMan.h b/code/Bmpman/BmpMan.h
new file mode 100644
index 0000000..5680d47
--- /dev/null
+++ b/code/Bmpman/BmpMan.h
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/Bmpman/BmpMan.h $
+ * $Revision: 16 $
+ * $Date: 8/10/99 6:54p $
+ * $Author: Dave $
+ *
+ * Prototypes for Bitmap Manager functions
+ *
+ * $Log: /Freespace2/code/Bmpman/BmpMan.h $
+ *
+ * 16 8/10/99 6:54p Dave
+ * Mad optimizations. Added paging to the nebula effect.
+ *
+ * 15 8/06/99 1:52p Dave
+ * Bumped up MAX_BITMAPS for the demo.
+ *
+ * 14 7/15/99 9:20a Andsager
+ * FS2_DEMO initial checkin
+ *
+ * 13 7/13/99 1:15p Dave
+ * 32 bit support. Whee!
+ *
+ * 12 6/29/99 10:35a Dave
+ * Interface polygon bitmaps! Whee!
+ *
+ * 11 6/16/99 4:06p Dave
+ * New pilot info popup. Added new draw-bitmap-as-poly function.
+ *
+ * 10 5/05/99 9:02p Dave
+ * Fixed D3D aabitmap rendering. Spiffed up nebula effect a bit (added
+ * rotations, tweaked values, made bitmap selection more random). Fixed
+ * D3D beam weapon clipping problem. Added D3d frame dumping.
+ *
+ * 9 2/08/99 5:07p Dave
+ * FS2 chat server support. FS2 specific validated missions.
+ *
+ * 8 2/05/99 12:52p Dave
+ * Fixed Glide nondarkening textures.
+ *
+ * 7 2/03/99 11:44a Dave
+ * Fixed d3d transparent textures.
+ *
+ * 6 12/06/98 2:36p Dave
+ * Drastically improved nebula fogging.
+ *
+ * 5 12/01/98 4:46p Dave
+ * Put in targa bitmap support (16 bit).
+ *
+ * 4 12/01/98 8:06a Dave
+ * Temporary checkin to fix some texture transparency problems in d3d.
+ *
+ * 3 11/30/98 1:07p Dave
+ * 16 bit conversion, first run.
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 32 4/16/98 6:31p Hoffoss
+ * Added function to get filename of a bitmap handle, which we don't have
+ * yet and I need.
+ *
+ * 31 4/02/98 11:40a Lawrance
+ * check for #ifdef DEMO instead of #ifdef DEMO_RELEASE
+ *
+ * 30 3/30/98 4:02p John
+ * Made machines with < 32 MB of RAM use every other frame of certain
+ * bitmaps. Put in code to ke7ep track of how much RAM we've malloc'd.
+ *
+ * 29 3/29/98 4:05p John
+ * New paging code that loads everything necessary at level startup.
+ *
+ * 28 3/26/98 5:21p John
+ * Added new code to preload all bitmaps at the start of a level.
+ * Commented it out, though.
+ *
+ * 27 3/24/98 6:18p John
+ * Hacked MAX_BITMAPS up to 3500
+ *
+ * 26 3/10/98 4:18p John
+ * Cleaned up graphics lib. Took out most unused gr functions. Made D3D
+ * & Glide have popups and print screen. Took out all >8bpp software
+ * support. Made Fred zbuffer. Made zbuffer allocate dynamically to
+ * support Fred. Made zbuffering key off of functions rather than one
+ * global variable.
+ *
+ * 25 3/02/98 6:46p John
+ * Upped MAX_BITMAPS to 2000
+ *
+ * 24 3/02/98 6:00p John
+ * Moved MAX_BITMAPS into BmpMan.h so the stuff in the graphics code that
+ * is dependent on it won't break if it changes. Made ModelCache slots
+ * be equal to MAX_OBJECTS which is what it is.
+ *
+ * 23 2/06/98 8:25p John
+ * Added code for new bitmaps since last frame
+ *
+ * 22 2/06/98 8:10p John
+ * Added code to show amout of texture usage each frame.
+ *
+ * 21 1/29/98 11:48a John
+ * Added new counter measure rendering as model code. Made weapons be
+ * able to have impact explosion.
+ *
+ * 20 1/11/98 2:14p John
+ * Changed a lot of stuff that had to do with bitmap loading. Made cfile
+ * not do callbacks, I put that in global code. Made only bitmaps that
+ * need to load for a level load.
+ *
+ * 19 9/03/97 4:19p John
+ * changed bmpman to only accept ani and pcx's. made passing .pcx or .ani
+ * to bm_load functions not needed. Made bmpman keep track of palettes
+ * for bitmaps not mapped into game palettes.
+ *
+ * 18 8/25/97 11:14p Lawrance
+ * added support for .ani files in bm_load_animation()
+ *
+ * 17 7/16/97 3:07p John
+ *
+ * 16 6/17/97 8:58p Lawrance
+ * fixed bug with not nulling bm.data with USER bitmaps
+ *
+ * 15 6/12/97 2:44a Lawrance
+ * changed bm_unlock() to take an index into bm_bitmaps(). Added
+ * ref_count to bitmap_entry struct
+ *
+ * 14 5/20/97 10:36a John
+ * Fixed problem with user bitmaps and direct3d caching.
+ *
+ * 13 3/24/97 3:25p John
+ * Cleaned up and restructured model_collide code and fvi code. In fvi
+ * made code that finds uvs work.. Added bm_get_pixel to BmpMan.
+ *
+ * 12 2/17/97 5:18p John
+ * Added a bunch of RCS headers to a bunch of old files that don't have
+ * them.
+ *
+ * $NoKeywords: $
+ */
+
+#ifndef _BMPMAN_H
+#define _BMPMAN_H
+
+#ifdef FS2_DEMO
+ #define MAX_BITMAPS 3500
+#else
+ #define MAX_BITMAPS 3500 // How many bitmaps the game can handle
+#endif
+
+// 16 bit pixel formats
+#define BM_PIXEL_FORMAT_ARGB 0 // for glide - can assume certain things, like 1555 LFB writes, whee!
+#define BM_PIXEL_FORMAT_D3D 1 // d3d - card dependant. booo!
+#define BM_PIXEL_FORMAT_ARGB_D3D 2 // this card has nice 1555 textures like Glide - ahhhhh!
+
+// 16 bit pixel formats
+extern int Bm_pixel_format;
+
+#define BYTES_PER_PIXEL(x) ((x+7)/8)
+
+// how many bytes of textures are used.
+extern int bm_texture_ram;
+
+// This loads a bitmap so we can draw with it later.
+// It returns a negative number if it couldn't load
+// the bitmap. On success, it returns the bitmap
+// number.
+int bm_load(char * filename);
+
+// special load function. basically allows you to load a bitmap which already exists (by filename).
+// this is useful because in some cases we need to have a bitmap which is locked in screen format
+// _and_ texture format, such as pilot pics and squad logos
+int bm_load_duplicate(char *filename);
+
+// Creates a bitmap that exists in RAM somewhere, instead
+// of coming from a disk file. You pass in a pointer to a
+// block of data. The data can be in the following formats:
+// 8 bpp (mapped into game palette)
+// 32 bpp
+// On success, it returns the bitmap number. You cannot
+// free that RAM until bm_release is called on that bitmap.
+// See example at bottom of this file
+int bm_create( int bpp, int w, int h, void * data, int flags = 0);
+
+// Frees up a bitmap's data, but bitmap number 'n' can
+// still be used, it will just have to be paged in next
+// time it is locked.
+int bm_unload( int n );
+
+// Frees up a bitmap's data, and it's slot, so bitmap
+// number 'n' cannot be used anymore, and bm_load or
+// bm_create might reuse the slot.
+void bm_release(int n);
+
+// This loads a bitmap sequence so we can draw with it later.
+// It returns a negative number if it couldn't load
+// the bitmap. On success, it returns the bitmap
+// number of the first frame and nframes is set.
+extern int bm_load_animation( char * filename, int * nframes, int *fps = NULL, int can_drop_frames = 0 );
+
+// This locks down a bitmap and returns a pointer to a bitmap
+// that can be accessed until you call bm_unlock. Only lock
+// a bitmap when you need it! This will convert it into the
+// appropriate format also.
+extern bitmap * bm_lock( int bitmapnum, ubyte bpp, ubyte flags );
+
+// The signature is a field that gets filled in with
+// a unique signature for each bitmap. The signature for each bitmap
+// will also change when the bitmap's data changes.
+extern uint bm_get_signature( int bitmapnum);
+
+// Unlocks a bitmap
+extern void bm_unlock( int bitmapnum );
+
+// Gets info. w,h,or flags,nframes or fps can be NULL if you don't care.
+extern void bm_get_info( int bitmapnum, int *w=NULL, int * h=NULL, ubyte * flags=NULL, int *nframes=NULL, int *fps=NULL, bitmap_section_info **sections = NULL );
+
+// get filename
+extern void bm_get_filename(int bitmapnum, char *filename);
+
+// resyncs all the bitmap palette
+extern void bm_update();
+
+// call to load all data for all bitmaps that have been requested to be loaded
+extern void bm_load_all();
+extern void bm_unload_all();
+
+// call to get the palette for a bitmap
+extern void bm_get_palette(int n, ubyte *pal, char *name);
+
+// Hacked function to get a pixel from a bitmap.
+// Only works good in 8bpp mode.
+void bm_get_pixel( int bitmap, float u, float v, ubyte *r, ubyte *g, ubyte *b );
+
+// Returns number of bytes of bitmaps locked this frame
+// ntotal = number of bytes of bitmaps locked this frame
+// nnew = number of bytes of bitmaps locked this frame that weren't locked last frame
+void bm_get_frame_usage(int *ntotal, int *nnew);
+
+/*
+ * Example on using bm_create
+ *
+ {
+ static int test_inited = 0;
+ static int test_bmp;
+ static uint test_bmp_data[128*64];
+
+ if ( !test_inited ) {
+ test_inited = 1;
+ // Create the new bitmap and fill in its data.
+ // When you're done with it completely, call
+ // bm_release to free up the bitmap handle
+ test_bmp = bm_create( 32, 128, 64, test_bmp_data );
+ int i,j;
+ for (i=0; i<64; i++ ) {
+ for (j=0; j<64; j++ ) {
+ uint r=i*4;
+ test_bmp_data[j+i*128] = r;
+ }
+ }
+ }
+
+ bm_unload(test_bmp); // this pages out the data, so that the
+ // next bm_lock will convert the new data to the
+ // correct bpp
+
+ // put in new data
+ int x,y;
+ gr_reset_clip();
+ for (y=0; y<64; y++)
+ for (x=0; x<128; x++ )
+ test_bmp_data[y*128+x] = 15;
+
+ // Draw the bitmap to upper left corner
+ gr_set_bitmap(test_bmp);
+ gr_bitmap( 0,0 );
+ }
+*/
+
+
+//============================================================================
+// Paging stuff
+//============================================================================
+
+void bm_page_in_start();
+void bm_page_in_stop();
+
+// Paging code in a library should call these functions
+// in its page in function.
+
+// Marks a texture as being used for this level
+// If num_frames is passed, assume this is an animation
+void bm_page_in_texture( int bitmapnum, int num_frames=1 );
+
+// Marks a texture as being used for this level
+// If num_frames is passed, assume this is an animation
+void bm_page_in_nondarkening_texture( int bitmap, int num_frames=1 );
+
+// marks a texture as being a transparent textyre used for this level
+// Marks a texture as being used for this level
+// If num_frames is passed, assume this is an animation
+void bm_page_in_xparent_texture( int bitmapnum, int num_frames=1 );
+
+// Marks an aabitmap as being used for this level
+// If num_frames is passed, assume this is an animation
+void bm_page_in_aabitmap( int bitmapnum, int num_frames=1 );
+
+//
+// Mode: 0 = High memory
+// 1 = Low memory ( every other frame of ani's)
+// 2 = Debug low memory ( only use first frame of each ani )
+void bm_set_low_mem( int mode );
+
+char *bm_get_filename(int handle);
+
+void BM_SELECT_SCREEN_FORMAT();
+void BM_SELECT_TEX_FORMAT();
+void BM_SELECT_ALPHA_TEX_FORMAT();
+
+// convert a 24 bit value to a 16 bit value
+void bm_24_to_16(int bit_24, ushort *bit_16);
+
+// set the rgba components of a pixel, any of the parameters can be NULL
+extern void (*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
+void bm_set_components_argb(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
+void bm_set_components_d3d(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
+void bm_set_components_argb_d3d_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
+void bm_set_components_argb_d3d_32_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
+void bm_set_components_argb_d3d_16_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
+void bm_set_components_argb_d3d_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
+
+// get the rgba components of a pixel, any of the parameters can be NULL
+void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
+
+//============================================================================
+// section info stuff
+//============================================================================
+
+// given a bitmap and a section, return the size (w, h)
+void bm_get_section_size(int bitmapnum, int sx, int sy, int *w, int *h);
+
+#endif \ No newline at end of file
diff --git a/code/CFile/CfileArchive.cpp b/code/CFile/CfileArchive.cpp
new file mode 100644
index 0000000..9f6fb22
--- /dev/null
+++ b/code/CFile/CfileArchive.cpp
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/CFile/CfileArchive.cpp $
+ * $Revision: 4 $
+ * $Date: 2/22/99 10:31p $
+ * $Author: Andsager $
+ *
+ * Low-level code for reading data out of large archive files or normal files. All
+ * reads/seeks come through here.
+ *
+ * $Log: /Freespace2/code/CFile/CfileArchive.cpp $
+ *
+ * 4 2/22/99 10:31p Andsager
+ * Get rid of unneeded includes.
+ *
+ * 3 1/06/99 2:24p Dave
+ * Stubs and release build fixes.
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 12 5/14/98 8:10p Lawrance
+ * Fix bug with trying to read past the end of a file (when from a
+ * packfile).
+ *
+ * 11 5/11/98 11:48a John
+ * fixed bug with memory mapped files
+ *
+ * 10 5/11/98 10:59a John
+ * added in debug code
+ *
+ * 9 5/11/98 10:59a John
+ * Moved the low-level file reading code into cfilearchive.cpp.
+ *
+ * 8 4/30/98 4:53p John
+ * Restructured and cleaned up cfile code. Added capability to read off
+ * of CD-ROM drive and out of multiple pack files.
+ *
+ * 7 4/20/98 11:49a Hoffoss
+ * Fixed bug with directory name getting.
+ *
+ * 6 4/10/98 12:18a Hoffoss
+ * Make pilot image search in pack file possible.
+ *
+ * 5 1/19/98 9:37p Allender
+ * Great Compiler Warning Purge of Jan, 1998. Used pragma's in a couple
+ * of places since I was unsure of what to do with code.
+ *
+ * 4 12/30/97 5:31p Lawrance
+ * fixed problem for people that didn't have a VP file
+ *
+ * 3 12/30/97 4:31p Sandeep
+ * Changed pakfile format
+ *
+ * 2 12/28/97 12:42p John
+ * Put in support for reading archive files; Made missionload use the
+ * cf_get_file_list function. Moved demos directory out of data tree.
+ *
+ * 1 12/28/97 11:48a John
+ *
+ * $NoKeywords: $
+ */
+
+#define _CFILE_INTERNAL
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <io.h>
+#include <direct.h>
+#include <windows.h>
+#include <winbase.h> /* needed for memory mapping of file functions */
+
+#include "pstypes.h"
+#include "cfile.h"
+//#include "OutWnd.h"
+//#include "VecMat.h"
+//#include "Timer.h"
+#include "CfileArchive.h"
+
+#define CHECK_POSITION
+
+// Called once to setup the low-level reading code.
+
+void cf_init_lowlevel_read_code( CFILE * cfile, int offset, int size )
+{
+ Assert(cfile != NULL);
+
+ Cfile_block *cb;
+ Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
+ cb = &Cfile_block_list[cfile->id];
+
+ cb->lib_offset = offset;
+ cb->raw_position = 0;
+ cb->size = size;
+
+ if ( cb->fp ) {
+ if ( cb->lib_offset ) {
+ fseek( cb->fp, cb->lib_offset, SEEK_SET );
+ }
+
+ #if defined(CHECK_POSITION) && !defined(NDEBUG)
+ int raw_position = ftell(cb->fp) - cb->lib_offset;
+ Assert(raw_position == cb->raw_position);
+ #endif
+ }
+}
+
+
+
+// cfeof() Tests for end-of-file on a stream
+//
+// returns a nonzero value after the first read operation that attempts to read
+// past the end of the file. It returns 0 if the current position is not end of file.
+// There is no error return.
+
+int cfeof(CFILE *cfile)
+{
+ Assert(cfile != NULL);
+
+ Cfile_block *cb;
+ Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
+ cb = &Cfile_block_list[cfile->id];
+
+ int result;
+
+ result = 0;
+
+ // cfeof() not supported for memory-mapped files
+ Assert( !cb->data );
+
+ Assert(cb->fp != NULL);
+
+ #if defined(CHECK_POSITION) && !defined(NDEBUG)
+ int raw_position = ftell(cb->fp) - cb->lib_offset;
+ Assert(raw_position == cb->raw_position);
+ #endif
+
+ if (cb->raw_position >= cb->size ) {
+ result = 1;
+ } else {
+ result = 0;
+ }
+
+ return result;
+}
+
+// cftell() returns offset into file
+//
+// returns: success ==> offset into the file
+// error ==> -1
+//
+int cftell( CFILE * cfile )
+{
+ Assert(cfile != NULL);
+ Cfile_block *cb;
+ Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
+ cb = &Cfile_block_list[cfile->id];
+
+ // Doesn't work for memory mapped files
+ Assert( !cb->data );
+
+ Assert(cb->fp != NULL);
+
+ #if defined(CHECK_POSITION) && !defined(NDEBUG)
+ int raw_position = ftell(cb->fp) - cb->lib_offset;
+ Assert(raw_position == cb->raw_position);
+ #endif
+
+ return cb->raw_position;
+}
+
+
+// cfseek() moves the file pointer
+//
+// returns: success ==> 0
+// error ==> non-zero
+//
+int cfseek( CFILE *cfile, int offset, int where )
+{
+
+ Assert(cfile != NULL);
+ Cfile_block *cb;
+ Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
+ cb = &Cfile_block_list[cfile->id];
+
+
+ // TODO: seek to offset in memory mapped file
+ Assert( !cb->data );
+ Assert( cb->fp != NULL );
+
+ int goal_position;
+
+ switch( where ) {
+ case CF_SEEK_SET:
+ goal_position = offset+cb->lib_offset;
+ break;
+ case CF_SEEK_CUR:
+ {
+ goal_position = cb->raw_position+offset+cb->lib_offset;
+ }
+ break;
+ case CF_SEEK_END:
+ goal_position = cb->size+offset+cb->lib_offset;
+ break;
+ default:
+ Int3();
+ return 1;
+ }
+
+ int result = fseek(cb->fp, goal_position, SEEK_SET );
+ cb->raw_position = goal_position - cb->lib_offset;
+
+ #if defined(CHECK_POSITION) && !defined(NDEBUG)
+ int tmp_offset = ftell(cb->fp) - cb->lib_offset;
+ Assert(tmp_offset==cb->raw_position);
+ #endif
+
+ return result;
+}
+
+
+// cfread() reads from a file
+//
+// returns: returns the number of full elements read
+//
+//
+int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
+{
+ Assert(cfile != NULL);
+ Assert(buf != NULL);
+ Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
+
+ Cfile_block *cb;
+ cb = &Cfile_block_list[cfile->id];
+
+ // cfread() not supported for memory-mapped files
+ Assert( !cb->data );
+ Assert(cb->fp != NULL);
+
+ int size = elsize*nelem;
+
+ Assert(nelem > 0);
+ Assert(elsize > 0);
+ Assert(size > 0);
+
+ if ( (cb->raw_position+size) > cb->size ) {
+ size = cb->size - cb->raw_position;
+ if ( size < 1 ) {
+ return 0;
+ }
+ //mprintf(( "CFILE: EOF encountered in file\n" ));
+ }
+
+ int bytes_read = fread( buf, 1, size, cb->fp );
+ if ( bytes_read > 0 ) {
+ cb->raw_position += bytes_read;
+ }
+
+ #if defined(CHECK_POSITION) && !defined(NDEBUG)
+ int tmp_offset = ftell(cb->fp) - cb->lib_offset;
+ Assert(tmp_offset==cb->raw_position);
+ #endif
+
+ return bytes_read / elsize;
+
+}
+
diff --git a/code/CFile/CfileArchive.h b/code/CFile/CfileArchive.h
new file mode 100644
index 0000000..5a6674b
--- /dev/null
+++ b/code/CFile/CfileArchive.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/CFile/CfileArchive.h $
+ * $Revision: 2 $
+ * $Date: 10/07/98 10:52a $
+ * $Author: Dave $
+ *
+ * External def's for CfileArchive.cpp. This should only be used
+ * internally by cfile stuff.
+ *
+ * $Log: /Freespace2/code/CFile/CfileArchive.h $
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 4 5/11/98 10:59a John
+ * Moved the low-level file reading code into cfilearchive.cpp.
+ *
+ * 3 4/30/98 4:53p John
+ * Restructured and cleaned up cfile code. Added capability to read off
+ * of CD-ROM drive and out of multiple pack files.
+ *
+ * 2 12/28/97 12:42p John
+ * Put in support for reading archive files; Made missionload use the
+ * cf_get_file_list function. Moved demos directory out of data tree.
+ *
+ * 1 12/28/97 11:48a John
+ *
+ * $NoKeywords: $
+ */
+
+#ifndef _CFILEARCHIVE_H
+#define _CFILEARCHIVE_H
+
+#ifndef _CFILE_INTERNAL
+#error This file should only be included internally in CFILE!!
+#endif
+
+// The following Cfile_block data is private to cfile.cpp
+// DO NOT MOVE the Cfile_block* information to cfile.h / do not extern this data
+//
+#define CFILE_BLOCK_UNUSED 0
+#define CFILE_BLOCK_USED 1
+
+typedef struct Cfile_block {
+ int type; // CFILE_BLOCK_UNUSED, CFILE_BLOCK_USED
+ int dir_type; // directory location
+ FILE *fp; // File pointer if opening an individual file
+ void *data; // Pointer for memory-mapped file access. NULL if not mem-mapped.
+ HANDLE hInFile; // Handle from CreateFile()
+ HANDLE hMapFile; // Handle from CreateFileMapping()
+ int lib_offset;
+ int raw_position;
+ int size; // for packed files
+
+} Cfile_block;
+
+#define MAX_CFILE_BLOCKS 64
+extern Cfile_block Cfile_block_list[MAX_CFILE_BLOCKS];
+extern CFILE Cfile_list[MAX_CFILE_BLOCKS];
+
+// Called once to setup the low-level reading code.
+void cf_init_lowlevel_read_code( CFILE * cfile, int offset, int size );
+
+#endif \ No newline at end of file
diff --git a/code/CFile/CfileList.cpp b/code/CFile/CfileList.cpp
new file mode 100644
index 0000000..c17e13e
--- /dev/null
+++ b/code/CFile/CfileList.cpp
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) Volition, Inc. 1999. All rights reserved.
+ *
+ * All source code herein is the property of Volition, Inc. You may not sell
+ * or otherwise commercially exploit the source or things you created based on the
+ * source.
+ *
+*/
+
+/*
+ * $Logfile: /Freespace2/code/CFile/CfileList.cpp $
+ * $Revision: 3 $
+ * $Date: 2/22/99 10:31p $
+ * $Author: Andsager $
+ *
+ * Code for doing directory lists and sorts
+ *
+ * $Log: /Freespace2/code/CFile/CfileList.cpp $
+ *
+ * 3 2/22/99 10:31p Andsager
+ * Get rid of unneeded includes.
+ *
+ * 2 10/07/98 10:52a Dave
+ * Initial checkin.
+ *
+ * 1 10/07/98 10:48a Dave
+ *
+ * 6 5/13/98 10:22p John
+ * Added cfile functions to read/write rle compressed blocks of data.
+ * Made palman use it for .clr files. Made alphacolors calculate on the
+ * fly rather than caching to/from disk.
+ *
+ * 5 5/06/98 5:30p John
+ * Removed unused cfilearchiver. Removed/replaced some unused/little used
+ * graphics functions, namely gradient_h and _v and pixel_sp. Put in new
+ * DirectX header files and libs that fixed the Direct3D alpha blending
+ * problems.
+ *
+ * 4 4/30/98 4:53p John
+ * Restructured and cleaned up cfile code. Added capability to read off
+ * of CD-ROM drive and out of multiple pack files.
+ *
+ * 3 4/10/98 12:18a Hoffoss
+ * Make pilot image search in pack file possible.
+ *
+ * 2 3/30/98 10:36p Allender
+ * be sure to call _findclose() when done reading a file list
+ *
+ * 1 12/28/97 11:48a John
+ *
+ * $NoKeywords: $
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <io.h>
+#include <direct.h>
+#include <windows.h>
+#include <winbase.h> /* needed for memory mapping of file functions */
+
+#include "pstypes.h"
+#include "cfile.h"
+//#include "OutWnd.h"
+//#include "VecMat.h"
+//#include "Timer.h"
+
+// Sorts a list of filenames using the specified sorting method (CF_SORT_*).
+// n = number of filenames in list to sort
+// list = list of filenames to be sorted
+// sort = sorting method to use (one of the CF_SORT_* defines)
+// info = extra info for each file. Only required if sorting by time, however if you
+// have extra file info, you should pass it as well to get it sorted too (so an
+// index into list is the same index for info for that file
+void cf_sort_filenames( int n, char **list, int sort, file_list_info *info )
+{
+ int i, j, incr;
+ char *t;
+ file_list_info tt;
+
+ if (sort == CF_SORT_NAME) {
+ incr = n / 2;
+ while (incr > 0) {
+ for (i=incr; i<n; i++) {
+ j = i - incr;
+ while (j >= 0) {
+ if (stricmp(list[j], list[j + incr]) > 0) {
+ t = list[j];
+ list[j] = list[j + incr];
+ list[j + incr] = t;
+
+ if (info) {
+ tt = info[j];
+ info[j] = info[j + incr];
+ info[j + incr] = tt;
+ }
+
+ j -= incr;
+
+ } else
+ break;
+ }
+ }
+
+ incr /= 2;
+ }
+
+ return;
+
+ } else if (sort == CF_SORT_TIME) {
+ Assert(info);
+ incr = n / 2;
+ while (incr > 0) {
+ for (i=incr; i<n; i++) {
+ j = i - incr;
+ while (j >= 0) {
+ if (info[j].write_time < info[j + incr].write_time) {
+ t = list[j];
+ list[j] = list[j + incr];
+ list[j + incr] = t;
+
+ tt = info[j];
+ info[j] = info[j + incr];
+ info[j + incr] = tt;
+ j -= incr;
+
+ } else
+ break;
+ }
+ }
+
+ incr /= 2;
+ }
+
+ return;
+ }
+
+ nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
+}
+
+
+// cf_compress - Do Run Length Compression on a block of data. Targa format.
+//
+// Usage:
+// out Buffer to write it out to
+// in Buffer to compress
+// bytecount Number of bytes input
+int cf_compress(char *out, char *in, int bytecount )
+{
+ int pixcount; // number of pixels in the current packet
+ char *inputpixel=NULL; // current input pixel position
+ char *matchpixel=NULL; // pixel value to match for a run
+ char *flagbyte=NULL; // location of last flag byte to set
+ int rlcount; // current count in r.l. string
+ int rlthresh; // minimum valid run length
+ char *copyloc; // location to begin copying at
+
+ // set the threshold -- the minimum valid run length
+ rlthresh = 2; // Require a 2 pixel span before rle'ing
+
+ // set the first pixel up
+
+ flagbyte = out; // place to put next flag if run
+ inputpixel = in;
+ pixcount = 1;
+ rlcount = 0;
+ copyloc = (char *)0;
+
+ // loop till data processing complete
+ do {
+
+ // if we have accumulated a 128-byte packet, process it
+ if ( pixcount == 129 ) {
+ *flagbyte = 127;
+
+ // set the run flag if this is a run
+
+ if ( rlcount >= rlthresh ) {
+ *flagbyte |= 0x80;
+ pixcount = 2;
+ }
+
+ // copy the data into place
+ ++flagbyte;
+ memmove( flagbyte, copyloc, pixcount-1 );
+ flagbyte += pixcount-1;
+ pixcount = 1;
+
+ // set up for next packet
+ continue;
+ }
+
+ // if zeroth byte, handle as special case
+ if ( pixcount == 1 ) {
+ rlcount = 0;
+ copyloc = inputpixel; /* point to 1st guy in packet */
+ matchpixel = inputpixel; /* set pointer to pix to match */
+ pixcount = 2;
+ inputpixel += 1;
+ continue;
+ }
+
+ // assembling a packet -- look at next pixel
+
+ // current pixel == match pixel?
+ if ( *inputpixel == *matchpixel ) {
+
+ // establishing a run of enough length to
+ // save space by doing it
+ // -- write the non-run length packet
+ // -- start run-length packet
+
+ if ( ++rlcount == rlthresh ) {
+
+ // close a non-run packet
+
+ if ( pixcount > (rlcount+1) ) {
+ // write out length and do not set run flag
+
+ *flagbyte++ = (char)(pixcount - 2 - rlthresh);
+
+ memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
+ flagbyte += (pixcount-1-rlcount);
+
+ copyloc = inputpixel;
+ pixcount = rlcount + 1;
+ }
+ }
+ } else {
+
+ // no match -- either break a run or continue without one
+ // if a run exists break it:
+ // write the bytes in the string (1+1)
+ // start the next string
+
+ if ( rlcount >= rlthresh ) {
+
+ *flagbyte++ = (char)(0x80 | rlcount);
+ memmove(flagbyte, copyloc, 1 );
+ flagbyte += 1;
+ pixcount = 1;
+ continue;
+ } else {
+
+ // not a match and currently not a run
+ // - save the current pixel
+ // - reset the run-length flag
+ rlcount = 0;
+ matchpixel = inputpixel;
+ }
+ }
+ pixcount++;
+ inputpixel += 1;
+ } while ( inputpixel < (in + bytecount));
+
+ // quit this buffer without loosing any data
+ if ( --pixcount >= 1 ) {
+ *flagbyte = (char)(pixcount - 1);
+ if ( rlcount >= rlthresh ) {
+ *flagbyte |= 0x80;
+ pixcount = 1;
+ }
+
+ // copy the data into place
+ ++flagbyte;
+ memmove(flagbyte, copyloc, pixcount );
+ flagbyte += pixcount;
+ }
+ return(flagbyte-out);
+}
+
+
+// cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
+//
+// Usage:
+// out Buffer to write it out to
+// in Buffer to compress
+// bytecount Number of bytes input
+int cf_decompress(char *out, char *in )
+{
+ int count;
+
+ char *param_out = out;
+
+ while(1) {
+
+ count = int(*in++);
+ int run_span = count & 0x80;
+
+ count &= (~0x80);
+
+ if ( count > 0 ) {
+ if ( run_span ) {
+ // RLE'd data
+ ubyte c = *in++;
+
+ memset( out, c, count );
+ out += count;
+ } else {
+ memmove( out, in, count );
+ in += count;
+ out += count;
+ }
+ }
+ }
+
+ return out - param_out;
+
+}
+
+
+// cfread() reads from a file and decompresses it
+//
+// returns: returns the number of full elements read
+//
+//
+int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
+{
+ char *out = (char *)buf;
+
+ while(1) {
+
+ byte count;
+
+ if ( cfread( &count, 1, 1, cfile ) != 1 ) {
+ break;
+ }
+
+ int run_span = count & 0x80;
+ count &= (~0x80);
+ count++;
+
+ if ( count > 0 ) {
+ if ( run_span ) {
+ // RLE'd data
+ byte c;
+ if ( cfread( &c, 1, 1, cfile ) != 1 ) {
+ break;
+ }
+ memset( out, c, count );
+ } else {
+ if ( cfread( out, 1, count, cfile ) != count ) {
+ break;
+ }
+ }
+ out += count;
+ if ( out >= (char *)buf + (elsize*nelem)) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ return (out - (char *)buf)/elsize;
+}
+
+int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
+{
+ char *in = (char *)param_buf;
+ int bytecount = (param_elsize * param_nelem );
+
+ int pixcount; // number of pixels in the current packet
+ char *inputpixel=NULL; // current input pixel position
+ char *matchpixel=NULL; // pixel value to match for a run
+ int rlcount; // current count in r.l. string
+ int rlthresh; // minimum valid run length
+ char *copyloc; // location to begin copying at
+
+ // set the threshold -- the minimum valid run length
+ rlthresh = 2; // Require a 2 pixel span before rle'ing
+
+ // set the first pixel up
+
+ inputpixel = in;
+ pixcount = 1;
+ rlcount = 0;
+ copyloc = (char *)0;
+
+ // loop till data processing complete
+ do {
+
+ // if we have accumulated a 128-byte packet, process it
+ if ( pixcount == 129 ) {
+ ubyte code = 127;
+
+ // set the run flag if this is a run
+
+ if ( rlcount >= rlthresh ) {
+ code |= 0x80;
+ pixcount = 2;
+ }
+
+ cfwrite( &code, 1, 1, cfile );
+
+ // copy the data into place
+ cfwrite( copyloc, 1, pixcount-1, cfile );
+ pixcount = 1;
+
+ // set up for next packet
+ continue;
+ }
+
+ // if zeroth byte, handle as special case
+ if ( pixcount == 1 ) {
+ rlcount = 0;
+ copyloc = inputpixel; /* point to 1st guy in packet */
+ matchpixel = inputpixel; /* set pointer to pix to match */
+ pixcount = 2;
+ inputpixel += 1;
+ continue;
+ }
+
+ // assembling a packet -- look at next pixel
+
+ // current pixel == match pixel?
+ if ( *inputpixel == *matchpixel ) {
+ <