initial commit

sources taken from book CD:

ack_lib -> /ACK/WIN/ACK_LIB
fdemo -> /ACK/DOS/FDEMO/SOURCE (and /ACK/DOS/BORLAND as needed)
mall -> /ACK/DOS/MALL/SOURCE (and /ACK/DOS/BORLAND as needed)

some source files were missing for the demo projects and needed to be
copied from /ACK/DOS/BORLAND (as indicated above)
This commit is contained in:
Gered 2019-11-02 13:17:24 -04:00
commit 865b466995
50 changed files with 19803 additions and 0 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
*.obj
*.exe
*.lib
*.lbc
*.lnk

436
ack_lib/ACK3D.H Normal file
View file

@ -0,0 +1,436 @@
// ACK-3D.H header file for the engine interface.
// This file contains the main data structures and definitions
// required to support the ACK-3D engine. The data structures defined are
// the ones you use to set up the communication links between your application
// and the ACK-3D library. The four main data structures set up in this header file
// include: ACKENG, DOORS, NEWOBJECT, and OBJSEQ.
// USED TO RID OURSELVES OF THE MANY CASTING PROBLEMS
#define CAST(t,f) (t)(f)
// Internal definitions used to simplify field declarations.
typedef unsigned long ULONG;
typedef unsigned short USHORT;
typedef unsigned char UCHAR;
// Error codes returned from ACK-3D functions. You can use these error codes in your
// applications to debug the function calls.
#define ERR_BADFILE 100 // File not found, usually bad filename
#define ERR_BADCOMMAND 101 // Bad command found in the .INF file
#define ERR_BADOBJNUMBER 102 // Object number out of range
#define ERR_BADSYNTAX 103 // Invalid syntax in the .INF file
#define ERR_LOADINGBITMAP 104 // Error while reading a Bitmap file
#define ERR_BADDIRECTION 105 // Obsolete, was error in direction field of objects
#define ERR_BADSTARTX 106 // Error in initial X position of player
#define ERR_BADSTARTY 107 // Error in initial Y position of player
#define ERR_BADANGLE 108 // Error in initial player angle
#define ERR_BADMAPFILE 109 // Error in map file header
#define ERR_READINGMAP 110 // Error during read of map file
#define ERR_BADPICNAME 111 // Error in bitmap filename
#define ERR_INVALIDFORM 112 // Error in .BBM or .LBM format
#define ERR_NOPBM 113 // Error in .BBM format
#define ERR_BADPICFILE 114 // Error reading a bitmap file
#define ERR_NOMEMORY 115 // Out of memory error
#define ERR_BADPALFILE 116 // Error reading raw palette file
#define ERR_BADWINDOWSIZE 117 // Invalid window size for engine
#define ERR_TOMANYVIEWS 118 // Out of range object views
#define ERR_BADOBJECTNUM 119 // Invalid object index
#define ERR_BADOBJTYPE 120 // Invalid object type
// Defines for angle sizes used with the ACK-3D engine.
// These values are used as table look up indexes. The range is from 0 to 1800
// where each value represents and angle increment of 0.5 degrees;
// 0 = 0 degrees and 1800 = 360 degrees.
#define INT_ANGLE_1 5
#define INT_ANGLE_2 10
#define INT_ANGLE_4 20
#define INT_ANGLE_6 30
#define INT_ANGLE_32 160
#define INT_ANGLE_45 225
#define INT_ANGLE_90 450
#define INT_ANGLE_135 675
#define INT_ANGLE_180 900
#define INT_ANGLE_225 1125
#define INT_ANGLE_270 1350
#define INT_ANGLE_315 1575
#define INT_ANGLE_360 1800
// These values are returned by the AckMovePOV() and AckMoveObjectPOV() functions.
#define POV_NOTHING 0 // Nothing was hit
#define POV_XWALL 1 // An X wall was hit
#define POV_YWALL 2 // A Y wall was hit
#define POV_OBJECT 3 // An object was hit
#define POV_PLAYER 4 // The player was hit by object
#define POV_SLIDEX 5 // Sliding along an X wall
#define POV_SLIDEY 6 // Sliding along a Y wall
#define POV_NODOOR 0 // No door was opened
#define POV_XDOOR 1 // An X door was opened
#define POV_YDOOR 2 // A Y door was opened
#define POV_XSECRETDOOR 3 // An X secret door was opened
#define POV_YSECRETDOOR 4 // A Y secret door was opened
#define POV_DOORLOCKED 0x80 // Bit is on if door is locked
// Defines required to support bitmaps.
// Each bitmap used in ACK-3D is 64x64 pixels in size.
#define BITMAP_WIDTH 64
#define BITMAP_HEIGHT 64
#define BITMAP_SHIFT 6 // Bits to shift for bitmap width
#define BITMAP_SIZE (BITMAP_WIDTH * BITMAP_HEIGHT)
// Defines used to set up map grid. The grid is used with the ACKENG structure.
// Each grid component is 64x64 units in size.
#define GRID_MASK 0xFFC0 // Use FF80 for 128 and FFC0 for 64
#define GRID_SIZE 64 // The size of an individual grid unit
#define GRID_WIDTH 64
#define GRID_HEIGHT 64
#define GRID_MAX GRID_WIDTH * GRID_HEIGHT
#define GRID_XMAX BITMAP_WIDTH * GRID_WIDTH
#define GRID_YMAX BITMAP_WIDTH * GRID_HEIGHT
#define GRID_XMAXLONG (GRID_XMAX * FP_MULT)
#define GRID_YMAXLONG (GRID_YMAX * FP_MULT)
// The main grid array used with the ACKENG structure
#define GRID_ARRAY (GRID_WIDTH+2) * (GRID_HEIGHT+2)
// Defines to specify maximum sizes for the various components used with
// ACK-3D, including wall bitmaps, light zones, shading palette, views, multi-
// height walls, doors, object bitmaps, and objects.
#define MAX_WALLBMPS 256 // Total wall bitmaps allowed
#define MAX_ZONES 8 // Number of light zones
#define PAL_SIZE 4096 // Shading palette ranges
#define MAX_VIEWS 47 // Total sides to an object
#define MAX_MULTI 3 // Max height for multi-height walls
#define MAX_DOORS 10 // Max number of doors that can be opened or
// // closed at one time
#define MAX_OBJBMPS 256 // Total object bitmaps allowed
#define MAX_OBJECTS 254 // Total objects allowed in map
// Defines to set up different wall types.
#define WALL_TYPE_TRANS 0x0800 // Transparent wall
#define WALL_TYPE_MULTI 0x0400 // Wall is 1.5 times high
#define WALL_TYPE_UPPER 0x0200 // Wall is above floor level
#define WALL_TYPE_PASS 0x0100 // Wall can be walked through
#define TYPE_WALL 0
#define TYPE_OBJECT 1
#define RES_LOW 1 // Resolution is low for walls, floor, and ceiling
#define RES_MEDIUM 2 // Resolution is low only for floor and ceiling
//***************************************************************
// Definitions and data structures used to represent and process objects.
// These defines specify the two settings for the Active field in the NEWOBJECT structure.
#define OBJECT_ACTIVE 1 // Active and may be moveable
#define OBJECT_INACTIVE 0 // Won't be considered moveable
// These defines specify values for the Flags field in the NEWOBJECT structure.
// They are used to indicate the type of animation available for an object.
#define OF_PASSABLE 0x80 // Object can be walked thru
#define OF_ANIMATE 0x40 // Object bitmaps are animated
#define OF_MOVEABLE 0x20 // Object will move X,Y
#define OF_MULTIVIEW 0x10 // Object has multiple sides
#define OF_ANIMONCE 0x08 // Animate once then stop
#define OF_ANIMDONE 0x04 // One shot animation is completed
// These defines specify values for the CurrentType field in the NEWOBJECT structure.
// They are used to indicate the current status of the object.
// The names given are arbitrary and can be used for a variety of purposes.
#define NO_CREATE 1
#define NO_DESTROY 2
#define NO_WALK 3
#define NO_ATTACK 4
#define NO_INTERACT 5
// The Object Sequence structure. This structure is used by the NEWOBJECT structure.
#define MAX_OBJ_BITMAPS 32 // Max bitmaps per sequence type
typedef struct {
UCHAR flags; // Flags for this sequence
UCHAR bitmaps[MAX_OBJ_BITMAPS]; // Bitmap numbers in this sequence
short bmSides; // Number of views in sequence
short bmBitmapsPerView; // Number of bitmaps in each view
short AngleFactor; // Used internally to support the object sequence
UCHAR MaxBitmaps; // Max bitmaps in this sequence
} OBJSEQ;
// The defininition of the main object structure--NEWOBJECT.
typedef struct {
char Active; // Determines object status: 0=Inactive, 1=Active
UCHAR Flags; // Misc flags for this object
char Speed; // Speed of obj (used by application)
short Dir; // Direction of obj (used by application)
short x; // Current x,y location in grid
short y;
short mPos; // Current map location in grid
UCHAR id; // Object id
short CurrentType; // Create, Destroy, etc. is current
UCHAR *CurrentBitmaps; // Current bitmap list
short Sides; // Number of views
short aFactor; // Angle factor
short BitmapsPerView; // Number of bitmaps in each view
UCHAR CurrentBm; // Current bitmap number
UCHAR Maxbm; // Max bitmap number for this view
OBJSEQ Create; // Stores structures for the 5 object sequences
OBJSEQ Destroy;
OBJSEQ Walk;
OBJSEQ Attack;
OBJSEQ Interact;
} NEWOBJECT;
//**************************************************************************
// The definitions and data structure that are used to represent doors.
// The default value for the Speed field in the DOORS structure.
#define DEFAULT_DOOR_SPEED 2
// These defines are used to set the Type field.
// Obsolete door codes since any wall can be a door
#define DOOR_XCODE 60 // Map codes for the various doors
#define DOOR_SIDECODE 61
#define DOOR_YCODE 62
// These two defines are used to set the Flags field in the DOORS structure.
#define DOOR_OPENING 0x80 // Set if door is currently opening
#define DOOR_CLOSING 0x40 // Set if door is currently closing
// Other attributes that can be assigned to the Flags field.
#define DOOR_TYPE_SECRET 0x8000 // Secret door
#define DOOR_LOCKED 0x4000 // Locked door
#define DOOR_TYPE_SLIDE 0x2000 // Sliding door
#define DOOR_TYPE_SPLIT 0x1000 // Split door
// The main DOORS structure.
typedef struct {
short mPos; // Stores position info for a door
short mPos1;
short mCode; // Bitmap ID of the door
short mCode1;
UCHAR ColOffset; // Column offset for the door
char Speed; // Speed setting for opening and closing the door
char Type; // Code for the door type
UCHAR Flags; // Door attribute settings
} DOORS;
//***********************************************************************
// The defines and data structure for the main interface structure--ACKENG.
// These defines are used for the LightFlag field in the ACKENG structure.
#define SHADING_ON 1 // Set if distance shading is on
#define SHADING_OFF 0
// These defines are used for the SysFlags field in the ACKENG structure.
#define SYS_SOLID_BACK 0x8000 // On if solid color bkgd vs picture
#define SYS_SOLID_FLOOR 0x4000 // On if solid vs texture floor
#define SYS_SOLID_CEIL 0x2000 // On if solid vs texture ceiling
#define SYS_NO_WALLS 0x1000 // On if walls are NOT to display
#define SYS_SINGLE_BMP 0x0800 // On if 1 bitmap for floor & ceiling
// These defines indicate how bitmaps will be loaded. they are used with the bmLoadType field.
#define BMLOAD_BBM 0 // Bitmaps will be loaded using BBM format
#define BMLOAD_GIF 1 // Bitmaps will be loaded using GIF format
#define BMLOAD_PCX 2 // Bitmaps will be loaded using PCX format
// The main interface structure used between the application and the ACK-3D engine.
// This structure MUST be allocated or defined before any ACK-3D calls are made.
typedef struct {
USHORT xGrid[GRID_ARRAY]; // Map for X walls
USHORT yGrid[GRID_ARRAY]; // Map for Y walls
UCHAR *mxGrid[GRID_ARRAY]; // Wall data for multi-height X walls
UCHAR *myGrid[GRID_ARRAY]; // Wall data for multi-height Y walls
UCHAR *bMaps[MAX_WALLBMPS]; // Pointers to wall bitmaps
UCHAR *oMaps[MAX_OBJBMPS]; // Pointers to object bitmaps
UCHAR *ScreenBuffer; // 64k buffer for screen
UCHAR *OverlayBuffer; // Buffer for compiled overlay
UCHAR *BkgdBuffer; // Buffer for ceiling, floor
short xPlayer; // X value from 0 to 4095--stores current position
short yPlayer; // Y value from 0 to 4095--stores current position
short PlayerAngle; // Angle value from 0 to 1799
short DoorSpeed; // Door open/close speed
short NonSecretCode; // Wall code for secret door
UCHAR TopColor; // Base color of ceiling
UCHAR BottomColor; // Base color of floor
UCHAR FloorBitmap; // Bitmap number for single floor
UCHAR CeilBitmap; // Bitmap number for single ceiling
UCHAR LightFlag; // 0 = no light shading, 1 = ON
UCHAR PalTable[PAL_SIZE]; // 16 zones of 256 colors each
short WinStartX; // Value of left side of viewport
short WinStartY; // Value of top side of viewport
short WinEndX; // Value of right side
short WinEndY; // Value of bottom side
short CenterRow; // Value of (WinEndY-WinStartY)/2
short CenterOffset; // Center row times bytes per row
short WinWidth; // Value of WinEndX - WinStartX
short WinHeight; // Value of WinEndY - WinStartY
USHORT WinLength; // Number of dwords in window
USHORT WinStartOffset; // Value of WinStartY * 320
USHORT SysFlags; // General system flags--determines display attributes
UCHAR bmLoadType; // Bitmap load flags (BBM, GIF, PCX, etc)
short MaxObjects; // Total number of objects in map
NEWOBJECT *ObjList[MAX_OBJECTS+1]; // Current objects in map
DOORS Door[MAX_DOORS]; // Doors moving at one time
} ACKENG;
// Structure used to build the palette ranges for light shading
// There are 16 color ranges (or zones) each containing 256 colors.
typedef struct {
unsigned char start; // Starting color for this range
unsigned char length; // Length of range
} ColorRange;
//*************************************************************************
// Function prototypes for the user callable ACK-3D functions.
//*************************************************************************
// The user callable functions defined in ACKINIT.C.
//*************************************************************************
// Reads trig files, builds wall and object maps, and performs the general
// initialization tasks. This function also sets up the distance table used by ACK-3D.
short AckInitialize(ACKENG *ae);
// Opens a resource file and prepares for reading.
short AckOpenResource(char *ResFileName);
// Closes the currently open resource file.
void AckCloseResource(void);
// Reads the map file and sets up the map grids.
short AckReadMapFile(ACKENG *ae,char *MapFileName);
//*************************************************************************
// The user callable functions defined in ACKLDBMP.C.
//*************************************************************************
// Loads a bitmap and places it in either a wall bitmap array or an object bitmap array.
short AckLoadBitmap(ACKENG *ae,short BitmapNumber,short BitmapType,char *bmFileName);
// Loads a wall bitmap and places it into the wall array.
short AckLoadWall(ACKENG *ae,short WallNumber,char *bmFileName);
// Loads an object bitmap and places it into the object array.
short AckLoadObject(ACKENG *ae,short BmpNumber,char *bmFileName);
// Fills in an ObjList structure with the information passed in.
short AckCreateObject(ACKENG *ae,short ObjNumber);
// Sets up an object into one of the pre-defined sequences (CREATE, DESTRY, and so on).
short AckSetObjectType(ACKENG *ae,short oNum,short oType);
// Fills in an object structure with a communication structure passed by the application.
short AckSetupObject(ACKENG *ae,short oNum,short oType,OBJSEQ *os);
//*************************************************************************
// The user callable functions defined in ACKIFF.C, ACKGIF.C, and ACKPCX.C
//*************************************************************************
// Reads in a .LBM or .BBM file and returns a buffer.
UCHAR *AckReadiff(char *FileName);
// Reads a 256 color GIF file and returns a buffer.
UCHAR *AckReadgif(char *FileName);
// Reads in a 256 color PCX file and returns a buffer.
UCHAR *AckReadPCX(char *filename);
//*************************************************************************
// The user callable functions defined in ACKVIEW.C.
//*************************************************************************
// Assigns the current engine structure to various global variables.
// This function MUST be called before AckBuildView() is called.
void AckRegisterStructure(ACKENG *ae);
// Draws the current view into ScreenBuffer.
void AckBuildView(void);
// Returns the angle (0-1919) between two objects.
short AckGetObjectAngle(long DeltaX,long DeltaY);
// Checks if a collision occurs. Used by AckCheckDoorOpen routine.
short AckCheckHit(short xPlayer,short yPlayer,short ViewAngle);
//*************************************************************************
// The user callable functions defined in ACKPOV.C.
//*************************************************************************
// Used by AckMovePOV() and AckMoveObjectPOV() to check collision with objects.
short AckCheckObjPosn(short xPlayer,short yPlayer,short oIndex);
// Runs the list of objects to check movement.
void AckCheckObjectMovement(void);
// Moves the POV by the specified amount at the specified angle.
short AckMovePOV(short Angle,short Amount);
// Moves the object POV by the specified amount at the specified angle.
short AckMoveObjectPOV(short ObjIndex,short Angle,short Amount);
//*************************************************************************
// The user callable function defined in ACKOVER.C.
//*************************************************************************
// Reads overlay file and compiles it into the OverlayBuffer.
short AckCreateOverlay(ACKENG *ae, UCHAR *OverlayScreen);
//*************************************************************************
// The user callable function defined in ACKBKGD.C.
//*************************************************************************
// Builds background buffer from TopColor, BottomColor, and LightFlag.
short AckBuildBackground(ACKENG *ae);
//*************************************************************************
// The user callable function defined in ACKDOOR.C.
//*************************************************************************
// Check if a door in front to open
short AckCheckDoorOpen(short xPlayer,short yPlayer,short PlayerAngle);
//*************************************************************************
// The user callable function defined in ACKWRAP.C.
//*************************************************************************
// Frees memory buffers.
short AckWrapUp(ACKENG *ae);
//*************************************************************************
// The user callable functions defined in ACKUTIL.C.
//*************************************************************************
// Internal memory allocation for development purposes
void *AckMalloc(size_t mSize);
// All memory allocated with AckMalloc() must use AckFree() to free memory.
void AckFree(void *m);
// Reads in a palette file and sets the screen palette.
short AckLoadAndSetPalette(char *FileName);
// Fills in the shading palette table.
void AckSetupPalRanges(ACKENG *ae,ColorRange *ranges);
// Returns the object index number of the last object hit.
short AckGetObjectHit(void);
// Returns the map location of the last wall hit.
short AckGetWallHit(void);
// Removes the specified object from the map.
short AckDeleteObject(ACKENG *ae,short ObjectIndex);
// Sets a new bitmap or changes image in the bitmap array.
short AckSetNewBitmapPtr(short BitmapNumber,UCHAR **Maps,UCHAR *NewBitmap);
// Frees up the memory used by the bitmap.
short AckFreeBitmap(UCHAR *bmType);
//*************************************************************************
// The user callable functions defined in ACKRTN.ASM.
//*************************************************************************
// Sets a previously loaded palette.
void AckSetPalette(UCHAR *PalBuffer);
// Places video in standard 320x200 mode 13h.
void AckSetVGAmode(void);
// Places video in 80x25 color text mode 3.
void AckSetTextmode(void);
// Displays the contents of ScreenBuffer and OverlayBuffer if desired.
short AckDisplayScreen(void);


42
ack_lib/ACKBKGD.C Normal file
View file

@ -0,0 +1,42 @@
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
//typedef unsigned short USHORT;
#include "ack3d.h"
#include "ackeng.h"
void AckBuildCeilingFloor (UCHAR *, short, short, short, short, short, short);
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Generates a solid floor and ceiling
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckBuildBackground (ACKENG * ae)
{
/* Let the assembly routine do all the hard work */
#if FLOOR_ACTIVE
#else
AckBuildCeilingFloor (ae->BkgdBuffer,
ae->LightFlag,
ae->TopColor,
ae->BottomColor,
ae->WinStartY,
ae->WinEndY,
ae->CenterRow);
#endif
return (0);
}


150
ack_lib/ACKDATA.C Normal file
View file

@ -0,0 +1,150 @@
#include <windows.h>
#include <stdio.h>
#include "ack3d.h"
#include "ackeng.h"
long scPtr;
UCHAR *bmWall;
long bmDistance;
long BackDropRows;
USHORT ScreenOffset;
long xPglobal;
long yPglobal;
long xBegGlobal;
long yBegGlobal;
ACKENG *aeGlobal;
USHORT *xGridGlobal;
USHORT *yGridGlobal;
long xPglobalHI;
long yPglobalHI;
ULONG *rbaTable;
short rsHandle;
long LastX1;
long LastY1;
long iLastX;
long iLastY;
long x_xPos;
long x_yPos;
long x_xNext;
long x_yNext;
long y_xPos;
long y_yPos;
long y_xNext;
long y_yNext;
short MaxDistance;
short LightFlag;
short ErrorCode;
long xMapPosn;
long yMapPosn;
USHORT *Grid;
USHORT *ObjGrid;
SLICE Slice[VIEW_WIDTH];
SLICE *sPtr;
short TotalSpecial;
short DistanceTable[MAX_DISTANCE + 1];
long *AdjustTable;
short xSecretmPos;
short xSecretmPos1;
short xSecretColumn;
short ySecretmPos;
short ySecretmPos1;
short ySecretColumn;
short TotalSecret;
short ViewColumn;
long *SinTable;
long *CosTable;
long *LongTanTable;
long *LongInvTanTable;
long InvCosTable[INT_ANGLE_360];
long InvSinTable[INT_ANGLE_360];
long *LongCosTable;
long *ViewCosTable;
long *xNextTable;
long *yNextTable;
short LastFloorAngle = -1;
short LastFloorX;
short LastFloorY;
short LastMapPosn;
short LastObjectHit;
short TotalObjects;
short FoundObjectCount;
UCHAR ObjectsSeen[MAX_OBJECTS + 1];
short MoveObjectCount;
UCHAR MoveObjectList[MAX_OBJECTS + 1];
UCHAR ObjNumber[MAX_OBJECTS + 1];
USHORT ObjRelDist[MAX_OBJECTS + 1];
short ObjColumn[MAX_OBJECTS + 1];
short ObjAngle[MAX_OBJECTS + 1];
short DirAngle[] =
{INT_ANGLE_270, INT_ANGLE_315, 0,
INT_ANGLE_45, INT_ANGLE_90,
INT_ANGLE_135, INT_ANGLE_180,
INT_ANGLE_225};
UCHAR WorkPalette[768];
UCHAR *BackArray[INT_ANGLE_360];
short Resolution;
long Flooru;
long Floorv;
long Floordu;
long Floordv;
long Floorkx;
long Floorky;
long Floorku;
long Floorkv;
long Floorkdu;
long Floorkdv;
UCHAR *Floorbm;
UCHAR *Floorscr;
UCHAR *FloorscrTop;
UCHAR *Floorptr2;
UCHAR *Floors1;
UCHAR *Floors2;
long Floorht;
long Floorwt;
short Floorvht;
short Flooreht;
long FloorLastbNum;
long FloorLastbm;
short ViewHeight = 31;
short CeilingHeight = 31;
short LastWallHeight;
short PlayerAngle;
short ViewAngle;
USHORT SysFlags;
UCHAR **WallbMaps;
UCHAR *VidTop;
UCHAR *VidBottom;
short BotRowTable[320];
USHORT FloorMap[4096];
USHORT CeilMap[4096];
UCHAR HitMap[4096];
UCHAR *VidSeg;
char *scantables[96];
UCHAR AckKeys[128]; // Buffer for keystrokes
long AckTimerCounter;
// **** End of Data ****


34
ack_lib/ACKDISP.C Normal file
View file

@ -0,0 +1,34 @@
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
//typedef unsigned short USHORT;
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
void AckDrawPage (void);
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// This function has been replaced by AckDisplayScreen in assembler
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short xxxAckDisplayScreen (void)
{
/* Let the assembly routine do the hard work */
AckDrawPage ();
return (0);
}


391
ack_lib/ACKDOOR.C Normal file
View file

@ -0,0 +1,391 @@
// This source file contains the functions needed to process doors.
// (c) 1995 ACK Software (Lary Myers)
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
extern DOORS *gDoor;
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Check all the active doors to see what current state they are in. If a
// door's column offset is non-zero, it is either opening or closing,
// so the speed of the door is added in and the door is checked to
// see if it is fully opened or fully closed.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
void CheckDoors (void)
{
short i, MapPosn, mPos, mPos1;
short mx, my, DeltaGrid;
short xPlayer, yPlayer;
DOORS *dPtr;
xPlayer = xPglobal;
yPlayer = yPglobal;
dPtr = &gDoor[0];
for (i = 0; i < MAX_DOORS; i++)
{
if (dPtr->ColOffset) // Door is not closed
{ // Add speed to door column offset
dPtr->ColOffset += dPtr->Speed;
mPos = dPtr->mPos; // Get grid position of door
mPos1 = dPtr->mPos1;
// Door is closing and is visible. Put old codes back to make non-passable
if (dPtr->Speed < 1 && dPtr->ColOffset < 65)
{ // Get corner of grid
MapPosn = (yPlayer & 0xFFC0) + (xPlayer >> BITMAP_SHIFT);
// Is player in same grid square that the door is in?
if (MapPosn == mPos || MapPosn == mPos1)
{
dPtr->ColOffset -= dPtr->Speed; // Reduce column offset
continue;
}
// Is the door along an x wall
if (dPtr->Type == DOOR_XCODE)
{ // Store bitmap ids for doors
xGridGlobal[mPos] = dPtr->mCode;
xGridGlobal[mPos1] = dPtr->mCode1;
}
else
{ // Door is along a y wall
yGridGlobal[mPos] = dPtr->mCode;
yGridGlobal[mPos1] = dPtr->mCode1;
}
// Door is close enough to fully closed to get rid
// of the door from the array
if (dPtr->ColOffset < 3)
{
dPtr->ColOffset = 0; // Close door
dPtr->mPos = -1;
dPtr->mPos1 = -1;
dPtr->Flags = 0;
}
}
// Door is fully opened--time to start closing it
if (dPtr->ColOffset > 0xA0)
{
dPtr->Speed = -dPtr->Speed; // Start to reduce speed
dPtr->Flags &= ~DOOR_OPENING; // Set flag to indicate door closing
dPtr->Flags |= DOOR_CLOSING;
}
}
dPtr++; // Advance to check next door
}
//=============================================================================
// Now check for any action occuring in a secret door. This is currently
// setup to handle only one door at a time in the X and Y directions, but
// it should be fairly straightforward to use a list of doors, similiar
// to normal doors, to handle more than one.
//=============================================================================
if (xSecretColumn)
{
if (xSecretColumn > 0) // See if the door is to the right of us
{
mPos = xSecretmPos1;
DeltaGrid = -1;
xSecretColumn += aeGlobal->DoorSpeed;
}
else
{
mPos = xSecretmPos;
DeltaGrid = 0;
xSecretColumn -= aeGlobal->DoorSpeed;
}
my = mPos & 0xFFC0;
mx = (mPos - my) << 6;
if (abs (xSecretColumn) > BITMAP_WIDTH) // Beyond one grid square
{
mx += xSecretColumn;
my = my + (mx >> BITMAP_SHIFT);
if (xGridGlobal[my]) // No further, an obstruction
{
xGridGlobal[xSecretmPos] = 0;
xGridGlobal[xSecretmPos1] = 0;
my += DeltaGrid;
xGridGlobal[my] = aeGlobal->NonSecretCode;
xGridGlobal[my + 1] = aeGlobal->NonSecretCode;
yGridGlobal[my] = aeGlobal->NonSecretCode;
yGridGlobal[my + GRID_WIDTH] = aeGlobal->NonSecretCode;
xSecretColumn = 0;
}
else
{
if (my != mPos)
{
xGridGlobal[xSecretmPos] = 0;
xGridGlobal[xSecretmPos1] = 0;
if (xSecretColumn > 0)
{
xSecretColumn -= (BITMAP_WIDTH - 1);
xGridGlobal[my] = DOOR_TYPE_SECRET + 1;
xSecretmPos1 = my;
my--;
xGridGlobal[my] = DOOR_TYPE_SECRET + 1;
xSecretmPos = my;
}
else
{
xSecretColumn += (BITMAP_WIDTH - 1);
xGridGlobal[my] = DOOR_TYPE_SECRET + 1;
xGridGlobal[my + 1] = DOOR_TYPE_SECRET + 1;
xSecretmPos = my;
xSecretmPos = my + 1;
}
}
} // End if (xGrid[my]) ... else ...
} // End if (abs(xSecretColumn) > GRID_SIZE)
} // End if (xSecretColumn)
//=============================================================================
// Perform same process on a secret door that may be moving in the Y
// direction. The same door can move either way, depending on which
// angle the player struck it at.
//=============================================================================
if (ySecretColumn)
{
if (ySecretColumn > 0)
{
mPos = ySecretmPos1;
DeltaGrid = -GRID_WIDTH;
ySecretColumn += aeGlobal->DoorSpeed;
}
else
{
mPos = ySecretmPos;
DeltaGrid = 0;
ySecretColumn -= aeGlobal->DoorSpeed;
}
my = mPos & 0xFFC0;
mx = (mPos - my) << 6;
if (abs (ySecretColumn) > BITMAP_WIDTH)
{
my += ySecretColumn;
my = (my & 0xFFC0) + (mx >> 6);
if (yGridGlobal[my])
{
yGridGlobal[ySecretmPos] = 0;
yGridGlobal[ySecretmPos1] = 0;
my += DeltaGrid;
xGridGlobal[my] = aeGlobal->NonSecretCode;
xGridGlobal[my + 1] = aeGlobal->NonSecretCode;
yGridGlobal[my] = aeGlobal->NonSecretCode;
yGridGlobal[my + GRID_WIDTH] = aeGlobal->NonSecretCode;
ySecretColumn = 0;
}
else
{
if (my != mPos)
{
yGridGlobal[ySecretmPos] = 0;
yGridGlobal[ySecretmPos1] = 0;
if (ySecretColumn > 0)
{
ySecretColumn -= (BITMAP_WIDTH - 1);
yGridGlobal[my] = DOOR_TYPE_SECRET + 1;
ySecretmPos1 = my;
my -= GRID_WIDTH;
yGridGlobal[my] = DOOR_TYPE_SECRET + 1;
ySecretmPos = my;
}
else
{
ySecretColumn += (BITMAP_WIDTH - 1);
yGridGlobal[my] = DOOR_TYPE_SECRET + 1;
yGridGlobal[my + GRID_WIDTH] = DOOR_TYPE_SECRET + 1;
ySecretmPos = my;
ySecretmPos = my + GRID_WIDTH;
}
}
}
}
}
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Internal function called by FindDoorSlot(). This function
// locates a door from its map coordinate and return the index.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short FindDoor (short MapPosn)
{
short index;
for (index = 0; index < MAX_DOORS; index++)
{
if (MapPosn == gDoor[index].mPos ||
MapPosn == gDoor[index].mPos1)
{
return (index);
}
}
return (-1);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Internal routine called by AckCheckDoorOpen() This function
// finds an empty slot for a door. If the door already occupies a slot
// and it is in a non-closed state, an error is returned.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short FindDoorSlot (short MapPosn)
{
short index;
index = FindDoor (MapPosn);
if (index >= 0 && gDoor[index].ColOffset)
return (-1);
for (index = 0; index < MAX_DOORS; index++)
{
if (gDoor[index].mPos == -1)
return (index);
}
return (-1);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Checks directly in front of the POV to see if a door is there. If so,
// and the door is not locked, the door is set to begin opening.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckCheckDoorOpen (short xPlayer, short yPlayer, short PlayerAngle)
{
short i,j,DoorCode;
DoorCode = POV_NODOOR;
// Check to see if player is close to a wall
i = AckCheckHit (xPlayer, yPlayer, PlayerAngle);
// A secret door is found along an x wall
if (i == 1 && xGridGlobal[xMapPosn] & DOOR_TYPE_SECRET)
{
if (xSecretColumn == 0) // Player is on the right side of door
{
DoorCode = POV_XSECRETDOOR;
// Secret door is locked; can't open
if (xGridGlobal[xMapPosn] & DOOR_LOCKED)
return (DoorCode | POV_DOORLOCKED);
// Get grid map position that corresponds with the x wall
// position of where the door starts
xSecretmPos = xMapPosn;
if (iLastX > xPlayer) // Door is to the right of player
{
xSecretmPos1 = xMapPosn + 1;
LastMapPosn = xMapPosn;
xSecretColumn = 1; // Set to indicate player is on right side
yGridGlobal[xMapPosn] = yGridGlobal[xMapPosn - GRID_WIDTH];
}
else
{ // Door is to the left of the player
LastMapPosn = xSecretmPos1 = xMapPosn - 1;
xSecretColumn = -1;
yGridGlobal[xSecretmPos1] = yGridGlobal[xSecretmPos1 - GRID_WIDTH];
}
}
}
// A secret door is found along a y wall
if (i == 2 && yGridGlobal[yMapPosn] & DOOR_TYPE_SECRET)
{
if (ySecretColumn == 0)
{
DoorCode = POV_YSECRETDOOR;
if (yGridGlobal[yMapPosn] & DOOR_LOCKED)
return (DoorCode | POV_DOORLOCKED);
ySecretmPos = yMapPosn;
if (iLastY > yPlayer)
{
LastMapPosn = yMapPosn;
ySecretmPos1 = yMapPosn + GRID_WIDTH;
xGridGlobal[yMapPosn] = xGridGlobal[yMapPosn - 1];
ySecretColumn = 1;
}
else
{
LastMapPosn = ySecretmPos1 = yMapPosn - GRID_WIDTH;
xGridGlobal[ySecretmPos1] = xGridGlobal[ySecretmPos1 - 1];
ySecretColumn = -1;
}
}
}
// A sliding or split door is found along an x wall
if (i == 1 && (xGridGlobal[xMapPosn] & (DOOR_TYPE_SLIDE + DOOR_TYPE_SPLIT)))
{
j = FindDoorSlot (xMapPosn);
if (j >= 0)
{
DoorCode = POV_XDOOR;
LastMapPosn = gDoor[j].mPos = xMapPosn;
if ((short) iLastX > xPlayer)
i = xMapPosn + 1;
else
LastMapPosn = i = xMapPosn - 1;
if (xGridGlobal[xMapPosn] & DOOR_LOCKED)
{
gDoor[j].mPos = -1;
return (DoorCode | POV_DOORLOCKED);
}
// Update door data structure
gDoor[j].mCode = xGridGlobal[xMapPosn];
gDoor[j].mCode1 = xGridGlobal[i];
gDoor[j].mPos1 = i;
gDoor[j].ColOffset = 1;
gDoor[j].Speed = aeGlobal->DoorSpeed;
gDoor[j].Type = DOOR_XCODE;
gDoor[j].Flags = DOOR_OPENING;
}
}
// A sliding or split door is found along a y wall
if (i == 2 && (yGridGlobal[yMapPosn] & (DOOR_TYPE_SLIDE + DOOR_TYPE_SPLIT)))
{
j = FindDoorSlot (yMapPosn);
if (j >= 0)
{
DoorCode = POV_YDOOR;
LastMapPosn = gDoor[j].mPos = yMapPosn;
if ((short) iLastY > yPlayer)
i = yMapPosn + GRID_WIDTH;
else
LastMapPosn = i = yMapPosn - GRID_WIDTH;
if (yGridGlobal[yMapPosn] & DOOR_LOCKED)
{
gDoor[j].mPos = -1;
return (DoorCode | POV_DOORLOCKED);
}
gDoor[j].mCode = yGridGlobal[yMapPosn];
gDoor[j].mCode1 = yGridGlobal[i];
gDoor[j].mPos1 = i;
gDoor[j].ColOffset = 1;
gDoor[j].Speed = aeGlobal->DoorSpeed;
gDoor[j].Type = DOOR_YCODE;
gDoor[j].Flags = DOOR_OPENING;
}
}
return (DoorCode);
}
// **** End of Source ****


66
ack_lib/ACKENG.H Normal file
View file

@ -0,0 +1,66 @@
// ACKENG.H header file for supporting raycasting routines.
// This file contains the main data structure named SLICE and definitions
// required to support the raycasting routines. The data structures defined
// in this file are not to be used directly by the programmer who is using
// the functions in the ACK-3D library. To locate data structures for the
// ACK-3D interface, see the file ACK3D.H.
#define TRANS_WALLS 0
#define FLOOR_ACTIVE 1
#define USE_XMS 0 // Set to 0 if XMS not desired
#define MAX_RBA 500 // Number of rba's in resource header
// Fixed point constants used to perform fixed point calculations.
#define FP_SHIFT 16
#define FP_MULT 65536
#define FP_HALF 32768
#define VIEW_WIDTH 320 // The number of columns in a view (screen)
#define MAX_DISTANCE 2048 // The max distance from the POV to a wall slice
#define TYPE_WALL 0
#define TYPE_OBJECT 1
#define TYPE_PALETTE 2
#define MAX_HEIGHT 960 // Maximum height of a wall
#define MIN_HEIGHT 8 // Minimum height of a wall
#define MAX_UPDOWN 30 // Max up or down spots for each level
#define MAP_STARTCODE 0xFC // Force player to this square
#define MAP_UPCODE 0xFD // Go up to previous level
#define MAP_DOWNCODE 0xFE // Go down to next level
#define MAP_GOALCODE 0xFF // Finish line!
#define ST_WALL 1
#define ST_OBJECT 2
#define COLS_PER_BYTE 1 // Use 1 for normal mode 13h, 4 for modeX
#define BYTES_PER_ROW 320 // Use 320 for normal mode 13h, 80 for modeX
#define DWORDS_PER_ROW (BYTES_PER_ROW / 4)
#define SCREEN_SIZE 64000
// Holds information for the current wall section found during the raycasting process.
// During the raycasting process, ACK-3D casts out rays, looks for a wall at a
// given screen column position, and if a wall (slice) is found, information about
// the slice is stored in this structure.
typedef struct _slicer {
UCHAR **bMap; // Pointer to wall bitmap found while ray casting
UCHAR *mPtr; // Grid pointer to reference multi-height wall data
short bNumber; // Bitmap number of the wall found
unsigned short bColumn; // Screen column location of the found slice
short Distance; // Distance from the POV to the slice
short mPos; // Position of the slice in the associated map
unsigned char Type; // Indicates if the slice is a wall or object
void (*Fnc)(void); // Pointer to a function to draw wall or object
unsigned char Active; // Indicates last slice in listif a wall or object is displayable or not
// The next two pointers are used if the current slice
// is part of a transparent wall
struct _slicer *Prev; // References the wall slice in front of current slice
struct _slicer *Next; // References the wall slice behind the current slice
} SLICE;


119
ack_lib/ACKEXT.H Normal file
View file

@ -0,0 +1,119 @@
/* ACK-3D ( Animation Construction Kit 3D ) */
extern UCHAR *BackArray[];
extern long xPglobal;
extern long yPglobal;
extern long xBegGlobal;
extern long yBegGlobal;
extern long BackDropRows;
extern ACKENG *aeGlobal;
extern USHORT *xGridGlobal;
extern USHORT *yGridGlobal;
extern long xPglobalHI;
extern long yPglobalHI;
extern ULONG *rbaTable;
extern long bmDistance;
extern short rsHandle;
extern long LastX1;
extern long LastY1;
extern long iLastX;
extern long iLastY;
extern short MaxDistance;
extern short ErrorCode;
extern short LightFlag;
extern long xMapPosn;
extern long yMapPosn;
extern short DefZone[];
extern short AckLightZones[];
extern UCHAR *HtTable[];
extern USHORT *Grid;
extern USHORT *ObjGrid;
extern UCHAR HitMap[];
extern UCHAR *BitmapXferPtr;
extern short TotalSpecial;
extern short DistanceTable[];
extern long *AdjustTable;
extern short xSecretmPos;
extern short xSecretmPos1;
extern short xSecretColumn;
extern short ySecretmPos;
extern short ySecretmPos1;
extern short ySecretColumn;
extern short TotalSecret;
extern short ViewColumn;
extern long *SinTable;
extern long *CosTable;
extern long *LongTanTable;
extern long *LongInvTanTable;
extern long InvCosTable[];
extern long InvSinTable[];
extern long *LongCosTable;
extern long *ViewCosTable;
extern long *xNextTable;
extern long *yNextTable;
extern UCHAR ObjectsSeen[];
extern UCHAR MoveObjectList[];
extern short TotalObjects;
extern short FoundObjectCount;
extern short MoveObjectCount;
extern short LastObjectHit;
extern short LastMapPosn;
extern UCHAR ObjNumber[];
extern USHORT ObjRelDist[];
extern short ObjColumn[];
extern short ObjAngle[];
extern short DirAngle[];
extern UCHAR LightMap[];
extern USHORT FloorMap[];
extern USHORT CeilMap[];
extern SLICE Slice[];
extern USHORT ScreenOffset;
extern short LastFloorAngle;
extern short LastFloorX;
extern short LastFloorY;
extern long Flooru;
extern long Floorv;
extern long Floordu;
extern long Floordv;
extern long Floorkx;
extern long Floorky;
extern long Floorku;
extern long Floorkv;
extern long Floorkdu;
extern long Floorkdv;
extern UCHAR *Floorbm;
extern UCHAR *Floorscr;
extern UCHAR *FloorscrTop;
extern UCHAR *Floorptr2;
extern UCHAR *Floors1;
extern UCHAR *Floors2;
extern long Floorht;
extern long Floorwt;
extern short Floorvht;
extern short Flooreht;
extern short ViewAngle;
extern short ViewHeight;
extern short CeilingHeight;
extern short Resolution;
extern short LastWallHeight;
extern short PlayerAngle;
extern short ViewAngle;
extern USHORT SysFlags;
extern SLICE Slice[];
extern SLICE *sPtr;
extern UCHAR **WallbMaps;
extern UCHAR *VidTop;
extern UCHAR *VidBottom;
extern short BotRowTable[];
extern USHORT FloorMap[];
extern USHORT CeilMap[];
extern char *scantables[];


1239
ack_lib/ACKFLOOR.C Normal file

File diff suppressed because it is too large Load diff

30
ack_lib/ACKGIF.C Normal file
View file

@ -0,0 +1,30 @@
// This source file contains the functions needed to read in GIF files.
// (c) 1995 ACK Software (Lary Myers)
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>
#include <bios.h>
#include <fcntl.h>
#include <malloc.h>
#include <string.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Read a GIF format file and return a buffer containing the uncompressed
// image.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
#pragma argsused
unsigned char *AckReadgif (char *picname)
{
// This is a stub routine used only as a place holder for the actual
// GIF read routine. It was omitted based on current patent issues.
return(NULL);
}
// **** End of Source ****


231
ack_lib/ACKIFF.C Normal file
View file

@ -0,0 +1,231 @@
// This source file contains the functions needed to read in BBM files.
// (c) 1995 ACK Software (Lary Myers)
//=============================================================================
// This function will return a pointer to a buffer that holds the raw image.
// just free the pointer to delete this buffer. After returning, the array
// colordat will hold the adjusted palette of this pic.
//
// Also, this has been modified to only read in form PBM brushes. form ILBM's
// (the "old" type) are not supported. use the "new" deluxe paint .lbm type
// and do not choose "old".
//=============================================================================
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>
#include <bios.h>
#include <fcntl.h>
#include <malloc.h>
#include <mem.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
#include "iff.h"
extern int errno;
extern char rsName[];
unsigned char colordat[768]; // maximum it can be...256 colors
unsigned char cplanes[8][80]; // setting max at 640 pixels width
// thats 8 pixels per byte per plane
unsigned char *pplanes= &cplanes[0][0]; // for a form pbm
#define MAX_BUF_POS 4096
int rdbufpos;
int rdSize;
UCHAR rdBuffer[MAX_BUF_POS+2];
//=============================================================================
//
//=============================================================================
void CloseFile(FILE *fp)
{
fclose(fp);
if (rsHandle)
{
rsHandle = _lopen(rsName,OF_READ);
if (rsHandle < 1)
rsHandle = 0;
}
}
unsigned char *AckReadiff(char *picname)
{
FILE *pic;
short handle;
form_chunk fchunk;
ChunkHeader chunk;
BitMapHeader bmhd;
long length,fpos;
char value; // must remain signed, no matter what. ignore any warnings.
short sofar;
short width,height,planes;
short pixw;
unsigned char *destx, *savedestx;
rdbufpos = MAX_BUF_POS + 1;
rdSize = MAX_BUF_POS;
if (!rsHandle)
handle = _lopen(picname,OF_READ);
else
{
handle = rsHandle;
_llseek(rsHandle,rbaTable[(ULONG)picname],SEEK_SET);
}
_lread(handle,&fchunk,sizeof(form_chunk));
if (fchunk.type != FORM)
{
if (!rsHandle)
_lclose(handle);
ErrorCode = ERR_INVALIDFORM;
return(0L);
}
if (fchunk.subtype != ID_PBM)
{
if (!rsHandle)
_lclose(handle);
ErrorCode = ERR_NOPBM;
return(0L);
}
// now lets loop...Because the Chunks can be in any order!
while(1)
{
_lread(handle,&chunk,sizeof(ChunkHeader));
chunk.ckSize = ByteFlipLong(chunk.ckSize);
if (chunk.ckSize & 1) chunk.ckSize ++; // must be word aligned
if(chunk.ckID == ID_BMHD)
{
_lread(handle,&bmhd,sizeof(BitMapHeader));
bmhd.w=iffswab(bmhd.w); // the only things we need.
bmhd.h=iffswab(bmhd.h);
destx = (unsigned char *)AckMalloc((bmhd.w * bmhd.h)+4);
if ( !destx )
{
if (!rsHandle)
_lclose(handle);
ErrorCode = ERR_NOMEMORY;
return(0L);
}
savedestx = destx;
destx[0] = bmhd.w%256;
destx[1] = bmhd.w/256;
destx[2] = bmhd.h%256;
destx[3] = bmhd.h/256;
destx += 4;
continue;
}
if(chunk.ckID == ID_CMAP)
{
short i;
unsigned char r,g;
_lread(handle,colordat,chunk.ckSize);
for (i=0;i<768;i++)
{
r = colordat[i]; // r,g do not stand for red and green
g = r >> 2;
colordat[i] = g;
}
continue;
}
if(chunk.ckID == ID_BODY)
{
for(height = 0; height<bmhd.h; height ++)
{
unsigned char *dest;
dest = (unsigned char *)&(pplanes[0]); // point at first char
sofar = bmhd.w; // number of bytes = 8
if (sofar&1) sofar++;
while (sofar)
{
if (bmhd.compression)
{
value = 0;
_lread(handle,&value,1);
if (value > 0)
{
short len;
len = value +1;
sofar -= len;
if (!(_lread(handle,dest,len)))
{
if (!rsHandle)
_lclose(handle);
ErrorCode = ERR_BADPICFILE;
AckFree(savedestx);
return(0L);
}
dest +=len;
}
else
{
short count;
count = -value; // get amount to dup
count ++;
sofar -= count;
value = 0;
_lread(handle,&value,1);
while (--count >= 0) *dest++ = value;
}
}
else
{
_lread(handle,dest,sofar);
sofar = 0;
}
}
if (sofar < 0)
{
if (!rsHandle)
_lclose(handle);
}
_fmemcpy(destx,pplanes,bmhd.w);
destx += bmhd.w;
}
break; // leave if we've unpacked the BODY
}
_llseek(handle,chunk.ckSize,SEEK_CUR);
}
if (!rsHandle)
_lclose(handle);
return((char *)savedestx);
}
long ByteFlipLong(long NUMBER)
{
long Y, T;
short I;
T = NUMBER;
Y=0;for (I=0;I<4;I++){Y = Y | (T & 0xFF);if (I<3) {Y = Y << 8;T = T >> 8;}}
return(Y);
}
short iffswab(unsigned short number)
{
unsigned short xx1,xx2;
unsigned short result;
xx1 = number <<8; xx2 = number >>8; result = xx1|xx2;
return(result);
}
// **** End of Source ****


542
ack_lib/ACKINIT.C Normal file
View file

@ -0,0 +1,542 @@
// This file contains the key initialization functions for the ACK-3D engine.
// The main function AckInitialize() must be called first before any of the
// other ACK-3D functions are called. The internal functions defined in this file
// perform all of the set up work of loading tables and resource files.
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
extern char AckKeyboardSetup;
extern char AckTimerSetup;
short *LowerTable[2048];
short tmpLowerValue[400];
short LowerLen[2048];
short OurDataSeg;
char rsName[128];
long FloorCosTable[VIEW_WIDTH+1];
short AckBuildTables(ACKENG *ae);
void AckBuildHeightTables(ACKENG *ae);
void AckBuildGrid(ACKENG *ae);
void SetupFloors(ACKENG *ae);
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
// Internal function called by AckInitialize(). This function sets up the
// internal variables that are required to support the off-screen buffer
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
void AckSetupWindow(ACKENG *ae)
{
// Access the center row of the viewport
ae->CenterRow = ae->WinStartY + ((ae->WinEndY - ae->WinStartY) / 2);
// Access a memory location for the center row
ae->CenterOffset = ae->CenterRow * BYTES_PER_ROW;
// Access the starting memory location of the viewport
ae->WinStartOffset = ae->WinStartY * BYTES_PER_ROW;
// Calculate the window length in double words
ae->WinLength = ((ae->WinEndY - ae->WinStartY)+1) * DWORDS_PER_ROW;
// Calculates the viewport window width and height
ae->WinWidth = (ae->WinEndX - ae->WinStartX) + 1;
ae->WinHeight = (ae->WinEndY - ae->WinStartY) + 1;
}
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
// Initializes the ACK interface structure and reads in the TRIG tables
// from either the stand alone file TRIG.DAT or from a resource file that
// was opened previous to this call.
// This function MUST be called before AckBuildView() and AckDisplayScreen()
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
short AckInitialize(ACKENG *ae)
{
short i,result = 0;
short j;
UCHAR topcolor;
#ifdef __BORLANDC__ // Conditional for Borland C++
OurDataSeg = _DS;
#endif
AckKeyboardSetup = 0; // Indicates keyboard interrupt has not been set up
AckTimerSetup = 0; // Indicates timer has not been set up
// Check to see if viewport coordinates are set up properly
if (!ae->WinEndY || !ae->WinEndX ||
(ae->WinEndY - ae->WinStartY) < 10 || // Height is less than 10 pixels
(ae->WinEndX - ae->WinStartX) < 10) // Width is less than 10 pixels
{
return(ERR_BADWINDOWSIZE); // Return error code for invalid viewport
}
result = AckBuildTables(ae); // Read in TRIG.DAT and allocate tables
if (result)
return(result);
AckSetupWindow(ae); // Set up the internal coordinates for the viewport
SetupFloors(ae); // Set up the floors
AckBuildHeightTables(ae); // Build height and adjustment tables
topcolor = ae->TopColor;
BackDropRows = 100;
for (i = 0; i < 640; i++)
{
BackArray[i] = AckMalloc(BackDropRows+1);
if (BackArray[i] == NULL)
return(ERR_NOMEMORY);
memset(BackArray[i],topcolor,BackDropRows);
}
return(result);
}
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
// Opens a resource file for use by any ACK routine that requires a
// filename. Only one resource file can be opened at a time.
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
short AckOpenResource(char *fName)
{
ULONG hLen;
if (rsHandle) // Is a resource file currently opened?
_lclose(rsHandle); // Close it before opening a new one
rsHandle = _lopen(fName,OF_READ); // Open new resource file
if (rsHandle < 1) // Check to see if file is opened properly
{
rsHandle = 0; // Reset file handle
return(ERR_BADFILE); // Return error code for faliure
}
hLen = MAX_RBA * sizeof(long); // Get size of file
if (rbaTable == NULL)
rbaTable = (ULONG *)AckMalloc(hLen); // Allocate buffer for file
if (rbaTable == NULL) // Was memory available?
{
_lclose(rsHandle); // Close file
rsHandle = 0; // Reset file handle
return(ERR_NOMEMORY); // Return error code
}
// Read in the file and check for byte count error
if (_lread(rsHandle,(ULONG *)rbaTable,hLen) != hLen)
{
_lclose(rsHandle); // Close file
rsHandle = 0; // Reset file handle
AckFree(rbaTable); // Free up buffer
return(ERR_BADFILE); // Return file error code
}
strcpy(rsName,fName); // Store resource filename
return(0);
}
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
// Closes a resource file if one is opened.
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
void AckCloseResource(void)
{
if (rsHandle) // Check to make sure resource file is opened
_lclose(rsHandle); // Close the resource
if (rbaTable != NULL) // Do we need to free the memory for the file buffer?
{
AckFree(rbaTable); // Free up the file buffer
rbaTable = NULL;
}
rsHandle = 0; // Reset the file handle
}
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
// Internal function used to pre-define height tables for the wall
// drawing code.
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
void BuildWallDstTables(void)
{
short i,j,dst,row,HiValue;
long ldst,value,LowValue,len;
short *lp;
for (ldst = 10;ldst < 2048; ldst++)
{
HiValue = value = 0;
row = 0;
while (HiValue < 64 && row < 100)
{
HiValue = (value >> 8) & 0xFF;
tmpLowerValue[row] = HiValue;
row++;
value += ldst;
}
LowerLen[ldst] = row;
len = row * 2;
j = 1;
if (row == LowerLen[ldst-1])
{
j = 0;
lp = LowerTable[ldst-1];
for (i = 0; i < row; i++)
{
if (tmpLowerValue[i] != lp[i])
{
j = 1;
break;
}
}
}
if (j)
{
lp = AckMalloc(len);
if (lp == NULL)
{
return;
}
LowerTable[ldst] = lp;
for (i = 0; i < row; i++)
lp[i] = tmpLowerValue[i];
}
else
{
LowerTable[ldst] = LowerTable[ldst-1];
}
}
}
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
// Internal function called from AckInitialize() to read in the trig tables
// and allocate memory for the various buffers.
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
short AckBuildTables(ACKENG *ae)
{
short handle,len,ca,na;
int c,s,ang;
long fAng,tu,tv;
SLICE *sa,*saNext;
BuildWallDstTables(); // Create the distance tables
if (!rsHandle) // Check to make sure resource file is not opened
{
handle = _lopen("trig.dat",OF_READ); // Open trig data file
if (handle < 1)
return(ERR_BADFILE); // File can't be opened; return error code
}
else
{
handle = rsHandle; // Get handle for resource file
_llseek(handle,rbaTable[0],SEEK_SET);
}
// Allocate memory for trig and coordinate tables
LongTanTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
LongInvTanTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
CosTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
SinTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
LongCosTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
xNextTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
yNextTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
ViewCosTable = (long *)AckMalloc(sizeof(long) * VIEW_WIDTH);
// Allocate memory for map grid and object grid
Grid = (unsigned short *)AckMalloc((GRID_MAX * 2)+1);
ObjGrid = (unsigned short *)AckMalloc((GRID_MAX * 2)+1);
// Allocate memory for height adjustment table
AdjustTable = (long *)AckMalloc((MAX_DISTANCE+1) * sizeof(long));
// Allocate memory for screen buffers
ae->ScreenBuffer = (UCHAR *)AckMalloc(SCREEN_SIZE+640);
ae->BkgdBuffer = (UCHAR *)AckMalloc(SCREEN_SIZE+640);
if (LongTanTable == NULL || // Make sure memory is allocated for tables
LongInvTanTable == NULL ||
CosTable == NULL ||
SinTable == NULL ||
LongCosTable == NULL ||
xNextTable == NULL ||
yNextTable == NULL ||
Grid == NULL ||
ObjGrid == NULL ||
AdjustTable == NULL ||
ae->ScreenBuffer == NULL ||
ae->BkgdBuffer == NULL ||
ViewCosTable == NULL)
{
if (!rsHandle)
_lclose(handle);
return(ERR_NOMEMORY); // Return memory allocation error code
}
len = sizeof(long) * INT_ANGLE_360; // Calculate size for each trig table
_lread(handle,SinTable,len); // Read in trig data and place in appropriate tables
_lread(handle,CosTable,len);
_lread(handle,LongTanTable,len);
_lread(handle,LongInvTanTable,len);
_lread(handle,InvCosTable,len);
_lread(handle,InvSinTable,len);
_lread(handle,LongCosTable,len);
if (!rsHandle)
_lclose(handle); // Done reading, close trig.dat
ca = INT_ANGLE_32;
na = -1;
// Set up viewing tables for 32 to -32 angle sweep
for (len = 0; len < VIEW_WIDTH; len++)
{
ViewCosTable[len] = LongCosTable[ca];
FloorCosTable[len] = InvCosTable[ca] >> 6;
ca += na;
if (ca <= 0) // Index is less than 0 so switch
{
ca = -ca;
na = -na;
}
}
// Adjust tables for 90, 180, and 270 degree angles
LongTanTable[INT_ANGLE_90] = LongTanTable[INT_ANGLE_90+1];
LongInvTanTable[INT_ANGLE_90] = LongInvTanTable[INT_ANGLE_90+1];
LongTanTable[INT_ANGLE_180] = LongTanTable[INT_ANGLE_180+1];
LongInvTanTable[INT_ANGLE_180] = LongInvTanTable[INT_ANGLE_180+1];
LongTanTable[INT_ANGLE_270] = LongTanTable[INT_ANGLE_270+1];
LongInvTanTable[INT_ANGLE_270] = LongInvTanTable[INT_ANGLE_270+1];
for (len = 0; len < INT_ANGLE_360; len++)
{
yNextTable[len] = (long)BITMAP_WIDTH * LongTanTable[len]; // Calculate y intercept increments
xNextTable[len] = (long)BITMAP_WIDTH * LongInvTanTable[len]; // Calculate x intercept increments
InvCosTable[len] = InvCosTable[len] >> 4; // Scale inverse tables
InvSinTable[len] = InvSinTable[len] >> 6;
}
// Set up the array od slice structures to represent the full width of the view
// Each slice structure is initialized by setting its data fields to 0s
// Each slice in the array is also linked to a second slice to reference a slice that
// could be visually behind the current slice
for (len = 0; len < VIEW_WIDTH; len++)
{
sa = &Slice[len]; // Initialize array of slice structures
memset(sa,0,sizeof(SLICE)); // Set all data to 0
for (ca = 0; ca < 8; ca++)
{
saNext = AckMalloc(sizeof(SLICE)); // Create a slice structure to link in
if (saNext == NULL)
return(ERR_NOMEMORY); // Check for memory allocation
memset(saNext,0,sizeof(SLICE)); // Initialize all data to 0
sa->Next = saNext; // Link in slice
saNext->Prev = sa;
sa = saNext;
}
}
return(0);
}
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
// Reads a map file and processes any multi-height walls.
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
short AckReadMapFile(ACKENG *ae,char *fName)
{
short len,handle,rdlen,count,i,pos;
int mLen,aLen;
UCHAR buf[MAX_MULTI+2];
UCHAR *mPtr;
if (!rsHandle) // Check to see if resource file is open already
{ // No resource file so open new one
handle = _lopen(fName,OF_READ); // Open the specified resource
if (handle < 1)
return(ERR_BADMAPFILE); // File was not opened; return error code
}
else
{
handle = rsHandle; // Get handle to open resource
_llseek(handle,rbaTable[(ULONG)fName],SEEK_SET); // Access opened resource file
}
aLen = GRID_ARRAY * 2;
mLen = GRID_MAX * 2;
if (_lread(handle,Grid,mLen) != mLen) // Read in grid map data
{
if (!rsHandle)
_lclose(handle);
return(ERR_READINGMAP); // Return file read error code
}
if (_lread(handle,ObjGrid,mLen) != mLen) // Read in object map data
{
if (!rsHandle)
_lclose(handle);
return(ERR_READINGMAP);
}
if (_lread(handle,ae->xGrid,aLen) != aLen) // Read in x grid data
{
if (!rsHandle)
_lclose(handle);
return(ERR_READINGMAP);
}
if (_lread(handle,ae->yGrid,aLen) != aLen) // Read in y grid data
{
if (!rsHandle)
_lclose(handle);
return(ERR_READINGMAP);
}
if (_lread(handle,FloorMap,mLen) != mLen) // Read in floor map data
{
if (!rsHandle)
_lclose(handle);
return(ERR_READINGMAP);
}
if (_lread(handle,CeilMap,mLen) != mLen) // Read in ceiling map data
{
if (!rsHandle)
_lclose(handle);
return(ERR_READINGMAP);
}
_lread(handle,&count,2); // Check counter for multi-height walls
if (count)
{
for (i = 0; i < count;i++) // Read in multi-height wall data
{
_lread(handle,&pos,2); // Get grid position for this multi-height wall
mPtr = (UCHAR *)AckMalloc(MAX_MULTI+1); // Allocate memory for multi-height wall data
if (mPtr == NULL)
{
if (!rsHandle)
_lclose(handle);
return(ERR_NOMEMORY);
}
ae->mxGrid[pos] = mPtr; // Store pointer to multi-height wall
ae->myGrid[pos] = mPtr;
ae->mxGrid[pos+1] = mPtr;
ae->myGrid[pos+GRID_WIDTH] = mPtr;
_lread(handle,buf,MAX_MULTI);
buf[MAX_MULTI] = '\0';
len = strlen(buf);
if (len > MAX_MULTI) len = MAX_MULTI;
*mPtr = len;
if (len)
memmove(&mPtr[1],buf,len);
}
}
if (!rsHandle) // Close handle
_lclose(handle);
AckBuildGrid(ae); // Build object lists
return(0);
}
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
// Internal function to create height and distance tables for objects. In
// the DistanceTable[] each entry represents the distance from the player
// to a wall. The value stored in the array is the hight of the wall at
// the corresponding distance. For example, DistanceTable[100] indicates
// that the distance to the wall is 100 units. The value stored at this
// location is 81--the pixel height f the wall.
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
void AckBuildHeightTables(ACKENG *ae)
{
short i,x;
short result;
long height;
height = BITMAP_WIDTH * 128L; // Calculate distance to height conversion factor
DistanceTable[0] = MAX_HEIGHT; // First entry = max. height (960)
//************ 64 * 65536 ********
AdjustTable[0] = 4194304L / height;
for (i = 1; i < MAX_DISTANCE; i++) // Loop to calculate each entry for the arrays
{
DistanceTable[i] = height / i;
if (height - (DistanceTable[i] * i) > (i / 2))
DistanceTable[i]++; // Add 1 to height value
if (DistanceTable[i] < MIN_HEIGHT) // Adjust for min. height (8)
DistanceTable[i] = MIN_HEIGHT;
if (DistanceTable[i] > MAX_HEIGHT) // Adjust for maax. height (960)
DistanceTable[i] = MAX_HEIGHT;
AdjustTable[i] = 2097152L / DistanceTable[i]; // Calculate entry for
}
}
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
// Internal function called by AckReadMapFile() to process the objects
// in the map. Moveable vs stationary objects are processed here.
//ññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
void AckBuildGrid(ACKENG *ae)
{
short i,j,CurIndex,pos,x1,y1;
USHORT MapCode,MapHiCode;
// Initialize doors
for (i = 0; i < MAX_DOORS; i++)
{
ae->Door[i].ColOffset = 0;
ae->Door[i].mPos = ae->Door[i].mPos1 = -1;
}
ae->SysFlags |= SYS_NO_WALLS; // Assume no floating walls
CurIndex = 1;
TotalSpecial = 0;
TotalSecret = 0;
for (i = 0; i < GRID_HEIGHT; i++) // Loop until entire grid has been checked
{
for (j = 0; j < GRID_WIDTH; j++)
{
pos = (i * GRID_WIDTH) + j;
MapCode = ObjGrid[pos]; // Check object at current grid position
if (MapCode) // Is there an object here?
{
CurIndex = MapCode & 0xFF;
if (CurIndex < MAX_OBJECTS) // Get the index of the object into
{
if (ae->ObjList[CurIndex] == NULL) // No object allocated yet
{
// Allocate memory for object
ae->ObjList[CurIndex] = (NEWOBJECT *)AckMalloc(sizeof(NEWOBJECT));
if (ae->ObjList[CurIndex] != NULL)
memset(ae->ObjList[CurIndex],0,sizeof(NEWOBJECT));
}
// If memory has been allocated calculate coordinates for object
if (ae->ObjList[CurIndex] != NULL)
{
x1 = (j * BITMAP_WIDTH) + (BITMAP_WIDTH/2);
y1 = (i * BITMAP_WIDTH) + (BITMAP_WIDTH/2);
ae->ObjList[CurIndex]->x = x1; // Store x,y position
ae->ObjList[CurIndex]->y = y1;
ae->ObjList[CurIndex]->mPos = pos; // Store map position
ae->ObjList[CurIndex]->Active = 1; // Indicates object is active
}
}
}
}
}
}
// **** End of Source ****


327
ack_lib/ACKLDBMP.C Normal file
View file

@ -0,0 +1,327 @@
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
char *GetExtent(char *s);
UCHAR *AckReadiff(char *s);
UCHAR *AckReadPCX(char *s);
short BlankSlice(short,UCHAR *);
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Determines if the column of the bitmap contains all transparent colors
// or not. If so then it is marked to be skipped during the draw phase.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short BlankSlice(short col,UCHAR *bmp)
{
short i,pos;
pos = col * 64;
for (i = 0; i < 64; i++)
{
if (bmp[pos++])
return(1);
}
return(0);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Loads a bitmap of different formats based on the setting of bmLoadType
// in the ACKENG interface structure. The bitmap loaded is placed into
// either the wall bitmap array or the object array based on the value
// of BitmapType passed to this function.
// BitmapName can be either a filename or an index into the currently
// open resource file.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckLoadBitmap(ACKENG *ae,short BitmapNumber,short BitmapType,char *BitmapName)
{
short handle,bFlag;
short x,y,bLen;
short sPos,dPos;
UCHAR ch;
UCHAR *buf;
UCHAR *bmp;
UCHAR *bmpFlags;
bFlag = 0;
bLen = BITMAP_SIZE + BITMAP_WIDTH;
buf = NULL;
if (ae->bmLoadType == BMLOAD_BBM)
buf = AckReadiff(BitmapName);
if (ae->bmLoadType == BMLOAD_GIF)
buf = AckReadgif(BitmapName);
if (ae->bmLoadType == BMLOAD_PCX)
buf = AckReadPCX(BitmapName);
if (buf == NULL)
return(ERR_LOADINGBITMAP);
x = (*(short *)buf);
y = (*(short *)&buf[2]);
if ((x*y) != BITMAP_SIZE)
{
AckFree(buf);
return(ERR_INVALIDFORM);
}
memmove(buf,&buf[4],BITMAP_SIZE);
bFlag = 1;
bmp = AckMalloc(bLen);
if (bmp == NULL)
{
AckFree(buf);
return(ERR_NOMEMORY);
}
if (BitmapType == TYPE_WALL)
{
ae->bMaps[BitmapNumber] = bmp;
}
if (BitmapType == TYPE_OBJECT)
{
ae->oMaps[BitmapNumber] = bmp;
}
if (!bFlag)
{
handle = _lopen(BitmapName,OF_READ);
if (handle < 1)
{
AckFree(buf);
AckFree(bmp);
return(ERR_BADFILE);
}
read(handle,buf,4); // Skip width and height for now
read(handle,buf,BITMAP_SIZE);
_lclose(handle);
}
for (y = 0; y < BITMAP_HEIGHT; y++)
{
sPos = y;
dPos = y * BITMAP_WIDTH;
for (x = 0; x < BITMAP_WIDTH; x++)
{
ch = buf[sPos];
bmp[dPos++] = ch;
sPos += BITMAP_WIDTH;
}
}
bmpFlags = &bmp[BITMAP_SIZE];
memset(bmpFlags,0,BITMAP_WIDTH);
for (x = 0; x < BITMAP_WIDTH; x++)
{
if (!BlankSlice(x,bmp))
bmpFlags[x] = 1;
}
AckFree(buf);
return(0);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Returns a pointer to the file extent
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
char *GetExtent(char *s)
{
char *e;
e = strchr(s,'.');
if (e == NULL)
return(s);
e++;
return(e);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Calls AckLoadBitmap with the TYPE_WALL flag set so the bitmap is placed
// in the wall array.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckLoadWall(ACKENG *ae,short WallNumber,char *bmFileName)
{
return( AckLoadBitmap(ae,WallNumber,TYPE_WALL,bmFileName) );
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Calls AckLoadBitmap with the TYPE_OBJECT flag set so the bitmap is
// placed in the object array.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckLoadObject(ACKENG *ae,short BmpNumber,char *bmFileName)
{
return( AckLoadBitmap(ae,BmpNumber,TYPE_OBJECT,bmFileName) );
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Creates an object structure. This function MUST be called before the
// object data can be initialized in the NEWOBJECT structure.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckCreateObject(ACKENG *ae,short ObjNumber)
{
if (ae->ObjList[ObjNumber] == NULL)
{
ae->ObjList[ObjNumber] = (NEWOBJECT *)AckMalloc(sizeof(NEWOBJECT));
if (ae->ObjList[ObjNumber] == NULL)
return(ERR_NOMEMORY);
memset(ae->ObjList[ObjNumber],0,sizeof(NEWOBJECT));
}
if (ObjNumber >= ae->MaxObjects)
ae->MaxObjects = ObjNumber + 1;
return(0);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Sets an object up into one of the predefined phase types (CREATE,DESTROY,
// etc.). Moveable objects are placed into a special list that is used
// later in the drawing phase.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckSetObjectType(ACKENG *ae,short oNum,short oType)
{
short i,j,result = 0;
OBJSEQ *os;
switch (oType)
{
case NO_CREATE:
os = &ae->ObjList[oNum]->Create;
break;
case NO_DESTROY:
os = &ae->ObjList[oNum]->Destroy;
break;
case NO_WALK:
os = &ae->ObjList[oNum]->Walk;
break;
case NO_ATTACK:
os = &ae->ObjList[oNum]->Attack;
break;
case NO_INTERACT:
os = &ae->ObjList[oNum]->Interact;
break;
default:
result = ERR_BADOBJTYPE;
break;
}
if (!result)
{
ae->ObjList[oNum]->CurrentBitmaps = (UCHAR *)&os->bitmaps;
ae->ObjList[oNum]->Flags = os->flags;
ae->ObjList[oNum]->Sides = os->bmSides;
ae->ObjList[oNum]->BitmapsPerView = os->bmBitmapsPerView;
ae->ObjList[oNum]->CurrentBm = 0;
ae->ObjList[oNum]->Maxbm = os->MaxBitmaps;
ae->ObjList[oNum]->CurrentType = oType;
ae->ObjList[oNum]->aFactor = os->AngleFactor;
}
if (ae->ObjList[oNum]->Flags & OF_MOVEABLE)
{
j = 0;
for (i = 0; i < MoveObjectCount; i++)
{
if (MoveObjectList[i] == oNum)
{
j = 1;
break;
}
}
if (!j)
MoveObjectList[MoveObjectCount++] = oNum;
i = (ae->ObjList[oNum]->y & 0xFFC0) + (ae->ObjList[oNum]->x >> 6);
ObjGrid[i] = 0;
}
return(result);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Fills in the object structure with a communication structure passed
// by the application. This allows the application to setup the fields
// such as number of sides to an object, what bitmaps are displayed for
// each side, etc. The object structures are defined in ACK3D.H
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckSetupObject(ACKENG *ae,short oNum,short oType,OBJSEQ *os)
{
short result = 0;
if (ae->ObjList[oNum] == NULL)
return(ERR_BADOBJECTNUM);
if (os->flags & OF_MULTIVIEW)
{
os->AngleFactor = INT_ANGLE_360 / os->bmSides;
}
switch (oType)
{
case NO_CREATE:
memmove(&ae->ObjList[oNum]->Create,os,sizeof(OBJSEQ));
break;
case NO_DESTROY:
memmove(&ae->ObjList[oNum]->Destroy,os,sizeof(OBJSEQ));
break;
case NO_WALK:
memmove(&ae->ObjList[oNum]->Walk,os,sizeof(OBJSEQ));
break;
case NO_ATTACK:
memmove(&ae->ObjList[oNum]->Attack,os,sizeof(OBJSEQ));
break;
case NO_INTERACT:
memmove(&ae->ObjList[oNum]->Interact,os,sizeof(OBJSEQ));
break;
default:
result = ERR_BADOBJTYPE;
break;
}
if (!result && ae->ObjList[oNum]->CurrentBitmaps == NULL)
result = AckSetObjectType(ae,oNum,oType);
return(result);
}
// **** End of Source ****


470
ack_lib/ACKOBJ.C Normal file
View file

@ -0,0 +1,470 @@
// This source file contains the internal functions needed to add objects
// to the slice structures as a view is being built.
// (c) 1995 ACK Software (Lary Myers)
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include <limits.h>
#include "ack3d.h" // Main ACK-3D internal and interface data structures
#include "ackeng.h" // Internal data structures and constants
#include "ackext.h" // Defines external (global) variables
extern short gWinStartX; // Global variables to define the left and
extern short gWinEndX; // right edge of the viewport
// A function pointer to refernce the actual routine used to build a wall slice
extern void (*WallMaskRtn)(void);
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Internal function called by FindObject(). Your programs may call this
// function if they need to calculate the angle between two points. dx and
// dy represent the deltas between the two points. (i.e. dx = x1 - x and
// dy = y1 - y)
//
// Quadrants
// 2 | 3 If the object is in quadrants 0 or 2, we need
// ---+--- to add the resulting angle to the quad value less
// 1 | 0 than the resulting angle. If the object is in
// quadrants 1 or 3, we need to subtract the
// resulting angle from the next higher quadrant
// value. This is because quads 1 and 3 are negative
// values returned from arctan, while 0 and 2 are
// positive.
//
// The angle between the two points is determined by using the formula:
// tan (angle) = dy/dx. The look-up table LongTanTable[] is used to
// access tangent values of angles.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckGetObjectAngle(long dx,long dy)
{
short i,quadrant,objAngle;
short Beg;
long avalue;
if (dx == 0 || dy == 0) // Test to see if angle is 0, 90, 180, or 270
{
if (dx == 0) // Distance is directly up or down
{
if (dy < 0) // Distance is straight up
return(INT_ANGLE_270);
return(INT_ANGLE_90);
}
if (dx < 0) // dy = 0; distance is directly left or right
return(INT_ANGLE_180);
return(0);
}
// Need to determine which quadrant is involved
quadrant = 0; // Set to quad 0 as default
if (dx < 0 && dy > 0) // We're in quad 1
quadrant = INT_ANGLE_180;
else
{
if (dx < 0 && dy < 0) // We're in quad 2
quadrant = INT_ANGLE_270;
else
{
if (dx > 0 && dy < 0) // We're in quad 3
quadrant = INT_ANGLE_360;
}
}
// Get the absolute values to use for our ratio
if (dy < 0)
dy = -dy;
if (dx < 0)
dx = -dx;
//=======================================================================
// Next we need to convert dy into the same fixed point representation
// as used in our tangent table. Then, we divide dy by dx (rise/run)
// to get the ratio so we can determine the tangent of the angle between
// the two pints. We use the ratio to search the tangent table
// and the index that is returned tells us what the actual angle is.
// We only need to check angles from 0 to 90 degrees. Later, the angle
// will be adjusted to take into account which quadrant we are in.
//=======================================================================
dy = dy << FP_SHIFT; // Make the dividend the same fixed point as the table
avalue = dy / dx; // Get our ratio to search for
// This ratio tells us the tangent of the angle
if (LongTanTable[INT_ANGLE_90-1] <= avalue) // Angle is 89 degrees
return(INT_ANGLE_90-1);
objAngle = 0; // Initialize angle to 0
//=============================================================================
// Now we use a binary lookup trick to speed up the search. This invloves
// a test to see if the angle is between o and 45 degrees or between 45 and
// 90 degrees. Then, we search the list sequentially to find the first value
// higher than our ratio.
//=============================================================================
Beg = 0; // Assume midpoint between 0 and 45 degrees
if (LongTanTable[INT_ANGLE_45] < avalue)
{
if (LongTanTable[360] < avalue)
Beg = 360; // Use angle of 360
else
Beg = INT_ANGLE_45; // Midpoint between 45 and 90 degrees
}
// Loop to check the tan table and find the correct angle
for (i = Beg; i < INT_ANGLE_90; i++)
{
if (LongTanTable[i] > avalue) // We've passed by the angle
{
objAngle = i - 1; // Get the correct angle
break;
}
}
if (objAngle < 0) // Adjust for angle=0
objAngle = 0;
//============================================================================
// Now we adjust the resulting angle based on the quadrant. If we are in
// quad 0 we do nothing. If we're in quads 1 and 3 we subtract the angle from
// the next higher quad angle. If we're in quad 2 we add the angle to the next
// lower quad angle to get the actual angle (0-1800) between the points.
//============================================================================
if (quadrant)
{
if (quadrant != INT_ANGLE_270)
objAngle = quadrant - objAngle;
else
objAngle += INT_ANGLE_180;
}
// Returns the angle between the two points. This value is mainly used for
// determining the angle between the POV and an object, but it could
// be used for generic purposes as well.
return(objAngle);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Internal function that returns the square root of a long value.
// This function is called by Find)bject().
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short long_sqrt(long v)
{
short i;
unsigned short result,tmp;
unsigned long low,high;
if (v <= 1L) return((unsigned)v); // Value is less than 1; return value
low = v; // Initialize starting variables
high = 0L;
result = 0;
for (i = 0; i < 16; i++)
{
result += result;
high = (high << 2) | ((low >>30) & 0x3);
low <<= 2; // Shift left by 2
tmp = result + result + 1;
if (high >= tmp)
{
result++;
high -= tmp;
}
}
return(result);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Internal function called by AckBuildView() which checks the list of
// objects found during the ray cast process and places the object slices
// into the wall slices.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
void FindObject(void)
{
short i,j,StartX,EndX;
short oCount;
short minAngle,maxAngle,objAngle;
short objColumn;
USHORT distance;
long dx,dy;
short count,SaveCenter;
short ObjNum,oQuad,pQuad,numsides,afact;
short NewX,NewY,LightFlag;
short MaxOpp,Column,ColBeg,ColEnd;
short wt,ObjIndex;
short vidwt,vidht,hoff;
short MaxObjs;
short SliceLen;
USHORT BmpColumn;
long xp,yp;
short wht;
UCHAR *wall,*ScreenBuffer;
UCHAR *pTable;
UCHAR **omaps;
SLICE *sa,*sa2,*saNext;
UCHAR *bmpFlags;
NEWOBJECT **oList;
NEWOBJECT *oPtr;
if (FoundObjectCount) // Make sure objects were found during ray casting
{
oList = &aeGlobal->ObjList[0]; // Get pointer to the array of objects
StartX = gWinStartX; // Starting column of view
EndX = gWinEndX; // Ending column of view
minAngle = PlayerAngle - (INT_ANGLE_32 + 10); // Starting angle of view
if (minAngle < 0) // Check for wrap-around at angle 0
minAngle += INT_ANGLE_360;
maxAngle = PlayerAngle + (INT_ANGLE_32 + 10); // Ending angle of view
if (maxAngle >= INT_ANGLE_360) // Check for wrap-around at angle 360
maxAngle -= INT_ANGLE_360;
TotalObjects = 0; // Stores nmber of objects in view
SliceLen = sizeof(SLICE) - 9; // Amount of slice we'll move later
// Loop and process each object in the view. This invloves setting up
// a few arrays to store the object number, the distance from the player
// to the object, the viewing angle, and the view column where the object
// will be displayed.
for (oCount = 0; oCount < FoundObjectCount; oCount++)
{
i = ObjectsSeen[oCount]; // Get index to possible object
oPtr = oList[i]; // Pointer to object structure
if (oPtr == NULL) // Make sure it's a valid object
continue;
if (!oPtr->Active) // Make sure it's visible
continue;
dx = oPtr->x - xPglobal; // Get the delta x,y between the
dy = oPtr->y - yPglobal; // object and the player
// Calculate the angle the object is relative to the player
if ((objAngle = AckGetObjectAngle(dx,dy)) < 0)
continue; // Negative angle means it can't be seen
// Here we determine if the POV is looking toward the right or
// the left and the actual column of the view (from 0 to view width)
// where the object would be seen.
if (minAngle > maxAngle) // If looking towards the right
{
if (objAngle >= minAngle) // Cal. view column of object
objColumn = objAngle - minAngle;
else
objColumn = (objAngle+INT_ANGLE_360) - minAngle;
}
else
{
objColumn = objAngle - minAngle; // Calc. view column of object
}
// Get the distance to the object
distance = long_sqrt((dx * dx) + (dy * dy));
// No need to check further if it's too far away
if (distance >= MaxDistance)
continue;
// Place the objects in the correct order so further ones are behind
j = TotalObjects; // Current number of objects we've found
if (j)
{
// Sort the objects found by distance so that further ones
// are drawn BEFORE closer ones.
for (count = 0; count < TotalObjects; count++)
{
if (distance <= ObjRelDist[count])
{
for (j = TotalObjects; j > count; j--)
{
ObjRelDist[j] = ObjRelDist[j-1];
ObjNumber[j] = ObjNumber[j-1];
ObjColumn[j] = ObjColumn[j-1];
ObjAngle[j] = ObjAngle[j-1];
}
j = count;
count = TotalObjects;
}
}
}
// Hold onto relavant data for the object found
ObjNumber[j] = i; // Store the object number
ObjRelDist[j] = distance; // Store the distance to the object
ObjColumn[j] = objColumn; // Store view column where object resides
ObjAngle[j] = objAngle; // Store the viewing angle
TotalObjects++; // Bump the count of objects in view
ObjRelDist[TotalObjects] = 0L; // Set to relative dist. in next object to 0
}
// Didn't find any objects on the above pass, so we're done
if (!TotalObjects)
return;
omaps = &aeGlobal->oMaps[0]; // Bitmaps used for objects
pQuad = PlayerAngle / INT_ANGLE_45; // Quadrant POV is facing
// Check each object in the list to be displayed and get the object's
// bitmap. Also, calulate the width and height of the object.
// This loop also checks to see if an object has multiple sides
// and it determines which bitmap should be used to display the object.
for (i = 0; i < TotalObjects; i++)
{
ObjIndex = ObjNumber[i]; // Actual object found
oPtr = oList[ObjIndex]; // Pointer to object structure
if (oPtr == NULL) // Again check for a null object
continue;
// Current bitmap for the object (this number can change if the
// object is animated)
ObjNum = oPtr->CurrentBitmaps[oPtr->CurrentBm];
distance = ObjRelDist[i]; // Get relative distance to object
// Make sure distance is within a reasonable entry in our
// pre-calculated table
if (distance >= (MAX_DISTANCE - 10))
distance = MAX_DISTANCE-11;
// Get the width of the object
wt = DistanceTable[distance]; // Adjust the width using the distance
// Keep the width of the object reasonable
if (wt > 300) // The object is too wide
continue; // Skip over
if (wt < 6) wt = 6; // Adjust if too small
// Get the scale factor which was pre-calculated based on
// distance in AckInitialize() function
yp = AdjustTable[distance];
xp = 0; // First col of the object to display
NewX = ObjColumn[i]; // View column where object resides
// Check if object has multiple sides. If so we need to determine
// the correct bitmap to display based on the angle between the
// POV and the object. We'll perform a trick here by breaking down
// the problem into quadrants and then use the quadrant to determine
// which side we're facing. The object itself is facing a certain
// angle (stored in the Dir field of the object structure) so this
// needs to be taken into account as well.
if (oPtr->Flags & OF_MULTIVIEW)
{
afact = oPtr->aFactor; // Get the angles per side of object
numsides = oPtr->Sides; // Get total sides for this object
pQuad = ObjAngle[i] / afact; // Get the quadrant from POV to object
oQuad = oPtr->Dir / afact; // Get the quadrant it wants to face
// The difference between the POV-Object angle and the angle the
// object is facing determines the actual side of the object that
// can currently be seen
j = (pQuad - oQuad) + (numsides >> 1);
// Check for wrap-around and keep within range
if (j >= numsides)
j -= numsides;
// Check wrap-around in both directions
if (j < 0)
j += numsides;
// Calculate which bitmap set we should use (each side could
// have multiple bitmaps for animation)
j *= oPtr->BitmapsPerView;
j += oPtr->CurrentBm;
// Get the actual bitmap for this side and animation
ObjNum = oPtr->CurrentBitmaps[j];
}
// Done processing multiple sides. Next, find the
// ending column based on the starting column plus the scaled
// width of the object.
ColEnd = NewX + wt;
// Finally get the pointer to the actual bitmap
wall = omaps[ObjNum];
// Pick up the transparent flags at end of bitmap
bmpFlags = &wall[BITMAP_SIZE];
j = distance;
// Loop from starting column to ending column and fold in the
// object into the appropriate slice structure.
for (Column = NewX - wt; Column < ColEnd; Column++)
{
// Make sure column is within view width
if (Column >= StartX && Column <= EndX)
{
// Scale bitmap column down from fixed point
BmpColumn = xp >> FP_SHIFT;
if (bmpFlags[BmpColumn]) // If transparent column
goto keepgoing; // Ouch! But it works
j = distance;
// Account for fisheye effect
dy = ViewCosTable[Column] >> 2;
dx = distance * dy;
// Now we strip off somemore decimal points and check round-up
dy = dx >> 12;
if (dx - (dy << 12) >= 4096)
dy++;
if (dy > 32L)
j = dy;
// Now we pick up the slice for this column and insert sort
// the object slice based on the distance. This allows objects
// to appear between walls at various distances, behind
// transparent walls, and so on.
sa = &Slice[Column]; // Access the corresponding slice
if (sa->Active) // Multiple slices for this column?
{
while (sa != NULL)
{
if (j <= sa->Distance)
{
sa2 = sa;
while (sa2->Next != NULL) // Go to end of slices
sa2 = sa2->Next;
saNext = sa2->Prev;
while (sa2 != sa) // Move slice down to create
{ // a space for new slice
memcpy(sa2,saNext,sizeof(SLICE)-9);
sa2->Active = saNext->Active;
sa2 = sa2->Prev;
saNext = saNext->Prev;
}
// Fill in the slice structure with the
// info about the object
sa->Distance = distance;
sa->bNumber = ObjNum;
sa->bColumn = BmpColumn;
sa->bMap = omaps;
sa->Active = 1;
sa->Type = ST_OBJECT;
sa->Fnc = WallMaskRtn;
break;
}
if (!sa->Active)
break;
sa = sa->Next;
}
}
else // Only one slice is used for this column (typical)
{
if (j <= sa->Distance) // Only put it in if object is
{ // closer than current slice
sa->Active = 1;
saNext = sa->Next;
memcpy(saNext,sa,sizeof(SLICE)-9);
sa->Distance = distance;
sa->bColumn = BmpColumn;
sa->bNumber = ObjNum;
sa->bMap = omaps;
sa->Type = ST_OBJECT;
sa->Fnc = WallMaskRtn;
saNext->Active = 0;
}
}
}
keepgoing:
xp += yp; // Advance the next column to display (scaling)
}
}
}
}
// **** End of Source ****

73
ack_lib/ACKOVER.C Normal file
View file

@ -0,0 +1,73 @@
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Creates an overlay buffer that contains non-transparent information
// about the image. Position and length of the non-transparent areas is
// stored for later processing after the drawing phase. Theoretically the
// amount of information stored in the overlay buffer could exceed the
// actual size of the image.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckCreateOverlay(ACKENG *ae,UCHAR *sBuf)
{
USHORT bPos,vPos,vLen;
USHORT len,sPos,sPos1;
vLen = (ae->WinEndY - ae->WinStartY) * BYTES_PER_ROW;
vPos = ae->WinStartY * BYTES_PER_ROW;
bPos = 0;
sPos = vPos;
while (vLen > 0)
{
if (sBuf[sPos])
{
sPos1 = sPos;
while (vLen > 0 && sBuf[sPos1++])
vLen--;
len = (sPos1 - sPos) - 1;
(*(short *)&ae->ScreenBuffer[bPos]) = len;
bPos += 2;
(*(short *)&ae->ScreenBuffer[bPos]) = sPos;
bPos += 2;
memmove(&ae->ScreenBuffer[bPos],&sBuf[sPos],len);
bPos += len;
sPos = sPos1;
}
else
{
sPos++;
vLen--;
}
}
(*(short *)&ae->ScreenBuffer[bPos]) = 0;
bPos += 2;
ae->OverlayBuffer = AckMalloc(bPos);
if (ae->OverlayBuffer != NULL)
{
memmove(ae->OverlayBuffer,ae->ScreenBuffer,bPos);
return(0);
}
return(ERR_NOMEMORY);
}
// **** End of Source ****


162
ack_lib/ACKPCX.C Normal file
View file

@ -0,0 +1,162 @@
// This source file contains the functions needed to read in PCX files.
// (c) 1995 ACK Software (Lary Myers)
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <dos.h>
//typedef unsigned short USHORT;
#include "ack3d.h" // Main ACK-3D internal and interface data structures
#include "ackeng.h" // Internal data structures and constants
#include "ackext.h" // Defines external (global) variables
typedef struct
{
char manufacturer; // Always set to 0
char version; // Always 5 for 256-color files
char encoding; // Always set to 1
char bits_per_pixel; // Should be 8 for 256-color files
short xmin,ymin; // Coordinates for top left corner
short xmax,ymax; // Width and height of image
short hres; // Horizontal resolution of image
short vres; // Vertical resolution of image
char palette16[48]; // EGA palette; not used for 256-color files
char reserved; // Reserved for future use
char color_planes; // Color planes
short bytes_per_line; // Number of bytes in 1 line of pixels
short palette_type; // Should be 2 for color palette
char filler[58]; // Reserved
} PcxHeader;
typedef struct
{
PcxHeader hdr; // Header information
UCHAR *bitmap; // The bitmap data
UCHAR pal[768]; // Color palette for the bitmap data
unsigned short imagebytes,width,height; // Size of the bitmap
} PcxFile;
#define PCX_MAX_SIZE 64000L
enum {PCX_OK,PCX_NOMEM,PCX_TOOBIG,PCX_NOFILE};
enum {NORMAL,RLE};
//enum {FALSE,TRUE};
PcxFile pcxGlobal; // data structure for reading PCX files
extern unsigned char colordat[];
//=============================================================================
// This routine loads a 256 color PCX file. The file can be a standalone
// PCX file or it can be combined with a resource. If the data is part
// of a resource, the rshandle flag will be set. The bitmap data is read
// into a buffer that is the size of the bitmap + 4 bytes. The first 4
// bytes in the buffer contain the width and height of the bitmap.
//=============================================================================
unsigned char *AckReadPCX(char *filename)
{
long i;
int mode=NORMAL,nbytes;
char abyte,*p;
short handle;
PcxFile *pcx;
pcx = &pcxGlobal;
// Open the file since no resource is open.
if (!rsHandle)
{
handle = _lopen(filename,OF_READ); // Open the file for reading
if (handle == HFILE_ERROR) // Make sure file is opened
{
ErrorCode = ERR_BADFILE;
return NULL;
}
}
else // Use the resource instead
{
handle = rsHandle; // Use the handle to the resource file
// Move to the location in the resource where the data is stored
_llseek(handle,rbaTable[(ULONG)filename],SEEK_SET);
}
_lread(handle,&pcx->hdr,sizeof(PcxHeader)); // Read in the header data
pcx->width=1+pcx->hdr.xmax-pcx->hdr.xmin; // Store width and height
pcx->height=1+pcx->hdr.ymax-pcx->hdr.ymin;
// Store number of bytes used for image
pcx->imagebytes=(unsigned int)(pcx->width*pcx->height);
// Make sure bitmap is correct size
if (pcx->imagebytes > PCX_MAX_SIZE)
{
if (!rsHandle)
_lclose(handle);
ErrorCode = ERR_INVALIDFORM;
return(NULL);
}
// Allocate size for bitmap. 4 extra bytes are included to give
// room to store bitmap width and height info.
pcx->bitmap=(char*)AckMalloc(pcx->imagebytes+4);
if (pcx->bitmap == NULL) // Make sure memory is allocated
{
if (!rsHandle)
_lclose(handle);
ErrorCode = ERR_NOMEMORY;
return(NULL);
}
p=&pcx->bitmap[4]; // Get address of data area
// Loop and read in pixel data for bitmap
// Uses RLE decompression
for (i=0;i<pcx->imagebytes;i++)
{
if (mode == NORMAL) // Normal color read mode
{
_lread(handle,&abyte,1); // Read in pixel value from file
if ((unsigned char)abyte > 0xbf) // Value read > 191
{
nbytes=abyte & 0x3f; // Get the RLE counter
_lread(handle,&abyte,1);
if (--nbytes > 0) // Is counter greater than 1?
mode=RLE; // Yes, we're in RLE mode
}
}
else if (--nbytes == 0) // When counter down to 0
mode=NORMAL; // return to color read mode
*p++=abyte; // Store pixel value
}
// Get palette from PCX file, 256 color palette store 768 bytes from
// end of file. For a resource file we need to find the position where
// the next file starts and then backup 768 bytes
if (rsHandle)
_llseek(handle,rbaTable[(ULONG)(filename + 1)]-768L,SEEK_CUR);
else
_llseek(handle,-768L,SEEK_END);
// Store the palette data in our global colordat array
_lread(handle,colordat,768);
p=colordat;
for (i=0;i<768;i++) // bit shift palette
*p++ = *p >> 2;
if (!rsHandle) // Close pcx file if not using a resource
_lclose(handle);
// Add in bitmap width and height to first 4 bytes of buffer
p = pcx->bitmap;
(*(short *)p) = pcx->width;
p += sizeof(short);
(*(short *)p) = pcx->height;
return(pcx->bitmap); // return bitmap buffer
}
// **** End of Source ****


671
ack_lib/ACKPOV.C Normal file
View file

@ -0,0 +1,671 @@
// Source file ACKPOV.C - Player and Object Movement routines
// (c) 1995 ACK Software (Lary Myers)
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
//************************************************************************
// Internal function called by AckMovePOV(). Checks the passed X and Y
// coordinates of the player against the object coordinates to see if the player will
// encouner an object.
//************************************************************************
short AckCheckObjPosn(short xPlayer,short yPlayer, short oIndex)
{
short i,result,maxObj;
short MapPosn;
NEWOBJECT **oList;
NEWOBJECT *oPtr;
result = POV_NOTHING; // Initialize to nothing found
MapPosn = (yPlayer & 0xFFC0) + (xPlayer >> 6); // Calculate grid square the player will be in
maxObj = aeGlobal->MaxObjects; // Total number of objects used
oList = &aeGlobal->ObjList[0]; // Reference the list of objects
for (i = 0; i < maxObj; i++) // Loop and check each object in the list
{
oPtr = oList[i]; // Point to current object
if (oPtr == NULL) // No object here; skip to next object in list
continue;
if (!oPtr->Active || oPtr->Flags & OF_PASSABLE) // Object is not active or is passable
continue; // Skip to next object in list
if (MapPosn == oPtr->mPos && i != oIndex) // Object is found in the player's grid position
{
LastObjectHit = i; // Store the number of the object found
return(POV_OBJECT); // Return flag to indicate an object is found
}
}
return(result);
}
//************************************************************************
// Internal function called by AckMovePOV() to see if a wall or object is located in
// the player's current grid square. This function checks for walls or objects in the
// x-plane using the xGrid array. The bitmap code for the wall or object is returned.
// A value returned of 0 indicates that no wall or object is present or that the wall
// is passable.
//************************************************************************
USHORT GetWallX(short mPos)
{
USHORT mCode;
mCode = xGridGlobal[mPos]; // Get bitmap code at specified map position
if (mCode & WALL_TYPE_PASS) // Passable walls can be walked through
mCode = 0;
return(mCode);
}
//************************************************************************
// Internal function called by AckMovePOV() to see if a wall or object is located in
// the player's current grid square. This function checks for walls or objects in the
// y-plane using the yGrid array. The bitmap code for the wall or object is returned.
// A value returned of 0 indicates that no wall or object is present or that the wall
// is passable.
//************************************************************************
USHORT GetWallY(short mPos)
{
USHORT mCode;
mCode = yGridGlobal[mPos]; // Get bitmap code at specified map position
if (mCode & WALL_TYPE_PASS) // Passable walls can be walked through
mCode = 0;
return(mCode);
}
//************************************************************************
// Moves the POV based on Angle for Amount. After moving but prior to
// returning the position of the POV is check for collisions.
//************************************************************************
short AckMovePOV(short Angle,short Amount)
{
short x1,y1,HitResult; // New coordinate position
short xp,yp; // Starting player coordinates
short xLeft,xRight,yTop,yBottom; // Coordinates for grid square
short mPos; // Map position for xGrid[], yGrid[]
USHORT mCodeX,mCodeY; // Return codes for x,y wall arrays
HitResult = POV_NOTHING; // We haven't hit anything yet
xp = aeGlobal->xPlayer; // Get the current x,y player coordinates
yp = aeGlobal->yPlayer;
xLeft = xp & 0xFFC0; // Determine coordinates of the boundaries
yTop = yp & 0xFFC0; // of the grid square we're in.
xRight = xLeft + GRID_SIZE;
yBottom = yTop + GRID_SIZE;
// Calculate the x,y distance of movement using the angle and distance
// x1,y1 = the new coordinate position of the player.
x1 = xp + (long)((CosTable[Angle] * Amount) >> FP_SHIFT);
y1 = yp + (long)((SinTable[Angle] * Amount) >> FP_SHIFT);
// Calculate current map position for the xGrid[] and yGrid[] arrays
mPos = yTop + (xp >> 6); // Current Map Posn
// It's time to see what happens when we move
if (x1 < xp) // Are we moving left?
{
if (GetWallX(mPos)) // Wall found in current square (left edge)
{
if (x1 < xLeft || abs(x1-xLeft) < 28) // We crossed the wall or we're too close
{
x1 = xp; // Use the previous x position
HitResult = POV_SLIDEX; // We're possibly sliding along the left x wall
}
}
}
if (x1 > xp) // Are we moving right?
{
if (GetWallX(mPos+1)) // Wall found in current square (right edge)
{
if (x1 > xRight || abs(xRight-x1) < 28) // We crossed the wall or we're too close
{
x1 = xp; // Use the previous x position
HitResult = POV_SLIDEX; // We're possibly sliding along the right x wall
}
}
}
if (y1 < yp) // Are we moving up?
{
if (GetWallY(mPos)) // Wall found in current square (top edge)
{
if (y1 < yTop || abs(y1-yTop) < 28) // We crossed the wall or we're too close
{
y1 = yp; // Use the previous y position
HitResult = POV_SLIDEY; // We're possibly sliding along the top wall
}
}
}
if (y1 > yp) // Are we moving down?
{
if (GetWallY(mPos+GRID_WIDTH)) // Wall found in current square (bottom edge)
{
if (y1 > yBottom || abs(yBottom-y1) < 28) // We crossed the wall or we're too close
{
y1 = yp; // Use the previous y position
HitResult = POV_SLIDEY; // We're sliding along the bottom wall
}
}
}
// A wall or object hasn't been hit yet--we must look further.
// The current grid sqaure will be divided into four regions:
// A = top left; B = top right; C = bottom left; D = bottom right
// Each of these regions will be checked to see if the player's new position (x1,y1)
// is close to a wall or object that borders one of these regions.
// Each grid square is 64x64 units, so each region to check is 32x32 units.
if (!HitResult)
{ // Check region A--top left area of grid
if (y1 < (yTop+32)) // New y position falls in top half
{
if (x1 < (xLeft+32)) // New x position falls in left half
{
mCodeX = GetWallX(mPos-GRID_WIDTH); // Check adjacent x wall (to left)
mCodeY = GetWallY(mPos-1); // Check adjacent y wall (above)
if (mCodeX && y1 < (yTop+28)) // Adjacent x wall found and new y coord
{ // is within 28 units
if (x1 < (xLeft+28)) // New x coord. is within 28 units of edge
{
if (xp > (xLeft+27)) // Previous x position was outside range
{
x1 = xp; // Use previous x position
HitResult = POV_SLIDEX;
}
else
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
}
}
if (mCodeY && x1 < (xLeft+28)) // Adjacent y wall found and new x coord.
{ // is within 28 units
if (y1 < (yTop+28)) // New y coord. is within 28 units of edge
{
if (yp > (yTop+27)) // Previous y position was outside range
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
else
{
x1 = xp; // Use previous x position
HitResult = POV_SLIDEX;
}
}
}
}
// Check region B--top right area
if (x1 > (xRight-32) && !HitResult)// New x is at top right
{
mCodeX = GetWallX(mPos+1-GRID_WIDTH); // Check adjacent x wall (to right)
mCodeY = GetWallY(mPos+1); // Check adjacent y wall (above)
if (mCodeX && y1 < (yTop+28)) // Adjacent x wall found
{
if (x1 > (xRight-28))
{
if (xp < (xRight-27))
{
x1 = xp; // Use previous x position
HitResult = POV_SLIDEX;
}
else
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
}
}
if (mCodeY && x1 > (xRight-28)) // Adjacent y wall found
{
if (y1 < (yTop+28))
{
if (yp > (yTop+27))
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
else
{
x1 = xp; // Use previous x position
HitResult = POV_SLIDEX;
}
}
}
}
}
// Check region C--bottom left area
if (y1 > (yTop+32) && !HitResult) // We are below upper half of square
{
if (x1 < (xLeft+32)) // and on the left half of square
{
mCodeX = GetWallX(mPos+GRID_WIDTH); // Check adjacent x wall (to left)
mCodeY = GetWallY(mPos-1+GRID_WIDTH); // Check adjacent y wall (below)
if (mCodeX && y1 > (yBottom-28)) // Adjacent x wall found
{
if (x1 < (xLeft+28))
{
if (xp > (xLeft+27))
{
x1 = xp; // Use previous x position
HitResult = POV_SLIDEX;
}
else
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
}
}
if (mCodeY && x1 < (xLeft+28)) // Adjacent y wall found
{
if (y1 > (yBottom-28))
{
if (yp < (yBottom-27))
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
else
{
x1 = xp; // Use previous x position
HitResult = POV_SLIDEX;
}
}
}
}
// Check region D--bottom right area
if (x1 > (xRight-32) && !HitResult) // Check right side of square
{
mCodeX = GetWallX(mPos+1+GRID_WIDTH); // Check adjacent x wall (to right)
mCodeY = GetWallY(mPos+1+GRID_WIDTH); // Check adjacent y wall (below)
if (mCodeX && y1 > (yBottom-28)) // Adjacent x wall found
{
if (x1 > (xRight-28))
{
if (xp < (xRight-27))
{
x1 = xp; // Use previous x position
HitResult = POV_SLIDEX;
}
else
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
}
}
if (mCodeY && x1 > (xRight-28)) // Adjacent y wall found
{
if (y1 > (yBottom-28))
{
if (yp < (yBottom-27))
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
else
{
x1 = xp; // Use previous x position
HitResult = POV_SLIDEX;
}
}
}
}
}
}
if (AckCheckObjPosn(x1,y1,0)) // We've hit an object--not a wall
return(POV_OBJECT);
if (HitResult == POV_SLIDEX && y1 == yp) // We've hit an x wall and we're not sliding
HitResult = POV_XWALL;
if (HitResult == POV_SLIDEY && x1 == xp) // We've hit a y wall and we're not sliding
HitResult = POV_YWALL;
aeGlobal->xPlayer = x1; // Update player's new x,y position
aeGlobal->yPlayer = y1;
return(HitResult);
}
//************************************************************************
// Moves an object based on Angle and Amount then checks for collision
// with other objects AND the POV.
//************************************************************************
short AckMoveObjectPOV(short ObjIndex,short Angle,short Amount)
{
short xp,yp,x1,y1,HitResult,oNum;
USHORT mCodeX,mCodeY;
short xLeft,xRight,yTop,yBottom,mPos;
short MapPosn,PlayerPosn;
NEWOBJECT **oList;
NEWOBJECT *oPtr;
oList = &aeGlobal->ObjList[0]; // Reference the start of the object list
oPtr = oList[ObjIndex]; // Set a pointer to the object being moved
if (oPtr == NULL) // no object is available to move; we're done
return(0);
xp = oPtr->x; // Get the current x,y coordinate of the object
yp = oPtr->y;
// Calculate the new x,y, cordinates of the object (after moving)
x1 = xp + (short)((CosTable[Angle] * Amount) >> FP_SHIFT);
y1 = yp + (short)((SinTable[Angle] * Amount) >> FP_SHIFT);
xLeft = xp & 0xFFC0; // Determine the coordinates of the grid square the
xRight = xLeft + GRID_SIZE - 1; // object is currently in
yTop = yp & 0xFFC0;
yBottom = yTop + GRID_SIZE - 1;
mPos = yTop + (xp >> 6); // Calculate the map position of the grid square the object is in
MapPosn = (y1 & 0xFFC0) + (x1 >> 6); // Calculate the map position of the grid square the
// object is moving to
// Check to see if the object will encouner another object while moving
oNum = AckCheckObjPosn(x1,y1,ObjIndex);
if (oNum > 0) // Yes, return falg to indicate object found
return(POV_OBJECT);
HitResult = POV_NOTHING; // Nothing found yet, initialize flag
if (x1 < xp) // Are we moving left?
{
if (GetWallX(mPos)) // Wall found in current square (left edge)
{
if (x1 < xLeft || abs(x1-xLeft) < 28) // We crossed the wall or we're too close
{
x1 = xp; // Use the previous x position
HitResult = POV_SLIDEX; // We're possibly sliding along the left x wall
}
}
}
if (x1 > xp) // Are we moving right?
{
if (GetWallX(mPos+1)) // Wall found in current square (right edge)
{
if (x1 > xRight || abs(xRight-x1) < 28) // We crossed the wall or we're too close
{
x1 = xp; // Use the previous x position
HitResult = POV_SLIDEX; // We're possibly sliding along the right x wall
}
}
}
if (y1 < yp) // Are we moving up?
{
if (GetWallY(mPos)) // Wall found in current square (top edge)
{
if (y1 < yTop || abs(y1-yTop) < 28) // We crossed the wall or we're too close
{
y1 = yp; // Use the previous y position
HitResult = POV_SLIDEY; // We're possibly sliding along the top wall
}
}
}
if (y1 > yp) // Are we moving down?
{
if (GetWallY(mPos+GRID_WIDTH)) // Wall found in current square (bottom edge)
{
if (y1 > yBottom || abs(yBottom-y1) < 28) // We crossed the wall or we're too close
{
y1 = yp; // Use the previous y position
HitResult = POV_SLIDEY; // We're sliding along the bottom wall
}
}
}
if (!HitResult) // Nothing hit yet, look further
{
if (y1 < (yTop+32)) // We are above upper half of square
{
if (x1 < (xLeft+32)) // and on the left half of square
{
mCodeX = GetWallX(mPos-GRID_WIDTH); // Check adjacent x wall (to left)
mCodeY = GetWallY(mPos-1); // Check adjacent y wall (above)
if (mCodeX && y1 < (yTop+28)) // Adjacent x wall found and new y coord
{ // is within 28 units
if (x1 < (xLeft+28)) // New x coord. is within 28 units of edge
{
if (xp > (xLeft+27)) // Previous x position was outside range
{
x1 = xp; // Use previous x position
HitResult = POV_SLIDEX;
}
else
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
}
}
if (mCodeY && x1 < (xLeft+28)) // Adjacent y wall found and new x coord.
{ // is within 28 units
if (y1 < (yTop+28)) // New y coord. is within 28 units of edge
{
if (yp > (yTop+27)) // Previous y position was outside range
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
else
{
x1 = xp; // Use previous x position
HitResult = POV_SLIDEX;
}
}
}
}
if (x1 > (xRight-32) && !HitResult) // New x is at top right
{
mCodeX = GetWallX(mPos+1-GRID_WIDTH); // Check adjacent x wall (to right)
mCodeY = GetWallY(mPos+1); // Check adjacent y wall (above)
if (mCodeX && y1 < (yTop+28)) // Adjacent x wall found
{
if (x1 > (xRight-28))
{
if (xp < (xRight-27))
{
x1 = xp; // Use previous x position
HitResult = POV_SLIDEX;
}
else
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
}
}
if (mCodeY && x1 > (xRight-28)) // Adjacent y wall found
{
if (y1 < (yTop+28))
{
if (yp > (yTop+27))
{
y1 = yp; // Use previous y position
HitResult = POV_SLIDEY;
}
else
{
x1 = xp;
HitResult = POV_SLIDEX;
}
}
}
}
}
if (y1 > (yTop+32) && !HitResult) // We are below upper half of square
{
if (x1 < (xLeft+32)) // and on the left half of square
{
mCodeX = GetWallX(mPos+GRID_WIDTH);
mCodeY = GetWallY(mPos-1+GRID_WIDTH);
if (mCodeX && y1 > (yBottom-28))
{
if (x1 < (xLeft+28))
{
if (xp > (xLeft+27))
{
x1 = xp;
HitResult = POV_SLIDEX;
}
else
{
y1 = yp;
HitResult = POV_SLIDEY;
}
}
}
if (mCodeY && x1 < (xLeft+28))
{
if (y1 > (yBottom-28))
{
if (yp < (yBottom-27))
{
y1 = yp;
HitResult = POV_SLIDEY;
}
else
{
x1 = xp;
HitResult = POV_SLIDEX;
}
}
}
}
if (x1 > (xRight-32) && !HitResult) // on right side of square
{
mCodeX = GetWallX(mPos+1+GRID_WIDTH);
mCodeY = GetWallY(mPos+1+GRID_WIDTH);
if (mCodeX && y1 > (yBottom-28))
{
if (x1 > (xRight-28))
{
if (xp < (xRight-27))
{
x1 = xp;
HitResult = POV_SLIDEX;
}
else
{
y1 = yp;
HitResult = POV_SLIDEY;
}
}
}
if (mCodeY && x1 > (xRight-28))
{
if (y1 > (yBottom-28))
{
if (yp < (yBottom-27))
{
y1 = yp;
HitResult = POV_SLIDEY;
}
else
{
x1 = xp;
HitResult = POV_SLIDEX;
}
}
}
}
}
}
oPtr->x = x1; // Update the new x,y coordinates for the object
oPtr->y = y1;
oPtr->mPos = MapPosn; // Update the grid map position for the object
PlayerPosn = (aeGlobal->yPlayer & 0xFFC0) + (aeGlobal->xPlayer >> 6);
if (MapPosn == PlayerPosn)
return(POV_PLAYER);
return(HitResult);
}
//************************************************************************
// Checks the list of objects used in an application and sets up the current bitmap for
// each object that can be animated. Object animation is performed by displaying
// different bitmaps for an object in sequence.
//************************************************************************
void AckCheckObjectMovement(void)
{
short i,maxObj;
short dx;
NEWOBJECT **oList;
NEWOBJECT *oPtr;
maxObj = aeGlobal->MaxObjects; // Get the number of objects used
oList = &aeGlobal->ObjList[0]; // Reference the list of objects
for (i = 1; i < maxObj; i++) // Loop to check each object in the list
{
oPtr = oList[i]; // Access current object in list
if (oPtr == NULL) // No object here; skip
continue;
if (!oPtr->Active) // Object is not active; skip
continue;
if (!oPtr->Speed) // Object has no speed setting; skip
continue;
if (!(oPtr->Flags & OF_ANIMATE)) // Object is not set up for animation
continue;
dx = oPtr->CurrentBm + 1; // Use the next bitmap
if (dx >= oPtr->Maxbm) // We're at the end of the list of bitmaps
{
if (oPtr->Flags & OF_ANIMONCE) // Object should only be animated once
{
oPtr->Flags &= ~OF_ANIMATE; // Reset flags to indicate that we're done
oPtr->Flags |= OF_ANIMDONE; // animating the object
dx = oPtr->CurrentBm; // Keep current bitmap number
}
else
dx = 0; // Start at the beginning of the set of bitmaps
}
oPtr->CurrentBm = dx; // Store the next bitmap as the current one
}
}
// **** End of Source ****


630
ack_lib/ACKRAY.C Normal file
View file

@ -0,0 +1,630 @@
//****************** ( Animation Construction Kit 3D ) **********************
// Ray Casting Routines
// CopyRight (c) 1993 Author: Lary Myers
//***************************************************************************
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
extern short ViewAngle;
//**************************************************************************
//
//**************************************************************************
short ObjectExist(UCHAR onum)
{
short i;
short result = 0;
if (!FoundObjectCount)
return(result);
for (i = 0; i < FoundObjectCount; i++)
{
if (ObjectsSeen[i] == onum)
return(1);
}
return(result);
}
long x_xPos,x_yPos,x_xNext,x_yNext;
long y_xPos,y_yPos,y_xNext,y_yNext;
//*************************************************************************
//
//*************************************************************************
void xRaySetup(void)
{
x_yNext = yNextTable[ViewAngle]; // PreCalc'd value of BITMAP_WIDTH * Tan(angle)
if (ViewAngle > INT_ANGLE_270 || ViewAngle < INT_ANGLE_90)
{
x_xPos = xBegGlobal + BITMAP_WIDTH; // Looking to the right
x_xNext = BITMAP_WIDTH; // Positive direction
}
else
{
x_xPos = xBegGlobal; // Looking to the left
x_xNext = -BITMAP_WIDTH; // Negative direction
x_yNext = -x_yNext;
}
// Calculate the Y coordinate for the current square
x_yPos = (((long)x_xPos - (long)xPglobal) * LongTanTable[ViewAngle]) + yPglobalHI;
}
//**************************************************************************
//
//**************************************************************************
UINT xRayCast(void)
{
UINT Color;
short i,j,mx,my;
short TablePosn;
short MapPosn,CurPosn;
short xBeg;
short BitmapColumn;
short xCenter,yCenter,xAdj;
short ObjPosn;
short oBegX,oBegY;
long xd,yd,sy;
long ObjDist;
while (1)
{
if (x_xPos < 0 || x_xPos > GRID_XMAX ||
x_yPos < 0 || x_yPos > GRID_YMAXLONG)
break;
//************* Fixed point Y/64 * 64 X / 64 **********
MapPosn = ((x_yPos >> FP_SHIFT) & 0xFFC0) + (x_xPos >> 6);
if ((Color = ObjGrid[MapPosn]) != 0)
{
Color &= 0x7F;
if (!ObjectExist(Color))
ObjectsSeen[FoundObjectCount++] = Color;
}
// Check to see if a wall is being struck by the ray
if ((Color = xGridGlobal[MapPosn]) != 0)
{
xMapPosn = MapPosn; // Hold onto the map location
iLastX = x_xPos;
LastY1 = x_yPos;
if ((Color & 0xFF) == DOOR_XCODE) // Is this a door?
{
yd = ((x_yPos >> FP_SHIFT) & GRID_MASK); // Get the left side
xd = yd + BITMAP_WIDTH; // And the right side
ObjDist = (x_yPos + (x_yNext >> 1)) >> FP_SHIFT; // Calc door distance
if (ObjDist < yd || ObjDist > xd) // Is door visible?
{
x_xPos += x_xNext; // Nope, continue casting
x_yPos += x_yNext; // the ray as before
continue;
}
LastY1 = x_yPos + (x_yNext >> 1); // Adjust the X,Y values so
iLastX += (x_xNext >> 1); // the door is halfway in sq.
}
if (Color & DOOR_TYPE_SECRET)
{
if (xSecretColumn != 0)
{
sy = xSecretColumn * LongTanTable[ViewAngle];
ObjDist = (x_yPos + sy) >> FP_SHIFT;
yd = ((x_yPos >> FP_SHIFT) & GRID_MASK); // Get the left side
xd = yd + BITMAP_WIDTH; // And the right side
if (ObjDist < yd || ObjDist > xd) // Is door visible?
{
x_xPos += x_xNext; // Nope, continue casting
x_yPos += x_yNext; // the ray as before
continue;
}
LastY1 = x_yPos + sy;
iLastX += xSecretColumn;
}
}
return(Color);
}
x_xPos += x_xNext; // Next X coordinate (fixed at 64 or -64)
x_yPos += x_yNext; // Next calculated Y coord for a delta of X
}
return(0); // Return that no wall was found
}
//*************************************************************************
//
//*************************************************************************
UINT OldxRay(void)
{
UINT Color;
short i,j,mx,my;
short TablePosn;
short MapPosn,CurPosn;
short xBeg;
long xPos,xNext;
short BitmapColumn;
short xCenter,yCenter,xAdj;
short ObjPosn;
short oBegX,oBegY;
long yPos;
long yNext;
long xd,yd,sy;
long ObjDist;
yNext = yNextTable[ViewAngle]; // PreCalc'd value of BITMAP_WIDTH * Tan(angle)
if (ViewAngle > INT_ANGLE_270 || ViewAngle < INT_ANGLE_90)
{
xPos = xBegGlobal + BITMAP_WIDTH; // Looking to the right
xNext = BITMAP_WIDTH; // Positive direction
}
else
{
xPos = xBegGlobal; // Looking to the left
xNext = -BITMAP_WIDTH; // Negative direction
yNext = -yNext;
}
// Calculate the Y coordinate for the current square
yPos = (((long)xPos - (long)xPglobal) * LongTanTable[ViewAngle]) + yPglobalHI;
while (1)
{
if (xPos < 0 || xPos > GRID_XMAX ||
yPos < 0 || yPos > GRID_YMAXLONG)
break;
//************* Fixed point Y/64 * 64 X / 64 ***********
MapPosn = ((yPos >> FP_SHIFT) & 0xFFC0) + (xPos >> 6);
if ((Color = ObjGrid[MapPosn]) != 0)
{
Color &= 0x7F;
if (!ObjectExist(Color))
ObjectsSeen[FoundObjectCount++] = Color;
}
// Check to see if a wall is being struck by the ray
if ((Color = xGridGlobal[MapPosn]) != 0)
{
xMapPosn = MapPosn; // Hold onto the map location
iLastX = xPos;
LastY1 = yPos;
if ((Color & 0xFF) == DOOR_XCODE) // Is this a door?
{
yd = ((yPos >> FP_SHIFT) & GRID_MASK); // Get the left side
xd = yd + BITMAP_WIDTH; // And the right side
ObjDist = (yPos + (yNext >> 1)) >> FP_SHIFT; // Calc door distance
if (ObjDist < yd || ObjDist > xd) // Is door visible?
{
xPos += xNext; // Nope, continue casting
yPos += yNext; // the ray as before
continue;
}
LastY1 = yPos + (yNext >> 1); // Adjust the X,Y values so
iLastX += (xNext >> 1); // the door is halfway in sq.
}
if (Color & DOOR_TYPE_SECRET)
{
if (xSecretColumn != 0)
{
sy = xSecretColumn * LongTanTable[ViewAngle];
ObjDist = (yPos + sy) >> FP_SHIFT;
yd = ((yPos >> FP_SHIFT) & GRID_MASK); // Get the left side
xd = yd + BITMAP_WIDTH; // And the right side
if (ObjDist < yd || ObjDist > xd) // Is door visible?
{
xPos += xNext; // Nope, continue casting
yPos += yNext; // the ray as before
continue;
}
LastY1 = yPos + sy;
iLastX += xSecretColumn;
}
}
return(Color);
}
xPos += xNext; // Next X coordinate (fixed at 64 or -64)
yPos += yNext; // Next calculated Y coord for a delta of X
}
return(0); // Return that no wall was found
}
//*************************************************************************
//
//*************************************************************************
void yRaySetup(void)
{
y_xNext = xNextTable[ViewAngle]; // Pre-calc'd value of BITMAP_WIDTH / tan(angle)
if (ViewAngle < INT_ANGLE_180)
{
y_yPos = yBegGlobal + BITMAP_WIDTH; // Looking down
y_yNext = BITMAP_WIDTH; // Positive direction
}
else
{
y_yPos = yBegGlobal; // Looking up
y_yNext = -BITMAP_WIDTH; // Negative direction
y_xNext = -y_xNext;
}
// Calculate the X coordinate for the current square
y_xPos = (((long)y_yPos - (long)yPglobal) * LongInvTanTable[ViewAngle]) + xPglobalHI;
}
//*************************************************************************
//
//*************************************************************************
UINT yRayCast(void)
{
UINT Color;
short i,j,mx,my;
short MapPosn;
short yBeg;
short BitmapColumn;
short xCenter,yCenter,yAdj;
short ObjPosn;
short oBegX;
long xd,yd,ObjDist,sx;
while (1)
{
if (y_xPos < 0 || y_xPos > GRID_XMAXLONG ||
y_yPos < 0 || y_yPos > GRID_YMAX)
break;
//********** Y/64 * 64 Fixed point and /64 *****
MapPosn = (y_yPos & 0xFFC0) + (y_xPos >> (FP_SHIFT+6));
if ((Color = ObjGrid[MapPosn]) != 0)
{
Color &= 0x7F;
if (!ObjectExist(Color))
ObjectsSeen[FoundObjectCount++] = Color;
}
// Check for a wall being struck
if ((Color = yGridGlobal[MapPosn]) != 0)
{
yMapPosn = MapPosn; // Hold onto map position
LastX1 = y_xPos;
iLastY = y_yPos;
if ((Color & 0xFF) == DOOR_YCODE) // Is this a door?
{
yd = ((y_xPos >> FP_SHIFT) & GRID_MASK); // Calc top side of square
xd = yd + BITMAP_WIDTH; // And bottom side of square
ObjDist = (y_xPos + (y_xNext >> 1)) >> FP_SHIFT;
if (ObjDist < yd || ObjDist > xd) // Is door visible?
{
y_xPos += y_xNext; // No, continue on with ray cast
y_yPos += y_yNext;
continue;
}
LastX1 = y_xPos + (y_xNext >> 1); // Adjust coordinates so door is
iLastY += (y_yNext >> 1); // Halfway into wall
}
if (Color & DOOR_TYPE_SECRET)
{
if (ySecretColumn != 0)
{
sx = ySecretColumn * LongInvTanTable[ViewAngle];
ObjDist = (y_xPos + sx) >> FP_SHIFT;
yd = ((y_xPos >> FP_SHIFT) & GRID_MASK); // Get the top side
xd = yd + BITMAP_WIDTH; // And the bottom side
if (ObjDist < yd || ObjDist > xd) // Is door visible?
{
y_xPos += y_xNext; // Nope, continue casting
y_yPos += y_yNext; // the ray as before
continue;
}
LastX1 = y_xPos + sx;
iLastY += ySecretColumn;
}
}
return(Color);
}
y_xPos += y_xNext; // Next calculated X value for delta Y
y_yPos += y_yNext; // Next fixed value of 64 or -64
}
return(0); // Return here if no Y wall is found
}
//*************************************************************************
//
//*************************************************************************
UINT OldyRay(void)
{
UINT Color;
short i,j,mx,my;
short MapPosn;
short yBeg;
long yPos,yNext;
short BitmapColumn;
short xCenter,yCenter,yAdj;
short ObjPosn;
short oBegX;
long xPos;
long xNext;
long xd,yd,ObjDist,sx;
xNext = xNextTable[ViewAngle]; // Pre-calc'd value of BITMAP_WIDTH / tan(angle)
if (ViewAngle < INT_ANGLE_180)
{
yPos = yBegGlobal + BITMAP_WIDTH; /* Looking down */
yNext = BITMAP_WIDTH; /* Positive direction */
}
else
{
yPos = yBegGlobal; /* Looking up */
yNext = -BITMAP_WIDTH; /* Negative direction */
xNext = -xNext;
}
/* Calculate the X coordinate for the current square */
xPos = (((long)yPos - (long)yPglobal) * LongInvTanTable[ViewAngle]) + xPglobalHI;
while (1)
{
if (xPos < 0 || xPos > GRID_XMAXLONG ||
yPos < 0 || yPos > GRID_YMAX)
break;
/*********** Y/64 * 64 Fixed point and /64 ******/
// MapPosn = ((yPos / BITMAP_WIDTH) * GRID_WIDTH) + (xPos >> (FP_SHIFT+BITMAP_SHIFT));
// MapPosn = ((yPos & GRID_MASK) >> 1) + (xPos >> (FP_SHIFT+BITMAP_SHIFT));
MapPosn = (yPos & 0xFFC0) + (xPos >> (FP_SHIFT+6));
if ((Color = ObjGrid[MapPosn]) != 0)
{
Color &= 0x7F;
if (!ObjectExist(Color))
ObjectsSeen[FoundObjectCount++] = Color;
}
/** Check for a wall being struck **/
if ((Color = yGridGlobal[MapPosn]) != 0)
{
yMapPosn = MapPosn; /* Hold onto map position */
LastX1 = xPos;
iLastY = yPos;
if ((Color & 0xFF) == DOOR_YCODE) /* Is this a door? */
{
yd = ((xPos >> FP_SHIFT) & GRID_MASK); /* Calc top side of square */
xd = yd + BITMAP_WIDTH; /* And bottom side of square */
ObjDist = (xPos + (xNext >> 1)) >> FP_SHIFT;
if (ObjDist < yd || ObjDist > xd) /* Is door visible? */
{
xPos += xNext; /* No, continue on with ray cast */
yPos += yNext;
continue;
}
LastX1 = xPos + (xNext >> 1); /* Adjust coordinates so door is */
iLastY += (yNext >> 1); /* Halfway into wall */
}
if (Color & DOOR_TYPE_SECRET)
{
if (ySecretColumn != 0)
{
sx = ySecretColumn * LongInvTanTable[ViewAngle];
ObjDist = (xPos + sx) >> FP_SHIFT;
yd = ((xPos >> FP_SHIFT) & GRID_MASK); /* Get the top side */
xd = yd + BITMAP_WIDTH; /* And the bottom side */
if (ObjDist < yd || ObjDist > xd) /* Is door visible? */
{
xPos += xNext; /* Nope, continue casting */
yPos += yNext; /* the ray as before */
continue;
}
LastX1 = xPos + sx;
iLastY += ySecretColumn;
}
}
return(Color);
}
xPos += xNext; /* Next calculated X value for delta Y */
yPos += yNext; /* Next fixed value of 64 or -64 */
}
return(0); /* Return here if no Y wall is found */
}
/****************************************************************************
** **
****************************************************************************/
UINT xRayMulti(UINT MinDist,short MinHeight)
{
UINT Color;
short i,j,mx,my;
short TablePosn;
short MapPosn,CurPosn;
short xBeg;
long xPos,xNext;
short BitmapColumn;
short xCenter,yCenter,xAdj;
short ObjPosn;
short oBegX,oBegY;
long yPos;
long yNext;
long xd,yd,sy;
long ObjDist;
yNext = yNextTable[ViewAngle]; /* PreCalc'd value of BITMAP_WIDTH * Tan(angle) */
if (ViewAngle > INT_ANGLE_270 || ViewAngle < INT_ANGLE_90)
{
xPos = xBegGlobal + BITMAP_WIDTH; /* Looking to the right */
xNext = BITMAP_WIDTH; /* Positive direction */
}
else
{
xPos = xBegGlobal; /* Looking to the left */
xNext = -BITMAP_WIDTH; /* Negative direction */
yNext = -yNext;
}
/* Calculate the Y coordinate for the current square */
yPos = (((long)xPos - (long)xPglobal) * LongTanTable[ViewAngle]) + yPglobalHI;
while (1)
{
if (xPos < 0 || xPos > GRID_XMAX ||
yPos < 0 || yPos > GRID_YMAXLONG)
break;
/************** Fixed point Y/64 * 64 X / 64 ***********/
MapPosn = ((yPos >> FP_SHIFT) & 0xFFC0) + (xPos >> 6);
/* Check to see if a wall is being struck by the ray */
if ((Color = xGridGlobal[MapPosn]) & WALL_TYPE_MULTI)
{
if ((Color & 0xFF) > MinHeight)
{
xd = xPos - xPglobal;
yd = InvCosTable[ViewAngle] >> 4;
if (MinDist < ((xd * yd) >> 10))
{
xMapPosn = MapPosn; /* Hold onto the map location */
iLastX = xPos;
LastY1 = yPos;
return(Color);
}
}
}
xPos += xNext; /* Next X coordinate (fixed at 64 or -64) */
yPos += yNext; /* Next calculated Y coord for a delta of X */
}
return(0); /* Return that no wall was found */
}
/****************************************************************************
** **
****************************************************************************/
UINT yRayMulti(UINT MinDist,short MinHeight)
{
UINT Color;
short i,j,mx,my;
short MapPosn;
short yBeg;
long yPos,yNext;
short BitmapColumn;
short xCenter,yCenter,yAdj;
short ObjPosn;
short oBegX;
long xPos;
long xNext;
long xd,yd,ObjDist,sx;
xNext = xNextTable[ViewAngle]; /* Pre-calc'd value of BITMAP_WIDTH / tan(angle) */
if (ViewAngle < INT_ANGLE_180)
{
yPos = yBegGlobal + BITMAP_WIDTH; /* Looking down */
yNext = BITMAP_WIDTH; /* Positive direction */
}
else
{
yPos = yBegGlobal; /* Looking up */
yNext = -BITMAP_WIDTH; /* Negative direction */
xNext = -xNext;
}
/* Calculate the X coordinate for the current square */
xPos = (((long)yPos - (long)yPglobal) * LongInvTanTable[ViewAngle]) + xPglobalHI;
while (1)
{
if (xPos < 0 || xPos > GRID_XMAXLONG ||
yPos < 0 || yPos > GRID_YMAX)
break;
/*********** Y/64 * 64 Fixed point and /64 ******/
MapPosn = (yPos & 0xFFC0) + (xPos >> (FP_SHIFT+6));
/** Check for a wall being struck **/
if ((Color = yGridGlobal[MapPosn]) & WALL_TYPE_MULTI)
{
if ((Color & 0xFF) > MinHeight)
{
xd = yPos - yPglobal;
yd = InvCosTable[ViewAngle] >> 4;
if (MinDist < ((xd * yd) >> 10))
{
yMapPosn = MapPosn; /* Hold onto the map location */
LastX1 = xPos;
iLastY = yPos;
return(Color);
}
}
}
xPos += xNext; /* Next calculated X value for delta Y */
yPos += yNext; /* Next fixed value of 64 or -64 */
}
return(0); /* Return here if no Y wall is found */
}


989
ack_lib/ACKRTN.ASM Normal file
View file

@ -0,0 +1,989 @@
locals
IDEAL
JUMPS
P386
P387 ; Allow 386 processor
MASM
.MODEL FLAT,STDCALL ;32-bit OS/2 model
.data
COLOR dw ?
RETVAL dw ?
MAPPOSN dw ?
XBEG dd ?
XD dd ?
YD dd ?
YTEMP dd ?
SY dd ?
SX dd ?
.CODE
IDEAL
include "ackrtn.inc"
SC_INDEX EQU 03C4h ; Sequencer Controller access
HIGH_ADDR equ 80h ; High byte of screen offset
GC_INDEX equ 3ceh ;Graphics Controller Index register
CRTC_INDEX equ 3d4h ;CRT Controller Index register
MAP_MASK equ 2 ;Map Mask register index in SC
MEMORY_MODE equ 4 ;Memory Mode register index in SC
MAX_SCAN_LINE equ 9 ;Maximum Scan Line reg index in CRTC
START_ADDRESS_HIGH equ 0ch ;Start Address High reg index in CRTC
UNDERLINE equ 14h ;Underline Location reg index in CRTC
MODE_CONTROL equ 17h ;Mode Control register index in CRTC
READ_MAP equ 4 ;Read Map register index in GC
GRAPHICS_MODE equ 5 ;Graphics Mode register index in GC
MISCELLANEOUS equ 6 ;Miscellaneous register index in GC
SCREEN_WIDTH equ 320 ;# of pixels across screen
SCREEN_HEIGHT equ 400 ;# of scan lines on screen
extrn _ViewAngle:word
extrn _ScreenOffset:word
extrn _xPglobal:dword
extrn _yPglobal:dword
extrn _xBegGlobal:dword
extrn _yBegGlobal:dword
extrn _aeGlobal:dword
extrn _xGridGlobal:dword
extrn _yGridGlobal:dword
extrn _xPglobalHI:dword
extrn _yPglobalHI:dword
extrn _rbaTable:dword
extrn _rsHandle:word
extrn _LastX1:dword
extrn _LastY1:dword
extrn _iLastX:dword
extrn _iLastY;dword
extrn _MaxDistance:word
extrn _ErrorCode:word
extrn _xMapPosn:dword
extrn _yMapPosn:dword
extrn _Grid:dword
extrn _ObjGrid:dword
extrn _xSecretmPos:word
extrn _xSecretmPos1:word
extrn _xSecretColumn:word
extrn _ySecretmPos:word
extrn _ySecretmPos1:word
extrn _ySecretColumn:word
extrn _TotalSecret:word
extrn _ViewColumn:word
extrn _SinTable:dword
extrn _CosTable:dword
extrn _LongTanTable:dword
extrn _LongInvTanTable:dword
extrn _InvCosTable:byte
extrn _InvSinTable:byte
extrn _LongCosTable:dword
extrn _ViewCosTable:dword
extrn _xNextTable:dword
extrn _yNextTable:dword
extrn _LastMapPosn:word
extrn _LastObjectHit:word
extrn _TotalObjects:word
extrn _FoundObjectCount:word
extrn _ObjectsSeen:byte
extrn _MoveObjectCount:word
extrn _MoveObjectList:byte
extrn _ObjNumber:byte
extrn _ObjRelDist:byte
extrn _ObjColumn:byte
extrn _x_xPos:dword
extrn _x_yPos:dword
extrn _x_xNext:dword
extrn _x_yNext:dword
extrn _y_xPos:dword
extrn _y_yPos:dword
extrn _y_xNext:dword
extrn _y_yNext:dword
extrn _Floorscr:dword
extrn _Floors1:dword
extrn _Floors2:dword
extrn _FloorscrTop:dword
extrn _Floorptr2:dword
extrn _Floorht:word
extrn _Floorwt:word
extrn _gScrnBuffer:dword
extrn _gWinStartY:word
extrn _gWinStartX:word
extrn _gWinWidth:word
extrn _gWinHeight:word
extrn _gWinFullWidth:word
extrn _gWinDWORDS:dword
extrn _gWinStartOffset:dword
extrn _VidSeg:dword
extrn _AckKeys:byte
extrn _OurDataSeg:word
extrn _HitMap:byte
ACKPUBS AckInkey
ACKPUBS AckKbdInt
ACKPUBS AckPutVideo
ACKPUBS AckGetVideo
ACKPUBS AckCopyToVideo
ACKPUBS AckSetPalette
ACKPUBS AckDisplayScreen
ACKPUBS AckInitVideoSelector
ACKPUBS AckGetIntVector
ACKPUBS AckSetIntVector
ACKPUBS AckSetVGAmode
ACKPUBS AckSetTextMode
ACKPUBS AckDrawPage
ACKPUBS xRaySetup
ACKPUBS yRaySetup
ACKPUBS xRayCast
ACKPUBS yRayCast
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Checks for a keystroke and returns 0 if none, else scan/char in AX
; This routine should NOT be used if the keyboard vector has been changed
; to the AckKbdInt routine below.
; unsigned short AckInkey(void);
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckInkey
push ebx
mov ax,0100h
int 16h
mov bx,0
jz ackinkey_10
xor ax,ax
int 16h
mov bx,ax
ackinkey_10:
mov ax,bx
pop ebx
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Interrupt 9 keyboard handler. Places keys into the keyboard array so they
; can be checked by the application.
; Do NOT call this routine directly!!!
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckKbdInt
push eax
push ebx
push esi
push ds
xor ebx,ebx
in al,60h
mov bl,al
in al,61h
mov ah,al
or al,80h
out 61h,al
mov al,ah
out 61h,al
mov al,20h
out 20h,al
mov ax,cs:[word ptr _OurDataSeg]
mov ds,ax
mov esi,offset _AckKeys
mov eax,ebx
and eax,127
mov [byte ptr esi+eax],1
test ebx,128
jz aki_10
mov [byte ptr esi+eax],0
aki_10:
pop ds
pop esi
pop ebx
pop eax
iretd
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Older version which now simply calls AckDrawPage.
; void AckDisplayScreen(void);
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckDisplayScreen
push ebp
ACKCALL AckDrawPage
pop ebp
xor eax,eax
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Puts a single byte onto the video
; void AckPutVideo(unsigned int offset,unsigned char color);
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckPutVideo
push ebp
mov ebp,esp
push es
push ebx
push edi
mov bx,[word ptr _VidSeg+2]
mov es,bx
movzx edi,[word ptr _VidSeg]
add edi,[dword ptr ebp+8]
mov edx,[ebp+12]
mov [edi],dl
pop edi
pop ebx
pop es
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Retrieves a single byte from the video
; unsigned char AckGetVideo(unsigned int offset);
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckGetVideo
push ebp
mov ebp,esp
push ds
push ebx
push esi
movzx esi,[word ptr _VidSeg]
add esi,[dword ptr ebp+8]
mov ax,[word ptr _VidSeg+2]
mov ds,ax
mov al,[esi]
mov ah,0
pop esi
pop ebx
pop ds
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Copies a block from the data segment buffer to the video screen
; void AckCopyToVideo(unsigned int SrcOff,unsigned int len);
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckCopyToVideo
push ebp
mov ebp,esp
push es
push ebx
push ecx
push edx
push esi
push edi
mov esi,[ebp+8]
mov ecx,[ebp+12]
movzx edi,[word ptr _VidSeg]
mov ax,[word ptr _VidSeg+2]
mov es,ax
rep movsb
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop es
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Retrieves a selector to Video memory and stores it in the VidSeg global
; void AckInitVideoSelector(void);
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckInitVideoSelector
push ebx
push ecx
push edx
mov ax,2 ; Allocate selector for real mode address
mov bx,0A000h ; Get Video address
int 31h
mov [word ptr _VidSeg+2],ax
mov [word ptr _VidSeg],0
pop edx
pop ecx
pop ebx
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Retrieves a protected mode interrupt vector.
; void AckGetIntVector(int VectorNumber,int *sel,int *off);
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckGetIntVector
push ebp
mov ebp,esp
push ebx
push ecx
push edx
push es
mov ebx,[ebp+8]
mov eax,204h
int 31h
mov ebx,[ebp+12]
mov [ebx],cx
mov ebx,[ebp+16]
mov [ebx],dx
pop es
; mov eax,ecx
pop edx
pop ecx
pop ebx
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Sets a protected mode interrupt handler.
; void AckSetIntVector(int VecNum,unsigned int VecSel,unsigned int VecOff);
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckSetIntVector
push ebp
mov ebp,esp
push ebx
push ecx
push edx
mov ebx,[ebp+8]
mov ecx,[ebp+12]
mov edx,[ebp+16]
;; mov cx,cs
mov eax,205h
cli
int 31h
sti
pop edx
pop ecx
pop ebx
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckSetPalette
push ebp
mov ebp,esp
push ds
push ebx
push ecx
push edx
mov esi,[ebp+8]
mov ebx,0
mov ecx,256
mov dx,3c8h
asp_loop:
mov al,bl
out dx,al
inc bx
inc dx
lodsb
out dx,al
lodsb
out dx,al
lodsb
out dx,al
dec dx
loop asp_loop
pop edx
pop ecx
pop ebx
pop ds
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckSetVGAmode
push ebx
push ecx
push edx
mov ax,0013h ;AH = 0 means mode set, AL = 13h selects
int 10h ;BIOS video interrupt
pop edx
pop ecx
pop ebx
ret
;------------------------------------------------------------------------------
; Uncomment the following code to setup a 320x200 modeX environment
;------------------------------------------------------------------------------
;; Change CPU addressing of video memory to linear (not odd/even,
;; chain, or chain 4), to allow us to access all 256K of display
;; memory. When this is done, VGA memory will look just like memory
;; in modes 10h and 12h, except that each byte of display memory will
;; control one 256-color pixel, with 4 adjacent pixels at any given
;; address, one pixel per plane.
;;------------------------------------------------------------------------------
; mov dx,SC_INDEX
; mov al,MEMORY_MODE
; out dx,al
; inc dx
; in al,dx
; and al,not 08h ;turn off chain 4
; or al,04h ;turn off odd/even
; out dx,al
; mov dx,GC_INDEX
; mov al,GRAPHICS_MODE
; out dx,al
; inc dx
; in al,dx
; and al,not 10h ;turn off odd/even
; out dx,al
; dec dx
; mov al,MISCELLANEOUS
; out dx,al
; inc dx
; in al,dx
; and al,not 02h ;turn off chain
; out dx,al
; mov dx,SC_INDEX
; mov ax,(0fh shl 8) + MAP_MASK
; out dx,ax
;
; mov dx,CRTC_INDEX
;;------------------------------------------------------------------------------
;; Change CRTC scanning from doubleword mode to byte mode, allowing
;; the CRTC to scan more than 64K of video data.
;;------------------------------------------------------------------------------
; mov al,UNDERLINE
; out dx,al
; inc dx
; in al,dx
; and al,not 40h ;turn off doubleword
; out dx,al
; dec dx
; mov al,MODE_CONTROL
; out dx,al
; inc dx
; in al,dx
; or al,40h ;turn on the byte mode bit, so memory is
; ; scanned for video data in a purely
; ; linear way, just as in modes 10h and 12h
; out dx,al
; ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckSetTextMode
push ebx
push ecx
push edx
mov ax,3
int 10h
pop edx
pop ecx
pop ebx
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckDrawPage
push esi
push edi
push ebx
push ecx
push edx
push es
push ds
;; mov edi,[_VidSeg]
mov edi,0
mov di,[word ptr _VidSeg]
mov esi,[_gScrnBuffer]
cmp [word ptr _gWinFullWidth],0
jz short dp_smallscreen
mov eax,[_gWinStartOffset]
add edi,eax
add esi,eax
mov ecx,[_gWinDWORDS]
mov ax,[word ptr _VidSeg+2]
mov es,ax
;; mov ds,ax
mov dx,3dah
fp020:
in al,dx ;Wait until vertical retrace is on
test al,8
jz fp020
fp030:
in al,dx ;Wait until vertical retrace is off
test al,8
jnz fp030
rep movsd
pop ds
pop es
pop edx
pop ecx
pop ebx
pop edi
pop esi
ret
dp_smallscreen:
mov eax,[_gWinStartOffset]
add edi,eax
add esi,eax
movzx eax,[_gWinStartX]
add edi,eax
add esi,eax
mov dx,[_gWinHeight]
inc dx
movzx ebx,[_gWinWidth]
mov ebp,320
sub ebp,ebx ;width to advance pointers
mov ax,[word ptr _VidSeg+2]
mov es,ax
;; mov ds,ax
dp010:
mov ecx,ebx
shr ecx,1
rep movsw
rcl ecx,1
rep movsb
add edi,ebp
add esi,ebp
dec dx
jnz dp010
dp090:
pop ds
pop es
pop edx
pop ecx
pop ebx
pop edi
pop esi
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC xRaySetup
push esi ; Save registers used
push ebx
push ecx
push edx
mov dx,[_ViewAngle] ; Get the current angle for casting
movzx esi,dx ; Use this angle for table look up
shl esi,2 ; Hold onto viewangle * 4 for table access
mov ebx,[_yNextTable] ; Base address of list of y increment coordinates
mov eax,[esi+ebx] ; Use angle as index into table
mov [dword ptr _x_yNext],eax; Store y increment value
cmp dx,INT_ANGLE_270 ; Is angle > 270 degrees?
jg short inbetween
cmp dx,INT_ANGLE_90 ; Is angle >= 90 degrees?
jge short not_inbetween
; Set up the ray for casting to the right (270 to 90 degrees)
inbetween:
mov ecx,[_xBegGlobal] ; Get left corner of grid square
add ecx,64 ; Calculate right corner
mov [dword ptr _x_xPos],ecx ; Store starting x position
mov [dword ptr _x_xNext],large 64 ; Store next x grid increment
jmp short xr_cont ; to the right (+64)
; Set up the ray for casting to the keft (90 to 270 degrees)
not_inbetween:
movzx ecx,[word ptr _xBegGlobal] ; Get left corner of grid square
mov [_x_xPos],ecx ; Store starting x position
mov [dword ptr _x_xNext],large -64 ; Store next x grid increment
; to the left (-64)
neg [dword ptr _x_yNext] ; Negate the second y intersection
; coordinate
xr_cont:
movzx eax,[word ptr _xPglobal] ; Get players x coordinate
sub ecx,eax ; x Distance from players position
; to edge of grid
mov ebx,[dword ptr _LongTanTable] ; Get address of tangent table
imul ecx,[dword ptr esi+ebx] ; Tangent(angle) * Distance
add ecx,[dword ptr _yPglobalHI] ;
mov [dword ptr _x_yPos],ecx ; Store first y coordinate where
; we hit an x boundary
pop edx ; Restore registers
pop ecx
pop ebx
pop esi
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC xRayCast
push esi ; Save registers used
push edi
push ebx
push ecx
push edx
mov esi,[_x_xPos] ; Get x,y starting position
mov edi,[_x_yPos] ; (1st grid border intersection point)
xor ecx,ecx ; Init our bitmap variable
looptop: ; Start the ray casting loop
mov edx,esi ; Get x starting position
cmp edx,large 0 ; If its < 0 were done!
jl short getout
cmp edx,large 4096 ; If its > 4,096 were done
jge short getout
mov eax,edi ; Get y starting position
cmp eax,large 0 ; If its < 0 were done
jl short getout
cmp eax,large 010000000h ; If its out of range were done
jl short inbounds
getout:
jmp loopdone
inbounds: ; Were in-range; continue casting
sar eax,16 ; Scale y starting position
and eax,-64
sar edx,6 ; Scale x starting position
add eax,edx ; Calculate grid map position
cmp eax,4095 ; Test map position to see if its in range
ja getout
mov [byte ptr _HitMap+eax],1 ; Record the square we cast through
mov ebx,[_xGridGlobal] ; Get pointer to x wall map
mov cx,[ebx+eax*2] ; Get the bitmap number there
jcxz next_square ; Nothing found in square--move ahead
wall_here: ; We found something!
mov [word ptr COLOR],cx ; Save the bitmap number
mov [_xMapPosn],eax ; Save the map position
mov [dword ptr _iLastX],esi ; Save the x,y position of the grid
mov [dword ptr _LastY1],edi ; border where the hit was found
test cx,DOOR_WALL ; Did we find a door?
jz short not_door ; No match--go process a wall slice
; At this point weve found a door, so we need to process it.
mov edx,edi ; Get y position
sar edx,16 ; Scale position
and edx,large 00000FFC0h
mov [dword ptr YD],edx ; YD = (yPos >> FP_SHIFT) & 0xFFC0;
; YD is the left side of door (grid corner)
add edx,large 64
mov [dword ptr XD],edx ; XD = YD + GRID_SIZE;
; XD is the right side of door (grid corner)
mov eax,[dword ptr _x_yNext] ; Get y increment
sar eax,1 ; Use half of inrement
add eax,edi ; Add 1/2 y increment to y position
; We need to calculate distance to door
mov [YTEMP],eax ; Store new y location
sar eax,16 ; We now have actual distance to door
cmp eax,[dword ptr YD] ; Is distance < YD?
jl short door_not_visible ; Process invisible door
cmp eax,[dword ptr XD] ; Is distance > XD?
jle short door_visible ; Process visible door
door_not_visible: ; Door is invisible so skip to next square
add esi,[dword ptr _x_xNext] ; Add x,y increment to current grid border
add edi,[dword ptr _x_yNext] ; position
jmp looptop ; Cast again to check next position
door_visible: ; Process a visible door
mov eax,[dword ptr YTEMP] ; Get y position of door
mov [dword ptr _LastY1],eax ; LastY1 = yTemp;
mov eax,[dword ptr _x_xNext] ; Adjust x,y position so that door
sar eax,1 ; is halfway in square
add [dword ptr _iLastX],eax ; iLastX += xNext >> 1;
not_door: ; We dont think we have a door
test cx,DOOR_TYPE_SECRET ; Check bitmap type
jz short br_no_secret ; Not a secret door
cmp [word ptr _xSecretColumn],0
jne short secret_door ; Weve found a secret door
br_no_secret:
jmp short give_color ; Move on and get the walls color
secret_door: ; Process a secret door
movzx eax,[word ptr _xSecretColumn] ; Get secret column location
movzx ebx,[word ptr _ViewAngle] ; Get ViewAngle to door
shl ebx,2
add ebx,[dword ptr _LongTanTable] ; Add in address of tan table
imul eax,[dword ptr ebx] ; Look up tangent of angle
mov [dword ptr SY],eax ; SY = xSecretColumn * tan(ViewAngle)
mov ebx,edi ; Get x_yPos
add eax,ebx ; SY + x_yPos
mov [dword ptr YTEMP],eax ; Store distance to door
sar eax,16 ; eax = (x_yPos + SY) >> FP_SHIFT
; This gives us actual distance to door
sar ebx,16 ; Now calculate the left side
and ebx,large 00000FFC0h
mov [dword ptr YD],ebx ; YD = x_yPos >> FP_SHIFT & GRID_MASK
mov ecx,ebx ; Calculate the right side (XD)
add ecx,large 64 ; XD = YD = BITMAP_WIDTH
cmp eax,ebx ; Is distance < YD?
jl short next_square
cmp eax,ecx ; Is distance <= XD?
jle short secret_is_visible
secret_not_visible: ; Process invisible secret door
jmp short next_square
secret_is_visible: ; Process visible secret door
mov eax,[dword ptr YTEMP]
mov [dword ptr _LastY1],eax
mov eax,[dword ptr _xSecretColumn]
add [dword ptr _iLastX],eax
jmp short give_color
next_square: ; Didint find anything--go to next square
add esi,[dword ptr _x_xNext] ; Add x,y increment to current grid border
add edi,[dword ptr _x_yNext] ; position
jmp looptop ; Start over again
loopdone:
mov [word ptr COLOR],0 ; Use bitmap value of 0 to indicate
; nothing has been found
give_color:
movzx eax,[word ptr COLOR] ; Get color of wall
xRayDone:
pop edx ; Restore registers
pop ecx
pop ebx
pop edi
pop esi
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC yRaySetup
push esi
push ebx
push ecx
push edx
mov dx,[word _ViewAngle]
movzx esi,dx
shl esi,2 ; // Hold onto viewangle * 4
mov ebx,[dword ptr _xNextTable]
mov eax,[esi+ebx]
mov [dword ptr _y_xNext],eax
cmp dx,INT_ANGLE_180
jge short y_not_inbetween
y_inbetween:
mov ecx,[_yBegGlobal]
add ecx,64
mov [dword ptr _y_yPos],ecx
mov [dword ptr _y_yNext],large 64
jmp short y_yr_cont
y_not_inbetween:
mov ecx,[_yBegGlobal]
mov [_y_yPos],ecx
mov [dword ptr _y_yNext],large -64
neg [dword ptr _y_xNext]
y_yr_cont:
mov eax,[_yPglobal]
sub ecx,eax
mov ebx,[dword ptr _LongInvTanTable]
imul ecx,[dword ptr esi+ebx]
add ecx,[dword ptr _xPglobalHI]
mov [dword ptr _y_xPos],ecx
pop edx
pop ecx
pop ebx
pop esi
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC yRayCast
push esi
push edi
push ebx
push ecx
push edx
mov esi,[dword ptr _y_xPos]
mov edi,[dword ptr _y_yPos]
xor ecx,ecx
y_looptop:
;-; mov edx,[dword ptr _y_xPos]
mov edx,esi
cmp edx,large 0
jl short y_getout
cmp edx,large 010000000h
jge short y_getout
;-; mov eax,[_y_yPos]
mov eax,edi
cmp eax,large 0
jl short y_getout
cmp eax,large 4096
jl short y_inbounds
y_getout:
jmp loopdone
y_inbounds:
sar edx,22
and eax,-64
add eax,edx
cmp eax,4095
ja y_getout
mov [byte ptr _HitMap+eax],1
mov ebx,[dword ptr _yGridGlobal]
mov cx,[ebx+eax*2]
;-; test cx,cx
;-; jnz short y_wall_here
;-; jmp y_next_square
jcxz y_next_square
y_wall_here:
mov [word ptr COLOR],cx
mov [_yMapPosn],eax
;-; mov ebx,[dword ptr _y_xPos]
mov ebx,esi
mov [dword ptr _LastX1],ebx
;-; mov edx,[dword ptr _y_yPos]
mov edx,edi
mov [dword ptr _iLastY],edx
mov edx,ebx
test cx,DOOR_WALL
jz short y_not_door
sar ebx,16
and ebx,large 00000FFC0h
mov [dword ptr YD],ebx
add ebx,large 64
mov [dword ptr XD],ebx
mov eax,[dword ptr _y_xNext]
sar eax,1
add edx,eax
mov [dword ptr YTEMP],edx
sar edx,16
cmp edx,[dword ptr YD]
jl short y_door_not_visible
cmp edx,[dword ptr XD]
jle short y_door_visible
y_door_not_visible:
;-; mov eax,[dword ptr _y_xNext]
;-; add [dword ptr _y_xPos],eax
;-; mov eax,[dword ptr _y_yNext]
;-; add [dword ptr _y_yPos],eax
add esi,[dword ptr _y_xNext]
add edi,[dword ptr _y_yNext]
jmp y_looptop
y_door_visible:
mov eax,[dword ptr YTEMP]
mov [dword ptr _LastX1],eax
mov eax,[dword ptr _y_yNext]
sar eax,1
add [dword ptr _iLastY],eax
y_not_door:
test cx,DOOR_TYPE_SECRET
jz short y_br_no_secret
cmp [word ptr _ySecretColumn],0
jne short y_secret_door
y_br_no_secret:
jmp y_give_color
y_secret_door:
movzx eax,[word ptr _ySecretColumn]
movzx edx,[word ptr _ViewAngle]
mov ebx,[dword ptr _LongInvTanTable]
imul eax,[dword ptr ebx+edx*4]
mov [dword ptr SX],eax
;-; mov ebx,[dword ptr _y_xPos]
mov ebx,esi
add eax,ebx
mov [dword ptr YTEMP],eax
sar eax,16
sar ebx,16
and ebx,large 00000FFC0h
mov ecx,ebx
add ecx,large 64
cmp eax,ebx
jl short y_secret_not_visible
cmp eax,ecx
jle short y_secret_is_visible
y_secret_not_visible:
jmp y_door_not_visible
y_secret_is_visible:
mov eax,[dword ptr YTEMP]
mov [dword ptr _LastX1],eax
mov eax,[dword ptr _ySecretColumn]
add [dword ptr _iLastY],eax
jmp short y_give_color
y_next_square:
;-; mov eax,[dword ptr _y_xNext]
;-; add [dword ptr _y_xPos],eax
;-; mov eax,[dword ptr _y_yNext]
;-; add [dword ptr _y_yPos],eax
add esi,[dword ptr _y_xNext]
add edi,[dword ptr _y_yNext]
jmp y_looptop
y_loopdone:
mov [word ptr COLOR],0
y_give_color:
movzx eax,[word ptr COLOR]
yRayDone:
pop edx
pop ecx
pop ebx
pop edi
pop esi
ret
endp
end


130
ack_lib/ACKRTN.INC Normal file
View file

@ -0,0 +1,130 @@
_BORLANDC_ = 1
MACRO ACKPROC L
IFDEF _BORLANDC_
PROC _&L NEAR
ENDIF
IFDEF _WATCOMC_
PROC &L_ NEAR
ENDIF
ENDM
MACRO ACKEXT L
IFDEF _BORLANDC_
extrn _&L:NEAR
ENDIF
IFDEF _WATCOMC_
extrn &L_:NEAR
ENDIF
ENDM
MACRO ACKPUBS LAB
IFDEF _BORLANDC_
public _&LAB
ENDIF
IFDEF _WATCOMC_
public &LAB_
ENDIF
ENDM
MACRO ACKCALL LAB
IFDEF _BORLANDC_
call _&LAB
ENDIF
IFDEF _WATCOMC_
call &LAB_
ENDIF
ENDM
IFDEF _BORLANDC_
VIDSEG equ 0a0000000h
ENDIF
IFDEF _WATCOMC_
VIDSEG equ 0a0000h
ENDIF
;; Equates for SLICE struct
sabMap equ 0
samPtr equ 4
sabNumber equ 8
sabColumn equ 10
saDist equ 12
samPos equ 14
saType equ 16
saFnc equ 17
saActive equ 21
saPrev equ 22
saNext equ 26
saSize equ 30 ;size of SLICE structure
; Equates for upper byte of walls
WALL_TYPE_UPPER equ 0200h
WALL_TYPE_MULTI equ 0400h
WALL_UPPER_MULTI equ 0600h
WALL_TYPE_TRANS equ 0800h
DOOR_TYPE_SECRET equ 8000h
DOOR_LOCKED equ 4000h
DOOR_TYPE_SLIDE equ 2000h
DOOR_TYPE_SPLIT equ 1000h
DOOR_WALL equ 3000h
; Equates for LightFlag
SHADING_OFF equ 0
SHADING_ON equ 1
ST_WALL equ 1
ST_OBJECT equ 2
DOOR_XCODE equ 60
DOOR_YCODE equ 62
RES_LOW equ 1
;; Equates for SCOL struct
Vid equ 0
Wall equ 4
Pal equ 8
dst equ 12
wht equ 14
multi equ 16
topht equ 18
botht equ 20
savwht equ 22
mulcnt equ 24
savVid equ 26
bNum equ 30
scLen equ 32 ; length of structure
; Equates for SysFlag
SYS_SOLID_BACK equ 8000h ; On if solid color bkgd vs picture
SYS_SOLID_FLOOR equ 4000h ; On if solid vs texture floor
SYS_SOLID_CEIL equ 2000h ; On if solid vs texture ceiling
SYS_NO_WALLS equ 1000h ; On if walls are NOT to display
Color equ ebp-4
retval equ ebp-6
MapPosn equ ebp-8
xBeg equ ebp-10
;xPos equ ebp-14
;xNext equ ebp-18
;yPos equ ebp-22
;yNext equ ebp-26
xd equ ebp-30
yd equ ebp-34
yTemp equ ebp-38
sy equ ebp-42
sx equ ebp-46
INT_ANGLE_32 equ 160
INT_ANGLE_90 equ 450
INT_ANGLE_135 equ 675
INT_ANGLE_180 equ 900
INT_ANGLE_225 equ 1125
INT_ANGLE_270 equ 1350
INT_ANGLE_360 equ 1800


571
ack_lib/ACKRTN1.ASM Normal file
View file

@ -0,0 +1,571 @@
IDEAL
JUMPS
P386
P387
MASM
.MODEL FLAT
.DATA
SVTABLE dd ?
ENDPOS dd ?
.CODE
IDEAL
include "ackrtn.inc"
extrn _VidSeg:dword
extrn _Resolution:word
extrn _ScreenOffset:word
extrn _bmDistance:dword
extrn _bmWall:dword
extrn _scPtr:dword
extrn _VidTop:dword
extrn _VidBottom:dword
extrn _Floors1:dword
extrn _Floors2:dword
extrn _gPalTable:dword
extrn _gWinStartX:word
extrn _gWinStartY:word
extrn _gWinEndX:word
extrn _gWinEndY:word
extrn _gWinHeight:word
extrn _ViewHeight:word
extrn _SysFlags:word
extrn _Slice:byte
extrn _gScrnBuffer:dword
extrn _gCenterOff:word
extrn _Floorht:word
extrn _Floorscr:dword
extrn _gWinStartOffset:dword
extrn _scVid:dword
extrn _scWall:dword
extrn _scPal:dword
extrn _scdst:word
extrn _scwht:word
extrn _scmulti:word
extrn _sctopht:word
extrn _scbotht:word
extrn _scsavwht:word
extrn _scmulcnt:word
extrn _scsavVid:dword
extrn _scbNum:word
extrn _scMulData:dword
extrn _scColumn:dword
extrn _WallbMaps:dword
extrn _LowerTable:dword
extrn _gBottomOff:dword
ACKEXT ShowColLow
ACKEXT ShowColMaskLow
ACKPUBS ShowCol
ACKPUBS ShowColMask
ACKPUBS DrawWalls
align 2
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC ShowCol
push ebp
push esi
push edi
mov edi,[_scVid] ;Video buffer position
mov ebp,[_scPal] ;Pointer to palette for shading
mov ax,[_scwht] ;Height to use
mov [_scsavwht],ax ;save for later
movzx ecx,[_sctopht]
mov ebx,[_scWall]
add ebx,ecx
mov [_bmWall],ebx
mov ch,al
inc ch
mov esi,[_bmDistance]
mov esi,[_LowerTable+esi*4]
mov [SVTABLE],esi
mov eax,0
mov ebx,0
test [word ptr _scbNum],WALL_TYPE_UPPER
jz short toprun
mov edx,[_bmDistance]
zztoploop:
dec ch
jz short zzdomulti
sub di,320
add bx,dx
cmp bh,cl
jge short zzdomulti
jmp zztoploop
zzdomulti:
mov [_scwht],cx
mov [_scsavVid],edi
jmp chkmulti
toprun:
mov ebx,[_bmWall]
toploop:
movzx edx,[word ptr esi]
cmp dl,cl
jg short botrun
lea esi,[esi+2]
neg edx
mov al,[ebx+edx]
mov al,[ebp+eax]
mov [edi],al
add edi,-320
dec ch
jnz toploop
botrun:
mov [_scwht],cx
mov [_scsavVid],edi
mov edi,[_scVid]
mov cx,[_scbotht]
mov dx,[_scsavwht]
mov ch,dl
mov esi,[SVTABLE]
inc ebx
dec cl
botloop:
lea edi,[edi+320]
movzx edx,[word ptr esi]
cmp dl,cl
jge short chkmulti
lea esi,[esi+2]
mov al,[ebx+edx]
mov al,[ebp+eax]
mov [edi],al
dec ch
jnz botloop
chkmulti:
mov edi,[_scsavVid]
cmp [word ptr _scmulti],0
jz alldone
mov cx,[_scmulcnt]
mov ebx,[_scMulData] ;ptr to count and wall data
mov cl,[ebx] ;get number of walls to draw
inc ebx
mov al,[ebx] ;first wall to show
inc ebx
mov [_scMulData],ebx
movzx ebx,al ;get wall number
mov esi,[_scColumn] ;Current bitmap column to display x 64
lea esi,[esi+63]
mov [_scColumn],esi ;save for later use
mov eax,[_WallbMaps] ;Get array of bitmaps
mov ebx,[eax+ebx*4] ;Get the bitmap we are using
add ebx,esi ;point to bottom of column
mov ax,[_scwht] ;Get height of window
mov ch,ah
cmp ch,0 ;Is there more room to draw?
jz short alldone ;br if at top of window
mov esi,[SVTABLE]
mov eax,0
mulloop:
movzx eax,[word ptr esi] ;Get height displacement for this row
cmp al,64 ;Did we do the entire column?
jge short nextlevel ;Yes, see if more walls
lea esi,[esi+2]
neg eax ;Invert so we can add it below
movzx eax,[byte ptr ebx+eax] ;Get the pixel from the bitmap
mov al,[ebp+eax] ;Map it to the palette for shading
mov [edi],al ;Place it into the video buffer
dec ch ;Bump the window height
jz short alldone ;br if at the top of the window
sub edi,320 ;next video row
jmp mulloop
nextlevel:
dec cl ;Bump wall count
jz short alldone ;br if no more walls
mov ebx,[_scMulData] ;Get pointer to the multi-ht data
movzx eax,[byte ptr ebx] ;next wall number
inc ebx ;Advance for next wall
mov [_scMulData],ebx
mov ebx,[_WallbMaps] ;Get wall array
mov ebx,[ebx+eax*4] ;Get wall bitmap to use
add ebx,[dword ptr _scColumn] ;add in current column
mov eax,0
mov esi,[SVTABLE]
jmp mulloop
alldone:
pop edi
pop esi
pop ebp
ret
endp
align 2
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC ShowColMask
push ebp
push esi
push edi
mov ebp,eax
mov [_scPtr],eax
mov edi,[_scVid]
mov edx,[_scPal]
mov ax,[_scwht]
mov [_scsavwht],ax
movzx ecx,[_sctopht]
mov ebx,[_scWall]
add ebx,ecx
mov [_bmWall],ebx
mov ch,al
inc ch
mov eax,0
mov ebx,0
;--TEST------------------------------------------------------------------------
test [word ptr _scbNum],WALL_TYPE_UPPER
jz short m_toprun
mov ebp,[_bmDistance]
m_zztoploop:
dec ch
jz short m_zzdomulti
add bx,bp
cmp bh,cl
jge short m_zzdomulti
sub edi,320
jmp m_zztoploop
m_zzdomulti:
mov ebp,[_scPtr]
mov [_scwht],cx
mov [_scsavVid],edi
jmp m_chkmulti
;--TEST------------------------------------------------------------------------
m_toprun:
mov ebp,[_bmDistance]
mov esi,[_bmWall]
m_toploop:
movzx eax,bh
neg eax
movzx eax,[byte ptr esi+eax]
or al,al
jz short m_blank1
mov al,[edx+eax]
mov [edi],al
m_blank1:
add bx,bp
cmp bh,cl
jg short m_botrun
dec ch
jz short m_botrun
sub edi,320
jmp m_toploop
m_botrun:
mov ebp,[_scPtr]
mov [_scwht],cx
mov [_scsavVid],edi
mov edi,[_scVid]
mov cx,[_scbotht]
mov bx,[_scsavwht]
mov ch,bl
mov ebx,0
inc esi
mov ebp,[_bmDistance]
mov eax,0
dec cl
m_botloop:
add edi,320
mov al,bh
mov al,[esi+eax]
or al,al
jz short m_blank2
mov al,[edx+eax]
mov [edi],al
m_blank2:
dec ch
jz short m_chkmulti
add bx,bp
cmp bh,cl
jl m_botloop
m_chkmulti:
mov ebp,[_scPtr]
cmp [word ptr _scmulti],0
jz short m_alldone
mov cx,[_scmulcnt]
mov bx,[_scwht]
mov ch,bh
cmp ch,0
jz short m_alldone
mov edi,[_scsavVid]
mov ebx,[_scWall]
add ebx,63
mov [_bmWall],ebx
mov ebx,0
mov ebp,[_bmDistance]
mov esi,[_bmWall]
m_mulloop:
sub edi,320
movzx eax,bh
neg eax
movzx eax,[byte ptr esi+eax]
or al,al
jz m_blank3
mov al,[edx+eax]
mov [edi],al
m_blank3:
dec ch
jz short m_alldone
add bx,bp
cmp bh,64
jge short m_nextlevel
jmp m_mulloop
m_nextlevel:
mov ebx,0
dec cl
jnz m_mulloop
m_alldone:
pop edi
pop esi
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; This routine runs through the list of slices and draws the walls.
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC DrawWalls
push ebp
push esi
push edi
mov ax,[_gWinHeight]
shr ax,1
mov [_Floorht],ax
mov ax,[_ViewHeight]
mov [_sctopht],ax
mov dx,64
sub dx,ax
mov [_scbotht],dx
movsx ebx,[word ptr _gWinStartX]
movsx ecx,[_gCenterOff]
add ecx,ebx
add ecx,[_gScrnBuffer]
mov [_scVid],ecx
cmp [word ptr _Resolution],1 ;is this low resolution?
je stw_lowres ;yes, perform faster draw
movzx eax,[_gWinEndX]
imul eax,saSize
mov [ENDPOS],eax
imul ebx,saSize
stw010:
mov ebp,offset _Slice ; offset to slices array
add ebp,ebx
stw020:
cmp [byte ptr ebp+saActive],0 ;is this an active slice?
jz short stw030 ;nope, so it's the last one
cmp [dword ptr ebp+saNext],0 ;is this the last slice?
jz short stw030 ;yes, so can't go further
mov ebp,[dword ptr ebp+saNext] ;point to next slice
jmp short stw020
stw030:
mov ax,[word ptr ebp+sabNumber] ;bitmap number
mov cx,ax
and cx,0ffh ;isolate number from flags
mov [_scmulcnt],cx ;save as current multi count
mov [_scbNum],ax ;and bitmap number and flags
mov cx,0 ;set multi-flag to none
test ax,WALL_TYPE_MULTI
jz short stw040
mov esi,[dword ptr ebp+samPtr]
mov [_scMulData],esi
or esi,esi ;is there multi-ht data?
jz short stw040 ;br if not
mov cx,1 ;set multi-flag to yes
stw040:
mov [_scmulti],cx
mov ecx,[dword ptr ebp+sabMap] ;get pointer to bitmaps
movzx esi,al ;get low byte of bitmap number
shl esi,2
mov esi,[dword ptr ecx+esi] ;get actual bitmap pointer
movsx ecx,[word ptr ebp+saDist] ;distance to slice
mov [_bmDistance],ecx ;save for draw routine
shr ecx,6 ;bring it down into palette range
cmp ecx,15 ;check against max palette number
jbe short stw050
mov ecx,15 ;force to max if above
stw050:
shl ecx,8 ;x256 for palette entry
mov edi,[_gPalTable] ;pointer to palette table
add edi,ecx
movsx ecx,[word ptr ebp+sabColumn] ;column of bitmap slice
shl ecx,6 ;x64 to get correct row (column)
add esi,ecx ;adjust wall point to correct column
mov [_scColumn],ecx ;save for multi-ht walls
mov [_scWall],esi
mov [_scPal],edi
mov eax,0
mov [_scsavVid],eax ;null out saved video
mov ax,[_Floorht] ;window height / 2 saved earlier
mov [_scwht],ax
mov esi,ebx
call [dword ptr ebp+saFnc]
mov ebx,esi
stw075:
cmp [dword ptr ebp+saPrev],0 ;is this the first slice?
jz short stw080 ;yes, go to next column
mov ebp,[dword ptr ebp+saPrev] ;pick up previous slice
jmp stw030 ;and start again with same column
stw080:
inc [dword ptr _scVid] ;next video position
add ebx,saSize
cmp ebx,[ENDPOS]
ja stw_getout ;yes, get out
jmp stw010
stw_lowres:
mov eax,ebx ; current column of display
imul eax,saSize ; size of slice structure
mov ebp,offset _Slice ; offset to slices
add ebp,eax
stwlr020:
cmp [byte ptr ebp+saActive],0 ;is this an active slice?
jz short stwlr030 ;nope, so it's the last one
cmp [dword ptr ebp+saNext],0 ;is this the last slice?
jz short stwlr030 ;yes, so can't go further
mov ebp,[dword ptr ebp+saNext] ;point to next slice
jmp short stwlr020
stwlr030:
mov ax,[word ptr ebp+sabNumber] ;bitmap number
mov cx,ax
and cx,0ffh ;isolate number from flags
mov [_scmulcnt],cx ;save as current multi count
mov [_scbNum],ax ;and bitmap number and flags
mov cx,0 ;set multi-flag to none
test ax,WALL_TYPE_MULTI
jz short stwlr040
mov esi,[dword ptr ebp+samPtr]
mov [_scMulData],esi
or esi,esi ;is there multi-height data?
jz short stwlr040 ;br if not
mov cx,1 ;set multi-flag to yes
stwlr040:
mov [_scmulti],cx
mov ecx,[dword ptr ebp+sabMap] ;get pointer to bitmaps
movzx esi,al ;get low byte of bitmap number
shl esi,2
mov esi,[dword ptr ecx+esi] ;get actual bitmap pointer
movsx ecx,[word ptr ebp+saDist] ;distance to slice
mov [_bmDistance],ecx ;save for draw routine
shr ecx,6 ;bring it down into palette range
cmp ecx,15 ;check against max palette number
jbe short stwlr050
mov ecx,15 ;force to max if above
stwlr050:
shl ecx,8 ;x256 for palette entry
mov edi,[_gPalTable] ;pointer to palette table
add edi,ecx
movsx ecx,[byte ptr ebp+sabColumn] ;column of bitmap slice
shl ecx,6 ;x64 to get correct row (column)
add esi,ecx ;adjust wall point to correct column
mov [_scColumn],ecx ;save for multi-ht walls
mov [_scWall],esi
mov [_scPal],edi
mov eax,0
mov [_scsavVid],eax ;null out saved video
mov ax,[_Floorht] ;window height / 2 saved earlier
mov [_scwht],ax
mov esi,ebx
cmp [byte ptr ebp+saType],ST_WALL ;transparent wall?
je short stwlr060 ;nope, use solid slice routine
ACKCALL ShowColMaskLow
jmp short stwlr070
stwlr060:
ACKCALL ShowColLow
stwlr070:
mov ebx,esi
cmp [dword ptr ebp+saPrev],0 ;is this the first slice?
jz short stwlr080 ;yes, go to next column
mov ebp,[dword ptr ebp+saPrev] ;pick up previous slice
jmp stwlr030 ;and start again with same column
stwlr080:
add [dword ptr _scVid],2 ;next video position
inc ebx ;next column
inc ebx ;next column
cmp bx,[word ptr _gWinEndX] ;are we at the end of the window?
ja short stw_getout ;yes, get out
jmp stw_lowres
stw_getout:
pop edi
pop esi
pop ebp
ret
endp
end


805
ack_lib/ACKRTN2.ASM Normal file
View file

@ -0,0 +1,805 @@
IDEAL
JUMPS
P386
P387 ; Allow 386 processor
MASM
.MODEL FLAT ;32-bit OS/2 model
IDEAL
include "ackrtn.inc"
MASM
extrn _WallDistTable:dword
extrn _FloorMap:word
extrn _CeilMap:word
extrn _LastWallHeight:word
extrn _ViewAngle:word
extrn _ScreenOffset:word
extrn _xPglobal:dword
extrn _yPglobal:dword
extrn _xBegGlobal:dword
extrn _yBegGlobal:dword
extrn _aeGlobal:dword
extrn _xGridGlobal:dword
extrn _yGridGlobal:dword
extrn _xPglobalHI:dword
extrn _yPglobalHI:dword
extrn _rbaTable:dword
extrn _rsHandle:word
extrn _LastX1:dword
extrn _LastY1:dword
extrn _iLastX:dword
extrn _iLastY;dword
extrn _MaxDistance:word
extrn _BackArray:dword
extrn _zdTable:dword
extrn _ErrorCode:word
extrn _xMapPosn:dword
extrn _yMapPosn:dword
extrn _Grid:dword
extrn _ObjGrid:dword
extrn _WallbMaps:dword
extrn _ViewHeight:word
extrn _CeilingHeight:word
extrn _gTopColor:byte
extrn _gBottomColor:byte
extrn _PlayerAngle:word
extrn _gScrnBuffer:dword
extrn _gBkgdBuffer:dword
extrn _gCenterOff:word
extrn _gWinStartOffset:dword
extrn _gWinHeight:word
extrn _gWinEndY:dword
extrn _SysFlags:word
extrn _sPtr:dword
extrn _mxGridGlobal:dword
extrn _myGridGlobal:dword
extrn _xSecretmPos:word
extrn _xSecretmPos1:word
extrn _xSecretColumn:word
extrn _ySecretmPos:word
extrn _ySecretmPos1:word
extrn _ySecretColumn:word
extrn _TotalSecret:word
extrn _ViewColumn:word
extrn _SinTable:dword
extrn _CosTable:dword
extrn _LongTanTable:dword
extrn _LongInvTanTable:dword
extrn _InvCosTable:byte
extrn _InvSinTable:byte
extrn _LongCosTable:dword
extrn _ViewCosTable:dword
extrn _xNextTable:dword
extrn _yNextTable:dword
extrn _LastMapPosn:word
extrn _LastObjectHit:word
extrn _TotalObjects:word
extrn _FoundObjectCount:word
extrn _ObjectsSeen:byte
extrn _MoveObjectCount:word
extrn _MoveObjectList:byte
extrn _ObjNumber:byte
extrn _ObjRelDist:byte
extrn _ObjColumn:byte
extrn _x_xPos:dword
extrn _x_yPos:dword
extrn _x_xNext:dword
extrn _x_yNext:dword
extrn _y_xPos:dword
extrn _y_yPos:dword
extrn _y_xNext:dword
extrn _y_yNext:dword
extrn _Resolution:word
extrn _Flooru:dword
extrn _Floorv:dword
extrn _Floordu:dword
extrn _Floordv:dword
extrn _Floorkx:dword
extrn _Floorky:dword
extrn _Floorku:dword
extrn _Floorkv:dword
extrn _Floorkdu:dword
extrn _Floorkdv:dword
extrn _Floorbm:dword
extrn _Floorscr:dword
extrn _Floors1:dword
extrn _Floors2:dword
extrn _FloorscrTop:dword
extrn _Floorptr2:dword
extrn _Floorht:dword
extrn _Floorwt:dword
extrn _Floorvht:word
extrn _Flooreht:word
extrn _FloorLastbNum:dword
extrn _FloorLastbm:dword
extrn _bmDistance:dword
extrn _scwht:word
extrn _scWall:dword
extrn _scPal:dword
extrn _scVid:dword
extrn _scantables:dword
ACKEXT DrawBackDrop
ACKEXT ShowCol
ACKEXT ShowColMask
ACKEXT FindDoor
ACKEXT xRayCast
ACKEXT yRayCast
ACKPUBS xxxAckDrawFloor
ACKPUBS xxxAckDrawFloorOnly
ACKPUBS xxxAckDrawCeilingOnly
.DATA
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Globals used by the AckDrawFloor routine
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
BCOL dd ?
HEIGHT dd ?
VA dd ?
SY dd ?
EY dd ?
BFSCRN dd ?
BCSCRN dd ?
FSCRN dd ?
CSCRN dd ?
CV dd ?
SV dd ?
BA dd ?
BA1 dd ?
ZDPTR dd ?
POS dd ?
BMPOS dd ?
MPOS dd ?
MPOSHI dd ?
SCANTBL dd ?
LINENUM dd ?
LASTDIST dd ?
;LASTX dd ?
;LASTY dd ?
LASTEBP dd ?
LASTEAX dd ?
LASTEDX dd ?
WALLDIST dd ?
.CODE
IDEAL
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC xxxAckDrawFloor
push ebp
push esi
push edi
push ebx
push ecx
push edx
movzx eax,[word ptr _PlayerAngle]
mov ecx,eax
sub eax,INT_ANGLE_32
jnc short adf_20
add eax,INT_ANGLE_360
adf_20:
mov ebx,640
cdq
idiv ebx
mov [BCOL],edx
mov eax,89
sub ax,[word ptr _ViewHeight]
mov [HEIGHT],eax
sub ecx,INT_ANGLE_32
jnc short adf_30
add ecx,INT_ANGLE_360
adf_30:
mov [VA],ecx
movzx eax,[word ptr _gWinHeight]
sar eax,1
movzx ebx,[word ptr _gWinEndY]
sub ebx,eax
inc ebx
sub ebx,5 ; 6
mov [EY],ebx
mov edi,[_gScrnBuffer]
movzx eax,[word ptr _gCenterOff]
mov ebx,eax
add eax,1920
add eax,edi
mov [BFSCRN],eax
sub ebx,1600 ;1920
add ebx,edi
mov [BCSCRN],ebx
mov ebp,0
mov [LINENUM],ebp
mov [LASTDIST],ebp
mov ebx,[dword ptr _scantables]
mov [SCANTBL],ebx
mov ebx,[VA]
adf_loop:
mov eax,[_CosTable]
shl ebx,2
mov eax,[eax+ebx]
mov [CV],eax
mov eax,[_SinTable]
mov eax,[eax+ebx]
mov [SV],eax
mov eax,[dword ptr _WallDistTable+ebp*4]
mov [WALLDIST],eax
mov eax,[BCSCRN]
mov [CSCRN],eax
mov ecx,[EY]
mov ebx,[BCOL]
mov eax,[_BackArray+ebx*4]
add eax,ecx
mov [BA],eax
inc ebx
cmp ebx,640
jb short adf_l10
sub ebx,ebx
adf_l10:
mov eax,[_BackArray+ebx*4]
add eax,ecx
mov [BA1],eax
inc ebx
cmp ebx,640
jb short adf_l20
sub ebx,ebx
adf_l20:
mov [BCOL],ebx
lea esi,[offset _zdTable]
mov ecx,[EY] ;Number of rows to draw
imul eax,ebp,800
add esi,eax
add esi,24 ;ebx
mov edi,[BFSCRN]
push ebp
adf_yloop:
mov edx,[esi]
lea esi,[esi+4]
cmp edx,[WALLDIST]
jb short adf_distokay
lea edi,[edi+320]
jmp adf_ycont
adf_distokay:
cmp edx,[LASTDIST]
jne short adf_newdist
; mov eax,[LASTX]
; mov ebx,[LASTY]
mov ebp,[LASTEBP]
mov eax,[LASTEAX]
mov edx,[LASTEDX]
jmp short adf_samedist
adf_newdist:
mov [LASTDIST],edx
mov eax,[CV]
mov ebx,[SV]
imul eax,edx
imul ebx,edx
sar eax,16
sar ebx,16
mov edx,[_xPglobal]
add eax,edx
mov edx,[_yPglobal]
add ebx,edx
; mov [LASTX],eax
; mov [LASTY],ebx
;adf_samedist:
mov edx,ebx
and edx,0FC0h
mov ebp,eax
sar ebp,6
add ebp,edx ;Pos within floor and ceiling maps
and ebx,63
shl ebx,6
and eax,63
add eax,ebx ;bitmap position
;; mov ebx,0
shl ebp,1
mov [LASTEBP],ebp
mov [LASTEAX],eax
movzx ebx,[word ptr _FloorMap+ebp]
mov edx,[_WallbMaps]
mov edx,[edx+ebx*4]
movzx edx,[byte ptr edx+eax]
mov ebx,[SCANTBL]
mov dl,[ebx+edx]
mov dh,dl
mov [LASTEDX],edx
adf_samedist:
mov [edi],dx
lea edi,[edi+320]
movzx ebx,[word ptr _CeilMap+ebp]
mov ebp,[CSCRN]
test bx,bx
jz short adf_yback
mov edx,[_WallbMaps]
mov edx,[edx+ebx*4]
movzx eax,[byte ptr edx+eax]
mov edx,[SCANTBL]
mov al,[edx+eax]
mov ah,al
mov [ebp],ax
mov eax,[LINENUM]
add eax,4
mov [LINENUM],eax
mov eax,[_scantables+eax]
mov [SCANTBL],eax
lea ebp,[ebp-320]
mov [CSCRN],ebp
dec [dword ptr BA]
dec [dword ptr BA1]
dec ecx
jnz adf_yloop
jmp short adf_ynext
adf_yback:
mov eax,[BA]
mov dl,[eax]
mov eax,[BA1]
mov dh,[eax]
mov [ebp],dx
adf_ycont:
mov eax,[LINENUM]
add eax,4
mov [LINENUM],eax
mov eax,[_scantables+eax]
mov [SCANTBL],eax
sub [dword ptr CSCRN],320
dec [dword ptr BA]
dec [dword ptr BA1]
dec ecx
jnz adf_yloop
adf_ynext:
mov [dword ptr LINENUM],0
mov eax,[dword ptr _scantables]
mov [SCANTBL],eax
mov ebx,[VA]
lea ebx,[ebx+2]
cmp ebx,INT_ANGLE_360
jb short adf_l90
sub ebx,INT_ANGLE_360
adf_l90:
mov [VA],ebx ;Note: EBX is used for VA at top of loop!
add [dword ptr BFSCRN],2
add [dword ptr BCSCRN],2
pop ebp
lea ebp,[ebp+2]
cmp ebp,320
jb adf_loop
adf_exit:
pop edx
pop ecx
pop ebx
pop edi
pop esi
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC xxxAckDrawFloorOnly
push ebp
push esi
push edi
push ebx
push ecx
push edx
movzx eax,[word ptr _PlayerAngle]
mov ecx,eax
sub eax,INT_ANGLE_32
jnc short adfo_20
add eax,INT_ANGLE_360
adfo_20:
mov ebx,640
cdq
idiv ebx
mov [BCOL],edx
mov eax,89
sub ax,[word ptr _ViewHeight]
mov [HEIGHT],eax
sub ecx,INT_ANGLE_32
jnc short adfo_30
add ecx,INT_ANGLE_360
adfo_30:
mov [VA],ecx
movzx eax,[word ptr _gWinHeight]
sar eax,1
movzx ebx,[word ptr _gWinEndY]
sub ebx,eax
inc ebx
sub ebx,5 ; 6
mov [EY],ebx
mov edi,[_gScrnBuffer]
movzx eax,[word ptr _gCenterOff]
mov ebx,eax
add eax,1920
add eax,edi
mov [BFSCRN],eax
sub ebx,1600 ;1920
add ebx,edi
mov [BCSCRN],ebx
mov ebp,0
mov [LINENUM],ebp
mov ebx,[dword ptr _scantables]
mov [SCANTBL],ebx
mov ebx,[VA]
adfo_loop:
mov eax,[_CosTable]
shl ebx,2
mov eax,[eax+ebx]
mov [CV],eax
mov eax,[_SinTable]
mov eax,[eax+ebx]
mov [SV],eax
mov eax,[BCSCRN]
mov [CSCRN],eax
mov ecx,[EY]
mov ebx,[BCOL]
mov eax,[_BackArray+ebx*4]
add eax,ecx
mov [BA],eax
inc ebx
cmp ebx,640
jb short adfo_l10
sub ebx,ebx
adfo_l10:
mov eax,[_BackArray+ebx*4]
add eax,ecx
mov [BA1],eax
inc ebx
cmp ebx,640
jb short adfo_l20
sub ebx,ebx
adfo_l20:
mov [BCOL],ebx
lea esi,[offset _zdTable]
mov ecx,[EY] ;Number of rows to draw
imul eax,ebp,800
add esi,eax
add esi,24 ;ebx
mov edi,[BFSCRN]
push ebp
adfo_yloop:
mov edx,[esi]
lea esi,[esi+4]
mov eax,[CV]
mov ebx,[SV]
imul eax,edx
imul ebx,edx
sar eax,16
sar ebx,16
mov edx,[_xPglobal]
add eax,edx
mov edx,[_yPglobal]
add ebx,edx
mov edx,ebx
and edx,0FC0h
mov ebp,eax
sar ebp,6
add ebp,edx ;Pos within floor and ceiling maps
and ebx,63
shl ebx,6
and eax,63
add eax,ebx ;bitmap position
mov ebx,0
shl ebp,1
mov bx,[word ptr _FloorMap+ebp]
mov edx,[_WallbMaps]
mov edx,[edx+ebx*4]
movzx edx,[byte ptr edx+eax]
mov ebx,[SCANTBL]
mov dl,[ebx+edx]
mov dh,dl
mov [edi],dx
lea edi,[edi+320]
mov eax,[BA]
mov dl,[eax]
mov eax,[BA1]
mov dh,[eax]
mov ebp,[CSCRN]
mov [ebp],dx
adfo_ycont:
lea ebp,[ebp-320]
mov [CSCRN],ebp
mov eax,[LINENUM]
add eax,4
mov [LINENUM],eax
mov eax,[_scantables+eax]
mov [SCANTBL],eax
dec [dword ptr BA]
dec [dword ptr BA1]
dec ecx
jnz adfo_yloop
adfo_ynext:
mov [dword ptr LINENUM],0
mov eax,[dword ptr _scantables]
mov [SCANTBL],eax
mov ebx,[VA]
lea ebx,[ebx+2]
cmp ebx,INT_ANGLE_360
jb short adfo_l90
sub ebx,INT_ANGLE_360
adfo_l90:
mov [VA],ebx ;Note: EBX is used for VA at top of loop!
add [dword ptr BFSCRN],2
add [dword ptr BCSCRN],2
pop ebp
lea ebp,[ebp+2]
cmp ebp,320
jb adfo_loop
adfo_exit:
pop edx
pop ecx
pop ebx
pop edi
pop esi
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC xxxAckDrawCeilingOnly
push ebp
push esi
push edi
push ebx
push ecx
push edx
movzx eax,[word ptr _PlayerAngle]
mov ecx,eax
sub eax,INT_ANGLE_32
jnc short adco_20
add eax,INT_ANGLE_360
adco_20:
mov ebx,640
cdq
idiv ebx
mov [BCOL],edx
mov eax,89
sub ax,[word ptr _ViewHeight]
mov [HEIGHT],eax
sub ecx,INT_ANGLE_32
jnc short adco_30
add ecx,INT_ANGLE_360
adco_30:
mov [VA],ecx
movzx eax,[word ptr _gWinHeight]
sar eax,1
movzx ebx,[word ptr _gWinEndY]
sub ebx,eax
inc ebx
sub ebx,5 ; 6
mov [EY],ebx
mov edi,[_gScrnBuffer]
movzx eax,[word ptr _gCenterOff]
mov ebx,eax
sub ebx,1600 ;1920
add ebx,edi
mov [BCSCRN],ebx
mov ebp,0
mov [LINENUM],ebp
mov ebx,[dword ptr _scantables]
mov [SCANTBL],ebx
mov ebx,[VA]
adco_loop:
mov eax,[_CosTable]
shl ebx,2
mov eax,[eax+ebx]
mov [CV],eax
mov eax,[_SinTable]
mov eax,[eax+ebx]
mov [SV],eax
mov eax,[BCSCRN]
mov [CSCRN],eax
mov ecx,[EY]
mov ebx,[BCOL]
mov eax,[_BackArray+ebx*4]
add eax,ecx
mov [BA],eax
inc ebx
cmp ebx,640
jb short adco_l10
sub ebx,ebx
adco_l10:
mov eax,[_BackArray+ebx*4]
add eax,ecx
mov [BA1],eax
inc ebx
cmp ebx,640
jb short adco_l20
sub ebx,ebx
adco_l20:
mov [BCOL],ebx
lea esi,[offset _zdTable]
mov ecx,[EY] ;Number of rows to draw
imul eax,ebp,800
add esi,eax
add esi,24 ;ebx
push ebp
adco_yloop:
mov edx,[esi]
lea esi,[esi+4]
mov eax,[CV]
mov ebx,[SV]
imul eax,edx
imul ebx,edx
sar eax,16
sar ebx,16
mov edx,[_xPglobal]
add eax,edx
mov edx,[_yPglobal]
add ebx,edx
mov edx,ebx
and edx,0FC0h
mov ebp,eax
sar ebp,6
add ebp,edx ;Pos within floor and ceiling maps
and ebx,63
shl ebx,6
and eax,63
add eax,ebx ;bitmap position
mov ebx,0
shl ebp,1
movzx ebx,[word ptr _CeilMap+ebp]
mov ebp,[CSCRN]
test bx,bx
jz short adco_yback
mov edx,[_WallbMaps]
mov edx,[edx+ebx*4]
movzx eax,[byte ptr edx+eax]
mov edx,[SCANTBL]
mov al,[edx+eax]
mov ah,al
mov [ebp],ax
mov eax,[LINENUM]
add eax,4
mov [LINENUM],eax
mov eax,[_scantables+eax]
mov [SCANTBL],eax
lea ebp,[ebp-320]
mov [CSCRN],ebp
dec [dword ptr BA]
dec [dword ptr BA1]
dec ecx
jnz adco_yloop
jmp short adco_ynext
adco_yback:
mov eax,[BA]
mov dl,[eax]
mov eax,[BA1]
mov dh,[eax]
mov [ebp],dx
adco_ycont:
mov eax,[LINENUM]
add eax,4
mov [LINENUM],eax
mov eax,[_scantables+eax]
mov [SCANTBL],eax
sub [dword ptr CSCRN],320
dec [dword ptr BA]
dec [dword ptr BA1]
dec ecx
jnz adco_yloop
adco_ynext:
mov [dword ptr LINENUM],0
mov eax,[dword ptr _scantables]
mov [SCANTBL],eax
mov ebx,[VA]
lea ebx,[ebx+2]
cmp ebx,INT_ANGLE_360
jb short adco_l90
sub ebx,INT_ANGLE_360
adco_l90:
mov [VA],ebx ;Note: EBX is used for VA at top of loop!
add [dword ptr BCSCRN],2
pop ebp
lea ebp,[ebp+2]
cmp ebp,320
jb adco_loop
adco_exit:
pop edx
pop ecx
pop ebx
pop edi
pop esi
pop ebp
ret
endp
end


830
ack_lib/ACKRTN3.ASM Normal file
View file

@ -0,0 +1,830 @@
IDEAL
JUMPS
P386
P387 ; Allow 386 processor
MASM
.MODEL FLAT ;32-bit OS/2 model
.CODE
IDEAL
include "ackrtn.inc"
extrn _gMultiWalls:word
extrn _WallDistTable:dword
extrn _BackDropRows:dword
extrn _FloorCeilRtn:dword
extrn _Resolution:word
extrn _ScreenOffset:word
extrn _bmDistance:dword
extrn _bmWall:dword
extrn _scPtr:dword
extrn _VidTop:dword
extrn _VidBottom:dword
extrn _Floors1:dword
extrn _Floors2:dword
extrn _PlayerAngle:word
extrn _BackArray:dword
extrn _gWinStartX:word
extrn _gWinStartY:word
extrn _gWinEndX:word
extrn _gWinEndY:word
extrn _gWinHeight:word
extrn _gWinWidth:word
extrn _gCenterRow:word
extrn _gCenterOff:word
extrn _scVid:dword
extrn _scWall:dword
extrn _scPal:dword
extrn _scdst:word
extrn _scwht:word
extrn _scmulti:word
extrn _sctopht:word
extrn _scbotht:word
extrn _scsavwht:word
extrn _scmulcnt:word
extrn _scsavVid:dword
extrn _scbNum:word
extrn _scMulData:dword
extrn _scColumn:dword
extrn _WallbMaps:dword
extrn _FloorMap:word
extrn _CeilMap:word
extrn _LastWallHeight:word
extrn _ViewAngle:word
extrn _ScreenOffset:word
extrn _xPglobal:dword
extrn _yPglobal:dword
extrn _xBegGlobal:dword
extrn _yBegGlobal:dword
extrn _aeGlobal:dword
extrn _xGridGlobal:dword
extrn _yGridGlobal:dword
extrn _xPglobalHI:dword
extrn _yPglobalHI:dword
extrn _rbaTable:dword
extrn _rsHandle:word
extrn _LastX1:dword
extrn _LastY1:dword
extrn _iLastX:dword
extrn _iLastY;dword
extrn _MaxDistance:word
extrn _ErrorCode:word
extrn _xMapPosn:dword
extrn _yMapPosn:dword
extrn _Grid:dword
extrn _ObjGrid:dword
extrn _ViewHeight:word
extrn _CeilingHeight:word
extrn _gTopColor:byte
extrn _gBottomColor:byte
extrn _PlayerAngle:word
extrn _gScrnBuffer:dword
extrn _gBkgdBuffer:dword
extrn _gCenterOff:word
extrn _gWinHeight:word
extrn _SysFlags:word
extrn _xSecretmPos:word
extrn _xSecretmPos1:word
extrn _xSecretColumn:word
extrn _ySecretmPos:word
extrn _ySecretmPos1:word
extrn _ySecretColumn:word
extrn _TotalSecret:word
extrn _ViewColumn:word
extrn _SinTable:dword
extrn _CosTable:dword
extrn _LongTanTable:dword
extrn _LongInvTanTable:dword
extrn _InvCosTable:byte
extrn _InvSinTable:byte
extrn _LongCosTable:dword
extrn _ViewCosTable:dword
extrn _xNextTable:dword
extrn _yNextTable:dword
extrn _LastMapPosn:word
extrn _LastObjectHit:word
extrn _TotalObjects:word
extrn _FoundObjectCount:word
extrn _ObjectsSeen:byte
extrn _MoveObjectCount:word
extrn _MoveObjectList:byte
extrn _ObjNumber:byte
extrn _ObjRelDist:byte
extrn _ObjColumn:byte
extrn _x_xPos:dword
extrn _x_yPos:dword
extrn _x_xNext:dword
extrn _x_yNext:dword
extrn _y_xPos:dword
extrn _y_yPos:dword
extrn _y_xNext:dword
extrn _y_yNext:dword
extrn _Slice:dword
extrn _sPtr:dword
extrn _HitMap:byte
ACKEXT xRaySetup
ACKEXT yRaySetup
ACKEXT BuildSlice
ACKEXT xRayCast
ACKEXT yRayCast
ACKEXT AckDrawFloor
ACKEXT AckDrawFloorOnly
ACKEXT AckDrawCeilingOnly
ACKEXT DrawWalls
ACKEXT CheckDoors
ACKEXT BuildSliceMulti
ACKEXT FindObject
ACKPUBS xRayCastMulti
ACKPUBS yRayCastMulti
ACKPUBS ShowColLow
ACKPUBS ShowColMaskLow
ACKPUBS BuildUpView
align 2
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC ShowColLow
push ebp
push esi
push edi
mov ebp,eax
mov [_scPtr],eax
mov edi,[_scVid]
mov edx,[_scPal]
mov ax,[_scwht]
mov [_scsavwht],ax
movsx ecx,[_sctopht]
mov ebx,[_scWall]
add ebx,ecx
mov [_bmWall],ebx
mov ch,al
inc ch
mov eax,0
mov ebx,0
;--TEST------------------------------------------------------------------------
test [word ptr _scbNum],WALL_TYPE_UPPER
jz short toprun
mov ebp,[_bmDistance]
zztoploop:
dec ch
jz short zzdomulti
add bx,bp
cmp bh,cl
jge short zzdomulti
sub di,320
jmp zztoploop
zzdomulti:
mov ebp,[_scPtr]
mov [_scwht],cx
mov [_scsavVid],edi
jmp chkmulti
;--TEST------------------------------------------------------------------------
toprun:
mov ebp,[_bmDistance]
toploop:
movsx eax,bh
mov esi,[_bmWall]
sub esi,eax
mov al,[esi]
mov al,[edx+eax]
mov ah,al
mov [edi],ax
add bx,bp
cmp bh,cl
jg short botrun
dec ch
jz short botrun
sub edi,320
jmp toploop
botrun:
mov ebp,[_scPtr]
mov [_scwht],cx
mov [_scsavVid],edi
mov [_VidTop],edi
mov edi,[_scVid]
mov cx,[_scbotht]
mov bx,[_scsavwht]
mov ch,bl
mov ebx,0
mov esi,[_bmWall]
inc esi
mov ebp,[_bmDistance]
dec cl
botloop:
add edi,320
movsx ax,bh
mov al,[esi+eax]
mov al,[edx+eax]
mov ah,al
mov [edi],ax
dec ch
jz short chkmulti
add bx,bp
cmp bh,cl
jl botloop
chkmulti:
mov [_VidBottom],edi
mov ebp,[_scPtr]
mov edi,[_scsavVid]
cmp [word ptr _scmulti],0
jz alldone
mov cx,[_scmulcnt]
mov ebx,[_scMulData] ;ptr to count and wall data
mov cl,[ebx] ;get count of data
inc ebx
mov al,[ebx] ;first wall to show
inc ebx
mov [_scMulData],ebx
movsx ebx,al ;get wall number
shl ebx,2 ;x4 for index into wall bitmap array
mov eax,[_WallbMaps]
mov ebx,[eax+ebx]
add ebx,[dword ptr _scColumn] ;add in current column
add ebx,63 ;point to bottom of column
mov [_bmWall],ebx
mov bx,[_scwht]
mov ch,bh
cmp ch,0
jz short alldone
mov ebx,0
mov ebp,[_bmDistance]
mulloop:
sub edi,320
movsx eax,bh
mov esi,[_bmWall]
sub esi,eax
mov al,[esi]
mov al,[edx+eax]
mov ah,al
mov [edi],ax
dec ch
jz short alldone
add bx,bp
cmp bh,64
jge short nextlevel
jmp mulloop
nextlevel:
dec cl
jz short alldone
mov ebx,[_scMulData]
mov al,[ebx] ;next wall number
inc ebx
mov [_scMulData],ebx
movsx ebx,al
shl ebx,2
mov eax,[_WallbMaps]
mov ebx,[eax+ebx]
add ebx,[dword ptr _scColumn] ;add in current column
add ebx,63 ;point to bottom of column
mov [_bmWall],ebx
mov ebx,0
jmp mulloop
alldone:
mov [_VidTop],edi
pop edi
pop esi
pop ebp
ret
endp
align 2
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC ShowColMaskLow
push ebp
push esi
push edi
mov ebp,eax
mov [_scPtr],eax
mov edi,[_scVid]
mov edx,[_scPal]
mov ax,[_scwht]
mov [_scsavwht],ax
movsx ecx,[_sctopht]
mov ebx,[_scWall]
add ebx,ecx
mov [_bmWall],ebx
mov ch,al
mov eax,0
mov ebx,0
;--TEST------------------------------------------------------------------------
test [word ptr _scbNum],WALL_TYPE_UPPER
jz short m_toprun
mov ebp,[_bmDistance]
m_zztoploop:
dec ch
jz short m_zzdomulti
add bx,bp
cmp bh,cl
jge short m_zzdomulti
sub edi,320
jmp m_zztoploop
m_zzdomulti:
mov ebp,[_scPtr]
mov [_scwht],cx
mov [_scsavVid],edi
jmp m_chkmulti
;--TEST------------------------------------------------------------------------
m_toprun:
mov ebp,[_bmDistance]
m_toploop:
movsx eax,bh
mov esi,[_bmWall]
sub esi,eax
mov al,[esi]
or al,al
jz m_blank1
mov al,[edx+eax]
mov ah,al
mov [edi],ax
m_blank1:
add bx,bp
cmp bh,cl
jg short m_botrun
dec ch
jz short m_botrun
sub edi,320
jmp m_toploop
m_botrun:
mov ebp,[_scPtr]
mov [_scwht],cx
mov [_scsavVid],edi
mov edi,[_scVid]
mov cx,[_scbotht]
mov bx,[_scsavwht]
mov ch,bl
mov ebx,0
mov esi,[_bmWall]
inc esi
mov ebp,[_bmDistance]
m_botloop:
add edi,320
movsx ax,bh
mov al,[esi+eax]
or al,al
jz m_blank2
mov al,[edx+eax]
mov ah,al
mov [edi],ax
m_blank2:
dec ch
jz short m_chkmulti
add bx,bp
cmp bh,cl
jl m_botloop
m_chkmulti:
mov ebp,[_scPtr]
cmp [word ptr _scmulti],0
jz short m_alldone
mov cx,[_scmulcnt]
mov bx,[_scwht]
mov ch,bh
cmp ch,0
jz short m_alldone
mov edi,[_scsavVid]
mov ebx,[_scWall]
add ebx,63
mov [_bmWall],ebx
mov ebx,0
mov ebp,[_bmDistance]
m_mulloop:
sub edi,320
movsx eax,bh
mov esi,[_bmWall]
sub esi,eax
mov al,[esi]
or al,al
jz m_blank3
mov al,[edx+eax]
mov ah,al
mov [edi],ax
m_blank3:
dec ch
jz short m_alldone
add bx,bp
cmp bh,64
jge short m_nextlevel
jmp m_mulloop
m_nextlevel:
mov ebx,0
dec cl
jnz m_mulloop
m_alldone:
pop edi
pop esi
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC xRayCastMulti
push ebp
mov ebp,esp
sub esp,50
push esi
push edi
push ebx
push ecx
push edx
mov [word ptr retval],0
looptop:
mov edx,[dword ptr _x_xPos]
cmp edx,large 0
jl short getout
cmp edx,large 4096
jg short getout
mov eax,[_x_yPos]
cmp eax,large 0
jl short getout
cmp eax,large 010000000h
jle short inbounds
getout:
jmp loopdone
inbounds:
sar eax,16
and ax,-64
sar edx,6
add ax,dx
mov si,ax
shl ax,1
movsx eax,ax
mov ebx,[dword ptr _ObjGrid]
mov ax,[word ptr ebx+eax]
or ax,ax
jz short no_obj
and ax,0FFh
mov [word ptr Color],ax
movsx ecx,[_FoundObjectCount] ;// Get number of current objects seen
mov ebx,ecx
jcxz short nofound ;// None found yet, add this new one
mov edi,offset _ObjectsSeen
repne scasb ;// See if this object already seen
jz short no_obj ;// Yes, ignore this ray then
nofound:
mov edi,offset _ObjectsSeen
mov [edi+ebx],al
inc bx
mov [word ptr _FoundObjectCount],bx
no_obj:
movsx eax,si
shl eax,1
mov ebx,[dword ptr _xGridGlobal]
mov cx,[ebx+eax]
or cx,cx
jz short next_square
test cx,WALL_UPPER_MULTI
jz short next_square
cmp cl,[byte ptr _LastWallHeight]
jbe short next_square
mov [word ptr _xMapPosn],si
mov ebx,[dword ptr _x_xPos]
mov [dword ptr _iLastX],ebx
mov edx,[dword ptr _x_yPos]
mov [dword ptr _LastY1],edx
movsx eax,cx
jmp short xRayDone
next_square:
mov eax,[dword ptr _x_xNext]
add [dword ptr _x_xPos],eax
mov eax,[dword ptr _x_yNext]
add [dword ptr _x_yPos],eax
jmp looptop
loopdone:
movsx eax,[word ptr retval]
xRayDone:
pop edx
pop ecx
pop ebx
pop edi
pop esi
mov esp,ebp
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC yRayCastMulti
push ebp
mov ebp,esp
sub esp,50
push esi
push edi
push ebx
push ecx
push edx
mov [word ptr retval],0
y_looptop:
mov edx,[dword ptr _y_xPos]
cmp edx,large 0
jl short y_getout
cmp edx,large 010000000h
jg short y_getout
mov eax,[_y_yPos]
cmp eax,large 0
jl short y_getout
cmp eax,large 4096
jle short y_inbounds
y_getout:
jmp loopdone
y_inbounds:
sar edx,22
and ax,-64
add ax,dx
mov si,ax
shl ax,1
movsx eax,ax
mov ebx,[dword ptr _ObjGrid]
mov ax,[ebx+eax]
or ax,ax
jz short y_no_obj
and ax,0FFh
mov [word ptr Color],ax
movsx ecx,[_FoundObjectCount]
mov ebx,ecx
jcxz short y_nofound
mov edi,offset _ObjectsSeen
repne scasb
jz short y_no_obj
y_nofound:
mov edi,offset _ObjectsSeen
mov [edi+ebx],al
inc bx
mov [word ptr _FoundObjectCount],bx
y_no_obj:
movsx eax,si
shl eax,1
mov ebx,[dword ptr _yGridGlobal]
mov cx,[ebx+eax]
or cx,cx
jz short y_next_square
y_wall_here:
test cx,WALL_UPPER_MULTI
jz short y_next_square
cmp cl,[byte ptr _LastWallHeight]
jbe short y_next_square
mov [word ptr _yMapPosn],si
mov ebx,[dword ptr _y_xPos]
mov [dword ptr _LastX1],ebx
mov edx,[dword ptr _y_yPos]
mov [dword ptr _iLastY],edx
mov edx,ebx
movsx eax,cx
jmp short yRayDone
y_next_square:
mov eax,[dword ptr _y_xNext]
add [dword ptr _y_xPos],eax
mov eax,[dword ptr _y_yNext]
add [dword ptr _y_yPos],eax
jmp y_looptop
y_loopdone:
movsx eax,[word ptr retval]
yRayDone:
pop edx
pop ecx
pop ebx
pop edi
pop esi
mov esp,ebp
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC CheckHitMap
mov edi,offset _HitMap
mov edx,edi
mov ecx,4096
mov esi,[dword ptr _ObjGrid]
chmLoop:
xor eax,eax
repe scasb
jcxz chmDone
mov ebx,edi ;get current location
sub ebx,edx ;minus start for actual offset
dec ebx ;minus base 0 offset
shl ebx,1 ;times 2 for word array
mov ax,[word ptr esi+ebx]
or al,al ;is there an object there?
jz chmLoop ;nope, keep checking
movzx ebx,[word ptr _FoundObjectCount]
mov [byte ptr _ObjectsSeen+ebx],al
inc ebx
mov [word ptr _FoundObjectCount],bx
jmp chmLoop
chmDone:
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC BuildUpView
push ebp ; Save registers used by this routine
push esi
push edi
push ebx
push ecx
push edx
ACKCALL CheckDoors ; Determine the state of the doors used in the view
mov edi,offset _HitMap ; Access the hit map
mov ecx,1024 ; Size of the hit map
xor eax,eax ; Clear each location
rep stosd ; Clear out entire hit map
; Check to see if moveable objects are found in the view. If so, access the object list
; and store the objects.
mov [word ptr _MaxDistance],0
movzx ecx,[word ptr _MoveObjectCount] ; Get # of moveable objects
mov [_FoundObjectCount],cx ; Store # of objects found in view
jcxz short buv010 ; No objects are used, jump ahead
mov edi,offset _ObjectsSeen ; Reference global object list
mov esi,offset _MoveObjectList ; List of movable objects
mov ebx,ecx ; # of moveable objects
sar ecx,2 ; Divide by 2
rep movsd
mov ecx,ebx ; # of moveable objects
and ecx,3
rep movsb ; Finish copying _ObjectSeen to
; _MoveObjectList
buv010:
movzx esi,[_gWinEndX] ; Get right side of viewport
cmp si,320 ; Is right coord. = 320?
jae short buv020
inc esi ; Adjust right viewport if not 320
buv020:
movzx eax,[_PlayerAngle] ; Get current players angle
sub eax,INT_ANGLE_32 ; Check with 32 degree point
jnc short buv030 ; Skip if in range
add eax,INT_ANGLE_360 ; Add 360 degrees to angle
buv030:
movzx ebx,[_gWinStartX] ; Get left side of viewport
mov [_ViewColumn],bx ; Save location in _ViewColumn
add eax,ebx ; Add angle to left side
cmp eax,INT_ANGLE_360 ; Are we out of range?
jl short buv040 ; Were ok!
sub eax,INT_ANGLE_360 ; Reduce angle by 360 degrees
buv040:
mov [_ViewAngle],ax ; Store updated angle
; The start of the main loop that builds individual slices for the view.
; This loop continues until the entire view has been built. Each time through
; the loop, the players viewing angle is increased. This continues until a full
; 64 degre range is casted (assuming a full width screen is used).
buv050:
movzx ebx,[_ViewColumn] ; Get left column position
mov [dword ptr _WallDistTable+ebx*4],4096 ; Max distance to walls
mov eax,offset _Slice ; Access base adress of Slice structure
imul ebx,saSize ; Calculate offset into actual slice
add eax,ebx ; Add offset to base address
mov [_sPtr],eax ; Set up pointer to actual column slice
movzx edi,[_ViewAngle] ; Use current viewing angle
ACKCALL xRaySetup ; Set up x ray to start casting
buv060:
ACKCALL yRaySetup ; Set up y ray to start casting
buv070:
mov [word ptr _LastWallHeight],0 ; For checking mult-height walls
ACKCALL BuildSlice ; Build the current slice
cmp [word ptr _gMultiWalls],0 ; Are multi-height walls used?
jz short buv080 ; Nope, no need to check
cmp [word ptr _LastWallHeight],200 ; No need to check if > 200
jg short buv080
mov eax,[_sPtr] ; Get base address of column slice
cmp [dword ptr eax+saNext],0 ; Check for any more walls
je short buv080
cmp [word ptr eax+saDist],96 ; Distance from POV to slice is
jle short buv080 ; less than or equal to 96
ACKCALL BuildSliceMulti ; Build the current slice for
; a multi-height wall
buv080:
movzx eax,[_ViewColumn] ; Get current column
inc eax ; Advance to the next column
inc edi ; Increment the casting angle
cmp [word ptr _Resolution],RES_LOW ; Check for screen resolution
jne short buv090
inc edi ; Increment angle and position
inc eax ; for higher resolution casting
buv090:
cmp edi,INT_ANGLE_360 ; Did we go past 360 degrees?
jl short buv100 ; Were ok
sub edi,INT_ANGLE_360 ; Adjust angle for building next slice
buv100:
mov [_ViewAngle],di ; Save current viewing angle
mov [_ViewColumn],ax ; Save column position
cmp eax,esi ; Are we done yet?
jl buv050 ; Nope; go build next slice
buv_exit:
ACKCALL CheckHitMap
ACKCALL FindObject ; Update slice structures with objects found
call [dword ptr _FloorCeilRtn] ; Build the floor and ceiling
ACKCALL DrawWalls ; Build the walls
pop edx ; Restore the registers used
pop ecx
pop ebx
pop edi
pop esi
pop ebp
ret
endp
end


412
ack_lib/ACKRTN4.ASM Normal file
View file

@ -0,0 +1,412 @@
IDEAL
JUMPS
P386
P387 ; Allow 386 processor
MASM
.MODEL FLAT ;32-bit OS/2 model
.DATA
SVTABLE dd ?
SAVEVID dd ?
SAVEROW dd ?
.CODE
IDEAL
include "ackrtn.inc"
extrn _BackDropRows:dword
extrn _PlayerAngle:word
extrn _BackArray:dword
extrn _Resolution:word
extrn _ScreenOffset:word
extrn _bmDistance:dword
extrn _bmWall:dword
extrn _scPtr:dword
extrn _VidTop:dword
extrn _VidBottom:dword
extrn _Floors1:dword
extrn _Floors2:dword
extrn _gPalTable:dword
extrn _gWinStartX:word
extrn _gWinStartY:word
extrn _gWinEndX:word
extrn _gWinEndY:word
extrn _gWinHeight:word
extrn _ViewHeight:word
extrn _SysFlags:word
extrn _Slice:byte
extrn _gScrnBuffer:dword
extrn _gCenterOff:word
extrn _gCenterRow:word
extrn _Floorscr:dword
extrn _gWinStartOffset:dword
extrn _scVid:dword
extrn _scWall:dword
extrn _scPal:dword
extrn _scdst:word
extrn _scwht:word
extrn _scmulti:word
extrn _sctopht:word
extrn _scbotht:word
extrn _scsavwht:word
extrn _scmulcnt:word
extrn _scsavVid:dword
extrn _scbNum:word
extrn _scMulData:dword
extrn _scColumn:dword
extrn _WallbMaps:dword
extrn _LowerTable:dword
extrn _gBottomOff:dword
extrn _LightFlag:word
ACKEXT ShowCol
ACKEXT ShowColMask
extrn _Resolution:word
extrn _Flooru:dword
extrn _Floorv:dword
extrn _Floordu:dword
extrn _Floordv:dword
extrn _Floorkx:dword
extrn _Floorky:dword
extrn _Floorku:dword
extrn _Floorkv:dword
extrn _Floorkdu:dword
extrn _Floorkdv:dword
extrn _Floorbm:dword
extrn _Floorscr:dword
extrn _Floors1:dword
extrn _Floors2:dword
extrn _FloorscrTop:dword
extrn _Floorptr2:dword
extrn _Floorwt:dword
extrn _Floorvht:word
extrn _Flooreht:word
extrn _FloorMap:word
extrn _gScrnBufferCenter:dword
extrn _gWinHalfHeight:word
extrn _zdTable:dword
extrn _CosTable:dword
extrn _SinTable:dword
extrn _xPglobal:dword
extrn _yPglobal:dword
extrn _WallDistTable:dword
extrn _CeilMap:word
extrn _AckTimerCounter:dword
ACKPUBS Mymemset
ACKPUBS AckSpeedUp
ACKPUBS AckSlowDown
ACKPUBS ShowColNS
ACKPUBS ShowColMaskNS
ACKPUBS DrawBackDrop
ACKPUBS AckTimerHandler
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckTimerHandler
inc cs:[dword ptr _AckTimerCounter]
iretd
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC Mymemset
push edi
push ebx
push ecx
push edx
mov edi,eax
mov dh,dl
mov ax,dx
shl eax,16
mov ax,dx
mov ecx,ebx
sar ecx,2
rep stosd
mov ecx,ebx
and ecx,3
rep stosb
pop edx
pop ecx
pop ebx
pop edi
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckSpeedUp
push ebx
push edx
mov bx,ax
mov ax,0FFFFH
xor dx,dx
idiv bx
mov bx,ax
mov dx,43h
mov al,36h
out dx,al
mov dx,40h
mov al,bl ; ffh = original value
out dx,al
mov dx,40h
mov al,bh ; 1fh = orignal value
out dx,al
pop edx
pop ebx
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckSlowDown
push edx
mov dx,43h
mov al,36h
out dx,al
mov dx,40h
mov al,0ffh
out dx,al
mov dx,40h
mov al,0ffh
out dx,al
pop edx
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC DrawBackDrop
push ebp
push esi
push edi
push ebx
push ecx
push edx
mov ax,[_PlayerAngle]
sub ax,INT_ANGLE_32
jnc ang_okay
add ax,INT_ANGLE_360
ang_okay:
mov cx,640
cwd
idiv cx ; Do mod 640 to get starting posn
; movsx ebx,dx
movzx ebx,dx
shl ebx,2 ; x 4 for memory pointers
mov edx,320
mov ebp,[_gScrnBuffer] ; get screen buffer
dbd010:
mov edi,ebp
mov esi,[dword ptr _BackArray+ebx] ;current image pointer
mov ecx,[_BackDropRows] ; rows to draw
dbd020:
; mov al,[esi]
; mov [edi],al
; inc esi
; lea edi,[edi+320]
movsb
lea edi,[edi+319]
dec ecx
jnz dbd020
inc ebp ;next screen column
lea ebx,[ebx+4]
cmp ebx,2560 ;see if 640x4 column yet
jb short dbd030 ;nope
mov ebx,0 ;else wrap to 0 column
dbd030:
dec edx ;see if done with all columns
jnz dbd010
pop edx
pop ecx
pop ebx
pop edi
pop esi
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC ShowColNS
push ebp
push esi
push edi
mov edi,[_scVid]
mov ebx,[_scWall]
mov ebp,[_bmDistance]
mov cx,[_gCenterRow]
mov edx,1FFFh
xor eax,eax
sns_top:
mov al,dh
sub edx,ebp
mov al,[ebx+eax]
mov [edi],al
jc short sns_bot
sub edi,320
dec cx
jns sns_top
xor ecx,ecx
sns_bot:
mov [SAVEVID],edi
mov [SAVEROW],ecx
mov edi,[_scVid]
mov cx,[_gCenterRow]
mov edx,2000h
sns_botloop:
mov al,dh
add edi,320
mov al,[ebx+eax]
add edx,ebp
mov [edi],al
cmp dh,64
jae short sns_exit
dec cx
jnz sns_botloop
sns_exit:
cmp [word ptr _scmulti],0
jz sns_alldone
mov esi,[SAVEROW]
or si,si
jz sns_alldone
mov ebx,[_scMulData] ;ptr to count and wall data
mov cl,[ebx] ;get number of walls to draw
inc ebx
mov al,[ebx] ;first wall to show
inc ebx
mov [_scMulData],ebx
movzx ebx,al ;get wall number
mov eax,[_WallbMaps] ;Get array of bitmaps
mov ebx,[eax+ebx*4] ;Get the bitmap we are using
mov eax,[_scColumn]
add ebx,eax
mov edi,[SAVEVID]
mov edx,3FFFh
mov ebp,[_bmDistance]
mov eax,0
sns_mulloop:
mov al,dh
sub edi,320
mov al,[ebx+eax]
dec si
mov [edi],al
jz short sns_alldone
sub edx,ebp
jnc sns_mulloop
sns_nextlevel:
dec cl ;Bump wall count
jz short sns_alldone ;br if no more walls
mov ebx,[_scMulData] ;Get pointer to the multi-ht data
movzx edx,[byte ptr ebx] ;next wall number
inc ebx ;Advance for next wall
mov [_scMulData],ebx
mov ebx,[_WallbMaps] ;Get wall array
mov ebx,[ebx+edx*4] ;Get wall bitmap to use
add ebx,[dword ptr _scColumn] ;add in current column
mov edx,3FFFh
jmp sns_mulloop
sns_alldone:
pop edi
pop esi
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC ShowColMaskNS
push ebp
push esi
push edi
mov edi,[_scVid]
mov ebx,[_scWall]
mov ebp,[_bmDistance]
mov cx,[_gCenterRow]
mov edx,1FFFh
xor eax,eax
smns_top:
mov al,dh
mov al,[ebx+eax]
or al,al
jz short smns_blank
mov [edi],al
smns_blank:
sub edx,ebp
jc short smns_bot
sub edi,320
dec cx
jnz smns_top
smns_bot:
mov edi,[_scVid]
mov cx,[_gCenterRow]
mov edx,2000h
smns_botloop:
add edi,320
mov al,dh
mov al,[ebx+eax]
or al,al
jz short smns_blank1
mov [edi],al
smns_blank1:
add edx,ebp
cmp dh,64
jae short smns_exit
dec cx
jnz smns_botloop
smns_exit:
pop edi
pop esi
pop ebp
ret
endp
end


552
ack_lib/ACKRTN5.ASM Normal file
View file

@ -0,0 +1,552 @@
IDEAL
JUMPS
P386
P387 ; Allow 386 processor
MASM
.MODEL FLAT ;32-bit OS/2 model
IDEAL
include "ackrtn.inc"
extrn _WallDistTable:dword
extrn _FloorMap:word
extrn _CeilMap:word
extrn _LastWallHeight:word
extrn _ViewAngle:word
extrn _ScreenOffset:word
extrn _xPglobal:dword
extrn _yPglobal:dword
extrn _xBegGlobal:dword
extrn _yBegGlobal:dword
extrn _aeGlobal:dword
extrn _xGridGlobal:dword
extrn _yGridGlobal:dword
extrn _xPglobalHI:dword
extrn _yPglobalHI:dword
extrn _rbaTable:dword
extrn _rsHandle:word
extrn _LastX1:dword
extrn _LastY1:dword
extrn _iLastX:dword
extrn _iLastY;dword
extrn _MaxDistance:word
extrn _BackArray:dword
extrn _zdTable:dword
extrn _ErrorCode:word
extrn _xMapPosn:dword
extrn _yMapPosn:dword
extrn _Grid:dword
extrn _ObjGrid:dword
extrn _WallbMaps:dword
extrn _ViewHeight:word
extrn _CeilingHeight:word
extrn _gTopColor:byte
extrn _gBottomColor:byte
extrn _PlayerAngle:word
extrn _gScrnBuffer:dword
extrn _gBkgdBuffer:dword
extrn _gCenterOff:word
extrn _gWinStartOffset:dword
extrn _gWinHeight:word
extrn _gWinEndY:dword
extrn _SysFlags:word
extrn _sPtr:dword
extrn _mxGridGlobal:dword
extrn _myGridGlobal:dword
extrn _xSecretmPos:word
extrn _xSecretmPos1:word
extrn _xSecretColumn:word
extrn _ySecretmPos:word
extrn _ySecretmPos1:word
extrn _ySecretColumn:word
extrn _TotalSecret:word
extrn _ViewColumn:word
extrn _SinTable:dword
extrn _CosTable:dword
extrn _LongTanTable:dword
extrn _LongInvTanTable:dword
extrn _InvCosTable:byte
extrn _InvSinTable:byte
extrn _LongCosTable:dword
extrn _ViewCosTable:dword
extrn _xNextTable:dword
extrn _yNextTable:dword
extrn _LastMapPosn:word
extrn _LastObjectHit:word
extrn _TotalObjects:word
extrn _FoundObjectCount:word
extrn _ObjectsSeen:byte
extrn _MoveObjectCount:word
extrn _MoveObjectList:byte
extrn _ObjNumber:byte
extrn _ObjRelDist:byte
extrn _ObjColumn:byte
extrn _x_xPos:dword
extrn _x_yPos:dword
extrn _x_xNext:dword
extrn _x_yNext:dword
extrn _y_xPos:dword
extrn _y_yPos:dword
extrn _y_xNext:dword
extrn _y_yNext:dword
extrn _Resolution:word
extrn _Flooru:dword
extrn _Floorv:dword
extrn _Floordu:dword
extrn _Floordv:dword
extrn _Floorkx:dword
extrn _Floorky:dword
extrn _Floorku:dword
extrn _Floorkv:dword
extrn _Floorkdu:dword
extrn _Floorkdv:dword
extrn _Floorbm:dword
extrn _Floorscr:dword
extrn _Floors1:dword
extrn _Floors2:dword
extrn _FloorscrTop:dword
extrn _Floorptr2:dword
extrn _Floorht:dword
extrn _Floorwt:dword
extrn _Floorvht:word
extrn _Flooreht:word
extrn _FloorLastbNum:dword
extrn _FloorLastbm:dword
extrn _bmDistance:dword
extrn _scwht:word
extrn _scWall:dword
extrn _scPal:dword
extrn _scVid:dword
extrn _scantables:dword
ACKEXT AckDrawFloor
ACKEXT AckDrawFloorOnly
ACKEXT AckDrawCeilingOnly
ACKEXT DrawBackDrop
ACKEXT AckDrawCeilingOnlyNS
ACKEXT AckDrawFloorOnlyNS
ACKPUBS AckDrawFloorNS
ACKPUBS DrawSolidCeilAndFloorNS
ACKPUBS DrawSolidCeilAndFloor
ACKPUBS DrawSolidFloorAndCeilNS
ACKPUBS DrawSolidFloorAndCeil
ACKPUBS DrawSolidCeilSolidFloor
ACKPUBS AckDoubleBuffer
MASM
.DATA
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Globals used by the AckDrawFloor routine
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
even
BCOL dd ?
HEIGHT dd ?
VA dd ?
SY dd ?
EY dd ?
BFSCRN dd ?
BCSCRN dd ?
FSCRN dd ?
CSCRN dd ?
CV dd ?
SV dd ?
BA dd ?
BA1 dd ?
ZDPTR dd ?
POS dd ?
BMPOS dd ?
MPOS dd ?
MPOSHI dd ?
SCANTBL dd ?
ROWNUM dd ?
LASTDIST dd ?
LASTEBP dd ?
LASTEAX dd ?
LASTEDX dd ?
WALLDIST dd ?
DSTPTR dd ?
COLNUM dd ?
.CODE
IDEAL
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckDrawFloorNS
push ebp
push esi
push edi
push ebx
push ecx
push edx
movzx eax,[word ptr _PlayerAngle]
mov ecx,eax
sub eax,INT_ANGLE_32
jnc short adf_20
add eax,INT_ANGLE_360
adf_20:
mov ebx,640
cdq
idiv ebx
mov [BCOL],edx
;;; mov eax,89
;;; sub ax,[word ptr _ViewHeight]
;;; mov [HEIGHT],eax
sub ecx,INT_ANGLE_32
jnc short adf_30
add ecx,INT_ANGLE_360
adf_30:
mov [VA],ecx
movzx eax,[word ptr _gWinHeight]
sar eax,1
movzx ebx,[word ptr _gWinEndY]
sub ebx,eax
inc ebx
sub ebx,5 ; 6
mov [EY],ebx
mov edi,[_gScrnBuffer]
movzx eax,[word ptr _gCenterOff]
mov ebx,eax
add eax,1920
add eax,edi
mov [BFSCRN],eax
sub ebx,1600 ;1920
add ebx,edi
mov [BCSCRN],ebx
mov eax,0
mov [DSTPTR],eax
mov ebx,[VA]
adf_loop:
;;; push ebp
even
mov [COLNUM],eax
mov eax,[dword ptr _WallDistTable+eax*4]
cmp eax,96
jb adf_ynext
mov [WALLDIST],eax
mov eax,[_CosTable]
shl ebx,2
mov eax,[eax+ebx]
mov [CV],eax
mov eax,[_SinTable]
mov eax,[eax+ebx]
mov [SV],eax
mov eax,[BCSCRN]
mov [CSCRN],eax
mov ecx,[EY]
mov ebx,[BCOL]
mov eax,[_BackArray+ebx*4]
add eax,ecx
mov [BA],eax
inc ebx
cmp ebx,640
jb short adf_l10
sub ebx,ebx
adf_l10:
mov eax,[_BackArray+ebx*4]
add eax,ecx
mov [BA1],eax
inc ebx
cmp ebx,640
jb short adf_l20
sub ebx,ebx
adf_l20:
mov [BCOL],ebx
lea esi,[offset _zdTable]
mov ecx,[EY] ;Number of rows to draw
mov [ROWNUM],ecx
;; imul eax,ebp,800
mov eax,[DSTPTR]
add esi,eax
add esi,24 ;ebx
add eax,1600
mov [DSTPTR],eax
mov edi,[BFSCRN]
mov ecx,[_WallbMaps]
adf_yloop:
mov edx,[esi]
cmp edx,[WALLDIST]
lea esi,[esi+4]
ja adf_ycont
adf_distokay:
cmp [LASTDIST],edx
jne short adf_newdist
mov ebp,[LASTEBP]
mov eax,[LASTEAX]
mov edx,[LASTEDX]
jmp short adf_samedist
adf_newdist:
mov [LASTDIST],edx
mov eax,[CV]
mov ebx,[SV]
imul eax,edx
imul ebx,edx
sar eax,16
sar ebx,16
mov edx,[_xPglobal]
add eax,edx
mov edx,[_yPglobal]
add ebx,edx
mov edx,ebx
and edx,0FC0h
mov ebp,eax
sar ebp,6
add ebp,edx ;Pos within floor and ceiling maps
and ebx,63
shl ebx,6
and eax,63
add eax,ebx ;bitmap position
shl ebp,1
movzx ebx,[word ptr _FloorMap+ebp]
mov [LASTEBP],ebp
mov [LASTEAX],eax
mov edx,[ecx+ebx*4]
add edx,eax
mov dl,[edx]
mov dh,dl
mov [LASTEDX],edx
adf_samedist:
mov [edi],dx
movzx ebx,[word ptr _CeilMap+ebp]
mov ebp,[CSCRN]
test bx,bx
jz short adf_yback
mov edx,[ecx+ebx*4]
dec [dword ptr BA]
add edx,eax
mov al,[edx]
mov ah,al
lea edi,[edi+320]
dec [dword ptr BA1]
mov [ebp],ax
add ebp,-320
mov [CSCRN],ebp
dec [dword ptr ROWNUM]
jnz adf_yloop
jmp short adf_ynext
adf_yback:
mov eax,[BA]
mov dl,[eax]
mov eax,[BA1]
mov dh,[eax]
mov [ebp],dx
adf_ycont:
lea edi,[edi+320]
add [dword ptr CSCRN],-320
dec [dword ptr BA]
dec [dword ptr BA1]
dec [dword ptr ROWNUM]
jnz adf_yloop
adf_ynext:
mov ebx,[VA]
lea ebx,[ebx+2]
cmp ebx,INT_ANGLE_360
jb short adf_l90
sub ebx,INT_ANGLE_360
adf_l90:
mov [VA],ebx ;Note: EBX is used for VA at top of loop!
add [dword ptr BFSCRN],2
add [dword ptr BCSCRN],2
;;; pop ebp
;;; lea ebp,[ebp+2]
;;; cmp ebp,320
;;; jb adf_loop
mov eax,[COLNUM]
add eax,2
cmp eax,320
jb adf_loop
adf_exit:
pop edx
pop ecx
pop ebx
pop edi
pop esi
pop ebp
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC DrawSolidCeilAndFloor
mov edi,[_gScrnBuffer]
movzx ecx,[word ptr _gCenterOff]
mov al,[byte ptr _gTopColor]
mov ah,al
shr cx,1
rep stosw
rcl cx,1
rep stosb
ACKCALL AckDrawFloorOnly
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC DrawSolidCeilAndFloorNS
mov edi,[_gScrnBuffer]
movzx ecx,[word ptr _gCenterOff]
mov al,[byte ptr _gTopColor]
mov ah,al
shr cx,1
rep stosw
rcl cx,1
rep stosb
ACKCALL AckDrawFloorOnlyNS
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC DrawSolidFloorAndCeilNS
mov edi,[_gScrnBuffer]
movzx ecx,[word ptr _gCenterOff]
add edi,ecx
mov al,[byte ptr _gBottomColor]
mov ah,al
shr cx,1
rep stosw
rcl cx,1
rep stosb
ACKCALL AckDrawCeilingOnlyNS
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC DrawSolidFloorAndCeil
mov edi,[_gScrnBuffer]
movzx ecx,[word ptr _gCenterOff]
add edi,ecx
mov al,[byte ptr _gBottomColor]
mov ah,al
shr cx,1
rep stosw
rcl cx,1
rep stosb
ACKCALL AckDrawCeilingOnly
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC DrawSolidCeilSolidFloor
mov edi,[_gScrnBuffer]
movzx ecx,[word ptr _gCenterOff]
mov al,[byte ptr _gTopColor]
mov ah,al
shr cx,1
rep stosw
rcl cx,1
rep stosb
mov edi,[_gScrnBuffer]
movzx ecx,[word ptr _gCenterOff]
add edi,ecx
mov al,[byte ptr _gBottomColor]
mov ah,al
shr cx,1
rep stosw
rcl cx,1
rep stosb
ret
endp
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ACKPROC AckDoubleBuffer
push ebp
mov ebp,esp
push esi
push edi
mov esi,[ebp+8] ;Source buffer
mov edi,[ebp+12] ;Destination buffer
mov ecx,200 ;Rows to double
adb010:
mov edx,160 ;Cols to double
mov ebx,edi ;Hold onto start of row
adb020:
lodsw
stosb
stosb
mov al,ah ;Make word
stosw ;Store in dest
dec edx ;Bump column count
jnz adb020
sub esi,4
mov eax,esi ;Hold onto source
mov esi,ebx ;Point at start of row
mov edx,ecx ;hold onto row count
mov ecx,160 ;Number of dwords
rep movsd ;duplicate the row
mov esi,eax ;get back the source
mov ecx,edx ;get row count back
dec ecx
jnz adb010 ;loop for all rows
pop edi
pop esi
pop ebp
ret
endp
end


348
ack_lib/ACKSND.C Normal file
View file

@ -0,0 +1,348 @@
/******************* ( Animation Construction Kit 3D ) ***********************/
/* Sound Routines: play CMF, VOC files in background on SB, Adlib or speaker */
/* CopyRight (c) 1993 Authors: Lary Myers & Frank Sachse */
/*****************************************************************************/
//***************************** WARNING **************************************
// NOTE: The Worx sound functions have NOT been converted to flat model.
// **** DO NOT USE THESE FUNCTIONS!!!! ****
//***************************** WARNING **************************************
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
#include "acksnd.h"
#include "worx.h"
static short SoundDevice;
void AckPlayNoSound(short index);
void AckPlayPCSpeaker(short index);
void AckPlayAdlib(short index);
void AckPlaySoundBlaster(short index);
short AckPlayMusic(char *MusicFile);
short IRQ; /* SB */
char *Cmf;
char *VocTable[SOUND_MAX_INDEX+1];
/****************************************************************************
** Call into here by the application before using any of the sound routines**
** The default sound device can be used as an overide, such as when the **
** application or user doesn't want any sound. **
****************************************************************************/
short AckSoundInitialize(short DefaultSoundDevice)
{
if (DefaultSoundDevice == DEV_NOSOUND)
{
SoundDevice = DefaultSoundDevice;
return(0);
}
/* Checks for sound board & sets SoundDevice to DEV_ define in ACKSND.H */
/* for use only with WORX lib, not WORXlite...
StartWorx();
*/
StartWorx();
if (DefaultSoundDevice == DEV_PCSPEAKER)
{
SoundDevice = DefaultSoundDevice;
return(0);
}
if (AdlibDetect())
{
SoundDevice = DEV_ADLIB;
SetFMVolume(0xf,0xf);
}
else
SoundDevice = DEV_PCSPEAKER;
if (DefaultSoundDevice == DEV_ADLIB)
{
SoundDevice = DEV_ADLIB;
return(0);
}
IRQ = DSPReset();
if (IRQ > 0)
{
SoundDevice = DEV_SOUNDBLASTER;
SetMasterVolume(0xf,0xf);
SetVOCVolume(0xf,0xf);
}
#if 0
/* for use only with WORX lib, not WORXlite...
IRQ = DSPReset() - if > 0, then SB present
if (WorxPresent()) /* use only with WORXlite */
{
SoundDevice = DEV_SOUNDBLASTER;
SetMasterVolume(0xf,0xf);
SetVOCVolume(0xf,0xf);
}
*/
#endif
return(0);
}
/****************************************************************************
** Here the application can call in and load the VOC files that it needs **
** **
****************************************************************************/
short AckLoadSound(short VocIndex,char *VocFile)
{
char buf[81];
if (SoundDevice == DEV_NOSOUND)
return(0);
if (VocIndex < 0 || VocIndex > SOUND_MAX_INDEX)
return(-1); /* index out of range */
strcpy(buf,VocFile);
strtok(buf,".");
switch (SoundDevice)
{
case DEV_SOUNDBLASTER:
strcat(buf,".VOC"); /* force extension */
break;
case DEV_ADLIB: /* adlib can't play voc's -> put thru pc spkr */
case DEV_PCSPEAKER:
#if 0
strcat(buf,".PWM"); /* force extension */
#endif
strcat(buf,".VOC"); /* force extension */
break;
default:
return(-2); /* Error if unknown device */
}
VocTable[VocIndex] = LoadOneShot(buf); /* load voc/pwm into mem */
if (VocTable[VocIndex] == NULL)
return(-2); /* file not found */
return(0);
}
/****************************************************************************
** **
****************************************************************************/
void AckStopBackground(void)
{
switch (SoundDevice)
{
case DEV_NOSOUND:
break;
case DEV_PCSPEAKER:
break;
case DEV_SOUNDBLASTER:
if (SequencePlaying())
StopSequence();
break;
case DEV_ADLIB:
if (SequencePlaying())
StopSequence();
break;
default:
break;
}
}
/****************************************************************************
** The Application would call this routine to begin playing background **
** music. **
** **
****************************************************************************/
short AckPlayBackground(char *MusicFile)
{
short result = 0;
switch (SoundDevice)
{
case DEV_NOSOUND:
break;
case DEV_PCSPEAKER:
break;
case DEV_SOUNDBLASTER:
result = AckPlayMusic(MusicFile);
break;
case DEV_ADLIB:
result = AckPlayMusic(MusicFile);
break;
default:
break;
}
return(result);
}
/****************************************************************************
** Start the music file playing in this routine. **
** **
****************************************************************************/
short AckPlayMusic(char *MusicFile)
{
char *BufPtr;
char buf[81];
strcpy(buf,MusicFile);
strtok(buf,"."); /* force CMF extention */
strcat(buf,".CMF");
Cmf = GetSequence(buf); /* load cmf into mem */
if(Cmf==NULL)
return(1);
SetLoopMode(1); /* set for continuous play */
PlayCMFBlock(Cmf); /* play background cmf */
return(0);
}
/****************************************************************************
** Call into here to play a particular sound. The indexes available are **
** listed in ACKSND.H which will be included by the application. **
** **
****************************************************************************/
void AckPlaySound(short SoundIndex)
{
switch (SoundDevice)
{
case DEV_NOSOUND:
break;
case DEV_PCSPEAKER:
AckPlayPCSpeaker(SoundIndex);
break;
case DEV_SOUNDBLASTER:
AckPlaySoundBlaster(SoundIndex);
break;
case DEV_ADLIB: /* can't play VOC's on Adlib -> play thru speaker */
AckPlayPCSpeaker(SoundIndex);
break;
default:
break;
}
}
/****************************************************************************
** This routine is used for simple speaker sounds. The ones here are for **
** testing at this point. Better ones would be need to be in the final **
** version. **
****************************************************************************/
/* I will adjust this later to play VOC's thru speaker x*/
void AckPlayPCSpeaker(short index)
{
if (VocTable[index] == NULL || index < 0 || index > SOUND_MAX_INDEX)
return;
PlayPWMBlock(VocTable[index]);
}
/****************************************************************************
** Sound Blaster routines go here. **
** **
** **
****************************************************************************/
void AckPlaySoundBlaster(short index)
{
if (VocTable[index] == NULL || index < 0 || index > SOUND_MAX_INDEX)
return;
PlayVOCBlock(VocTable[index],255);
}
/****************************************************************************
** Call into here by the application before exiting. **
****************************************************************************/
void AckSoundShutdown(void)
{
switch (SoundDevice)
{
case DEV_NOSOUND:
break;
case DEV_PCSPEAKER:
CloseWorx();
break;
case DEV_SOUNDBLASTER:
if (SequencePlaying())
StopSequence(); /* stop background CMF, if playing */
DSPClose(); /* free Sound Blaster DSP */
/* for use only with WORX lib, not WORXlite...
CloseWorx();
*/
CloseWorx();
break;
case DEV_ADLIB:
if (SequencePlaying())
StopSequence();
/* for use only with WORX lib, not WORXlite...
CloseWorx();
*/
break;
default:
break;
}
}


35
ack_lib/ACKSND.H Normal file
View file

@ -0,0 +1,35 @@
/* Header file to accompany ACKSND.C */
#define DEV_NOSOUND 0
#define DEV_PCSPEAKER 1
#define DEV_SOUNDBLASTER 2
#define DEV_ADLIB 3
#define SOUND_WALKING 0
#define SOUND_HITWALL 1
#define SOUND_HITOBJECT 2
#define SOUND_HITBADOBJECT 3
#define SOUND_DOOROPENING 4
#define SOUND_SECRETDOOROPENING 5
#define SOUND_FIRING 6
#define SOUND_DOORCLOSING 7
#define SOUND_LOST 8
#define SOUND_WON 9
#define SOUND_INTRO 10
#define SOUND_EXPLODE 11
#define SOUND_USER1 12
#define SOUND_USER2 13
#define SOUND_USER3 14
#define SOUND_USER4 15
#define SOUND_MAX_INDEX 15
short AckSoundInitialize(short DefaultSoundDevice);
short AckPlayBackground(char *MusicFile);
void AckPlaySound(short SoundIndex);
void AckSoundShutdown(void);
void AckStopBackground(void);
short AckLoadSound(short VocIndex,char *VocFileName);


296
ack_lib/ACKUTIL.C Normal file
View file

@ -0,0 +1,296 @@
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
typedef struct {
int sel;
int off;
} SELOFF;
void AckGetIntVector(int VecNum,int *sel,int *off);
void AckSetIntVector(int VecNum,int sel,void *VecOff);
void AckKbdInt(void);
void AckTimerHandler(void);
void AckSetTextMode(void);
long AckMemUsed;
short AckDisplayErrors;
SELOFF OldKeybdInt;
char AckKeyboardSetup;
SELOFF OldTimerInt;
char AckTimerSetup;
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Establish a hook into interrupt 9 for keyboard handling
// The application can access which key is pressed by looking at the
// AckKeys global array
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
#ifndef _MSC_VER
void AckSetupKeyboard(void)
{
AckGetIntVector(9,&OldKeybdInt.sel,&OldKeybdInt.off);
AckSetIntVector(9,_CS,AckKbdInt);
AckKeyboardSetup = 1;
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Establish a hook into the user timer interrupt
// The application can access a counter by looking at the AckTimerCounter
// global variable.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
void AckSetupTimer(void)
{
AckGetIntVector(0x1C,&OldTimerInt.sel,&OldTimerInt.off);
AckSetIntVector(0x1C,_CS,AckKbdInt);
AckTimerSetup = 1;
}
#endif
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Utility routine used to track memory usage by the ACK engine and
// applications.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
void *AckMalloc(size_t mSize)
{
UCHAR *mBlock;
mSize += sizeof(long);
mSize++;
mBlock = malloc(mSize);
if (mBlock == NULL)
{
if (AckDisplayErrors)
{
AckSetTextMode();
printf("\n\nOut of memory on call to AckMalloc.\n");
printf("Memory used: %ld bytes.\n",AckMemUsed);
}
return(mBlock);
}
(*(UCHAR *)mBlock) = 0xF2;
mBlock += 1;
(*(long *)mBlock) = mSize;
mBlock += sizeof(long);
AckMemUsed += mSize;
return(mBlock);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Matching routine for AckMalloc(). This routine MUST be used to free
// memory if AckMalloc() is used to allocate memory.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
void AckFree(void *m)
{
UCHAR *mBlock;
long mSize;
mBlock = (UCHAR *)m;
mBlock -= sizeof(long);
mBlock -= 1;
if ((*(UCHAR *)mBlock) != 0xF2)
{
if (AckDisplayErrors)
{
AckSetTextMode();
printf("\n\nCorrupt memory block in AckFree.\n");
printf("Mem ptr: %p",mBlock);
return;
}
}
mBlock += 1;
mSize = (*(long *)mBlock);
mBlock -= 1;
AckMemUsed -= mSize;
free(mBlock);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Read a palette from a file and immediately set it into the VGA regs.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckLoadAndSetPalette(char *PalName)
{
short handle,ErrCode;
char *buf;
buf = AckMalloc(800);
if (buf == NULL)
return(ERR_NOMEMORY);
ErrCode = 0;
if (!rsHandle)
handle = _lopen(PalName,O_RDWR|O_BINARY);
else
{
handle = rsHandle;
_llseek(handle,rbaTable[(ULONG)PalName],SEEK_SET);
}
if (handle > 0)
{
read(handle,buf,768);
if (!rsHandle)
_lclose(handle);
memset(buf,0,3); // Make sure color 0 is always black
AckSetPalette(buf);
}
else
ErrCode = ERR_BADFILE;
AckFree(buf);
return(ErrCode);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Set up the palette range for light shading. The incoming ranges are in
// a 16 by 256 array where there are 16 different distance levels each
// having a full color tranlation table for light shading.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
void AckSetupPalRanges(ACKENG *ae,ColorRange *ranges)
{
short i,j,k,found;
short rangenos;
UCHAR plotcolor;
if (ae->LightFlag == SHADING_OFF)
{
for ( i = 0;i<16;i++)
{
for (j=0;j<256;j++)
{
ae->PalTable[j+(i*256)] = j;
}
}
return;
}
for (rangenos = 0; rangenos < 64; rangenos++)
{
if (ranges[rangenos].start == 0)
break;
}
for ( i = 0;i<16;i++)
{
for (j=0;j<256;j++)
{
found = 0;
// find the range the color is in.
for ( k = 0; k < rangenos; k++ )
{
if (j >= ranges[k].start && j < ranges[k].start+ranges[k].length)
{
found = 1;
break;
}
}
if (found)
{
//=============================================================================
// add color + i;
// if color + i > color+range then plot color = 0;
// otherwise plotcolor = color+i
//=============================================================================
if (j+i >= ranges[k].start+ranges[k].length)
plotcolor = 0;
else
plotcolor = j+i;
}
else
{
plotcolor = j;
}
ae->PalTable[j+(i*256)] = plotcolor;
}
}
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Returns the index of the last object hit by the POV.
// The variable LastObjectHit can also be accessed globally.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckGetObjectHit(void)
{
return(LastObjectHit);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Returns the map location of the last wall hit. LastMapPosn is a global
// variable.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckGetWallHit(void)
{
return(LastMapPosn);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Sets the object to inactive. The memory used by the object is NOT
// freed by this routine.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckDeleteObject(ACKENG *ae,short ObjIndex)
{
if (ae->ObjList[ObjIndex] == NULL)
return(-1);
if (!ae->ObjList[ObjIndex]->Active)
return(-1);
ae->ObjList[ObjIndex]->Active = 0;
return(0);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Sets a new wall or object index into the map array specified.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckSetNewBitmap(short index,UCHAR **Maps,UCHAR *NewBitmap)
{
UCHAR *bPtr;
bPtr = Maps[index];
Maps[index] = NewBitmap;
if (bPtr != NULL)
AckFree(bPtr);
return(0);
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Obsolete routine for real mode. Flat model memory can be freed by the
// application. Real mode required XMS memory to be handled. This routine
// is maintained for backward compatability with the older versions.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckFreeBitmap(UCHAR *bmType)
{
short i;
UCHAR *Bmp;
if (bmType != NULL)
AckFree(bmType);
return(0);
}
// **** End of Source ****


851
ack_lib/ACKVIEW.C Normal file
View file

@ -0,0 +1,851 @@
// This file contains the declarations and functions to set up views for the
// ray casting engine.
#include <windows.h> // Required for Windows version of engine
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include <limits.h>
#include "ack3d.h" // Main ACK-3D internal and interface data structures
#include "ackeng.h" // Intrnal structures and constants
#include "ackext.h" // Defines external (global) variables
extern long FloorCosTable[];
void (*FloorCeilRtn)(void);
void (*WallRtn)(void);
void (*WallMaskRtn)(void);
short gWinFullWidth; // Global variables for setting up a viewport
long gWinDWORDS; // These are the global variables used by the
long gWinStartOffset; // low-level assembly language routines to draw slices
short gWinStartX;
short gWinStartY;
short gWinEndX;
short gWinEndY;
short gWinHeight;
short gWinHalfHeight;
short gWinWidth;
short gCenterRow;
short gCenterOff;
long gBottomOff;
UCHAR *gScrnBufferCenter;
UCHAR *gScrnBuffer;
UCHAR *gBkgdBuffer;
UCHAR *gPalTable;
short gMultiWalls;
UCHAR **mxGridGlobal; // Global variables to reference the x and y
UCHAR **myGridGlobal; // map arrays
UCHAR gTopColor;
UCHAR gBottomColor;
UCHAR *scVid; // Variables used in low level routines for
UCHAR *scWall; // building and drawing slices
UCHAR *scPal;
short scdst;
short scwht;
short scmulti;
short sctopht;
short scbotht;
short scsavwht;
short scmulcnt;
UCHAR *scsavVid;
USHORT scbNum;
UCHAR *scMulData;
UCHAR *scColumn;
UCHAR *gPtr;
UCHAR *gmPtr;
short gBitmapNumber;
short gBitmapColumn;
short gyBitmapNumber;
short gyBitmapColumn;
long gWallDistance;
short gmPos;
DOORS *gDoor;
DOORS *gDoorPosn;
short wFound;
UCHAR *mgPtr;
short BegX,EndX;
extern long x_xPos; // Variables for tracking coordinates during
extern long x_yPos; // the ray casting process
extern long x_xNext;
extern long x_yNext;
extern long y_xPos;
extern long y_yPos;
extern long y_xNext;
extern long y_yNext;
short LastVht;
long WallDistTable[VIEW_WIDTH];
// Functions used to build views and perform the ray casting process
void AckSetupWindow(ACKENG *ae); // Sets up variables for viewport
void BuildUpView(void); // Main assemply language routine for building views
void BuildSlice(void); // Assembly language routines for building slices
void BuildSliceMulti(void); // Assembly language routine for building multi-slices
void CheckDoors(void); // Internal routines for locating and checking doors
void FindObject(void); // and objects
short FindDoor(short MapPosn);
void FloorLoop(void);
void CeilLoop(void);
void DrawSlices(void);
short BlankSlice(USHORT col,UCHAR *bmp);
void BuildSliceAsm(void);
void xRaySetup(void); // Routines for setting up and casting rays
USHORT xRayCast(void);
void yRaySetup(void);
USHORT yRayCast(void);
USHORT xRayCastMulti(void);
USHORT yRayCastMulti(void);
void ShowCol(void); // Routines for drawing a slice
void ShowColMask(void); // column by column
void ShowColNS(void);
void ShowColMaskNS(void);
void ShowColLow(void);
void ShowColMaskLow(void);
void DrawFloorCeiling(void); // Routines for drawing floors and ceilings
void AckDrawFloor(void);
void AckDrawFloorOnly(void);
void AckDrawCeilingOnly(void);
void AckDrawFloorNS(void);
void AckDrawFloorOnlyNS(void);
void AckDrawCeilingOnlyNS(void);
void AckDrawFloorHz(void);
void AckDrawOneFloor(void);
void DrawSolidCeilAndFloor(void);
void DrawSolidCeilAndFloorNS(void);
void DrawSolidFloorAndCeil(void);
void DrawSolidFloorAndCeilNS(void);
void DrawSolidCeilSolidFloor(void);
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Transfers certain variables from the interface structure to global
// variables that can be accessed faster by the drawing functions. The
// interface structure is kept by the application and more than one of
// them can be used for different views. Each time a new view needs to
// be processed, this function MUST be called before calling the
// drawing routines.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
void AckRegisterStructure(ACKENG *ae)
{
int mode,i;
aeGlobal = ae; // Global variable to reference ACKENG structure
AckSetupWindow(ae); // Assign window variables to ACKENG structure
xGridGlobal = ae->xGrid; // Global map for x walls
yGridGlobal = ae->yGrid; // Global map for y walls
mxGridGlobal = ae->mxGrid; // Wall data for multi-height walls
myGridGlobal = ae->myGrid;
WallbMaps = ae->bMaps; // Wall bitmap data
gWinStartX = ae->WinStartX; // Coordinates of viewport; upper-left
gWinStartY = ae->WinStartY;
gWinEndX = ae->WinEndX; // Lower-right viewport coordinates
gWinEndY = ae->WinEndY;
gWinHeight = ae->WinHeight; // Height of viewport
gWinWidth = ae->WinWidth; // Width of viewport
gWinHalfHeight = (gWinEndY - (gWinHeight >> 1)) + 1;
gCenterRow = ae->CenterRow; // Start of center row in viewport
gCenterOff = ae->CenterOffset; // Offset to center of viewport
gScrnBuffer = ae->ScreenBuffer; // Screen buffer access
gScrnBufferCenter = gScrnBuffer + gCenterOff;
gBkgdBuffer = ae->BkgdBuffer; // Buffer for ceiling and floors
gPalTable = ae->PalTable; // Palette of colors used
gDoor = &ae->Door[0]; // List of moving doors
gTopColor = ae->TopColor; // Base color of ceiling
gBottomColor = ae->BottomColor; // Base color of floor
LightFlag = ae->LightFlag; // Light shading on or off indicator
SysFlags = ae->SysFlags; // Scene display attributes (floors and ceilings)
mode = 0; // Draw both textured floor and ceiling
if (SysFlags & SYS_SOLID_CEIL) // Soild ceiling is selcted
{
mode = 1; // Draw floor only (ceiling will be solid)
if (SysFlags & SYS_SOLID_FLOOR) // Solid floor is selcted
mode = 2; // Draw solid floor and ceiling
}
if (SysFlags & SYS_SOLID_FLOOR) // Solid floor is selected
{
if (!mode)
mode = 3; // Draw Ceiling only (floor will be solid)
}
if (!LightFlag) // No light shading used
{
WallRtn = ShowColNS; // Assembly routines for drawing slices
WallMaskRtn = ShowColMaskNS; // using light shading
switch (mode) // Check floor and ceiling type
{
case 0: // Draw both solid floor and ceiling
if (ae->SysFlags & SYS_SINGLE_BMP)
FloorCeilRtn = AckDrawOneFloor; // Use the same bitmap for each
else
FloorCeilRtn = AckDrawFloorHz;
break;
case 1: // Draw solid ceiling and texture floor
FloorCeilRtn = DrawSolidCeilAndFloorNS;
break;
case 2: // Draw both solid floor and solid ceiling
FloorCeilRtn = DrawSolidCeilSolidFloor;
break;
case 3: // Draw solid floor and texture ceiling
FloorCeilRtn = DrawSolidFloorAndCeilNS;
break;
default:
break;
}
}
else // Light shading is used
{
WallRtn = ShowCol; // Assembly routines for drawing slices
WallMaskRtn = ShowColMask; // using light shading
switch (mode)
{
case 0: // Draw both floor and ceiling
FloorCeilRtn = AckDrawFloor;
break;
case 1: // Draw solid ceiling and texture floor
FloorCeilRtn = DrawSolidCeilAndFloor;
break;
case 2: // Draw both solid floor and solid ceiling
FloorCeilRtn = DrawSolidCeilSolidFloor;
break;
case 3: // Draw solid floor and texture ceiling
FloorCeilRtn = DrawSolidFloorAndCeil;
break;
default:
break;
}
}
// Test to see if viewport is full width (320 units)
gWinStartOffset = ae->WinStartOffset; // Offset to viewport
gBottomOff = (gWinEndY * 320);
gWinFullWidth = 0; // Set flag to indicate viewport is not full width
if (gWinStartX == 0 && gWinEndX == 319) // Viewport is full size
{
gWinFullWidth = 1; // Indicates viewport is full size
gWinDWORDS = (gWinEndY - gWinStartY) * 80; // Calculate number of double
} // words to access buffer
// Test to see if multi-height walls are used
gMultiWalls = 0;
for (i = 0; i < GRID_MAX; i++)
{
if ((xGridGlobal[i] & WALL_TYPE_MULTI) || (yGridGlobal[i] & WALL_TYPE_MULTI))
{
gMultiWalls = 1; // Indicates multi-height walls are used
break;
}
}
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Render the current scene into the off-screen buffer based on the POV
// coordinates and angle. This function does NOT display the scene once
// it is rendered so the application can overlay graphics into the buffer
// before it is actually displayed.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
void AckBuildView(void)
{
// Set up global variables to be used with assembly language routines
xPglobal = aeGlobal->xPlayer; // The player's x coordinate
xBegGlobal = xPglobal & GRID_MASK; // Upper left corner (x) of the grid
// square the player is in
xPglobalHI = ((long)xPglobal << FP_SHIFT); // Convert x coordinate to fixed point
yPglobal = aeGlobal->yPlayer; // The player's y coordinate
yBegGlobal = yPglobal & GRID_MASK; // Upper left corner (y) of grid square
yPglobalHI = ((long)yPglobal << FP_SHIFT); // Convert y coordinate to fixed point
PlayerAngle = aeGlobal->PlayerAngle; // The player's angle
SysFlags = aeGlobal->SysFlags; // Ceiling and floor attributes;
BuildUpView(); // Assembly routine defined in ACKRTN3.ASM. This routine
// kicks off the ray casting process.
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Stub function for drawing slices that do not contain walls.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
void ShowNone(void)
{
return;
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Internal function to cast the x and y rays and build a slice structure
// for each column of the viewing window.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
void BuildSlice(void)
{
short j,index,wFound;
long xBitmap,yBitmap,BitmapNumber;
short DoorOpenColumn;
ULONG xDistance,yDistance;
ULONG xd,yd,mf;
long WallDistance,UnAdjustDist;
long distance,LightAdj;
USHORT BitmapColumn,yBitmapColumn;
long OldMapPosn,OldMapPosn1;
long HoldAngle;
long offset;
long mPos;
USHORT *gPtr;
UCHAR *mgPtr;
SLICE *spNext;
WallDistance = 3000000; // Set to a ridiculous distance
sPtr->Distance = 200; // Initialize the distance from the POV to the slice
wFound = 0; // Wall not found yet
sPtr->Fnc = ShowNone; // Use the stub function for now for drawing the slice
// Call the low level ray casting function and see if anything is hit.
if ((BitmapNumber = xRayCast()) != 0) // Something has been hit while casting
{ // in the x plane
wFound = 1; // Set flag to indicate a hit
// Use the y intercept to determine the column of the slice
BitmapColumn = (LastY1 >> FP_SHIFT) & (BITMAP_WIDTH-1);
// Keep the orientation the same no matter which side we're on
if ((short)iLastX < xPglobal)
BitmapColumn = (BITMAP_WIDTH-1) - BitmapColumn;
// Did we strike a door?
if ((BitmapNumber & (DOOR_TYPE_SLIDE+DOOR_TYPE_SPLIT)))
{
index = FindDoor(xMapPosn); // Locate the position of the door
if (index >= 0) // Is this is a valid door?
{
j = aeGlobal->Door[index].ColOffset; // Get the door's current pos
offset = 0;
if (BitmapNumber & DOOR_TYPE_SLIDE) // Is the door a slider?
{
DoorOpenColumn = BITMAP_WIDTH-1;
if ((short)iLastX > xPglobal) // Handle orientation
j = -j;
BitmapColumn += j; // Adjust column to show
}
if (BitmapNumber & DOOR_TYPE_SPLIT) // Is the door a split door?
{
DoorOpenColumn = (BITMAP_WIDTH/2)-1;
if (BitmapColumn < (BITMAP_WIDTH/2))
{
BitmapColumn += j;
if (BitmapColumn > (BITMAP_WIDTH/2)-1)
offset = 1;
}
else
{
BitmapColumn -= j;
if (BitmapColumn < (BITMAP_WIDTH/2))
offset = 1;
}
} // End processing split door
if (offset == 1 || BitmapColumn > (BITMAP_WIDTH-1))
{
// Get the grid coordinates for this door
OldMapPosn = aeGlobal->Door[index].mPos;
OldMapPosn1 = aeGlobal->Door[index].mPos1;
// Fake the engine into thinking no door is there
xGridGlobal[OldMapPosn] = 0;
xGridGlobal[OldMapPosn1] = 0;
// Cast the ray to get walls beyond the door
BitmapNumber = xRayCast();
// Put back the door codes if not fully open
if (aeGlobal->Door[index].ColOffset < DoorOpenColumn)
{
xGridGlobal[OldMapPosn] = aeGlobal->Door[index].mCode;
xGridGlobal[OldMapPosn1] = aeGlobal->Door[index].mCode1;
}
// Calc the new bitmap column of wall behind door
BitmapColumn = (LastY1 >> FP_SHIFT) & (BITMAP_WIDTH-1);
if ((short)iLastX < xPglobal)
BitmapColumn = (BITMAP_WIDTH-1) - BitmapColumn;
}
}
} // End processing doors
//==============================================================
// Calculate the distance to the wall. Since the x position was
// fixed to move 64 or -64 we can use it to determine the actual
// wall distance. The InvCosTable values were stored with a fixed
// point of 20 decimal places. At this time we'll knock off 14 of
// them so we can later multiply with a fixed point value of 16
//==============================================================
xd = iLastX - xPglobal; // x Distance to the found slice
mf = InvCosTable[ViewAngle]; // Get the cosine of the angle
WallDistance = (xd * mf) >> 10; // Calculate the actual distance to the slice
if (WallDistance > 33554432L) // Check for out of range
WallDistance = 1200000L;
gPtr = xGridGlobal; // Point to xGrid map
mgPtr = mxGridGlobal[xMapPosn]; // Point to grid map for multi-height walls
mPos = xMapPosn; // Access actual map position
} // End (if BitmapNumber = xRayCast() ...)
// Time to cast the ray in the y plane
if ((yBitmap = yRayCast()) != 0) // Something has been hit while casting
{
// Use the X intercept to determine the column of the bitmap
yBitmapColumn = (LastX1 >> FP_SHIFT) & (BITMAP_WIDTH-1);
// Handle orientation from either side of the wall
if ((short)iLastY > yPglobal)
yBitmapColumn = (BITMAP_WIDTH-1) - yBitmapColumn;
// Did we strike a door?
if ((yBitmap & (DOOR_TYPE_SLIDE+DOOR_TYPE_SPLIT)))
{
index = FindDoor(yMapPosn);
if (index >= 0) // Is this is a valid door?
{
// Get the current door column offset
j = aeGlobal->Door[index].ColOffset;
offset = 0;
// Deal with orientation
if (yBitmap & DOOR_TYPE_SLIDE) // Is this a sliding door?
{
DoorOpenColumn = BITMAP_WIDTH-1;
if ((short)iLastY < yPglobal)
j = -j;
yBitmapColumn += j;
} // End processing sliding door
if (yBitmap & DOOR_TYPE_SPLIT) // Is this a split door?
{
DoorOpenColumn = (BITMAP_WIDTH/2)-1;
if (yBitmapColumn < (BITMAP_WIDTH/2))
{
yBitmapColumn += j;
if (yBitmapColumn > (BITMAP_WIDTH/2)-1)
offset = 1;
}
else
{
yBitmapColumn -= j;
if (yBitmapColumn < (BITMAP_WIDTH/2))
offset = 1;
}
} // End processing split door
// If beyond width of bitmap than cast again
if (offset == 1 || yBitmapColumn > (BITMAP_WIDTH-1))
{
// Get the yGrid coordinates for this door
OldMapPosn = aeGlobal->Door[index].mPos;
OldMapPosn1 = aeGlobal->Door[index].mPos1;
// Fool the engine into thinking no door is there
yGridGlobal[OldMapPosn] = 0;
yGridGlobal[OldMapPosn1] = 0;
// Cast again for walls beyond the door
yBitmap = yRayCast();
// Put door code back if not fully open
if (aeGlobal->Door[index].ColOffset < DoorOpenColumn)
{
yGridGlobal[OldMapPosn] = aeGlobal->Door[index].mCode;
yGridGlobal[OldMapPosn1] = aeGlobal->Door[index].mCode1;
}
// Get the bitmap column of wall beyond door
yBitmapColumn = (LastX1 >> FP_SHIFT) & (BITMAP_WIDTH-1);
if ((short)iLastY > yPglobal)
yBitmapColumn = (BITMAP_WIDTH-1) - yBitmapColumn;
}
}
}
//==============================================================
// Calculate the distance to the wall. Since the y position was
// fixed to move 64 or -64 we can use it to determine the actual
// wall distance. The InvSinTable values were stored with a fixed
// point of 20 decimal places. At this time we'll knock off 14 of
// them so we can later multiply with a fixed point value of 16
//==============================================================
yd = iLastY - yPglobal; // Distance from player's position to intersection point
mf = InvSinTable[ViewAngle]; // Use angle with look up table
yDistance = (yd * mf) >> 8; // Calculate y distance
if (yDistance > 33554432L) // Distance is out of range, adjust
yDistance = 120000L;
//==============================================================
// At this point check the distance to the y wall against the x
// wall to see which one is closer. The closer one is the one
// we'll draw at this column of the screen.
//==============================================================
if (yDistance < WallDistance) // Use distance to y slice if this slice is closer
{
wFound = 1; // Indicates that a slice has been found
WallDistance = yDistance; // Use distance to y slice
BitmapNumber = yBitmap; // Transfer bitmap number
BitmapColumn = yBitmapColumn; // Transfer bitmap column
gPtr = yGridGlobal; // Store pointer to global y grid
mPos = yMapPosn; // Store position of y wall in map
mgPtr = myGridGlobal[mPos];
}
} // End (if yBitmap = yRayCast()) != 0)
// A slice has been found so process it
if (wFound)
{
//=============================================================
// To avoid a fishbowl affect we need to adjust the distance so
// it appears perpendicular to the center point of the display
// which is relative angle 0 from the players current angle. We
// started at -32 degrees for the first screen column and will
// cycle from -32 down to 0 then back up to +32 degrees. This
// cosine value was pre-calculated and placed in ViewCosTable.
//=============================================================
UnAdjustDist = WallDistance >> 5;
yd = ViewCosTable[ViewColumn] >> 3; // Use current column as look up index
WallDistance *= yd;
// Now we strip off somemore decimal points and check round-up
xd = WallDistance >> 12;
if (WallDistance - (xd << 12) >= 2048)
xd++;
// The last decimal points from the multiplication after the x and
// y rays is stripped off and checked for round-up
WallDistance = xd >> 5;
if (xd - (WallDistance << 5) >= 16)
WallDistance++;
// This is an arbitrary minimum distance to look for
if (WallDistance < 10)
WallDistance = 10; // Reset distance to minimum allowed
// Don't want it to go outside our table boundaries
if (WallDistance >= MAX_DISTANCE)
WallDistance = MAX_DISTANCE - 1; // Reset distance to max allowed
// Save the wall data to display when done with entire screen
sPtr->Distance = WallDistance; // Store the adjusted distance to the wall
sPtr->bNumber = BitmapNumber; // The bitmap number for the wall slice
sPtr->bColumn = BitmapColumn; // The screen column position to display the bitmap
sPtr->bMap = WallbMaps; // Pointer to the bitmap
sPtr->Active = 0; // Indicates slice is not displayable yetlast one
sPtr->Type = ST_WALL; // Indicates this slice is part of a wall
sPtr->Fnc = WallRtn; // Pointer to function to draw slice
sPtr->mPos = mPos; // Position of the slice in the grid map
sPtr->mPtr = mgPtr; // Grid pointer to reference multi-height wall
spNext = sPtr->Next; // Reference wall slice behind current slice
if (WallDistance > MaxDistance)
MaxDistance = WallDistance;
if (CeilMap[mPos])
LastWallHeight = 9000;
if (((BitmapNumber & WALL_TYPE_UPPER) || // Wall is above the floor level
(BitmapNumber & WALL_TYPE_TRANS)) && // or wall slice is transparent and it
spNext != NULL) // has something behind it
{
BitmapColumn = gPtr[mPos]; // Get position of the mult-height wall
gPtr[mPos] = 0;
sPtr->Active = 1; // More slices to follow if wall is displayable!
if (BitmapNumber & WALL_TYPE_TRANS) // The wall is transparent
{
sPtr->Type = ST_OBJECT; // We have an object
sPtr->Fnc = WallMaskRtn; // Using a different drawing routine
}
sPtr = spNext; // Point to slice behind
spNext->Active = 0; // Initialize the slice behind before building it
spNext->bNumber = 0;
BuildSlice(); // Call BuildSlice() again to build the slice behind
gPtr[mPos] = BitmapColumn; // Store position of slice
if (!sPtr->bNumber) // Slice behind is no longer visible
{
spNext = sPtr->Prev; // Link up slices
if (spNext != NULL)
spNext->Active = 0;
}
}
else
{ // Keep tack of each distance to wall slice for drawing floor later on
if (UnAdjustDist < WallDistTable[ViewColumn])
WallDistTable[ViewColumn] = UnAdjustDist;
}
}
}
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Continues the ray cast for multi-height walls so that any wall that is
// taller than the walls in front of it will be displayed.
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
void BuildSliceMulti(void)
{
short j,index,wFound;
USHORT yHeight;
USHORT xBitmap,yBitmap,BitmapNumber;
short DoorOpenColumn;
short xWallHeight,yWallHeight;
ULONG xDistance,yDistance;
ULONG xd,yd,mf;
long WallDistance;
USHORT distance,LightAdj;
USHORT BitmapColumn,yBitmapColumn;
short OldMapPosn,OldMapPosn1;
short HoldAngle,HoldX,HoldY,xp1,yp1;
USHORT offset;
short mPos;
USHORT *gPtr;
UCHAR *mgPtr;
SLICE *spNext;
WallDistance = 3000000; // Set to a very far off distance
wFound = 0; // Indicates a slice has not been found
// Don't cast an x ray if its impossible to intercept any x walls
if (ViewAngle != INT_ANGLE_90 && ViewAngle != INT_ANGLE_270)
{
if ((BitmapNumber = xRayCastMulti()) != 0) // Cast the x ray and build multi-height slice
{
xBitmap = BitmapNumber & 0xFF; // Get the bitmap code
if (((BitmapNumber & WALL_TYPE_MULTI) || // Check for multi-height
(BitmapNumber & WALL_TYPE_UPPER)) && // or slice that is taller than one in front
(xBitmap > LastWallHeight))
{
// LastWallHeight = xBitmap;
wFound = 1; // Indicates a multi-slice wall has been found
// Use the y intercept to determine the wall column
BitmapColumn = (LastY1 >> FP_SHIFT) & (BITMAP_WIDTH-1);
// Keep the orientation the same no matter which side we're on
if ((short)iLastX < xPglobal)
BitmapColumn = (BITMAP_WIDTH-1) - BitmapColumn;
xd = iLastX - xPglobal;
mf = InvCosTable[ViewAngle]; // Use angle to calculate distance to slice
WallDistance = (xd * mf) >> 10;
if (WallDistance > 33554432L) // Check for out of range
WallDistance = 1200000L;
gPtr = xGridGlobal; // Reference global map grid
mPos = xMapPosn; // Use position of slice
mgPtr = mxGridGlobal[mPos]; // Get pointer to multi-height slice found
}
}
}
// Don't cast a y ray if its impossible to intercept any y walls
if (ViewAngle != 0 && ViewAngle != INT_ANGLE_180)
{
if ((yBitmap = yRayCastMulti()) != 0) // Cast the y ray to build multi-height slice
{
yHeight = yBitmap & 0xFF; // Get the bitmap code of slice
if (((yBitmap & WALL_TYPE_MULTI) ||
(yBitmap & WALL_TYPE_UPPER)) &&
(yHeight > LastWallHeight))
{
yWallHeight = yHeight;
// Use the x intercept to determine the column of the bitmap
yBitmapColumn = (LastX1 >> FP_SHIFT) & (BITMAP_WIDTH-1);
// Handle orientation from either side of the wall
if ((short)iLastY > yPglobal)
yBitmapColumn = (BITMAP_WIDTH-1) - yBitmapColumn;
yd = iLastY - yPglobal;
mf = InvSinTable[ViewAngle]; // Use angle to calculate distance to slice
yDistance = (yd * mf) >> 8;
if (yDistance > 33554432L) // Is distance in range?
yDistance = 120000L;
//==============================================================
// At this point check the distance to the Y wall against the
// wall to see which one is closer. The closer one is the one
// we'll draw at this column of the screen.
//==============================================================
if (yDistance < WallDistance) // Use distance to y slice if this slice is closer
{
wFound = 1; // Indicates that a slice has been found
WallDistance = yDistance; // Use distance to y slice
BitmapNumber = yBitmap; // Transfer bitmap number
BitmapColumn = yBitmapColumn; // Transfer bitmap column
gPtr = yGridGlobal; // Store pointer to global y grid
mPos = yMapPosn; // Store position of y wall in map
xBitmap = yHeight;
mgPtr = myGridGlobal[mPos]; // Store pointer to multi-height slice
}
}
}
}
if (wFound) // A multi-wall slice has been found so process it
{
LastWallHeight = xBitmap;
yd = ViewCosTable[ViewColumn] >> 2;
WallDistance *= yd;
// Now we strip off somemore decimal points and check round-up
xd = WallDistance >> 12;
if (WallDistance - (xd << 12) >= 2048)
xd++;
//==============================================================
// The last decimal points from the multiplication after the X and
// Y rays is stripped off and checked for round-up.
//==============================================================
WallDistance = xd >> 5;
if (xd - (WallDistance << 5) >= 16)
WallDistance++;
// Don't really need to, but put it into an integer for fast compare
distance = WallDistance;
// This is an arbitrary minimum distance to look for
if (distance < 10)
distance = 10;
// Don't want it to go outside our table boundaries
if (distance >= MAX_DISTANCE)
distance = MAX_DISTANCE - 1;
// Save the wall data to display when done with entire screen
sPtr->Active = 1;
sPtr = sPtr->Next;
if (sPtr == NULL)
return;
sPtr->Distance = distance; // Update slice data in slice structure
sPtr->bNumber = BitmapNumber;
sPtr->bColumn = BitmapColumn;
sPtr->bMap = WallbMaps;
sPtr->Active = 0;
sPtr->Type = ST_WALL;
sPtr->Fnc = WallRtn;
sPtr->mPos = mPos;
sPtr->mPtr = mgPtr;
spNext = sPtr->Next;
if (spNext != NULL)
{
BuildSliceMulti(); // Recursive call to build the slice behind
}
}
}
//********************************************************************
// Internal function called by AckCheckDoorOpen() to
// check for a collision with a wall within a certain distance.
//********************************************************************
short AckCheckHit(short xPlayer,short yPlayer,short vAngle)
{
short BitmapNumber,yBitmap;
short WallCode;
ULONG WallDistance;
ULONG xd,yd,mf,yDistance;
long CheckDist;
WallDistance = 3000000; // Set to a ridiculous value
WallCode = POV_NOTHING;
CheckDist = 56L; // (was 48) Initial minimum distance to look for
BitmapNumber = 0; // Initialize to no bitmap found
xPglobal = xPlayer;
xBegGlobal = xPglobal & GRID_MASK;
xPglobalHI = ((long)xPglobal << FP_SHIFT);
yPglobal = yPlayer;
yBegGlobal = yPglobal & GRID_MASK;
yPglobalHI = ((long)yPglobal << FP_SHIFT);
ViewAngle = vAngle;
if (MoveObjectCount)
memmove(ObjectsSeen,MoveObjectList,MoveObjectCount);
FoundObjectCount = MoveObjectCount;
//************************************************************************
// Don't allow one of these angles, causes either the X or Y ray to not be
// cast which gives a false reading about an obstacle.
//************************************************************************
if (ViewAngle == INT_ANGLE_45 ||
ViewAngle == INT_ANGLE_135 ||
ViewAngle == INT_ANGLE_225 ||
ViewAngle == INT_ANGLE_315)
{
ViewAngle++;
}
xRaySetup();
BitmapNumber = xRayCast();
if (BitmapNumber & (WALL_TYPE_UPPER+WALL_TYPE_PASS))
BitmapNumber = 0;
if (BitmapNumber)
{
xd = iLastX - xPlayer;
mf = InvCosTable[ViewAngle];
WallDistance = (xd * mf) >> 10;
if (WallDistance > 33554432L)
WallDistance = 1200000L;
// Set the wall struck code to an X wall
WallCode = POV_XWALL;
LastMapPosn = xMapPosn;
}
yRaySetup();
yBitmap = yRayCast();
if (yBitmap & (WALL_TYPE_UPPER+WALL_TYPE_PASS))
yBitmap = 0;
if (yBitmap)
{
yd = iLastY - yPlayer;
mf = InvSinTable[ViewAngle];
yDistance = (yd * mf) >> 8;
if (yDistance > 33554432L)
yDistance = 120000L;
// If Y wall closer than X wall then use Y wall data
if (yDistance < WallDistance)
{
WallDistance = yDistance;
// Indicate the wall struck was a Y wall
WallCode = POV_YWALL;
BitmapNumber = yBitmap;
LastMapPosn = yMapPosn;
}
}
//************************************************************************
// Since doors appear in the middle of the wall, adjust the minimum distance
// to it. This handles walking up close to a door.
//************************************************************************
if (BitmapNumber & (DOOR_TYPE_SLIDE+DOOR_TYPE_SPLIT))
CheckDist += 64L;
BitmapNumber &= 0xFF;
if (WallCode)
{
yd = ViewCosTable[160] >> 3;
WallDistance *= yd;
// Now we strip off somemore decimal points and check round-up
xd = WallDistance >> 12;
if (WallDistance - (xd << 12) >= 2048)
xd++;
//*********************************************************************
// The last decimal points from the multiplication after the X and
// Y rays is stripped off and checked for round-up.
//*********************************************************************
WallDistance = xd >> 5;
if (xd - (WallDistance << 5) >= 16)
WallDistance++;
//*********************************************************************
// If the wall or object is further than the minimum distance, we can
// continue moving in this direction.
//*********************************************************************
if (WallDistance > CheckDist)
WallCode = POV_NOTHING;
}
return(WallCode);
}
// **** End of Source ****


79
ack_lib/ACKWRAP.C Normal file
View file

@ -0,0 +1,79 @@
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
typedef struct {
int sel;
int off;
} SELOFF;
extern char AckKeyboardSetup;
extern SELOFF OldKeybdInt;
extern char AckTimerSetup;
extern SELOFF OldTimerInt;
void AckSetIntVector(int VecNum,int sel,int VecOff);
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// Frees up buffers and closes any resource file that may be open.
// After calling this function, do NOT call AckBuildView() or
// AckDisplayScreen()
//±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
short AckWrapUp (ACKENG * ae)
{
AckFree (LongTanTable);
AckFree (LongInvTanTable);
AckFree (CosTable);
AckFree (SinTable);
AckFree (LongCosTable);
AckFree (xNextTable);
AckFree (yNextTable);
AckFree (ViewCosTable);
AckFree (AdjustTable);
if (ae->OverlayBuffer != NULL)
AckFree (ae->OverlayBuffer);
ae->OverlayBuffer = NULL;
if (ae->BkgdBuffer != NULL)
AckFree (ae->BkgdBuffer);
ae->BkgdBuffer = NULL;
if (ae->ScreenBuffer != NULL)
AckFree (ae->ScreenBuffer);
ae->ScreenBuffer = NULL;
if (rsHandle)
{
close (rsHandle);
rsHandle = 0;
}
if (AckKeyboardSetup)
{
AckSetIntVector(9,OldKeybdInt.sel,OldKeybdInt.off);
AckKeyboardSetup = 0;
}
if (AckTimerSetup)
{
AckSetIntVector(0x1C,OldTimerInt.sel,OldTimerInt.off);
AckTimerSetup = 0;
}
return (0);
}
// **** End of Source ****


98
ack_lib/IFF.H Normal file
View file

@ -0,0 +1,98 @@
#ifndef NULL
#define NULL 0
#endif
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
#define LONG unsigned long
#define ULONG unsigned long
#define UBYTE unsigned char
#define UWORD unsigned short
#define DWORD unsigned long
long ByteFlipLong(long);
UCHAR *Readiff(char *); /* this returns back a bitmap with a picture in it*/
typedef LONG ID; /* An ID is four printable ASCII chars like FORM or DPPV */
/* original
#define MakeID(d,c,b,a) ((DWORD)(a)<<24 | (DWORD)(b)<<16 | (DWORD)(c)<<8 | (DWORD)(d) )*/
#define MakeID(d,c,b,a) (((DWORD)(a)<<24) | ((DWORD)(b)<<16) | ((DWORD)(c)<<8) | ((DWORD)(d)))
#define FORM MakeID('F','O','R','M')
#define PROP MakeID('P','R','O','P')
#define LIST MakeID('L','I','S','T')
#define CAT MakeID('C','A','T',' ')
#define FILLER MakeID(' ',' ',' ',' ')
typedef struct
{
ID type;
long cksize;
ID subtype;
} form_chunk;
typedef struct {
ID ckID;
LONG ckSize;
} ChunkHeader;
typedef struct {
ID ckID;
LONG ckSize;
UBYTE ckData[ 1 /*REALLY: ckSize*/ ];
} Chunk;
#define ID_PBM MakeID('P','B','M',' ')
#define ID_ILBM MakeID('I','L','B','M')
#define ID_BMHD MakeID('B','M','H','D')
#define ID_CMAP MakeID('C','M','A','P')
#define ID_GRAB MakeID('G','R','A','B')
#define ID_DEST MakeID('D','E','S','T')
#define ID_SPRT MakeID('S','P','R','T')
#define ID_CAMG MakeID('C','A','M','G')
#define ID_BODY MakeID('B','O','D','Y')
/* ---------- BitMapHeader ---------------------------------------------*/
typedef UBYTE Masking; /* Choice of masking technique.*/
#define mskNone 0
#define mskHasMask 1
#define mskHasTransparentColor 2
#define mskLasso 3
#define cmpNone 0
#define cmpByteRun1 1
/* A BitMapHeader is stored in a BMHD chunk. */
typedef struct {
UWORD w, h; /* raster width & height in pixels */
UWORD x, y; /* position for this image */
UBYTE nPlanes; /* # source bitplanes */
UBYTE masking; /* masking technique */
UBYTE compression; /* compression algoithm */
UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/
UWORD transparentColor; /* transparent "color number" */
UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */
UWORD pageWidth, pageHeight; /* source "page" size in pixels */
} BitMapHeader;
/* RowBytes computes the number of bytes in a row, from the width in pixels.*/
#define RowBytes(w) (((w) + 15) >> 4 << 1)
/* A CMAP chunk is a packed array of ColorRegisters (3 bytes each). */
typedef struct {
UBYTE red, green, blue; /* MUST be UBYTEs so ">> 4" won't sign extend.*/
} ColorRegister;
/* Use this constant instead of sizeof(ColorRegister). */
#define sizeofColorRegister 3
long ByteFlipLong(long);
void ByteFlipShort(short *);
short iffswab(unsigned short);
short swab(unsigned short);


140
ack_lib/KIT.H Normal file
View file

@ -0,0 +1,140 @@
// Header file for 3D Construction Kit
// Started: 01/02/94
// Author: Lary Myers
// Module: KIT.H
// (c) CopyRight 1994 All Rights Reserved
#define MODE_GRAPHICS 0x13
#define MODE_TEXT 0x03
#define SCREEN_LENGTH 64000 // Bytes in one full screen
#define SCREEN_LEN_WORDS 32000 // Words in one screen
#define SCREEN_LEN_DWORDS 16000 // DWORDS in one screen
#define SCREEN_PLANES 1 // Number of planes for this mode
#define SCREEN_WIDTH 320 // Number of bytes in one row
#define SCREEN_HEIGHT 200 // Number of rows on screen
#define BUTTON_OK 0
#define BUTTON_OKCANCEL 1
#define BUTTON_YESNO 2
#define BUTTON_ABORTRETRY 3
#define BUTTON_RET_OK 0
#define BUTTON_RET_CANCEL 1
#define BUTTON_RET_YES 2
#define BUTTON_RET_NO 3
#define BUTTON_RET_ABORT 4
#define BUTTON_RET_RETRY 5
// Used in IORTN.C for message boxes
typedef struct {
short x;
short y;
short x1;
short y1;
short index;
} BUTTON;
// Used in IORTN.C for message boxes
typedef struct {
short Count;
short List[4];
} INDEXES;
// Used in IORTN.C list boxes
typedef struct _lcb {
struct _lcb *Back;
struct _lcb *Fwd;
char Data[1];
} LCB;
typedef struct {
short ux;
short uy;
short ux1;
short uy1;
short dx;
short dy;
short dx1;
short dy1;
} ARROWRECT;
//=============================================================================
// Prototypes in UTIL.C
//=============================================================================
UINT Inkey(void);
char *GetExtent(char *s);
char *StripEndOfLine(char *s);
char *SkipSpaces(char *s);
char *AddExtent(char *s,char *ext);
char *CopyToComma(char *dest,char *src);
short HasWildCards(char *s);
void SetCurrentPath(char *p);
void InitDiskList(void);
char *GetPath(char *s);
//=============================================================================
// Prototypes in GRAPHICS.C
//=============================================================================
void SetMode(short mode);
void ClearScreen(UCHAR color);
void PutPixel(short x,short y,UCHAR color);
void DrawVerticalLine(short x,short y,short y1,UCHAR color);
void DrawHorizontalLine(short x,short y,short x1,UCHAR color);
void DrawBox(short x,short y,short x1,short y1,UCHAR color);
void DrawRoundBox(short x,short y,short x1,short y1,UCHAR color);
void Draw3DBox(short x,short y,short x1,short y1,UCHAR TopColor,UCHAR BottomColor);
void DrawSolidBox(short x,short y,short x1,short y1,UCHAR color);
void DrawXORBox(short x,short y,short x1,short y1,UCHAR color);
void DrawXORRect(short x,short y,short x1,short y1,UCHAR color);
void DrawLine(short x1,short y1,short x2,short y2,UCHAR color);
void PutBitmap(short x,short y,short width,short height,UCHAR *Bitmap);
UCHAR *GetBitmap(short x,short y,short width,short height,UCHAR *buffer);
UINT GetBufferSize(short width,short height);
void PutBitmapAsIcon(short x,short y,UCHAR *bm);
void PutAckBitmap(short x,short y,UCHAR *bm);
UCHAR *ScreenToBuffer(UCHAR *buffer);
void BufferToScreen(UCHAR *buffer);
void SetPalette(UCHAR *PalBuf);
void ShowChar(short x,short y,char ch);
void ShowString(short x,short y,char *s);
UCHAR *LoadAndShowScreen(char *PicName);
//=============================================================================
// Prototypes in MOUSE.C
//=============================================================================
short MouseInstalled(void);
void ShowMouse(void);
void HideMouse(void);
short ReadMouseCursor(short *mrow,short *mcol);
short ReadMouseButtons(void);
void SetMouseCursor(short mrow,short mcol);
void SetMouseMinMaxColumns(short mincol,short maxcol);
void SetMouseMinMaxRows(short minrow,short maxrow);
void SetMouseShape(short hsrow,short hscol,char *mask);
void MouseReleased(void);
void MouseSetFunction(UCHAR,void *);
//=============================================================================
// Prototypes in READIFF.C
//=============================================================================
UCHAR *Readiff(char *picname);
//=============================================================================
// Prototypes in IO.C
//=============================================================================
void GetFontTable(void);
void ShowChar(short x,short y,char ch);
void ShowString(short x,short y,char *s);
short ShowMessageBox(char *Body,UINT Buttons);
void ShowListBox(short x,short y,short x1,short y1,short index,LCB *lcb);
char *FileBox(char *fName,char *Path,char *rBuf,char *Title,char *ActiveButton);
void TestListBox(void);
short PickList(short x,short y,short x1,short y1,LCB *Anchor);
short CreateSelectPickList(short x,short y,short x1,short y1,short count,char **List,short SortFlag);
short ShowPickList(char **p,short SortFlag);
//=============================================================================
// Prototypes in SETS.C
//=============================================================================
short LoadSet(char *fName);


78
ack_lib/WING.H Normal file
View file

@ -0,0 +1,78 @@
/*****************************************************************************\
*
* wing.h - WinG functions, types, and definitions
*
* Copyright (c) 1994 Microsoft Corp. All rights reserved.
*
\*****************************************************************************/
#ifndef _INC_WING
#define _INC_WING
#ifndef _INC_WINDOWS
#include <windows.h> /* Include windows.h if not already included */
#endif
#ifdef __cplusplus
extern "C" { /* Assume C declarations for C++ */
#endif
#if defined(WIN32) || defined(_WIN32)
#define WINGAPI WINAPI
#else
#define WINGAPI WINAPI _loadds
#endif
/***** WingDC and WinGBitmap *************************************************/
HDC WINGAPI WinGCreateDC( void );
BOOL WINGAPI WinGRecommendDIBFormat( BITMAPINFO FAR *pFormat );
HBITMAP WINGAPI WinGCreateBitmap( HDC WinGDC, BITMAPINFO const FAR *pHeader,
void FAR *FAR *ppBits );
void FAR *WINGAPI WinGGetDIBPointer( HBITMAP WinGBitmap,
BITMAPINFO FAR *pHeader );
UINT WINGAPI WinGGetDIBColorTable( HDC WinGDC, UINT StartIndex,
UINT NumberOfEntries, RGBQUAD FAR *pColors );
UINT WINGAPI WinGSetDIBColorTable( HDC WinGDC, UINT StartIndex,
UINT NumberOfEntries, RGBQUAD const FAR *pColors );
/***** Halftoning ************************************************************/
HPALETTE WINGAPI WinGCreateHalftonePalette( void );
typedef enum WING_DITHER_TYPE
{
WING_DISPERSED_4x4,
WING_DISPERSED_8x8,
WING_CLUSTERED_4x4
} WING_DITHER_TYPE;
HBRUSH WINGAPI WinGCreateHalftoneBrush( HDC Context, COLORREF crColor,
WING_DITHER_TYPE DitherType );
/***** Blts ******************************************************************/
BOOL WINGAPI WinGBitBlt( HDC hdcDest, int nXOriginDest,
int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc,
int nXOriginSrc, int nYOriginSrc );
BOOL WINGAPI WinGStretchBlt( HDC hdcDest, int nXOriginDest,
int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc,
int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc );
#ifdef __cplusplus
} /* End of extern "C" */
#endif
#endif // _INC_WING

60
ack_lib/WINGDLL.H Normal file
View file

@ -0,0 +1,60 @@
/////////////////////////////////////////////////////////////////////////////
// WINGDLL.H
//
// Interface class for WinG.
/////////////////////////////////////////////////////////////////////////////
#ifndef _INC_WINGDLL
#define _INC_WINGDLL
typedef HDC (WINAPI *wingCreateDC)( void );
typedef BOOL (WINAPI *wingRecommendDIBFormat)( BITMAPINFO FAR *pFormat );
typedef HBITMAP (WINAPI *wingCreateBitmap)( HDC WinGDC, BITMAPINFO const *pHeader,
void *ppBits );
typedef void FAR *(WINAPI *wingGetDIBPointer)( HBITMAP WinGBitmap,
BITMAPINFO FAR *pHeader );
typedef UINT (WINAPI *wingGetDIBColorTable)( HDC WinGDC, UINT StartIndex,
UINT NumberOfEntries, RGBQUAD FAR *pColors );
typedef UINT (WINAPI *wingSetDIBColorTable)( HDC WinGDC, UINT StartIndex,
UINT NumberOfEntries, RGBQUAD const FAR *pColors );
typedef HPALETTE (WINAPI *wingCreateHalftonePalette)( void );
typedef HBRUSH (WINAPI *wingCreateHalftoneBrush)( HDC, COLORREF,
WING_DITHER_TYPE);
typedef BOOL (WINAPI *wingBitBlt)( HDC hdcDest, int nXOriginDest,
int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc,
int nXOriginSrc, int nYOriginSrc );
typedef BOOL (WINAPI *wingStretchBlt)( HDC hdcDest, int nXOriginDest,
int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc,
int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc );
class WinGdll {
public:
WinGdll();
~WinGdll();
BOOL Load();
BOOL Free();
HINSTANCE m_hLib;
BOOL m_bLoaded;
//I would have used m_ prefix, but too laborious to type when using
//the class. Would have inlined the function pointers,
//without typedef's, but the compiler didn't like it.
//Anyway, this method makes casting GetProcAddress()
//easier.
wingCreateDC pCreateDC;
wingRecommendDIBFormat pRecommendDIBFormat;
wingCreateBitmap pCreateBitmap;
wingGetDIBPointer pGetDIBPointer;
wingGetDIBColorTable pGetDIBColorTable;
wingSetDIBColorTable pSetDIBColorTable;
wingCreateHalftonePalette pCreateHalftonePalette;
wingCreateHalftoneBrush pCreateHalftoneBrush;
wingBitBlt pBitBlt;
wingStretchBlt pStretchBlt;
} ;
#endif // _INC_WINGDLL

2310
fdemo/FDEMO.C Normal file

File diff suppressed because it is too large Load diff

140
fdemo/KIT.H Normal file
View file

@ -0,0 +1,140 @@
// Header file for 3D Construction Kit
// Started: 01/02/94
// Author: Lary Myers
// Module: KIT.H
// (c) CopyRight 1994 All Rights Reserved
#define MODE_GRAPHICS 0x13
#define MODE_TEXT 0x03
#define SCREEN_LENGTH 64000 // Bytes in one full screen
#define SCREEN_LEN_WORDS 32000 // Words in one screen
#define SCREEN_LEN_DWORDS 16000 // DWORDS in one screen
#define SCREEN_PLANES 1 // Number of planes for this mode
#define SCREEN_WIDTH 320 // Number of bytes in one row
#define SCREEN_HEIGHT 200 // Number of rows on screen
#define BUTTON_OK 0
#define BUTTON_OKCANCEL 1
#define BUTTON_YESNO 2
#define BUTTON_ABORTRETRY 3
#define BUTTON_RET_OK 0
#define BUTTON_RET_CANCEL 1
#define BUTTON_RET_YES 2
#define BUTTON_RET_NO 3
#define BUTTON_RET_ABORT 4
#define BUTTON_RET_RETRY 5
// Used in IORTN.C for message boxes
typedef struct {
short x;
short y;
short x1;
short y1;
short index;
} BUTTON;
// Used in IORTN.C for message boxes
typedef struct {
short Count;
short List[4];
} INDEXES;
// Used in IORTN.C list boxes
typedef struct _lcb {
struct _lcb *Back;
struct _lcb *Fwd;
char Data[1];
} LCB;
typedef struct {
short ux;
short uy;
short ux1;
short uy1;
short dx;
short dy;
short dx1;
short dy1;
} ARROWRECT;
//=============================================================================
// Prototypes in UTIL.C
//=============================================================================
UINT Inkey(void);
char *GetExtent(char *s);
char *StripEndOfLine(char *s);
char *SkipSpaces(char *s);
char *AddExtent(char *s,char *ext);
char *CopyToComma(char *dest,char *src);
short HasWildCards(char *s);
void SetCurrentPath(char *p);
void InitDiskList(void);
char *GetPath(char *s);
//=============================================================================
// Prototypes in GRAPHICS.C
//=============================================================================
void SetMode(short mode);
void ClearScreen(UCHAR color);
void PutPixel(short x,short y,UCHAR color);
void DrawVerticalLine(short x,short y,short y1,UCHAR color);
void DrawHorizontalLine(short x,short y,short x1,UCHAR color);
void DrawBox(short x,short y,short x1,short y1,UCHAR color);
void DrawRoundBox(short x,short y,short x1,short y1,UCHAR color);
void Draw3DBox(short x,short y,short x1,short y1,UCHAR TopColor,UCHAR BottomColor);
void DrawSolidBox(short x,short y,short x1,short y1,UCHAR color);
void DrawXORBox(short x,short y,short x1,short y1,UCHAR color);
void DrawXORRect(short x,short y,short x1,short y1,UCHAR color);
void DrawLine(short x1,short y1,short x2,short y2,UCHAR color);
void PutBitmap(short x,short y,short width,short height,UCHAR *Bitmap);
UCHAR *GetBitmap(short x,short y,short width,short height,UCHAR *buffer);
UINT GetBufferSize(short width,short height);
void PutBitmapAsIcon(short x,short y,UCHAR *bm);
void PutAckBitmap(short x,short y,UCHAR *bm);
UCHAR *ScreenToBuffer(UCHAR *buffer);
void BufferToScreen(UCHAR *buffer);
void SetPalette(UCHAR *PalBuf);
void ShowChar(short x,short y,char ch);
void ShowString(short x,short y,char *s);
UCHAR *LoadAndShowScreen(char *PicName);
//=============================================================================
// Prototypes in MOUSE.C
//=============================================================================
short MouseInstalled(void);
void ShowMouse(void);
void HideMouse(void);
short ReadMouseCursor(short *mrow,short *mcol);
short ReadMouseButtons(void);
void SetMouseCursor(short mrow,short mcol);
void SetMouseMinMaxColumns(short mincol,short maxcol);
void SetMouseMinMaxRows(short minrow,short maxrow);
void SetMouseShape(short hsrow,short hscol,char *mask);
void MouseReleased(void);
void MouseSetFunction(UCHAR,void *);
//=============================================================================
// Prototypes in READIFF.C
//=============================================================================
UCHAR *Readiff(char *picname);
//=============================================================================
// Prototypes in IO.C
//=============================================================================
void GetFontTable(void);
void ShowChar(short x,short y,char ch);
void ShowString(short x,short y,char *s);
short ShowMessageBox(char *Body,UINT Buttons);
void ShowListBox(short x,short y,short x1,short y1,short index,LCB *lcb);
char *FileBox(char *fName,char *Path,char *rBuf,char *Title,char *ActiveButton);
void TestListBox(void);
short PickList(short x,short y,short x1,short y1,LCB *Anchor);
short CreateSelectPickList(short x,short y,short x1,short y1,short count,char **List,short SortFlag);
short ShowPickList(char **p,short SortFlag);
//=============================================================================
// Prototypes in SETS.C
//=============================================================================
short LoadSet(char *fName);


BIN
fdemo/KIT.OVL Normal file

Binary file not shown.

1166
fdemo/MODPLAY.ASM Normal file

File diff suppressed because it is too large Load diff

162
fdemo/MODPLAY.H Normal file
View file

@ -0,0 +1,162 @@
/* modplay.h - Tiny MOD Player V2.02 for Watcom C/C++32 and DOS/4GW header file
Module player for Sound Blaster and compatibles.
Copyright 1993,94 Carlos Hasan
*/
/******************************************************************************\
QUICK REFERENCE GUIDE:
MODPlayModule
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Start playing a Modulefile.
Prototype: int MODPlayModule(Song,Chans,Rate,Port,IRQ,DRQ)
Parameters: Song - Address of the Modulefile Image
Chans - Number of channels (1-8)
Rate - Mixing speed in Hertz (4kHz-22kHz)
Port - I/O Port address (220h..280h)
IRQ - IRQ level (2,3,5,7,11)
DRQ - DMA channel (0,1,3)
Returns: On success, return a zero value.
On error, return a non zero value.
Remarks: This function will initialize the Sound Blaster card and
will start playing the module file immediately. The module
file must be a 4,6 or 8 channels Protracker or FastTracker
music module file.
The player supports two kinds of channels, music and sample
audio channels. The music channels are used by the player
to play the module, and the sample channels are used for
sound effects and the like.
The channels voices 0 to N-1 are used for music channels,
where N is the number of channels of the module file.
MODStopModule
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Stop playing the current Modulefile.
Prototype: void MODStopModule()
Parameters: None.
Returns: None.
Remarks: This function shut down the playing system. Must be called
before exiting the user program.
MODPlaySample
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Play instrument at specified period and volume.
Prototype: void MODPlaySample(Voice,Instr)
Parameters: Voice - Audio channel number (0-7)
Instr - Instrument address
Returns: None.
Remarks: This function is useful to play samples over music. The sample
structure holds the period, volume and the address of the 8-bit
signed samples to be played in the channel.
MODPlayVoice
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Set the sample, period and volume for a sample channel.
Prototype: void MODPlayVoice(Voice,Instr,Period,Volume)
Parameters: Voice - Audio channel number (0-7)
Instr - Instrument number (1-31)
Period - Amiga period value (113-856)
Volume - Volume value (0-64)
Returns: None.
Remarks: This function is useful to play samples over music. You must
use a sample channel or the music system will override
these parameters when polling the current module.
The amiga period value can be translated to hertz using the
following formula: Hertz = 8363*428/Period
MODStopVoice
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Stop a sample channel.
Prototype: void MODStopVoice(Voice)
Parameters: Voice - Audio channel number (0-7)
Remarks: This function will stop the specified voice setting the channel
volume to zero. The voice should be a sample channel.
MODSetPeriod
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Set the sample channel period value.
Prototype: void MODSetPeriod(Voice,Period)
Parameters: Voice - Audio channel number (0-7)
Period - Amiga Period (113-856)
Returns: None.
Remarks: This function will change the current frequency of the sample
channel. The voice should be a sample channel.
MODSetVolume
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Set the sample channel volume.
Prototype: void MODSetVolume(Voice,Volume)
Parameters: Voice - Audio channel number (0-7)
Volume - Volume (0-64)
Returns: None.
Remarks: This function will change the channel volume. The voice should
be a sample channel.
\******************************************************************************/
#ifndef __MODPLAY_H
#define __MODPLAY_H
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
typedef struct {
word Period;
word Volume;
dword Length;
void *Data;
} Sample;
#pragma aux MODPlayModule "_*" parm caller [];
#pragma aux MODStopModule "_*" parm caller [];
#pragma aux MODPlaySample "_*" parm caller [];
#pragma aux MODPlayVoice "_*" parm caller [];
#pragma aux MODStopVoice "_*" parm caller [];
#pragma aux MODSetPeriod "_*" parm caller [];
#pragma aux MODSetVolume "_*" parm caller [];
extern int MODPlayModule(void *Modulefile,word Chans,word Rate,word Port,byte IRQ,byte DRQ);
extern void MODStopModule(void);
extern void MODPlaySample(byte Voice,Sample *Instr);
extern void MODPlayVoice(byte Voice,byte Instr,word Period,byte Volume);
extern void MODStopVoice(byte Voice);
extern void MODSetPeriod(byte Voice,word Period);
extern void MODSetVolume(byte Voice,byte Volume);
#endif

181
fdemo/MOUSE.C Normal file
View file

@ -0,0 +1,181 @@
// 3D Construction Kit
// Started: 01/02/94
// Author: Lary Myers
// Module: MOUSE.C
// (c) CopyRight 1994 All Rights Reserved
#include <dos.h>
#include <stdio.h>
#include <dos.h>
void Mymemset(void *,int,int);
int MouseModifier = 2;
//=============================================================================
// Check if mouse is installed, returns -1 if it IS installed
//=============================================================================
int MouseInstalled(void)
{
int yesno;
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
intr(0x33,&regs);
yesno = regs.w.ax;
return(yesno);
}
//=============================================================================
// Show the mouse cursor
//=============================================================================
void ShowMouse(void)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 1;
intr(0x33,&regs);
}
//=============================================================================
// Hide the mouse cursor
//=============================================================================
void HideMouse(void)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 2;
intr(0x33,&regs);
}
//=============================================================================
// Returns button status, mouse row and column
//=============================================================================
int ReadMouseCursor(int *mrow,int *mcol)
{
int bstatus;
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 3;
intr(0x33,&regs);
bstatus = regs.w.bx;
*mrow = regs.w.dx;
*mcol = regs.w.cx / MouseModifier;
return(bstatus);
}
//=============================================================================
// Returns just the mouse button status
//=============================================================================
int ReadMouseButtons(void)
{
int bstatus;
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 3;
intr(0x33,&regs);
bstatus = regs.w.bx;
return(bstatus);
}
//=============================================================================
// Set mouse cursor to desired row and column
//=============================================================================
void SetMouseCursor(int mrow,int mcol)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 4;
regs.w.dx = mrow;
regs.w.cx = mcol * MouseModifier;
intr(0x33,&regs);
}
//=============================================================================
// Defines left and right columns for mouse travel
//=============================================================================
void SetMouseMinMaxColumns(int mincol,int maxcol)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 7;
regs.w.cx = mincol * MouseModifier;
regs.w.dx = maxcol * MouseModifier;
intr(0x33,&regs);
}
//=============================================================================
// Defines top and bottom rows for mouse travel
//=============================================================================
void SetMouseMinMaxRows(int minrow,int maxrow)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 8;
regs.w.cx = minrow;
regs.w.dx = maxrow;
intr(0x33,&regs);
}
//=============================================================================
// Set shape of mouse cursor. 8 byte mask, hotspot row,col
//=============================================================================
void SetMouseShape(int hsrow,int hscol,char far *mask)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 9;
regs.w.dx = FP_OFF(mask);
regs.w.es = FP_SEG(mask);
regs.w.bx = hscol;
regs.w.cx = hsrow;
intr(0x33,&regs);
}
//=============================================================================
// Wait for the mouse button to be released
//=============================================================================
void MouseReleased(void)
{
while (ReadMouseButtons());
}
//=============================================================================
//
//=============================================================================
void MouseSetFunction(unsigned char mFlag,void *Func)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 12;
regs.w.dx = FP_OFF(Func);
regs.w.es = FP_SEG(Func);
regs.w.cx = mFlag;
intr(0x33,&regs);
}


BIN
fdemo/PICS.DTF Normal file

Binary file not shown.

BIN
fdemo/SAHARA.MOD Normal file

Binary file not shown.

140
mall/KIT.H Normal file
View file

@ -0,0 +1,140 @@
// Header file for 3D Construction Kit
// Started: 01/02/94
// Author: Lary Myers
// Module: KIT.H
// (c) CopyRight 1994 All Rights Reserved
#define MODE_GRAPHICS 0x13
#define MODE_TEXT 0x03
#define SCREEN_LENGTH 64000 // Bytes in one full screen
#define SCREEN_LEN_WORDS 32000 // Words in one screen
#define SCREEN_LEN_DWORDS 16000 // DWORDS in one screen
#define SCREEN_PLANES 1 // Number of planes for this mode
#define SCREEN_WIDTH 320 // Number of bytes in one row
#define SCREEN_HEIGHT 200 // Number of rows on screen
#define BUTTON_OK 0
#define BUTTON_OKCANCEL 1
#define BUTTON_YESNO 2
#define BUTTON_ABORTRETRY 3
#define BUTTON_RET_OK 0
#define BUTTON_RET_CANCEL 1
#define BUTTON_RET_YES 2
#define BUTTON_RET_NO 3
#define BUTTON_RET_ABORT 4
#define BUTTON_RET_RETRY 5
// Used in IORTN.C for message boxes
typedef struct {
short x;
short y;
short x1;
short y1;
short index;
} BUTTON;
// Used in IORTN.C for message boxes
typedef struct {
short Count;
short List[4];
} INDEXES;
// Used in IORTN.C list boxes
typedef struct _lcb {
struct _lcb *Back;
struct _lcb *Fwd;
char Data[1];
} LCB;
typedef struct {
short ux;
short uy;
short ux1;
short uy1;
short dx;
short dy;
short dx1;
short dy1;
} ARROWRECT;
//=============================================================================
// Prototypes in UTIL.C
//=============================================================================
UINT Inkey(void);
char *GetExtent(char *s);
char *StripEndOfLine(char *s);
char *SkipSpaces(char *s);
char *AddExtent(char *s,char *ext);
char *CopyToComma(char *dest,char *src);
short HasWildCards(char *s);
void SetCurrentPath(char *p);
void InitDiskList(void);
char *GetPath(char *s);
//=============================================================================
// Prototypes in GRAPHICS.C
//=============================================================================
void SetMode(short mode);
void ClearScreen(UCHAR color);
void PutPixel(short x,short y,UCHAR color);
void DrawVerticalLine(short x,short y,short y1,UCHAR color);
void DrawHorizontalLine(short x,short y,short x1,UCHAR color);
void DrawBox(short x,short y,short x1,short y1,UCHAR color);
void DrawRoundBox(short x,short y,short x1,short y1,UCHAR color);
void Draw3DBox(short x,short y,short x1,short y1,UCHAR TopColor,UCHAR BottomColor);
void DrawSolidBox(short x,short y,short x1,short y1,UCHAR color);
void DrawXORBox(short x,short y,short x1,short y1,UCHAR color);
void DrawXORRect(short x,short y,short x1,short y1,UCHAR color);
void DrawLine(short x1,short y1,short x2,short y2,UCHAR color);
void PutBitmap(short x,short y,short width,short height,UCHAR far *Bitmap);
UCHAR far *GetBitmap(short x,short y,short width,short height,UCHAR far *buffer);
UINT GetBufferSize(short width,short height);
void PutBitmapAsIcon(short x,short y,UCHAR far *bm);
void PutAckBitmap(short x,short y,UCHAR far *bm);
UCHAR far *ScreenToBuffer(UCHAR far *buffer);
void BufferToScreen(UCHAR far *buffer);
void SetPalette(UCHAR far *PalBuf);
void ShowChar(short x,short y,char ch);
void ShowString(short x,short y,char *s);
UCHAR far *LoadAndShowScreen(char *PicName);
//=============================================================================
// Prototypes in MOUSE.C
//=============================================================================
short MouseInstalled(void);
void ShowMouse(void);
void HideMouse(void);
short ReadMouseCursor(short *mrow,short *mcol);
short ReadMouseButtons(void);
void SetMouseCursor(short mrow,short mcol);
void SetMouseMinMaxColumns(short mincol,short maxcol);
void SetMouseMinMaxRows(short minrow,short maxrow);
void SetMouseShape(short hsrow,short hscol,char far *mask);
void MouseReleased(void);
void MouseSetFunction(UCHAR,void *);
//=============================================================================
// Prototypes in READIFF.C
//=============================================================================
UCHAR *Readiff(char *picname);
//=============================================================================
// Prototypes in IO.C
//=============================================================================
void GetFontTable(void);
void ShowChar(short x,short y,char ch);
void ShowString(short x,short y,char *s);
short ShowMessageBox(char *Body,UINT Buttons);
void ShowListBox(short x,short y,short x1,short y1,short index,LCB *lcb);
char *FileBox(char *fName,char *Path,char *rBuf,char *Title,char *ActiveButton);
void TestListBox(void);
short PickList(short x,short y,short x1,short y1,LCB *Anchor);
short CreateSelectPickList(short x,short y,short x1,short y1,short count,char **List,short SortFlag);
short ShowPickList(char **p,short SortFlag);
//=============================================================================
// Prototypes in SETS.C
//=============================================================================
short LoadSet(char *fName);


BIN
mall/KIT.OVL Normal file

Binary file not shown.

2303
mall/MALL.C Normal file

File diff suppressed because it is too large Load diff

1166
mall/MODPLAY.ASM Normal file

File diff suppressed because it is too large Load diff

162
mall/MODPLAY.H Normal file
View file

@ -0,0 +1,162 @@
/* modplay.h - Tiny MOD Player V2.02 for Watcom C/C++32 and DOS/4GW header file
Module player for Sound Blaster and compatibles.
Copyright 1993,94 Carlos Hasan
*/
/******************************************************************************\
QUICK REFERENCE GUIDE:
MODPlayModule
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Start playing a Modulefile.
Prototype: int MODPlayModule(Song,Chans,Rate,Port,IRQ,DRQ)
Parameters: Song - Address of the Modulefile Image
Chans - Number of channels (1-8)
Rate - Mixing speed in Hertz (4kHz-22kHz)
Port - I/O Port address (220h..280h)
IRQ - IRQ level (2,3,5,7,11)
DRQ - DMA channel (0,1,3)
Returns: On success, return a zero value.
On error, return a non zero value.
Remarks: This function will initialize the Sound Blaster card and
will start playing the module file immediately. The module
file must be a 4,6 or 8 channels Protracker or FastTracker
music module file.
The player supports two kinds of channels, music and sample
audio channels. The music channels are used by the player
to play the module, and the sample channels are used for
sound effects and the like.
The channels voices 0 to N-1 are used for music channels,
where N is the number of channels of the module file.
MODStopModule
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Stop playing the current Modulefile.
Prototype: void MODStopModule()
Parameters: None.
Returns: None.
Remarks: This function shut down the playing system. Must be called
before exiting the user program.
MODPlaySample
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Play instrument at specified period and volume.
Prototype: void MODPlaySample(Voice,Instr)
Parameters: Voice - Audio channel number (0-7)
Instr - Instrument address
Returns: None.
Remarks: This function is useful to play samples over music. The sample
structure holds the period, volume and the address of the 8-bit
signed samples to be played in the channel.
MODPlayVoice
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Set the sample, period and volume for a sample channel.
Prototype: void MODPlayVoice(Voice,Instr,Period,Volume)
Parameters: Voice - Audio channel number (0-7)
Instr - Instrument number (1-31)
Period - Amiga period value (113-856)
Volume - Volume value (0-64)
Returns: None.
Remarks: This function is useful to play samples over music. You must
use a sample channel or the music system will override
these parameters when polling the current module.
The amiga period value can be translated to hertz using the
following formula: Hertz = 8363*428/Period
MODStopVoice
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Stop a sample channel.
Prototype: void MODStopVoice(Voice)
Parameters: Voice - Audio channel number (0-7)
Remarks: This function will stop the specified voice setting the channel
volume to zero. The voice should be a sample channel.
MODSetPeriod
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Set the sample channel period value.
Prototype: void MODSetPeriod(Voice,Period)
Parameters: Voice - Audio channel number (0-7)
Period - Amiga Period (113-856)
Returns: None.
Remarks: This function will change the current frequency of the sample
channel. The voice should be a sample channel.
MODSetVolume
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Function: Set the sample channel volume.
Prototype: void MODSetVolume(Voice,Volume)
Parameters: Voice - Audio channel number (0-7)
Volume - Volume (0-64)
Returns: None.
Remarks: This function will change the channel volume. The voice should
be a sample channel.
\******************************************************************************/
#ifndef __MODPLAY_H
#define __MODPLAY_H
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
typedef struct {
word Period;
word Volume;
dword Length;
void *Data;
} Sample;
#pragma aux MODPlayModule "_*" parm caller [];
#pragma aux MODStopModule "_*" parm caller [];
#pragma aux MODPlaySample "_*" parm caller [];
#pragma aux MODPlayVoice "_*" parm caller [];
#pragma aux MODStopVoice "_*" parm caller [];
#pragma aux MODSetPeriod "_*" parm caller [];
#pragma aux MODSetVolume "_*" parm caller [];
extern int MODPlayModule(void *Modulefile,word Chans,word Rate,word Port,byte IRQ,byte DRQ);
extern void MODStopModule(void);
extern void MODPlaySample(byte Voice,Sample *Instr);
extern void MODPlayVoice(byte Voice,byte Instr,word Period,byte Volume);
extern void MODStopVoice(byte Voice);
extern void MODSetPeriod(byte Voice,word Period);
extern void MODSetVolume(byte Voice,byte Volume);
#endif

181
mall/MOUSE.C Normal file
View file

@ -0,0 +1,181 @@
// 3D Construction Kit
// Started: 01/02/94
// Author: Lary Myers
// Module: MOUSE.C
// (c) CopyRight 1994 All Rights Reserved
#include <dos.h>
#include <stdio.h>
#include <dos.h>
void Mymemset(void *,int,int);
int MouseModifier = 2;
//=============================================================================
// Check if mouse is installed, returns -1 if it IS installed
//=============================================================================
int MouseInstalled(void)
{
int yesno;
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
intr(0x33,&regs);
yesno = regs.w.ax;
return(yesno);
}
//=============================================================================
// Show the mouse cursor
//=============================================================================
void ShowMouse(void)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 1;
intr(0x33,&regs);
}
//=============================================================================
// Hide the mouse cursor
//=============================================================================
void HideMouse(void)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 2;
intr(0x33,&regs);
}
//=============================================================================
// Returns button status, mouse row and column
//=============================================================================
int ReadMouseCursor(int *mrow,int *mcol)
{
int bstatus;
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 3;
intr(0x33,&regs);
bstatus = regs.w.bx;
*mrow = regs.w.dx;
*mcol = regs.w.cx / MouseModifier;
return(bstatus);
}
//=============================================================================
// Returns just the mouse button status
//=============================================================================
int ReadMouseButtons(void)
{
int bstatus;
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 3;
intr(0x33,&regs);
bstatus = regs.w.bx;
return(bstatus);
}
//=============================================================================
// Set mouse cursor to desired row and column
//=============================================================================
void SetMouseCursor(int mrow,int mcol)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 4;
regs.w.dx = mrow;
regs.w.cx = mcol * MouseModifier;
intr(0x33,&regs);
}
//=============================================================================
// Defines left and right columns for mouse travel
//=============================================================================
void SetMouseMinMaxColumns(int mincol,int maxcol)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 7;
regs.w.cx = mincol * MouseModifier;
regs.w.dx = maxcol * MouseModifier;
intr(0x33,&regs);
}
//=============================================================================
// Defines top and bottom rows for mouse travel
//=============================================================================
void SetMouseMinMaxRows(int minrow,int maxrow)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 8;
regs.w.cx = minrow;
regs.w.dx = maxrow;
intr(0x33,&regs);
}
//=============================================================================
// Set shape of mouse cursor. 8 byte mask, hotspot row,col
//=============================================================================
void SetMouseShape(int hsrow,int hscol,char far *mask)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 9;
regs.w.dx = FP_OFF(mask);
regs.w.es = FP_SEG(mask);
regs.w.bx = hscol;
regs.w.cx = hsrow;
intr(0x33,&regs);
}
//=============================================================================
// Wait for the mouse button to be released
//=============================================================================
void MouseReleased(void)
{
while (ReadMouseButtons());
}
//=============================================================================
//
//=============================================================================
void MouseSetFunction(unsigned char mFlag,void *Func)
{
union REGPACK regs;
Mymemset(&regs,0,sizeof(union REGPACK));
regs.w.ax = 12;
regs.w.dx = FP_OFF(Func);
regs.w.es = FP_SEG(Func);
regs.w.cx = mFlag;
intr(0x33,&regs);
}


BIN
mall/PICS.DTF Normal file

Binary file not shown.

BIN
mall/WALK.MOD Normal file

Binary file not shown.