first commit

This commit is contained in:
Mike Diskett 2017-05-20 11:14:17 +10:00
commit f9e2faf45a
1142 changed files with 697829 additions and 0 deletions

125
MFLib1/Headers/Display.h Normal file
View File

@ -0,0 +1,125 @@
// Display.h
// Guy Simmons, 6th October 1996.
#ifndef _DISPLAY_H_
#define _DISPLAY_H_
#ifndef _MF_TYPES_H_
#include <MFTypes.h>
#endif
//---------------------------------------------------------------
// DModes.cpp
#define DS_THREAD_ACTIVE (1<<0)
#define DS_SHELL_WINDOW_OPEN (1<<1)
#define DS_DIRECT_DRAW_ACTIVE (1<<2)
#define DS_DISPLAY_MODE_SET (1<<3)
#define DS_CREATED_SURFACES (1<<4)
#define DS_SCREEN_LOCKED (1<<5)
enum DisplayModes
{
DISPLAY_MODE_NONE = 0,
DISPLAY_MODE_320_200_8, // 320x200
DISPLAY_MODE_320_200_16,
DISPLAY_MODE_320_200_24,
DISPLAY_MODE_320_200_32,
DISPLAY_MODE_320_240_8, // 320x240
DISPLAY_MODE_320_240_16,
DISPLAY_MODE_320_240_24,
DISPLAY_MODE_320_240_32,
DISPLAY_MODE_320_400_8, // 320x400
DISPLAY_MODE_320_400_16,
DISPLAY_MODE_320_400_24,
DISPLAY_MODE_320_400_32,
DISPLAY_MODE_512_384_8, // 512x384
DISPLAY_MODE_512_384_16,
DISPLAY_MODE_512_384_24,
DISPLAY_MODE_512_384_32,
DISPLAY_MODE_640_400_8, // 640x400
DISPLAY_MODE_640_400_16,
DISPLAY_MODE_640_400_24,
DISPLAY_MODE_640_400_32,
DISPLAY_MODE_640_480_8, // 640x480
DISPLAY_MODE_640_480_16,
DISPLAY_MODE_640_480_24,
DISPLAY_MODE_640_480_32,
DISPLAY_MODE_800_600_8, // 800x600
DISPLAY_MODE_800_600_16,
DISPLAY_MODE_800_600_24,
DISPLAY_MODE_800_600_32,
DISPLAY_MODE_1024_768_8, // 1024x768
DISPLAY_MODE_1024_768_16,
DISPLAY_MODE_1024_768_24,
DISPLAY_MODE_1024_768_32,
DISPLAY_MODE_1152_864_8, // 1152x864
DISPLAY_MODE_1152_864_16,
DISPLAY_MODE_1152_864_24,
DISPLAY_MODE_1152_864_32,
DISPLAY_MODE_1280_1024_8, // 1280x1024
DISPLAY_MODE_1280_1024_16,
DISPLAY_MODE_1280_1024_24,
DISPLAY_MODE_1280_1024_32,
DISPLAY_MODE_COUNT
};
typedef struct
{
BOOL Availability; // Do we have this mode?
ULONG Width, // Display dimensions.
Height,
Depth;
SLONG DisplayMode; // Internal host screen mode identifier.
#ifdef _MF_WINDOWS
DDSURFACEDESC DD_ModeDesc;
#endif
}DisplayModeInfo;
extern DisplayModeInfo DisplayModes[];
SLONG DisplayModeAvailable(ULONG width, ULONG height, ULONG depth);
//---------------------------------------------------------------
// Display.cpp
#define FLAGS_USE_3DFX (1<<0)
#define DS_WAIT_VBI (1<<0)
#define DS_DO_FLIP (1<<1)
extern UBYTE DisplayActive,
WorkScreenDepth,
*WorkScreen;
extern SLONG WorkScreenHeight,
WorkScreenPixelWidth,
WorkScreenWidth;
#ifdef _MF_WINDOWS
extern DDSURFACEDESC DD_DisplayDesc;
extern LPDIRECTDRAW lp_DD; // Main DirectDraw object
extern LPDIRECTDRAWSURFACE lp_DD_FrontSurface,
lp_DD_BackSurface;
extern volatile UBYTE MFShellActive;
#endif
SLONG OpenDisplay(ULONG width, ULONG height, ULONG depth, ULONG flags);
SLONG CloseDisplay(void);
SLONG SetDisplay(ULONG width,ULONG height,ULONG depth);
void ClearDisplay(void);
void FadeDisplay(UBYTE mode);
void *LockWorkScreen(void);
void UnlockWorkScreen(void);
void ShowWorkScreen(ULONG flags);
void ShowWorkWindow(ULONG flags);
void ClearWorkScreen(UBYTE colour);
//---------------------------------------------------------------
#endif

101
MFLib1/Headers/Draw2d.h Normal file
View File

@ -0,0 +1,101 @@
// Draw2D.h
// Guy Simmons, 7th October 1996.
#ifndef _DRAW2D_H_
#define _DRAW2D_H_
#ifndef _MF_TYPES_H_
#include <MFTypes.h>
#endif
#ifndef _DISPLAY_H_
#include <Display.h>
#endif
typedef struct
{
SLONG X,
Y;
}MFPoint;
typedef struct
{
SLONG Left,
Top,
Right,
Bottom,
Width,
Height;
}MFRect;
inline BOOL XYInRect(SLONG x,SLONG y,MFRect *the_rect) { if(x>=the_rect->Left&&y>=the_rect->Top&&x<=the_rect->Right&&y<=the_rect->Bottom)return TRUE;else return FALSE; }
inline BOOL PointInRect(MFPoint *the_point,MFRect *the_rect) { if(the_point->X>=the_rect->Left&&the_point->Y>=the_rect->Top&&the_point->X<=the_rect->Right&&the_point->Y<=the_rect->Bottom)return TRUE;else return FALSE; }
//---------------------------------------------------------------
// Draw2D.c
extern UBYTE *WorkWindow;
extern SLONG WorkWindowHeight,
WorkWindowWidth;
extern MFRect WorkWindowRect;
void SetWorkWindowBounds(SLONG left, SLONG top, SLONG width, SLONG height);
MFPoint *GlobalToLocal(MFPoint *the_point);
void GlobalXYToLocal(SLONG *x,SLONG *y);
inline void SetWorkWindow(void) { WorkWindow=(WorkScreen+WorkWindowRect.Left*WorkScreenDepth+(WorkWindowRect.Top*WorkScreenWidth)); }
//---------------------------------------------------------------
// DrawBox.c
extern void (*DrawBox)(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour);
extern void (*DrawBoxC)(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour);
//---------------------------------------------------------------
// DrawLine.c
extern void (*DrawLine)(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour);
extern void (*DrawLineC)(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour);
extern void (*DrawHLine)(SLONG x1,SLONG x2,SLONG y,ULONG colour);
extern void (*DrawHLineC)(SLONG x1,SLONG x2,SLONG y,ULONG colour);
extern void (*DrawVLine)(SLONG x,SLONG y1,SLONG y2,ULONG colour);
extern void (*DrawVLineC)(SLONG x,SLONG y1,SLONG y2,ULONG colour);
//---------------------------------------------------------------
// DrawPoint.c
extern void (*DrawPoint)(MFPoint *the_point,ULONG colour);
extern void (*DrawPointC)(MFPoint *the_point,ULONG colour);
//---------------------------------------------------------------
// DrawPixel.c
extern void (*DrawPixel)(SLONG x,SLONG y,ULONG colour);
extern void (*DrawPixelC)(SLONG x,SLONG y,ULONG colour);
//---------------------------------------------------------------
// DrawRect.c
void DrawRect(MFRect *the_rect,ULONG colour);
void DrawRectC(MFRect *the_rect,ULONG colour);
//---------------------------------------------------------------
// QuickText.c
extern UBYTE *CharTable[];
extern void (*QuickText)(SLONG x,SLONG y,CBYTE *the_string,ULONG colour);
extern void (*QuickTextC)(SLONG x,SLONG y,CBYTE *the_string,ULONG colour);
extern void (*QuickChar)(SLONG x,SLONG y,CBYTE the_char,ULONG colour);
extern void (*QuickCharC)(SLONG x,SLONG y,CBYTE the_char,ULONG colour);
SLONG QTStringWidth(CBYTE *the_string);
inline SLONG QTStringHeight(void) { return 8; }
inline SLONG QTCharWidth(CBYTE the_char) { return (CharTable[the_char])[0]; }
inline SLONG QTCharHeight(CBYTE the_char) { return (CharTable[the_char])[1]; }
//---------------------------------------------------------------
#endif

View File

@ -0,0 +1,8 @@
// DrawPoly.h
// Guy Simmons, 1st November 1996.
#ifndef _DRAWPOLY_H_
#define _DRAWPOLY_H_
#endif

142
MFLib1/Headers/Keyboard.h Normal file
View File

@ -0,0 +1,142 @@
// Keyboard.h
// Guy Simmons, 11th February 1997.
#ifndef _KEYBOARD_H_
#define _KEYBOARD_H_
#ifndef _MF_TYPES_H_
#include <MFTypes.h>
#endif
// Row1
#define KB_ESC 0x01
#define KB_1 0x02
#define KB_2 0x03
#define KB_3 0x04
#define KB_4 0x05
#define KB_5 0x06
#define KB_6 0x07
#define KB_7 0x08
#define KB_8 0x09
#define KB_9 0x0a
#define KB_0 0x0b
#define KB_MINUS 0x0c
#define KB_PLUS 0x0d
#define KB_BS 0x0e
// Row2
#define KB_TAB 0x0f
#define KB_Q 0x10
#define KB_W 0x11
#define KB_E 0x12
#define KB_R 0x13
#define KB_T 0x14
#define KB_Y 0x15
#define KB_U 0x16
#define KB_I 0x17
#define KB_O 0x18
#define KB_P 0x19
#define KB_LBRACE 0x1a
#define KB_RBRACE 0x1b
#define KB_ENTER 0x1c
// Row3
#define KB_LCONTROL 0x1d
#define KB_CAPSLOCK 0x3a
#define KB_A 0x1e
#define KB_S 0x1f
#define KB_D 0x20
#define KB_F 0x21
#define KB_G 0x22
#define KB_H 0x23
#define KB_J 0x24
#define KB_K 0x25
#define KB_L 0x26
#define KB_COLON 0x27
#define KB_QUOTE 0x28
#define KB_TILD 0x29
// Row4
#define KB_LSHIFT 0x2a
#define KB_BACKSLASH 0x2b
#define KB_Z 0x2c
#define KB_X 0x2d
#define KB_C 0x2e
#define KB_V 0x2f
#define KB_B 0x30
#define KB_N 0x31
#define KB_M 0x32
#define KB_COMMA 0x33
#define KB_POINT 0x34
#define KB_FORESLASH 0x35
#define KB_RSHIFT 0x36
#define KB_LALT 0x38
#define KB_SPACE 0x39
#define KB_RALT (0x38+0x80)
#define KB_RCONTROL (0x1d+0x80)
// Function key row.
#define KB_F1 0x3b
#define KB_F2 0x3c
#define KB_F3 0x3d
#define KB_F4 0x3e
#define KB_F5 0x3f
#define KB_F6 0x40
#define KB_F7 0x41
#define KB_F8 0x42
#define KB_F9 0x43
#define KB_F10 0x44
#define KB_F11 0x57
#define KB_F12 0x58
#define KB_PRTSC (0x37+0x80)
#define KB_SCROLLLOCK 0x46
//#define KB_PAUSE ????
// Edit pad.
#define KB_INS (0x52+0x80)
#define KB_HOME (0x47+0x80)
#define KB_PGUP (0x49+0x80)
#define KB_DEL (0x53+0x80)
#define KB_END (0x4f+0x80)
#define KB_PGDN (0x51+0x80)
// Cursor pad.
#define KB_LEFT (0x4b+0x80)
#define KB_UP (0x48+0x80)
#define KB_RIGHT (0x4d+0x80)
#define KB_DOWN (0x50+0x80)
// Key pad.
#define KB_NUMLOCK 0x45
#define KB_PSLASH (0x35+0x80)
#define KB_ASTERISK 0x37
#define KB_PMINUS 0x4a
#define KB_P7 0x47
#define KB_P8 0x48
#define KB_P9 0x49
#define KB_PPLUS 0x4e
#define KB_P4 0x4b
#define KB_P5 0x4c
#define KB_P6 0x4d
#define KB_P1 0x4f
#define KB_P2 0x50
#define KB_P3 0x51
#define KB_PENTER (0x1c+0x80)
#define KB_P0 0x52
#define KB_PPOINT 0x53
extern volatile UBYTE AltFlag,
ControlFlag,
ShiftFlag;
extern volatile UBYTE Keys[256],
LastKey;
BOOL SetupKeyboard(void);
void ResetKeyboard(void);
#endif

26
MFLib1/Headers/MFD3D.h Normal file
View File

@ -0,0 +1,26 @@
// MFD3D.h
// Guy Simmons, 13th May 1997.
#ifndef MFD3D_H
#define MFD3D_H
#define D3D_HARDWARE (1<<0)
#define D3D_GOURAUD (1<<1)
#define D3D_ZBUFFER (1<<2)
#define D3D_RAMP (1<<3)
extern BOOL HasHardware;
extern IDirect3DDevice2 *lp_D3D_Device;
extern LPDIRECT3D2 lp_D3D_2;
//----------------------------------------------------------------------
void SetupD3D2(void);
void ResetD3D2(void);
BOOL ChooseD3DDevice(ULONG flags);
//----------------------------------------------------------------------
#endif

46
MFLib1/Headers/MFErrors.h Normal file
View File

@ -0,0 +1,46 @@
// Errors.h
// Guy Simmons, 6th October 1996.
#ifndef _MF_ERRORS_H_
#define _MF_ERRORS_H_
#ifdef _DEBUG
#else
#endif
extern int MFMessage(const char *pMessage, const char *pFile, ULONG dwLine);
#define ERROR_MSG(e,m) { if(!e) MFMessage(m,__FILE__,__LINE__); }
#ifndef ASSERT
#define ASSERT(e) ERROR_MSG(e,"Assert failed");
#endif
// Library Errors.
enum
{
NoError = 0
};
// Display Errors.
enum
{
DisplayCreationError = -100,
DisplayShutdownError = -101
};
// File Errors.
enum
{
FileOpenError = -1,
FileCloseError = -2,
FileCreationError = -3,
FileSizeError = -4,
FileReadError = -5,
FileWriteError = -6,
FileSeekError = -7,
FileLoadAtError = -8
};
#endif

41
MFLib1/Headers/MFFile.h Normal file
View File

@ -0,0 +1,41 @@
// MFFile.h
// Guy Simmons, 10th February 1997.
#ifndef _MF_FILE_H_
#define _MF_FILE_H_
#ifdef _MF_WINDOWS
typedef HANDLE MFFileHandle;
#else
typedef SLONG MFFileHandle;
#endif
#define FILE_OPEN_ERROR ((MFFileHandle)FileOpenError)
#define FILE_CLOSE_ERROR ((MFFileHandle)FileCloseError)
#define FILE_CREATION_ERROR ((MFFileHandle)FileCreationError)
#define FILE_SIZE_ERROR ((SLONG)FileSizeError)
#define FILE_READ_ERROR ((SLONG)FileReadError)
#define FILE_WRITE_ERROR ((SLONG)FileWriteError)
#define FILE_SEEK_ERROR ((SLONG)FileSeekError)
#define FILE_LOAD_AT_ERROR ((SLONG)FileLoadAtError)
enum SeekModes
{
SEEK_MODE_BEGINNING,
SEEK_MODE_CURRENT,
SEEK_MODE_END
};
BOOL FileExists(CBYTE *file_name);
MFFileHandle FileOpen(CBYTE *file_name);
void FileClose(MFFileHandle file_handle);
MFFileHandle FileCreate(CBYTE *file_name,BOOL overwrite);
void FileDelete(CBYTE *file_name);
SLONG FileSize(MFFileHandle file_handle);
SLONG FileRead(MFFileHandle file_handle,void *buffer,ULONG size);
SLONG FileWrite(MFFileHandle file_handle,void *buffer,ULONG size);
SLONG FileSeek(MFFileHandle file_handle,enum SeekModes mode,SLONG offset);
SLONG FileLoadAt(CBYTE *file_name,void *buffer);
#endif

81
MFLib1/Headers/MFHeader.h Normal file
View File

@ -0,0 +1,81 @@
// MFHeader.h
// Guy Simmons, 1st Februry 1997.
#ifndef MFHEADER_H
#define MFHEADER_H
// Standard 'C' includes.
#ifndef TARGET_DC
#include <iostream.h>
#include <time.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
// Set up Compilation defines.
#include <MFLbType.h>
// Specific Windows includes.
#ifdef _MF_WINDOWS
#ifndef _WIN32
#define _WIN32
#endif
#ifndef WIN32
#define WIN32
#endif
#define D3D_OVERLOADS
#include <windows.h>
#include <windowsx.h>
// #include <mmsystem.h>
#include <ddraw.h>
// #include <dinput.h>
#include <dplay.h>
#include <d3d.h>
#include <d3dtypes.h>
#ifdef TARGET_DC
// Dreamcast-specific fixups and so on.
#include "target.h"
#endif
#include <MFD3D.h>
#endif
// Specific DOS includes.
#ifdef _MF_DOSX
#include <fcntl.h>
#include <io.h>
#include <share.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif
// Mucky Foot library includes.
#include <Display.h>
#include <Draw2D.h>
#include <DrawPoly.h>
#include <Keyboard.h>
#include <MFErrors.h>
#include <MFFile.h>
#include <MFHost.h>
#include <MFMaths.h>
#include <MFMem.h>
#include <MFStd.h>
#include <MFUtils.h>
#include <Mouse.h>
#include <Palette.h>
#include <Sprites.h>
#endif

36
MFLib1/Headers/MFHost.h Normal file
View File

@ -0,0 +1,36 @@
// MFHost.h - Windows.
// Guy Simmons, 1st February 1997.
#define H_CREATE_LOG (1<<0)
#ifdef _MF_WINDOWS
extern int iGlobalCmdShow;
extern HINSTANCE hGlobalInstance,
hGlobalPrevInstance;
extern LPSTR szGlobalCmdLine;
#define main(ac,av) MF_main(ac,av)
SLONG main(UWORD argc, TCHAR** argv);
#endif
struct MFTime
{
SLONG Hours,
Minutes,
Seconds,
MSeconds;
SLONG DayOfWeek, // 0 - 6; Sunday = 0
Day,
Month, // 1 - 12; January = 1
Year;
SLONG Ticks; // Number of ticks(milliseconds) since windows started.
};
BOOL SetupHost(ULONG flags);
void ResetHost(void);
void LogText(CBYTE *error, ...);
void Time(struct MFTime *the_time);

133
MFLib1/Headers/MFLbType.h Normal file
View File

@ -0,0 +1,133 @@
// MFLbType.h
// Guy Simmons, 31st January 1997.
#ifndef _MFLBTYPE_H_
#define _MFLBTYPE_H_
//----------------------------------------------------------------------
// Common header for generic types, macros & functions
//----------------------------------------------------------------------
/*
Predefined macros - Environment & Compilation defines.
Compile state:
_DEBUG Compiles a debug build.
_RELEASE Comples a release build.
Compiler:
_CW_ Codewarrior
__MSC__ Microsoft Visual C++.
__WATCOMC__ Watcom C++ Optimising compiler.
Host Platform:
_MF_WINDOWS Microsoft Windows OS conforming to Win32 specification (Win95, NT3.51).
_MF_DOSX Extended DOS.
_MAC68K Macintosh 68K based machines.
_MACPPC Macintosh PPC based machines.
_PSX Sony Playstation.
Host Processor:
_X86_ Intel compatible (PC).
_68K_ Motorola 68K series compatible (Amiga, Macintosh, Pilot).
_PPC_ Motorola PPC series compatible (M2, Macintosh).
_MIPS_ (PSX)
*/
#ifdef _DEBUG
#ifdef _RELEASE
#error Cannot compile Debug & Release builds at the same time.
#endif
#else
#ifndef _RELEASE
#error _DEBUG or _RELEASE need to be defined.
#endif
#endif
#ifdef __WINDOWS_386__ // Watcom predefined for Windows build
#define _MF_WINDOWS
#elif defined(WIN32)
#define _MF_WINDOWS
#elif defined(_WIN32_WCE)
#define _MF_WINDOWS
#endif
#ifdef __DOS__
#define _MF_DOSX
#endif
/*
Implicit library linking - Set according to compile state.
Naming convention.
Compiler : (C)Codewarrior,
(M)MSDev,
(W)Watcom.
Platform : (_DOS)Extended dos,
(_M68)Macintosh 68K,
(_MPP)Macintosh PPC,
(_PSX)Playstation,
(_WIN)Windows.
Version : 1
Compilation : (_D)Debug,
(_R)Release.
*/
#ifdef _DEBUG
#ifdef _MSC_VER
#pragma comment(lib, "ddraw.lib")
#ifndef TARGET_DC
#pragma comment(lib, "dplay.lib")
#pragma comment(lib, "d3drm.lib")
#else
#pragma comment(lib, "dplayx.lib")
#endif
#pragma comment(lib, "M_WIN1_D")
#elif defined(__WATCOMC__)
#ifdef _MF_WINDOWS
#pragma library("W_WIN1_D")
#elif defined(_MF_DOSX)
#pragma library("W_DOS1_D")
#endif
#endif
#else
#ifdef _MSC_VER
#pragma comment(lib, "ddraw.lib")
#ifndef TARGET_DC
#pragma comment(lib, "dplay.lib")
#pragma comment(lib, "d3drm.lib")
#else
#pragma comment(lib, "dplayx.lib")
#endif
#pragma comment(lib, "M_WIN1_R")
#elif defined(__WATCOMC__)
#ifdef _MF_WINDOWS
#pragma library("W_WIN1_R")
#elif defined(_MF_DOSX)
#pragma library("W_DOS1_R")
#endif
#endif
#endif
//----------------------------------------------------------------------
#endif

70
MFLib1/Headers/MFMaths.h Normal file
View File

@ -0,0 +1,70 @@
// Trig.h
// Guy Simmons, 16th February 1997.
#define SIN(a) SinTable[a]
#define COS(a) CosTable[a]
#define SIN_F(a) SinTableF[a]
#define COS_F(a) CosTableF[a]
//---------------------------------------------------------------
// Maths.cpp
SLONG Arctan(SLONG X,SLONG Y);
SLONG Root(SLONG square);
#ifdef __WATCOMC__
extern UWORD ini_table[];
SLONG Root(SLONG square);
#pragma aux Root = \
" xor ebx,ebx "\
" bsr eax,ecx "\
" je done_it "\
" movzx ebx,ini_table[eax*2] "\
"do_it: "\
" mov eax,ecx "\
" xor edx,edx "\
" div ebx "\
" cmp eax,ebx "\
" jge done_it "\
" add ebx,eax "\
" shr ebx,1 "\
" jmp do_it "\
"done_it: "\
" mov eax,ebx "\
parm[ecx] \
modify[eax ebx ecx edx] \
value[eax];
#endif
//---------------------------------------------------------------
// Trig.cpp
extern float *CosTableF,
SinTableF[];
extern SWORD AtanTable[];
extern SLONG *CosTable,
SinTable[];
extern SLONG Proportions[];
//---------------------------------------------------------------
#define PROPTABLE_SIZE 256
#define PROP(x) Proportions[(x)+PROPTABLE_SIZE]
static inline SLONG Hypotenuse(SLONG x,SLONG y)
{
x = abs(x);
y = abs(y);
if(x>y)
return((PROP((y<<8)/x)*x)>>13);
else
if(y)
return((PROP((x<<8)/y)*y)>>13);
else
return(0);
}
//---------------------------------------------------------------

12
MFLib1/Headers/MFMem.h Normal file
View File

@ -0,0 +1,12 @@
// MFMem.h
// Guy Simmons, 10th February 1997.
#ifndef _MF_MEM_H_
#define _MF_MEM_H_
BOOL SetupMemory(void);
void ResetMemory(void);
void *MemAlloc(ULONG size);
void MemFree(void *mem_ptr);
#endif

16
MFLib1/Headers/MFStd.h Normal file
View File

@ -0,0 +1,16 @@
// MFStd.h
// Guy Simmons, 17th October 1996.
#ifndef _MFSTD_H_
#define _MFSTD_H_
#ifndef _MF_TYPES_H_
#include <MFTypes.h>
#endif
#ifndef _MF_ERRORS_H_
#include <MFErrors.h>
#endif
#endif

26
MFLib1/Headers/MFTypes.h Normal file
View File

@ -0,0 +1,26 @@
// MFTypes.h
// Guy Simmons, 6th October 1996.
// Type definitions for 'Mucky Foot' Libraries.
#ifndef _MF_TYPES_H_
#define _MF_TYPES_H_
#define TRUE 1
#define FALSE 0
#if defined(_MF_DOSX)
typedef unsigned long BOOL;
#endif
typedef unsigned char UBYTE;
typedef signed char SBYTE;
typedef char CBYTE;
typedef unsigned short UWORD;
typedef signed short SWORD;
typedef unsigned long ULONG;
typedef signed long SLONG;
#endif

23
MFLib1/Headers/MFUtils.h Normal file
View File

@ -0,0 +1,23 @@
// Utils.h
// Guy Simmons, 7th October 1996.
#ifndef _MF_UTILS_H_
#define _MF_UTILS_H_
#ifdef __WATCOMC__
#define abs(a) (((a)<0) ? -(a) : (a))
#endif
#define sgn(a) (((a)<0) ? -1 : 1)
#define swap(a,b) {a^=b;b^=a;a^=b;}
#define in_range(a,min,max) {if(a>(max))a=(max);else if(a<(min))a=(min);}
#ifndef min
#define min(a,b) (((a)<(b)) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) (((a)>(b)) ? (a) : (b))
#endif
#endif

32
MFLib1/Headers/Mouse.h Normal file
View File

@ -0,0 +1,32 @@
// Mouse.h
// Guy Simmons, 19th February 1997.
#ifndef _MOUSE_H_
#define _MOUSE_H_
struct LastMouse
{
SLONG ButtonState,
MouseX,
MouseY;
MFPoint MousePoint;
};
extern volatile UBYTE MouseMoved,
LeftButton,
MiddleButton,
RightButton;
extern volatile SLONG MouseX,
MouseY;
extern volatile LastMouse LeftMouse,
MiddleMouse,
RightMouse;
extern volatile MFPoint MousePoint;
extern void RemoveMouse(void);
extern void PlaceMouse(void);
#endif

24
MFLib1/Headers/Palette.h Normal file
View File

@ -0,0 +1,24 @@
// Palette.h
// Guy Simmons, 11th February 1997.
#ifndef _PALETTE_H_
#define _PALETTE_H_
#ifndef _MF_TYPES_H_
#include <MFTypes.h>
#endif
#define FADE_IN 1<<0
#define FADE_OUT 1<<1
extern UBYTE CurrentPalette[256*3];
void InitPalettes(void);
SLONG CreatePalettes(void);
void DestroyPalettes(void);
void RestorePalettes(void);
void SetPalette(UBYTE *the_palette);
SLONG FindColour(UBYTE *pal,SLONG r,SLONG g,SLONG b);
#endif

41
MFLib1/Headers/Sprites.h Normal file
View File

@ -0,0 +1,41 @@
// Sprites.h
// Guy Simmons, 13th February 1997.
#ifndef _SPRITES_H_
#define _SPRITES_H_
#ifndef _MF_TYPES_H_
#include <MFTypes.h>
#endif
#define END_LINE 0x00
#define COPY_PIXELS 0x01
#define SKIP_PIXELS 0x02
#define DUPLICATE_PIXELS 0x03
#define FINISHED 0x04
typedef struct
{
UBYTE *SpriteData;
UWORD SpriteHeight;
UWORD SpriteWidth;
}BSprite;
extern void (*DrawBSprite)(SLONG x,SLONG y,BSprite *the_sprite);
extern void (*DrawBSpriteC)(SLONG x,SLONG y,BSprite *the_sprite);
extern void DrawBSpritePal16(SLONG x,SLONG y,BSprite *the_sprite,UBYTE *pal);
extern void DrawBSpritePal32(SLONG x,SLONG y,BSprite *the_sprite,UBYTE *pal);
extern void (*DrawMonoBSprite)(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour);
extern void (*DrawMonoBSpriteC)(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour);
extern void DrawBSpritePalC16(SLONG x,SLONG y,BSprite *the_sprite,UBYTE *pal);
extern void DrawBSpritePalC32(SLONG x,SLONG y,BSprite *the_sprite,UBYTE *pal);
extern void SetupBSprites(BSprite *sprite_ref,UBYTE *sprite_data);
#endif

242
MFLib1/MFLib1.dsp Normal file
View File

@ -0,0 +1,242 @@
# Microsoft Developer Studio Project File - Name="MFLib1" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=MFLib1 - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "MFLib1.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "MFLib1.mak" CFG="MFLib1 - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "MFLib1 - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "MFLib1 - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP Scc_ProjName ""$/MFLib1", NABAAAAA"
# PROP Scc_LocalPath "."
CPP=cl.exe
!IF "$(CFG)" == "MFLib1 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\Release"
# PROP BASE Intermediate_Dir ".\Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\Source\C\Windows\MRelease"
# PROP Intermediate_Dir ".\Source\C\Windows\MRelease"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_RELEASE" /YX /FD /c
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:".\Libs\M_win1_r.lib"
!ELSEIF "$(CFG)" == "MFLib1 - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\Debug"
# PROP BASE Intermediate_Dir ".\Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\Source\C\Windows\MDebug"
# PROP Intermediate_Dir ".\Source\C\Windows\MDebug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:".\Libs\M_win1_d.lib"
!ENDIF
# Begin Target
# Name "MFLib1 - Win32 Release"
# Name "MFLib1 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
# Begin Source File
SOURCE=.\Source\C\Windows\D3D.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Windows\Display.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\DModes.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\Draw2d.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\DrawBox.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\DrawLine.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\DrawPnt.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\DrawPxl.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\DrawRect.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Windows\File.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Windows\Keyboard.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\Maths.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Windows\Mem.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Windows\MFHost.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Windows\Mouse.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Windows\Palette.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\QuickTxt.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\Sprites.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\TextDef.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\C\Common\Trig.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=.\Headers\Display.h
# End Source File
# Begin Source File
SOURCE=.\Headers\Draw2d.h
# End Source File
# Begin Source File
SOURCE=.\Headers\DrawPoly.h
# End Source File
# Begin Source File
SOURCE=.\Headers\Keyboard.h
# End Source File
# Begin Source File
SOURCE=.\Headers\MFD3D.h
# End Source File
# Begin Source File
SOURCE=.\Headers\MFErrors.h
# End Source File
# Begin Source File
SOURCE=.\Headers\MFFile.h
# End Source File
# Begin Source File
SOURCE=.\Headers\MFHeader.h
# End Source File
# Begin Source File
SOURCE=.\Headers\MFHost.h
# End Source File
# Begin Source File
SOURCE=.\Headers\MFLbType.h
# End Source File
# Begin Source File
SOURCE=.\Headers\MFMaths.h
# End Source File
# Begin Source File
SOURCE=.\Headers\MFMem.h
# End Source File
# Begin Source File
SOURCE=.\Headers\MFStd.h
# End Source File
# Begin Source File
SOURCE=.\Headers\MFTypes.h
# End Source File
# Begin Source File
SOURCE=.\Headers\MFUtils.h
# End Source File
# Begin Source File
SOURCE=.\Headers\Mouse.h
# End Source File
# Begin Source File
SOURCE=.\Headers\Palette.h
# End Source File
# Begin Source File
SOURCE=.\Headers\Sprites.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@ -0,0 +1,101 @@
// DModes.cpp
// Guy Simmons, 8th February 1996.
#include <MFHeader.h>
//---------------------------------------------------------------
DisplayModeInfo DisplayModes[] =
{
{ FALSE, 0,0,0, DISPLAY_MODE_NONE },
{ FALSE, 320,200,8, DISPLAY_MODE_320_200_8 }, // 320x200
{ FALSE, 320,200,16, DISPLAY_MODE_320_200_16 },
{ FALSE, 320,200,24, DISPLAY_MODE_320_200_24 },
{ FALSE, 320,200,32, DISPLAY_MODE_320_200_32 },
{ FALSE, 320,240,8, DISPLAY_MODE_320_240_8 }, // 320x240
{ FALSE, 320,240,16, DISPLAY_MODE_320_240_16 },
{ FALSE, 320,240,24, DISPLAY_MODE_320_240_24 },
{ FALSE, 320,240,32, DISPLAY_MODE_320_240_32 },
{ FALSE, 320,400,8, DISPLAY_MODE_320_400_8 }, // 320x400
{ FALSE, 320,400,16, DISPLAY_MODE_320_400_16 },
{ FALSE, 320,400,24, DISPLAY_MODE_320_400_24 },
{ FALSE, 320,400,32, DISPLAY_MODE_320_400_32 },
{ FALSE, 512,384,8, DISPLAY_MODE_512_384_8 }, // 512x384
{ FALSE, 512,384,16, DISPLAY_MODE_512_384_16 },
{ FALSE, 512,384,24, DISPLAY_MODE_512_384_24 },
{ FALSE, 512,384,32, DISPLAY_MODE_512_384_32 },
{ FALSE, 640,400,8, DISPLAY_MODE_640_400_8 }, // 640x400
{ FALSE, 640,400,16, DISPLAY_MODE_640_400_16 },
{ FALSE, 640,400,24, DISPLAY_MODE_640_400_24 },
{ FALSE, 640,400,32, DISPLAY_MODE_640_400_32 },
{ FALSE, 640,480,8, DISPLAY_MODE_640_480_8 }, // 640x480
{ FALSE, 640,480,16, DISPLAY_MODE_640_480_16 },
{ FALSE, 640,480,24, DISPLAY_MODE_640_480_24 },
{ FALSE, 640,480,32, DISPLAY_MODE_640_480_32 },
{ FALSE, 800,600,8, DISPLAY_MODE_800_600_8 }, // 800x600
{ FALSE, 800,600,16, DISPLAY_MODE_800_600_16 },
{ FALSE, 800,600,24, DISPLAY_MODE_800_600_24 },
{ FALSE, 800,600,32, DISPLAY_MODE_800_600_32 },
{ FALSE, 1024,768,8, DISPLAY_MODE_1024_768_8 }, // 1024x768
{ FALSE, 1024,768,16, DISPLAY_MODE_1024_768_16 },
{ FALSE, 1024,768,24, DISPLAY_MODE_1024_768_24 },
{ FALSE, 1024,768,32, DISPLAY_MODE_1024_768_32 },
{ FALSE, 1152,864,8, DISPLAY_MODE_1152_864_8 }, // 1152x864
{ FALSE, 1152,864,16, DISPLAY_MODE_1152_864_16 },
{ FALSE, 1152,864,24, DISPLAY_MODE_1152_864_24 },
{ FALSE, 1152,864,32, DISPLAY_MODE_1152_864_32 },
{ FALSE, 1280,1024,8, DISPLAY_MODE_1280_1024_8 }, // 1280x1024
{ FALSE, 1280,1024,16, DISPLAY_MODE_1280_1024_16 },
{ FALSE, 1280,1024,24, DISPLAY_MODE_1280_1024_24 },
{ FALSE, 1280,1024,32, DISPLAY_MODE_1280_1024_32 }
};
//---------------------------------------------------------------
extern BOOL EmulateLoRes;
SLONG DisplayModeAvailable(ULONG width, ULONG height, ULONG depth)
{
#ifdef _DEBUG
// Shut the compiler up.
width = width;
height = height;
depth = depth;
return TRUE;
#else
ULONG c0;
SLONG result = DISPLAY_MODE_NONE;
EmulateLoRes = FALSE;
for(c0=1;c0<DISPLAY_MODE_COUNT;c0++)
{
if (
DisplayModes[c0].Width==width &&
DisplayModes[c0].Height==height &&
DisplayModes[c0].Depth==depth
)
{
if(DisplayModes[c0].Availability)
{
result = DisplayModes[c0].DisplayMode;
break;
}
}
}
if(result==DISPLAY_MODE_NONE && width==320 && depth==8 && (height==200||height==240))
{
EmulateLoRes = TRUE;
if(height==200)
result = DISPLAY_MODE_320_200_8;
else
result = DISPLAY_MODE_320_240_8;
}
return result;
#endif
}
//---------------------------------------------------------------

View File

@ -0,0 +1,265 @@
// Draw2D.c
// Guy Simmons, 7th October 1996.
#include <MFHeader.h>
UBYTE *WorkWindow;
SLONG WorkWindowHeight,
WorkWindowWidth;
MFRect WorkWindowRect;
//---------------------------------------------------------------
extern void DrawBox8(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour);
extern void DrawBoxC8(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour);
extern void DrawBox16(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour);
extern void DrawBoxC16(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour);
extern void DrawBox32(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour);
extern void DrawBoxC32(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour);
extern void DrawLine8(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour);
extern void DrawLineC8(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour);
extern void DrawLine16(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour);
extern void DrawLineC16(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour);
extern void DrawLine32(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour);
extern void DrawLineC32(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour);
extern void DrawHLine8(SLONG x1,SLONG x2,SLONG y,ULONG colour);
extern void DrawHLineC8(SLONG x1,SLONG x2,SLONG y,ULONG colour);
extern void DrawHLine16(SLONG x1,SLONG x2,SLONG y,ULONG colour);
extern void DrawHLineC16(SLONG x1,SLONG x2,SLONG y,ULONG colour);
extern void DrawHLine32(SLONG x1,SLONG x2,SLONG y,ULONG colour);
extern void DrawHLineC32(SLONG x1,SLONG x2,SLONG y,ULONG colour);
extern void DrawVLine8(SLONG x,SLONG y1,SLONG y2,ULONG colour);
extern void DrawVLineC8(SLONG x,SLONG y1,SLONG y2,ULONG colour);
extern void DrawVLine16(SLONG x,SLONG y1,SLONG y2,ULONG colour);
extern void DrawVLineC16(SLONG x,SLONG y1,SLONG y2,ULONG colour);
extern void DrawVLine32(SLONG x,SLONG y1,SLONG y2,ULONG colour);
extern void DrawVLineC32(SLONG x,SLONG y1,SLONG y2,ULONG colour);
extern void DrawPoint8(MFPoint *the_point,ULONG colour);
extern void DrawPointC8(MFPoint *the_point,ULONG colour);
extern void DrawPoint16(MFPoint *the_point,ULONG colour);
extern void DrawPointC16(MFPoint *the_point,ULONG colour);
extern void DrawPoint32(MFPoint *the_point,ULONG colour);
extern void DrawPointC32(MFPoint *the_point,ULONG colour);
extern void DrawPixel8(SLONG x,SLONG y,ULONG colour);
extern void DrawPixelC8(SLONG x,SLONG y,ULONG colour);
extern void DrawPixel16(SLONG x,SLONG y,ULONG colour);
extern void DrawPixelC16(SLONG x,SLONG y,ULONG colour);
extern void DrawPixel32(SLONG x,SLONG y,ULONG colour);
extern void DrawPixelC32(SLONG x,SLONG y,ULONG colour);
extern void QuickText8(SLONG x,SLONG y,CBYTE *the_string,ULONG colour);
extern void QuickTextC8(SLONG x,SLONG y,CBYTE *the_string,ULONG colour);
extern void QuickChar8(SLONG x,SLONG y,CBYTE the_char,ULONG colour);
extern void QuickCharC8_16_32(SLONG x,SLONG y,CBYTE the_char,ULONG colour);
extern void QuickText16(SLONG x,SLONG y,CBYTE *the_string,ULONG colour);
extern void QuickTextC16(SLONG x,SLONG y,CBYTE *the_string,ULONG colour);
extern void QuickChar16(SLONG x,SLONG y,CBYTE the_char,ULONG colour);
extern void QuickText32(SLONG x,SLONG y,CBYTE *the_string,ULONG colour);
extern void QuickTextC32(SLONG x,SLONG y,CBYTE *the_string,ULONG colour);
extern void QuickChar32(SLONG x,SLONG y,CBYTE the_char,ULONG colour);
extern void DrawBSprite8(SLONG x,SLONG y,BSprite *the_sprite);
extern void DrawBSprite16(SLONG x,SLONG y,BSprite *the_sprite);
extern void DrawBSprite32(SLONG x,SLONG y,BSprite *the_sprite);
extern void DrawBSpriteC8(SLONG x,SLONG y,BSprite *the_sprite);
extern void DrawBSpriteC16(SLONG x,SLONG y,BSprite *the_sprite);
extern void DrawBSpriteC32(SLONG x,SLONG y,BSprite *the_sprite);
extern void DrawMonoBSprite8(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour);
extern void DrawMonoBSprite16(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour);
extern void DrawMonoBSprite32(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour);
extern void DrawMonoBSpriteC8(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour);
extern void DrawMonoBSpriteC16(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour);
extern void DrawMonoBSpriteC32(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour);
//---------------------------------------------------------------
// Set Function pointers for this display depth
void (*DrawBox)(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour);
void (*DrawBoxC)(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour);
void (*DrawLine)(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour);
void (*DrawLineC)(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour);
void (*DrawHLine)(SLONG x1,SLONG x2,SLONG y,ULONG colour);
void (*DrawHLineC)(SLONG x1,SLONG x2,SLONG y,ULONG colour);
void (*DrawVLine)(SLONG x,SLONG y1,SLONG y2,ULONG colour);
void (*DrawVLineC)(SLONG x,SLONG y1,SLONG y2,ULONG colour);
void (*DrawPoint)(MFPoint *the_point,ULONG colour);
void (*DrawPointC)(MFPoint *the_point,ULONG colour);
void (*DrawPixel)(SLONG x,SLONG y,ULONG colour);
void (*DrawPixelC)(SLONG x,SLONG y,ULONG colour);
void (*QuickText)(SLONG x,SLONG y,CBYTE *the_string,ULONG colour);
void (*QuickTextC)(SLONG x,SLONG y,CBYTE *the_string,ULONG colour);
void (*QuickChar)(SLONG x,SLONG y,CBYTE the_char,ULONG colour);
void (*QuickCharC)(SLONG x,SLONG y,CBYTE the_char,ULONG colour);
void (*DrawBSprite)(SLONG x,SLONG y,BSprite *the_sprite);
void (*DrawBSpriteC)(SLONG x,SLONG y,BSprite *the_sprite);
void (*DrawMonoBSprite)(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour);
void (*DrawMonoBSpriteC)(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour);
void SetDrawFunctions(ULONG depth)
{
switch (depth)
{
case 8:
DrawBox=DrawBox8;
DrawBoxC=DrawBoxC8;
DrawLine=DrawLine8;
DrawLineC=DrawLineC8;
DrawHLine=DrawHLine8;
DrawHLineC=DrawHLineC8;
DrawVLine=DrawVLine8;
DrawVLineC=DrawVLineC8;
DrawPoint=DrawPoint8;
DrawPointC=DrawPointC8;
DrawPixel=DrawPixel8;
DrawPixelC=DrawPixelC8;
QuickText =QuickText8;
QuickTextC=QuickTextC8;
QuickChar =QuickChar8;
QuickCharC=QuickCharC8_16_32;
DrawBSprite=DrawBSprite8;
DrawBSpriteC=DrawBSpriteC8;
DrawMonoBSprite=DrawMonoBSprite8;
DrawMonoBSpriteC=DrawMonoBSpriteC8;
WorkScreenDepth=1;
break;
case 15:
case 16:
DrawBox=DrawBox16;
DrawBoxC=DrawBoxC16;
DrawLine=DrawLine16;
DrawLineC=DrawLineC8;
DrawHLine=DrawHLine16;
DrawHLineC=DrawHLineC16;
DrawVLine=DrawVLine16;
DrawVLineC=DrawVLineC16;
DrawPoint=DrawPoint16;
DrawPointC=DrawPointC16;
DrawPixel=DrawPixel16;
DrawPixelC=DrawPixelC16;
QuickText =QuickText16;
QuickTextC=QuickTextC16;
QuickChar =QuickChar16;
QuickCharC=QuickCharC8_16_32;
DrawBSprite=DrawBSprite16;
DrawBSpriteC=DrawBSpriteC16;
DrawMonoBSprite=DrawMonoBSprite16;
DrawMonoBSpriteC=DrawMonoBSpriteC16;
WorkScreenDepth=2;
break;
case 24:
case 32:
DrawBox=DrawBox32;
DrawBoxC=DrawBoxC32;
DrawLine=DrawLine32;
DrawLineC=DrawLineC8;
DrawHLine=DrawHLine32;
DrawHLineC=DrawHLineC32;
DrawVLine=DrawVLine32;
DrawVLineC=DrawVLineC32;
DrawPoint=DrawPoint32;
DrawPointC=DrawPointC32;
DrawPixel=DrawPixel32;
DrawPixelC=DrawPixelC32;
QuickText =QuickText32;
QuickTextC=QuickTextC32;
QuickChar =QuickChar32;
QuickCharC=QuickCharC8_16_32;
DrawBSprite=DrawBSprite32;
DrawBSpriteC=DrawBSpriteC32;
DrawMonoBSprite=DrawMonoBSprite32;
DrawMonoBSpriteC=DrawMonoBSpriteC32;
WorkScreenDepth=4;
break;
}
}
//---------------------------------------------------------------
void SetWorkWindowBounds(SLONG left, SLONG top, SLONG width, SLONG height)
{
if((left+width)>=WorkScreenPixelWidth)
{
width -= (left+width)-WorkScreenPixelWidth;
if(width<1)
{
left = 0;
width = 1;
}
}
if((top+height)>=WorkScreenHeight)
{
height -= (top+height)-WorkScreenHeight;
if(height<1)
{
top = 0;
height = 1;
}
}
WorkWindowRect.Left = left;
WorkWindowRect.Top = top;
WorkWindowRect.Right = (left+width)-1;
WorkWindowRect.Bottom = (top+height)-1;
WorkWindowRect.Width = width;
WorkWindowRect.Height = height;
WorkWindowHeight = height;
WorkWindowWidth = width;
SetWorkWindow();
}
//---------------------------------------------------------------
MFPoint *GlobalToLocal(MFPoint *the_point)
{
the_point->X -= WorkWindowRect.Left;
the_point->Y -= WorkWindowRect.Top;
return the_point;
}
//---------------------------------------------------------------
void GlobalXYToLocal(SLONG *x,SLONG *y)
{
*x -= WorkWindowRect.Left;
*y -= WorkWindowRect.Top;
}
//---------------------------------------------------------------

View File

@ -0,0 +1,329 @@
// DrawBox.cpp
// Guy Simmons, 11th February 1997.
#include <MFHeader.h>
#define COLOUR_TO_LONG(c) (0x01010101*c)
#define COLOURW_TO_LONG(c) (0x00010001*c)
//---------------------------------------------------------------
void DrawBox8(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour)
{
UBYTE *ptr;
ULONG big_col,
*ptr_big,
w2;
SLONG temp_width;
ptr = WorkWindow+x+(y*WorkScreenWidth); //have to use window
temp_width = width;
if(width<=4)
{
// Thin rectangles.
for(;height>=0;height--)
{
for(width=temp_width;width>0;width--)
{
*ptr++ = (UBYTE)colour;
}
ptr += WorkScreenWidth-temp_width;
}
}
else
{
// Fat rectangles.
big_col = COLOUR_TO_LONG(colour);
for(;height>=0;height--)
{
for(width=x&3;width>0;width--)
{
*ptr++ = (UBYTE)colour;
}
w2 = temp_width-(x&3);
ptr_big = (ULONG*)ptr;
for(width=w2>>2;width>0;width--)
{
*ptr_big++ = big_col;
}
ptr = (UBYTE*)ptr_big;
for(width=w2&3;width>0;width--)
{
*ptr++ = (UBYTE)colour;
}
ptr += WorkScreenWidth-temp_width;
}
}
}
void DrawBox16(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour)
{
UWORD *ptr;
ULONG big_col,
*ptr_big,
w2;
SLONG temp_width;
ptr = (UWORD*)WorkWindow+x+(y*WorkScreenWidth>>1); //have to use window
temp_width = width;
if(width<=2)
{
// Thin rectangles.
for(;height>=0;height--)
{
for(width=temp_width;width>0;width--)
{
*ptr++ = (UWORD)colour;
}
ptr += WorkScreenWidth-temp_width;
}
}
else
{
// Fat rectangles.
big_col = COLOURW_TO_LONG(colour);
for(;height>=0;height--)
{
for(width=x&1;width>0;width--)
{
*ptr++ = (UWORD)colour;
}
w2 = temp_width-(x&1);
ptr_big = (ULONG*)ptr;
for(width=w2>>1;width>0;width--)
{
*ptr_big++ = big_col;
}
ptr = (UWORD*)ptr_big;
for(width=w2&1;width>0;width--)
{
*ptr++ = (UBYTE)colour;
}
ptr += (WorkScreenWidth>>1)-temp_width;
}
}
}
void DrawBox32(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour)
{
ULONG *ptr;
SLONG temp_width;
ptr = (ULONG*)WorkWindow+x+(y*WorkScreenWidth>>2); //have to use window
temp_width = width;
{
// Thin rectangles.
for(;height>=0;height--)
{
for(width=temp_width;width>0;width--)
{
*ptr++ = colour;
}
ptr += ((WorkScreenWidth>>2)-temp_width);
}
}
}
//---------------------------------------------------------------
void DrawBoxC8(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour)
{
UBYTE *ptr;
ULONG big_col,
*ptr_big,
w2;
SLONG temp_width;
if(x>=WorkWindowWidth || y>=WorkWindowHeight)
return;
if(x<0)
{
width += x;
x = 0;
}
if(y<0)
{
height += y;
y = 0;
}
if((x+width)>=WorkWindowWidth)
{
width -= (x+width)-WorkWindowWidth;
}
if((y+height)>=WorkWindowHeight)
{
height -= (y+height)-WorkWindowHeight;
}
if(width<=0 || height<=0)
return;
ptr = WorkWindow+x+(y*WorkScreenWidth); //have to use window
temp_width = width;
if(width<=4)
{
// Thin rectangles.
for(;height;height--)
{
for(width=temp_width;width>0;width--)
{
*ptr++ = (UBYTE)colour;
}
ptr += WorkScreenWidth-temp_width;
}
}
else
{
// Fat rectangles.
big_col = COLOUR_TO_LONG(colour);
for(;height;height--)
{
for(width=x&3;width>0;width--)
{
*ptr++ = (UBYTE)colour;
}
w2 = temp_width-(x&3);
ptr_big = (ULONG*)ptr;
for(width=w2>>2;width>0;width--)
{
*ptr_big++ = big_col;
}
ptr = (UBYTE*)ptr_big;
for(width=w2&3;width>0;width--)
{
*ptr++ = (UBYTE)colour;
}
ptr += WorkScreenWidth-temp_width;
}
}
}
void DrawBoxC16(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour)
{
UWORD *ptr;
ULONG big_col,
*ptr_big,
w2;
SLONG temp_width;
if(x>=WorkWindowWidth || y>=WorkWindowHeight)
return;
if(x<0)
{
width += x;
x = 0;
}
if(y<0)
{
height += y;
y = 0;
}
if((x+width)>=WorkWindowWidth)
{
width -= (x+width)-WorkWindowWidth;
}
if((y+height)>=WorkWindowHeight)
{
height -= (y+height)-WorkWindowHeight;
}
if(width<=0 || height<=0)
return;
ptr = (UWORD*)WorkWindow+x+(y*WorkScreenWidth>>1); //have to use window
temp_width = width;
if(width<=2)
{
// Thin rectangles.
for(;height;height--)
{
for(width=temp_width;width>0;width--)
{
*ptr++ = (UWORD)colour;
}
ptr += (WorkScreenWidth>>1)-temp_width;
}
}
else
{
// Fat rectangles.
big_col = COLOURW_TO_LONG(colour);
for(;height;height--)
{
for(width=x&1;width>0;width--)
{
*ptr++ = (UWORD)colour;
}
w2 = temp_width-(x&1);
ptr_big = (ULONG*)ptr;
for(width=w2>>1;width>0;width--)
{
*ptr_big++ = big_col;
}
ptr = (UWORD*)ptr_big;
for(width=w2&1;width>0;width--)
{
*ptr++ = (UWORD)colour;
}
ptr += (WorkScreenWidth>>1)-temp_width;
}
}
}
void DrawBoxC32(SLONG x,SLONG y,SLONG width,SLONG height,ULONG colour)
{
ULONG *ptr;
SLONG temp_width;
if(x>=WorkWindowWidth || y>=WorkWindowHeight)
return;
if(x<0)
{
width += x;
x = 0;
}
if(y<0)
{
height += y;
y = 0;
}
if((x+width)>=WorkWindowWidth)
{
width -= (x+width)-WorkWindowWidth;
}
if((y+height)>=WorkWindowHeight)
{
height -= (y+height)-WorkWindowHeight;
}
if(width<=0 || height<=0)
return;
ptr = (ULONG*)WorkWindow+(x)+(y*WorkScreenWidth>>2); //have to use window
temp_width = width;
for(;height;height--)
{
for(width=temp_width;width>0;width--)
{
*ptr++ = colour;
}
ptr += ((WorkScreenWidth>>2)-temp_width);
}
}
//---------------------------------------------------------------

View File

@ -0,0 +1,562 @@
// DrawLine.c
// Guy Simmons, 7th October 1996
#include <MFHeader.h>
//---------------------------------------------------------------
// Standard Bresenham algorithm.
void DrawLine8(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour)
{
UBYTE *line_dest;
SLONG ax,ay,
d,
dx,dy,
modulo,
sx,sy,
x,y;
dx = x2-x1;
dy = y2-y1;
if(abs(dx)+abs(dy)>10000)
return;
ax = abs(dx)<<1;
ay = abs(dy)<<1;
sx = sgn(dx);
sy = sgn(dy);
modulo = WorkScreenWidth*sy;
x = x1;
y = y1;
line_dest = WorkWindow+x+(y*WorkScreenWidth);
if(ax>ay)
{
d = ay-(ax>>1);
while(1)
{
*line_dest = (UBYTE)colour;
if(x==x2)
return;
if(d>=0)
{
d -= ax;
line_dest += modulo;
}
x += sx;
d += ay;
line_dest += sx;
}
}
else
{
d = ax-(ay>>1);
while(1)
{
*line_dest = (UBYTE)colour;
if(y==y2)
return;
if(d>=0)
{
d -= ay;
line_dest += sx;
}
y += sy;
d += ax;
line_dest += modulo;
}
}
}
void DrawLine16(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour)
{
UWORD *line_dest;
SLONG ax,ay,
d,
dx,dy,
modulo,
sx,sy,
x,y;
dx = x2-x1;
dy = y2-y1;
if(abs(dx)+abs(dy)>10000)
return;
ax = abs(dx)<<1;
ay = abs(dy)<<1;
sx = sgn(dx);
sy = sgn(dy);
modulo = (WorkScreenWidth>>1)*sy;
x = x1;
y = y1;
line_dest = (UWORD*)WorkWindow+x+(y*WorkScreenWidth>>1);
if(ax>ay)
{
d = ay-(ax>>1);
while(1)
{
*line_dest = (UWORD)colour;
if(x==x2)
return;
if(d>=0)
{
d -= ax;
line_dest += modulo;
}
x += sx;
d += ay;
line_dest += sx;
}
}
else
{
d = ax-(ay>>1);
while(1)
{
*line_dest = (UWORD)colour;
if(y==y2)
return;
if(d>=0)
{
d -= ay;
line_dest += sx;
}
y += sy;
d += ax;
line_dest += modulo;
}
}
}
void DrawLine32(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour)
{
ULONG *line_dest;
SLONG ax,ay,
d,
dx,dy,
modulo,
sx,sy,
x,y;
dx = x2-x1;
dy = y2-y1;
if(abs(dx)+abs(dy)>10000)
return;
ax = abs(dx)<<1;
ay = abs(dy)<<1;
sx = sgn(dx);
sy = sgn(dy);
modulo = (WorkScreenWidth>>2)*sy;
x = x1;
y = y1;
line_dest = (ULONG*)WorkWindow+x+(y*WorkScreenWidth>>2);
if(ax>ay)
{
d = ay-(ax>>1);
while(1)
{
*line_dest = (ULONG)colour;
if(x==x2)
return;
if(d>=0)
{
d -= ax;
line_dest += modulo;
}
x += sx;
d += ay;
line_dest += sx;
}
}
else
{
d = ax-(ay>>1);
while(1)
{
*line_dest = (ULONG)colour;
if(y==y2)
return;
if(d>=0)
{
d -= ay;
line_dest += sx;
}
y += sy;
d += ax;
line_dest += modulo;
}
}
}
//---------------------------------------------------------------
// Standard Bresenham algorithm.
// Bloody slow at clipping tho'
void DrawLineC8(SLONG x1,SLONG y1,SLONG x2,SLONG y2,ULONG colour)
{
SLONG ax,ay,
d,
dx,dy,
sx,sy,
x,y;
dx = x2-x1;
dy = y2-y1;
if(abs(dx)+abs(dy)>10000)
return;
ax = abs(dx)<<1;
ay = abs(dy)<<1;
sx = sgn(dx);
sy = sgn(dy);
x = x1;
y = y1;
if(ax>ay)
{
d = ay-(ax>>1);
while(1)
{
DrawPixelC(x,y,colour);
if(x==x2)
return;
if(d>=0)
{
y += sy;
d -= ax;
}
x += sx;
d += ay;
}
}
else
{
d = ax-(ay>>1);
while(1)
{
DrawPixelC(x,y,colour);
if(y==y2)
return;
if(d>=0)
{
x += sx;
d -= ay;
}
y += sy;
d += ax;
}
}
}
//---------------------------------------------------------------
void DrawHLine8(SLONG x1,SLONG x2,SLONG y,ULONG colour)
{
UBYTE *line_dest;
ULONG count;
if(x1>x2)
{
swap(x1,x2);
}
line_dest = WorkWindow+x1+(y*WorkScreenWidth);
count = (x2-x1)+1;
while(count--)
{
*(line_dest++) = (UBYTE)colour;
}
}
void DrawHLine16(SLONG x1,SLONG x2,SLONG y,ULONG colour)
{
UWORD *line_dest;
ULONG count;
if(x1>x2)
{
swap(x1,x2);
}
line_dest = (UWORD*)WorkWindow+x1+(y*WorkScreenWidth>>1);
count = (x2-x1)+1;
while(count--)
{
*(line_dest++) = (UWORD)colour;
}
}
void DrawHLine32(SLONG x1,SLONG x2,SLONG y,ULONG colour)
{
ULONG *line_dest;
ULONG count;
if(x1>x2)
{
swap(x1,x2);
}
line_dest = (ULONG*)WorkWindow+x1+(y*WorkScreenWidth>>2);
count = (x2-x1)+1;
while(count--)
{
*(line_dest++) = (ULONG)colour;
}
}
//---------------------------------------------------------------
void DrawHLineC8(SLONG x1,SLONG x2,SLONG y,ULONG colour)
{
UBYTE *line_dest;
ULONG count;
if(y>=0 && y<WorkWindowHeight)
{
if(x1>x2)
{
swap(x1,x2);
}
if(x1<WorkWindowWidth && x2>=0)
{
if(x1<0)
x1 = 0;
if(x2>=WorkWindowWidth)
x2 = WorkWindowWidth-1;
line_dest = WorkWindow+x1+(y*WorkScreenWidth);
count = (x2-x1)+1;
while(count--)
{
*(line_dest++) = (UBYTE)colour;
}
}
}
}
void DrawHLineC16(SLONG x1,SLONG x2,SLONG y,ULONG colour)
{
UWORD *line_dest;
ULONG count;
if(y>=0 && y<WorkWindowHeight)
{
if(x1>x2)
{
swap(x1,x2);
}
if(x1<WorkWindowWidth && x2>=0)
{
if(x1<0)
x1 = 0;
if(x2>=WorkWindowWidth)
x2 = WorkWindowWidth-1;
line_dest = (UWORD*)WorkWindow+x1+(y*WorkScreenWidth>>1);
count = (x2-x1)+1;
while(count--)
{
*(line_dest++) = (UWORD)colour;
}
}
}
}
void DrawHLineC32(SLONG x1,SLONG x2,SLONG y,ULONG colour)
{
ULONG *line_dest;
ULONG count;
if(y>=0 && y<WorkWindowHeight)
{
if(x1>x2)
{
swap(x1,x2);
}
if(x1<WorkWindowWidth && x2>=0)
{
if(x1<0)
x1 = 0;
if(x2>=WorkWindowWidth)
x2 = WorkWindowWidth-1;
line_dest = (ULONG*)WorkWindow+x1+(y*WorkScreenWidth>>2);
count = (x2-x1)+1;
while(count--)
{
*(line_dest++) = (ULONG)colour;
}
}
}
}
//---------------------------------------------------------------
void DrawVLine8(SLONG x,SLONG y1,SLONG y2,ULONG colour)
{
UBYTE *line_dest;
ULONG count,
modulo;
if(y1>y2)
{
swap(y1,y2);
}
line_dest = WorkWindow+x+(y1*WorkScreenWidth);
count = (y2-y1)+1;
modulo = WorkScreenWidth;
while(count--)
{
*line_dest = (UBYTE)colour;
line_dest += modulo;
}
}
void DrawVLine16(SLONG x,SLONG y1,SLONG y2,ULONG colour)
{
UWORD *line_dest;
ULONG count,
modulo;
if(y1>y2)
{
swap(y1,y2);
}
line_dest = (UWORD*)WorkWindow+x+(y1*WorkScreenWidth>>1);
count = (y2-y1)+1;
modulo = WorkScreenWidth>>1;
while(count--)
{
*line_dest = (UWORD)colour;
line_dest += modulo;
}
}
void DrawVLine32(SLONG x,SLONG y1,SLONG y2,ULONG colour)
{
ULONG *line_dest;
ULONG count,
modulo;
if(y1>y2)
{
swap(y1,y2);
}
line_dest = (ULONG*)WorkWindow+x+(y1*WorkScreenWidth>>2);
count = (y2-y1)+1;
modulo = WorkScreenWidth>>2;
while(count--)
{
*line_dest = (ULONG)colour;
line_dest += modulo;
}
}
//---------------------------------------------------------------
void DrawVLineC8(SLONG x,SLONG y1,SLONG y2,ULONG colour)
{
UBYTE *line_dest;
ULONG count;
if(x>=0 && x<WorkWindowWidth)
{
if(y1>y2)
{
swap(y1,y2);
}
if(y1<WorkWindowHeight && y2>=0)
{
if(y1<0)
y1 = 0;
if(y2>=WorkWindowHeight)
y2 = WorkWindowHeight-1;
line_dest = WorkWindow+x+(y1*WorkScreenWidth);
count = (y2-y1)+1;
while(count--)
{
*line_dest = (UBYTE)colour;
line_dest += WorkScreenWidth;
}
}
}
}
void DrawVLineC16(SLONG x,SLONG y1,SLONG y2,ULONG colour)
{
UWORD *line_dest;
ULONG count;
if(x>=0 && x<WorkWindowWidth)
{
if(y1>y2)
{
swap(y1,y2);
}
if(y1<WorkWindowHeight && y2>=0)
{
if(y1<0)
y1 = 0;
if(y2>=WorkWindowHeight)
y2 = WorkWindowHeight-1;
line_dest = (UWORD*)WorkWindow+x+(y1*WorkScreenWidth>>1);
count = (y2-y1)+1;
while(count--)
{
*line_dest = (UWORD)colour;
line_dest += WorkScreenWidth>>1;
}
}
}
}
void DrawVLineC32(SLONG x,SLONG y1,SLONG y2,ULONG colour)
{
ULONG *line_dest;
ULONG count;
if(x>=0 && x<WorkWindowWidth)
{
if(y1>y2)
{
swap(y1,y2);
}
if(y1<WorkWindowHeight && y2>=0)
{
if(y1<0)
y1 = 0;
if(y2>=WorkWindowHeight)
y2 = WorkWindowHeight-1;
line_dest = (ULONG*)WorkWindow+x+(y1*WorkScreenWidth>>2);
count = (y2-y1)+1;
while(count--)
{
*line_dest = (ULONG)colour;
line_dest += WorkScreenWidth>>2;
}
}
}
}
//---------------------------------------------------------------

View File

@ -0,0 +1,75 @@
// DrawPoint.c
// Guy Simmons, 7th October 1996.
#include <MFHeader.h>
//---------------------------------------------------------------
void DrawPoint8(MFPoint *the_point,ULONG colour)
{
*(WorkWindow+the_point->X+(the_point->Y*WorkScreenWidth)) = (UBYTE)colour;
}
void DrawPoint16(MFPoint *the_point,ULONG colour)
{
UWORD *ptr;
ptr = (UWORD*)WorkWindow+the_point->X+(the_point->Y*WorkScreenWidth>>1);
*ptr = (UWORD)colour;
}
void DrawPoint32(MFPoint *the_point,ULONG colour)
{
ULONG *ptr;
ptr = (ULONG*)WorkWindow+the_point->X+(the_point->Y*WorkScreenWidth>>2);
*ptr = (ULONG)colour;
}
//---------------------------------------------------------------
void DrawPointC8(MFPoint *the_point,ULONG colour)
{
if (
the_point->X>=0 &&
the_point->X<WorkWindowWidth &&
the_point->Y>=0 &&
the_point->Y<WorkWindowHeight
)
{
*(WorkWindow+the_point->X+(the_point->Y*WorkScreenWidth)) = (UBYTE)colour;
}
}
void DrawPointC16(MFPoint *the_point,ULONG colour)
{
UWORD *ptr;
if (
the_point->X>=0 &&
the_point->X<WorkWindowWidth &&
the_point->Y>=0 &&
the_point->Y<WorkWindowHeight
)
{
ptr = (UWORD*)WorkWindow+the_point->X+(the_point->Y*WorkScreenWidth>>1);
*ptr = (UWORD)colour;
}
}
void DrawPointC32(MFPoint *the_point,ULONG colour)
{
ULONG *ptr;
if (
the_point->X>=0 &&
the_point->X<WorkWindowWidth &&
the_point->Y>=0 &&
the_point->Y<WorkWindowHeight
)
{
ptr = (ULONG*)WorkWindow+the_point->X+(the_point->Y*WorkScreenWidth>>2);
*ptr = (ULONG)colour;
}
}
//---------------------------------------------------------------

View File

@ -0,0 +1,59 @@
// DrawPixel.c
// Guy Simmons, 7th October 1996.
#include <MFHeader.h>
//---------------------------------------------------------------
void DrawPixel8(SLONG x,SLONG y,ULONG colour)
{
*(WorkWindow+x+(y*WorkScreenWidth)) = (UBYTE)colour;
}
void DrawPixel16(SLONG x,SLONG y,ULONG colour)
{
UWORD *ptr;
ptr = (UWORD*)WorkWindow+x+(y*WorkScreenWidth>>1);
*ptr = (UWORD)colour;
}
void DrawPixel32(SLONG x,SLONG y,ULONG colour)
{
ULONG *ptr;
ptr = (ULONG*)WorkWindow+x+(y*WorkScreenWidth>>2);
*ptr = (ULONG)colour;
}
//---------------------------------------------------------------
void DrawPixelC8(SLONG x,SLONG y,ULONG colour)
{
if(x>=0 && x<WorkWindowWidth && y>=0 && y<WorkWindowHeight)
{
*(WorkWindow+x+(y*WorkScreenWidth)) = (UBYTE)colour;
}
}
void DrawPixelC16(SLONG x,SLONG y,ULONG colour)
{
if(x>=0 && x<WorkWindowWidth && y>=0 && y<WorkWindowHeight)
{
UWORD *ptr;
ptr = (UWORD*)WorkWindow+x+(y*WorkScreenWidth>>1);
*ptr = (UWORD)colour;
}
}
void DrawPixelC32(SLONG x,SLONG y,ULONG colour)
{
if(x>=0 && x<WorkWindowWidth && y>=0 && y<WorkWindowHeight)
{
ULONG *ptr;
ptr = (ULONG*)WorkWindow+x+(y*WorkScreenWidth>>2);
*ptr = (ULONG)colour;
}
}
//---------------------------------------------------------------

View File

@ -0,0 +1,24 @@
// DrawRect.cpp
// Guy Simmons, 11th February 1997.
#include <MFHeader.h>
//---------------------------------------------------------------
void DrawRect(MFRect *the_rect,ULONG colour)
{
the_rect = the_rect;
colour = colour;
}
//---------------------------------------------------------------
void DrawRectC(MFRect *the_rect,ULONG colour)
{
the_rect = the_rect;
colour = colour;
}
//---------------------------------------------------------------

View File

@ -0,0 +1,145 @@
// Maths.cpp
// Guy Simmons, 27th March 1997.
#include <MFHeader.h>
#ifdef TARGET_DC
#include <shintr.h>
#endif
//---------------------------------------------------------------
#define LookUp ax = AtanTable[(ax<<8)/bx];
#define xchg(a,b) {a^=b;b^=a;a^=b;}
SLONG Arctan(SLONG X,SLONG Y)
{
register SLONG ax,bx;
ax = X;
if(ax)
goto just_do_it;
bx = Y;
if(bx)
goto done_it;
return 0;
just_do_it:
bx = Y;
done_it:
if(ax < 0)
goto xneg;
// x positive
if(bx < 0)
goto xposyneg;
// x positive, y positive
if(ax < bx)
goto ppyprimary;
// ppxprimary
xchg(ax,bx)
LookUp
return ax+512;
ppyprimary:
LookUp
return (-ax)+1024;
xposyneg: //*******************************************************************
bx = -bx;
if(ax < bx)
goto pnyprimary;
// pnxprimary
xchg(ax,bx)
LookUp
return (-ax)+512;
pnyprimary:
LookUp
return ax;
xneg:
ax = -ax;
if(bx < 0)
goto xnegyneg;
// x negative, y positive
if(ax < bx)
goto npyprimary;
// npxprimary
xchg(ax,bx)
LookUp
return (-ax)+1536;
npyprimary:
LookUp
return ax+1024;
// x negative, y negative
xnegyneg:
bx = -bx;
if(ax < bx)
goto nnyprimary;
// nnxprimary
xchg(ax,bx)
LookUp
return ax+1536;
nnyprimary:
LookUp
return (-ax)+2048;
}
//---------------------------------------------------------------
#ifndef TARGET_DC
UWORD ini_table[] =
{
1, 2, 2, 4,
5, 8, 11, 16,
22, 32, 45, 64,
90, 128, 181, 256,
362, 512, 724, 1024,
1448, 2048, 2896, 4096,
5792, 8192, 11585, 16384,
23170, 32768, 46340, 65535
};
#ifdef _MSC_VER
SLONG Root(SLONG square)
{
__asm
{
xor ebx,ebx
mov ecx,square
bsr eax,ecx
je done_it
movzx ebx,ini_table[eax*2]
do_it:
mov eax,ecx
xor edx,edx
div ebx
cmp eax,ebx
jge done_it
add ebx,eax
shr ebx,1
jmp do_it
done_it:
mov eax,ebx
}
}
#endif
#else //#ifndef TARGET_DC
// Just use the standard rout for the moment - it uses a fast path anyway.
SLONG Root ( SLONG square )
{
return ( (int) sqrtf ( (float)square ) );
}
#endif //#else //#ifndef TARGET_DC
//---------------------------------------------------------------

View File

@ -0,0 +1,481 @@
// QuickText.c
// Guy Simmons, 7th October 1996.
#include <MFHeader.h>
extern UBYTE *CharTable[];
#define DRAW_CHAR for(c0=char_height;c0;c0--,string_dest+=WorkScreenWidth) \
{ \
for(c1=0;c1<char_width;c1++) \
{ \
if(*(the_char_def++)) \
{ \
*(string_dest+c1) = (UBYTE)colour; \
} \
} \
}
#define DRAW_CHAR16 for(c0=char_height;c0;c0--,string_dest+=WorkScreenWidth>>1) \
{ \
for(c1=0;c1<char_width;c1++) \
{ \
if(*(the_char_def++)) \
{ \
*(string_dest+c1) = (UWORD)colour; \
} \
} \
}
#define DRAW_CHAR32 for(c0=char_height;c0;c0--,string_dest+=WorkScreenWidth>>2) \
{ \
for(c1=0;c1<char_width;c1++) \
{ \
if(*(the_char_def++)) \
{ \
*(string_dest+c1) = (ULONG)colour; \
} \
} \
}
//---------------------------------------------------------------
void QuickText8(SLONG x,SLONG y,CBYTE *the_string,ULONG colour)
{
UBYTE *the_char_def,
*string_dest;
ULONG char_height,
char_width;
ULONG c0,c1;
while(*the_string)
{
the_char_def = CharTable[*(the_string++)];
char_width = *(the_char_def++);
char_height = *(the_char_def++);
string_dest = WorkWindow+x+((y+*(the_char_def++))*WorkScreenWidth);
DRAW_CHAR
x += char_width+1;
}
}
void QuickText16(SLONG x,SLONG y,CBYTE *the_string,ULONG colour)
{
UBYTE *the_char_def;
UWORD *string_dest;
ULONG char_height,
char_width;
ULONG c0,c1;
while(*the_string)
{
the_char_def = CharTable[*(the_string++)];
char_width = *(the_char_def++);
char_height = *(the_char_def++);
string_dest = (UWORD*)WorkWindow+x+((y+*(the_char_def++))*WorkScreenWidth>>1);
DRAW_CHAR16
x += char_width+1;
}
}
void QuickText32(SLONG x,SLONG y,CBYTE *the_string,ULONG colour)
{
UBYTE *the_char_def;
ULONG *string_dest;
ULONG char_height,
char_width;
ULONG c0,c1;
while(*the_string)
{
the_char_def = CharTable[*(the_string++)];
char_width = *(the_char_def++);
char_height = *(the_char_def++);
string_dest = (ULONG*)WorkWindow+x+((y+*(the_char_def++))*WorkScreenWidth>>2);
DRAW_CHAR32
x += char_width+1;
}
}
//---------------------------------------------------------------
void QuickTextC8(SLONG x,SLONG y,CBYTE *the_string,ULONG colour)
{
UBYTE *string_dest,
*the_char_def,
*the_pixel;
SLONG c0,c1,
char_draw_height,
char_draw_width,
char_height,
char_width,
char_v_offset,
char_x_offset,
char_y,
char_y_offset,
clip;
if(x>=WorkWindowWidth || y>=WorkWindowHeight)
return;
while(*the_string)
{
the_char_def = CharTable[*(the_string++)];
char_width = *(the_char_def++);
char_height = *(the_char_def++);
char_v_offset = *(the_char_def++);
char_draw_width = char_width;
char_draw_height= char_height;
char_x_offset = 0;
char_y_offset = 0;
char_y = y;
clip = 0;
if(x<0)
{
if((x+char_width)<0)
goto done_char;
char_x_offset = -x;
char_draw_width += x;
x = 0;
clip = 1;
}
if(y<0)
{
if((y+char_v_offset+char_height)<0)
goto done_char;
if((y+char_v_offset)<0)
{
char_y_offset = -(y+char_v_offset);
char_draw_height+= y+char_v_offset;
char_v_offset = 0;
}
else
{
char_v_offset += y;
}
char_y = 0;
clip = 1;
}
if((x+char_draw_width)>=WorkWindowWidth)
{
char_draw_width -= (x+char_draw_width)-WorkWindowWidth;
clip = 1;
}
if((y+char_v_offset+char_draw_height)>=WorkWindowHeight)
{
char_draw_height-= (char_y+char_v_offset+char_draw_height)-WorkWindowHeight;
if(char_draw_height<=0)
goto done_char;
clip = 1;
}
string_dest = WorkWindow+x+((char_y+char_v_offset)*WorkScreenWidth);
if(clip)
{
for(c0=0;c0<char_draw_height;c0++,string_dest+=WorkScreenWidth,the_char_def+=char_width)
{
the_pixel = the_char_def+(char_y_offset*char_width)+char_x_offset;
for(c1=0;c1<char_draw_width;c1++)
{
if(*(the_pixel++))
{
*(string_dest+c1) = (UBYTE)colour;
}
}
}
}
else
{
DRAW_CHAR
}
done_char:
x += char_draw_width+1;
if(x>=WorkWindowWidth)
return;
}
}
void QuickTextC16(SLONG x,SLONG y,CBYTE *the_string,ULONG colour)
{
UWORD *string_dest;
UBYTE *the_char_def,
*the_pixel;
SLONG c0,c1,
char_draw_height,
char_draw_width,
char_height,
char_width,
char_v_offset,
char_x_offset,
char_y,
char_y_offset,
clip;
if(x>=WorkWindowWidth || y>=WorkWindowHeight)
return;
while(*the_string)
{
the_char_def = CharTable[*(the_string++)];
char_width = *(the_char_def++);
char_height = *(the_char_def++);
char_v_offset = *(the_char_def++);
char_draw_width = char_width;
char_draw_height= char_height;
char_x_offset = 0;
char_y_offset = 0;
char_y = y;
clip = 0;
if(x<0)
{
if((x+char_width)<0)
goto done_char;
char_x_offset = -x;
char_draw_width += x;
x = 0;
clip = 1;
}
if(y<0)
{
if((y+char_v_offset+char_height)<0)
goto done_char;
if((y+char_v_offset)<0)
{
char_y_offset = -(y+char_v_offset);
char_draw_height+= y+char_v_offset;
char_v_offset = 0;
}
else
{
char_v_offset += y;
}
char_y = 0;
clip = 1;
}
if((x+char_draw_width)>=WorkWindowWidth)
{
char_draw_width -= (x+char_draw_width)-WorkWindowWidth;
clip = 1;
}
if((y+char_v_offset+char_draw_height)>=WorkWindowHeight)
{
char_draw_height-= (char_y+char_v_offset+char_draw_height)-WorkWindowHeight;
if(char_draw_height<=0)
goto done_char;
clip = 1;
}
string_dest = (UWORD*)WorkWindow+x+((char_y+char_v_offset)*WorkScreenWidth>>1);
if(clip)
{
for(c0=0;c0<char_draw_height;c0++,string_dest+=WorkScreenWidth,the_char_def+=char_width)
{
the_pixel = the_char_def+(char_y_offset*char_width)+char_x_offset;
for(c1=0;c1<char_draw_width;c1++)
{
if(*(the_pixel++))
{
*(string_dest+c1) = (UWORD)colour;
}
}
}
}
else
{
DRAW_CHAR16
}
done_char:
x += char_draw_width+1;
if(x>=WorkWindowWidth)
return;
}
}
void QuickTextC32(SLONG x,SLONG y,CBYTE *the_string,ULONG colour)
{
ULONG *string_dest;
UBYTE *the_char_def,
*the_pixel;
SLONG c0,c1,
char_draw_height,
char_draw_width,
char_height,
char_width,
char_v_offset,
char_x_offset,
char_y,
char_y_offset,
clip;
if(x>=WorkWindowWidth || y>=WorkWindowHeight)
return;
while(*the_string)
{
the_char_def = CharTable[*(the_string++)];
char_width = *(the_char_def++);
char_height = *(the_char_def++);
char_v_offset = *(the_char_def++);
char_draw_width = char_width;
char_draw_height= char_height;
char_x_offset = 0;
char_y_offset = 0;
char_y = y;
clip = 0;
if(x<0)
{
if((x+char_width)<0)
goto done_char;
char_x_offset = -x;
char_draw_width += x;
x = 0;
clip = 1;
}
if(y<0)
{
if((y+char_v_offset+char_height)<0)
goto done_char;
if((y+char_v_offset)<0)
{
char_y_offset = -(y+char_v_offset);
char_draw_height+= y+char_v_offset;
char_v_offset = 0;
}
else
{
char_v_offset += y;
}
char_y = 0;
clip = 1;
}
if((x+char_draw_width)>=WorkWindowWidth)
{
char_draw_width -= (x+char_draw_width)-WorkWindowWidth;
clip = 1;
}
if((y+char_v_offset+char_draw_height)>=WorkWindowHeight)
{
char_draw_height-= (char_y+char_v_offset+char_draw_height)-WorkWindowHeight;
if(char_draw_height<=0)
goto done_char;
clip = 1;
}
string_dest = (ULONG*)WorkWindow+x+((char_y+char_v_offset)*WorkScreenWidth>>2);
if(clip)
{
for(c0=0;c0<char_draw_height;c0++,string_dest+=WorkScreenWidth,the_char_def+=char_width)
{
the_pixel = the_char_def+(char_y_offset*char_width)+char_x_offset;
for(c1=0;c1<char_draw_width;c1++)
{
if(*(the_pixel++))
{
*(string_dest+c1) = (UWORD)colour;
}
}
}
}
else
{
DRAW_CHAR32
}
done_char:
x += char_draw_width+1;
if(x>=WorkWindowWidth)
return;
}
}
//---------------------------------------------------------------
void QuickChar8(SLONG x,SLONG y,CBYTE the_char,ULONG colour)
{
UBYTE *the_char_def,
*string_dest;
ULONG char_height,
char_width;
ULONG c0,c1;
the_char_def = CharTable[the_char];
char_width = *(the_char_def++);
char_height = *(the_char_def++);
string_dest = WorkWindow+x+((y+*(the_char_def++))*WorkScreenWidth);
DRAW_CHAR
}
void QuickChar16(SLONG x,SLONG y,CBYTE the_char,ULONG colour)
{
UBYTE *the_char_def;
UWORD *string_dest;
ULONG char_height,
char_width;
ULONG c0,c1;
the_char_def = CharTable[the_char];
char_width = *(the_char_def++);
char_height = *(the_char_def++);
string_dest = (UWORD*)WorkWindow+x+((y+*(the_char_def++))*WorkScreenWidth>>1);
DRAW_CHAR16
}
void QuickChar32(SLONG x,SLONG y,CBYTE the_char,ULONG colour)
{
UBYTE *the_char_def;
ULONG *string_dest;
ULONG char_height,
char_width;
ULONG c0,c1;
the_char_def = CharTable[the_char];
char_width = *(the_char_def++);
char_height = *(the_char_def++);
string_dest = (ULONG*)WorkWindow+x+((y+*(the_char_def++))*WorkScreenWidth>>2);
DRAW_CHAR32
}
//---------------------------------------------------------------
void QuickCharC8_16_32(SLONG x,SLONG y,CBYTE the_char,ULONG colour)
{
if(x>=WorkWindowWidth || y>=WorkWindowHeight)
return;
if(x<0 || y<0)
return;
QuickChar(x,y,the_char,colour);
}
//---------------------------------------------------------------
SLONG QTStringWidth(CBYTE *the_string)
{
SLONG width = 0;
while(*the_string)
{
width += (*CharTable[*(the_string++)])+1;
}
return width;
}
//---------------------------------------------------------------

View File

@ -0,0 +1,809 @@
// Sprites.cpp
// Guy Simmons, 13th February 1997.
#include <MFHeader.h>
extern UBYTE CurrentPalette[256*3];
#define RGB_TO_RGB565(r,g,b) (UWORD)(((r>>4)<<11)|((g>>3)<<5)|(b>>4))
#define RGB_TO_RGB888(r,g,b) ((r<<16)|(g<<8)|(b))
#define COL_TO_RGB565(col,PALETTE) (UWORD)(((PALETTE[(col)*3]>>3)<<11)|((PALETTE[(col)*3+1]>>2)<<5)|(PALETTE[(col)*3+2]>>3))
#define COL_TO_RGB888(col,PALETTE) ((PALETTE[(col)*3]<<16)|(PALETTE[(col)*3+1]<<8)|PALETTE[(col)*3+2])
#define DRAW_SPRITE while(1) \
{ \
packet = *src_ptr++; \
switch(packet) \
{ \
case END_LINE: \
dst_ptr += WorkScreenWidth; \
line_ptr = dst_ptr; \
break; \
case COPY_PIXELS: \
c0 = (*src_ptr++)+1; \
while(c0--) \
*line_ptr++ = *src_ptr++; \
break; \
case SKIP_PIXELS: \
line_ptr += (*src_ptr++)+1; \
break; \
case DUPLICATE_PIXELS: \
c0 = (*src_ptr++)+1; \
dup_pixel = *src_ptr++; \
while(c0--) \
*line_ptr++ = dup_pixel; \
break; \
case FINISHED: \
return; \
} \
}
#define DRAW_SPRITE16(pal) while(1) \
{ \
packet = *src_ptr++; \
switch(packet) \
{ \
case END_LINE: \
dst_ptr += WorkScreenPixelWidth; \
line_ptr = dst_ptr; \
break; \
case COPY_PIXELS: \
c0 = (*src_ptr++)+1; \
while(c0--) \
{ \
*line_ptr++ =COL_TO_RGB565(*src_ptr,pal); \
src_ptr++; \
} \
break; \
case SKIP_PIXELS: \
line_ptr += *(src_ptr++)+1; \
break; \
case DUPLICATE_PIXELS: \
c0 = (*src_ptr++)+1; \
dup_pixel =COL_TO_RGB565(*src_ptr,pal); \
src_ptr++; \
while(c0--) \
*line_ptr++ = dup_pixel; \
break; \
case FINISHED: \
return; \
} \
}
#define DRAW_SPRITE32(pal) while(1) \
{ \
packet = *src_ptr++; \
switch(packet) \
{ \
case END_LINE: \
dst_ptr += WorkScreenPixelWidth; \
line_ptr = dst_ptr; \
break; \
case COPY_PIXELS: \
c0 = (*src_ptr++)+1; \
while(c0--) \
{ \
*line_ptr++ =COL_TO_RGB888(*src_ptr,pal); \
src_ptr++; \
} \
break; \
case SKIP_PIXELS: \
line_ptr += *(src_ptr++)+1; \
break; \
case DUPLICATE_PIXELS: \
c0 = (*src_ptr++)+1; \
dup_pixel =COL_TO_RGB888(*src_ptr,pal); \
src_ptr++; \
while(c0--) \
*line_ptr++ = dup_pixel; \
break; \
case FINISHED: \
return; \
} \
}
#define DRAW_M_SPRITE while(1) \
{ \
packet = *src_ptr++; \
switch(packet) \
{ \
case END_LINE: \
dst_ptr += WorkScreenPixelWidth; \
line_ptr = dst_ptr; \
break; \
case COPY_PIXELS: \
c0 = (*src_ptr++)+1; \
src_ptr += c0; \
while(c0--) \
*line_ptr++ = dup_pixel; \
break; \
case SKIP_PIXELS: \
line_ptr += (*src_ptr++)+1; \
break; \
case DUPLICATE_PIXELS: \
c0 = (*src_ptr++)+1; \
src_ptr++; \
while(c0--) \
*line_ptr++ = dup_pixel; \
break; \
case FINISHED: \
return; \
} \
}
#define V_SCAN while(v_scan) \
{ \
packet = *src_ptr++; \
switch(packet) \
{ \
case END_LINE: \
v_scan--; \
break; \
case COPY_PIXELS: \
src_ptr += 1+*(src_ptr++); \
break; \
case SKIP_PIXELS: \
src_ptr++; \
break; \
case DUPLICATE_PIXELS: \
src_ptr += 2; \
break; \
} \
}
#define L_SCAN while(l_scan&&sprite_height) \
{ \
packet = *src_ptr++; \
switch(packet) \
{ \
case END_LINE: \
dst_ptr += WorkScreenPixelWidth; \
line_ptr = dst_ptr; \
sprite_height--; \
pixel_count = 0; \
break; \
case COPY_PIXELS: \
c0 = (*src_ptr++)+1; \
if((pixel_count+c0)>=l_scan) \
{ \
src_ptr += l_scan-pixel_count; \
c0 -= l_scan-pixel_count; \
pixel_count = l_scan; \
goto copy_pixels; \
} \
else \
{ \
pixel_count += c0; \
src_ptr += c0; \
} \
break; \
case SKIP_PIXELS: \
c0 = (*src_ptr++)+1; \
if((pixel_count+c0)>=l_scan) \
{ \
c0 -= l_scan-pixel_count; \
pixel_count = l_scan; \
goto skip_pixels; \
} \
else \
{ \
pixel_count += c0; \
} \
break; \
case DUPLICATE_PIXELS: \
c0 = (*src_ptr++)+1; \
if((pixel_count+c0)>=l_scan) \
{ \
c0 -= l_scan-pixel_count; \
pixel_count = l_scan; \
goto duplicate_pixels; \
} \
else \
{ \
pixel_count += c0; \
src_ptr++; \
} \
break; \
case FINISHED: \
return; \
} \
}
#define R_SCAN while(1) \
{ \
packet = *src_ptr++; \
switch(packet) \
{ \
case END_LINE: \
goto end_line; \
case COPY_PIXELS: \
src_ptr += 1+*(src_ptr++); \
break; \
case SKIP_PIXELS: \
src_ptr++; \
break; \
case DUPLICATE_PIXELS: \
src_ptr += 2; \
break; \
case FINISHED: \
return; \
} \
}
//---------------------------------------------------------------
void DrawBSpritePal16(SLONG x,SLONG y,BSprite *the_sprite,UBYTE *pal)
{
UBYTE packet,
*src_ptr;
ULONG c0;
UWORD dup_pixel,
*dst_ptr,
*line_ptr;
dst_ptr = (UWORD*)WorkWindow+x+(y*WorkScreenPixelWidth);
line_ptr = dst_ptr;
src_ptr = the_sprite->SpriteData;
DRAW_SPRITE16(pal)
}
void DrawBSpritePal32(SLONG x,SLONG y,BSprite *the_sprite,UBYTE *pal)
{
UBYTE packet,
*src_ptr;
ULONG c0;
ULONG dup_pixel,
*dst_ptr,
*line_ptr;
dst_ptr = (ULONG*)WorkWindow+x+(y*WorkScreenPixelWidth);
line_ptr = dst_ptr;
src_ptr = the_sprite->SpriteData;
DRAW_SPRITE32(pal)
}
void DrawBSprite8(SLONG x,SLONG y,BSprite *the_sprite)
{
UBYTE dup_pixel,
packet,
*dst_ptr,
*line_ptr,
*src_ptr;
ULONG c0;
dst_ptr = WorkWindow+x+(y*WorkScreenWidth);
line_ptr = dst_ptr;
src_ptr = the_sprite->SpriteData;
DRAW_SPRITE
}
void DrawBSprite16(SLONG x,SLONG y,BSprite *the_sprite)
{
DrawBSpritePal16(x,y,the_sprite,CurrentPalette);
}
void DrawBSprite32(SLONG x,SLONG y,BSprite *the_sprite)
{
DrawBSpritePal32(x,y,the_sprite,CurrentPalette);
}
//---------------------------------------------------------------
void DrawMonoBSprite8(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour)
{
UBYTE dup_pixel,
packet,
*dst_ptr,
*line_ptr,
*src_ptr;
ULONG c0;
dst_ptr = WorkWindow+x+(y*WorkScreenWidth);
line_ptr = dst_ptr;
src_ptr = the_sprite->SpriteData;
dup_pixel = (UBYTE)colour;
DRAW_M_SPRITE
}
void DrawMonoBSprite16(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour)
{
UBYTE packet,
*src_ptr;
ULONG c0;
UWORD dup_pixel,
*dst_ptr,
*line_ptr;
dst_ptr = (UWORD*)WorkWindow+x+(y*WorkScreenPixelWidth);
line_ptr = dst_ptr;
src_ptr = the_sprite->SpriteData;
dup_pixel = (UWORD)colour;
DRAW_M_SPRITE
}
void DrawMonoBSprite32(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour)
{
UBYTE packet,
*src_ptr;
ULONG c0;
ULONG dup_pixel,
*dst_ptr,
*line_ptr;
dst_ptr = (ULONG*)WorkWindow+x+(y*WorkScreenPixelWidth);
line_ptr = dst_ptr;
src_ptr = the_sprite->SpriteData;
dup_pixel = (ULONG)colour;
DRAW_M_SPRITE
}
void DrawMonoBSpriteC8(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour)
{
if(x<0 || (x+the_sprite->SpriteWidth)>=WorkWindowWidth || y<0 || (y+the_sprite->SpriteHeight)>=WorkWindowHeight)
return;
DrawMonoBSprite8(x,y,the_sprite,colour);
}
void DrawMonoBSpriteC16(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour)
{
if(x<0 || (x+the_sprite->SpriteWidth)>=WorkWindowWidth || y<0 || (y+the_sprite->SpriteHeight)>=WorkWindowHeight)
return;
DrawMonoBSprite16(x,y,the_sprite,colour);
}
void DrawMonoBSpriteC32(SLONG x,SLONG y,BSprite *the_sprite,ULONG colour)
{
if(x<0 || (x+the_sprite->SpriteWidth)>=WorkWindowWidth || y<0 || (y+the_sprite->SpriteHeight)>=WorkWindowHeight)
return;
DrawMonoBSprite32(x,y,the_sprite,colour);
}
//---------------------------------------------------------------
void DrawBSpriteC8(SLONG x,SLONG y,BSprite *the_sprite)
{
UBYTE dup_pixel,
packet,
*dst_ptr,
*line_ptr,
*src_ptr;
ULONG c0,
clip,
count_diff,
pixel_count,
sprite_height;
ULONG l_scan,
v_scan;
SLONG sprite_x;
if(x>=WorkWindowWidth || (x+the_sprite->SpriteWidth)<0 || y>=WorkWindowHeight || (y+the_sprite->SpriteHeight)<0)
return;
sprite_height = the_sprite->SpriteHeight;
sprite_x = x;
src_ptr = the_sprite->SpriteData;
clip = 0;
l_scan = 0;
if(x<0)
{
l_scan = -x;
sprite_x= 0;
clip = 1;
}
if(y<0)
{
v_scan = -y;
sprite_height += y;
V_SCAN
y = 0;
clip = 1;
}
if((SLONG)(x+the_sprite->SpriteWidth)>=WorkWindowWidth)
{
clip = 1;
}
if((SLONG)(y+sprite_height)>=WorkWindowHeight)
{
sprite_height -= (y+sprite_height)-WorkWindowHeight;
clip = 1;
}
dst_ptr = WorkWindow+sprite_x+(y*WorkScreenWidth);
line_ptr = dst_ptr;
if(clip)
{
pixel_count = 0;
L_SCAN
while(sprite_height)
{
packet = *src_ptr++;
switch(packet)
{
case END_LINE:
end_line:
dst_ptr += WorkScreenWidth;
line_ptr = dst_ptr;
sprite_height--;
pixel_count = 0;
L_SCAN
break;
case COPY_PIXELS:
c0 = (*src_ptr++)+1;
copy_pixels:
pixel_count += c0;
if((SLONG)(x+pixel_count)>=WorkWindowWidth)
{
count_diff = (x+pixel_count)-WorkWindowWidth;
c0 -= count_diff;
while(c0--)
*line_ptr++ = *src_ptr++;
src_ptr += count_diff;
R_SCAN
}
else
{
while(c0--)
*line_ptr++ = *src_ptr++;
}
break;
case SKIP_PIXELS:
c0 = (*src_ptr++)+1;
skip_pixels:
pixel_count += c0;
if((SLONG)(x+pixel_count)>=WorkWindowWidth)
{
R_SCAN
}
else
line_ptr += c0;
break;
case DUPLICATE_PIXELS:
c0 = (*src_ptr++)+1;
duplicate_pixels:
pixel_count += c0;
dup_pixel = *src_ptr++;
if((SLONG)(x+pixel_count)>=WorkWindowWidth)
{
c0 -= (x+pixel_count)-WorkWindowWidth;
while(c0--)
*line_ptr++ = dup_pixel;
R_SCAN
}
else
{
while(c0--)
*line_ptr++ = dup_pixel;
}
break;
case FINISHED:
return;
}
}
}
else
{
DRAW_SPRITE
}
}
extern void DrawBSpritePalC16(SLONG x,SLONG y,BSprite *the_sprite,UBYTE *pal);
extern void DrawBSpritePalC32(SLONG x,SLONG y,BSprite *the_sprite,UBYTE *pal);
void DrawBSpriteC16(SLONG x,SLONG y,BSprite *the_sprite)
{
DrawBSpritePalC16(x,y,the_sprite,CurrentPalette);
}
void DrawBSpriteC32(SLONG x,SLONG y,BSprite *the_sprite)
{
DrawBSpritePalC32(x,y,the_sprite,CurrentPalette);
}
void DrawBSpritePalC16(SLONG x,SLONG y,BSprite *the_sprite,UBYTE *pal)
{
UBYTE packet,
*src_ptr;
ULONG c0,
clip,
count_diff,
pixel_count,
sprite_height;
ULONG l_scan,
v_scan;
SLONG sprite_x;
UWORD dup_pixel,
*dst_ptr,
*line_ptr;
if(x>=WorkWindowWidth || (x+the_sprite->SpriteWidth)<0 || y>=WorkWindowHeight || (y+the_sprite->SpriteHeight)<0)
return;
sprite_height = the_sprite->SpriteHeight;
sprite_x = x;
src_ptr = the_sprite->SpriteData;
clip = 0;
l_scan = 0;
if(x<0)
{
l_scan = -x;
sprite_x= 0;
clip = 1;
}
if(y<0)
{
v_scan = -y;
sprite_height += y;
V_SCAN
y = 0;
clip = 1;
}
if((SLONG)(x+the_sprite->SpriteWidth)>=WorkWindowWidth)
{
clip = 1;
}
if((SLONG)(y+sprite_height)>=WorkWindowHeight)
{
sprite_height -= (y+sprite_height)-WorkWindowHeight;
clip = 1;
}
dst_ptr = (UWORD*)WorkWindow+sprite_x+(y*WorkScreenPixelWidth);
line_ptr = dst_ptr;
if(clip)
{
pixel_count = 0;
L_SCAN
while(sprite_height)
{
packet = *src_ptr++;
switch(packet)
{
case END_LINE:
end_line:
dst_ptr += WorkScreenPixelWidth;
line_ptr = dst_ptr;
sprite_height--;
pixel_count = 0;
L_SCAN
break;
case COPY_PIXELS:
c0 = (*src_ptr++)+1;
copy_pixels:
pixel_count += c0;
if((SLONG)(x+pixel_count)>=WorkWindowWidth)
{
count_diff = (x+pixel_count)-WorkWindowWidth;
c0 -= count_diff;
while(c0--)
{
*line_ptr++ =COL_TO_RGB565(*src_ptr,pal);
src_ptr++;
}
src_ptr += count_diff;
R_SCAN
}
else
{
while(c0--)
{
*line_ptr++ =COL_TO_RGB565(*src_ptr,pal);
src_ptr++;
}
}
break;
case SKIP_PIXELS:
c0 = (*src_ptr++)+1;
skip_pixels:
pixel_count += c0;
if((SLONG)(x+pixel_count)>=WorkWindowWidth)
{
R_SCAN
}
else
line_ptr += c0;
break;
case DUPLICATE_PIXELS:
c0 = (*src_ptr++)+1;
duplicate_pixels:
pixel_count += c0;
dup_pixel = COL_TO_RGB565(*src_ptr,pal);
src_ptr++;
if((SLONG)(x+pixel_count)>=WorkWindowWidth)
{
c0 -= (x+pixel_count)-WorkWindowWidth;
while(c0--)
*line_ptr++ = dup_pixel;
R_SCAN
}
else
{
while(c0--)
*line_ptr++ = dup_pixel;
}
break;
case FINISHED:
return;
}
}
}
else
{
DRAW_SPRITE16(pal)
}
}
void DrawBSpritePalC32(SLONG x,SLONG y,BSprite *the_sprite,UBYTE *pal)
{
UBYTE packet,
*src_ptr;
ULONG c0,
clip,
count_diff,
pixel_count,
sprite_height;
ULONG l_scan,
v_scan;
SLONG sprite_x;
ULONG dup_pixel,
*dst_ptr,
*line_ptr;
if(x>=WorkWindowWidth || (x+the_sprite->SpriteWidth)<0 || y>=WorkWindowHeight || (y+the_sprite->SpriteHeight)<0)
return;
sprite_height = the_sprite->SpriteHeight;
sprite_x = x;
src_ptr = the_sprite->SpriteData;
clip = 0;
l_scan = 0;
if(x<0)
{
l_scan = -x;
sprite_x= 0;
clip = 1;
}
if(y<0)
{
v_scan = -y;
sprite_height += y;
V_SCAN
y = 0;
clip = 1;
}
if((SLONG)(x+the_sprite->SpriteWidth)>=WorkWindowWidth)
{
clip = 1;
}
if((SLONG)(y+sprite_height)>=WorkWindowHeight)
{
sprite_height -= (y+sprite_height)-WorkWindowHeight;
clip = 1;
}
dst_ptr = (ULONG*)WorkWindow+sprite_x+(y*WorkScreenPixelWidth);
line_ptr = dst_ptr;
if(clip)
{
pixel_count = 0;
L_SCAN
while(sprite_height)
{
packet = *src_ptr++;
switch(packet)
{
case END_LINE:
end_line:
dst_ptr += WorkScreenPixelWidth;
line_ptr = dst_ptr;
sprite_height--;
pixel_count = 0;
L_SCAN
break;
case COPY_PIXELS:
c0 = (*src_ptr++)+1;
copy_pixels:
pixel_count += c0;
if((SLONG)(x+pixel_count)>=WorkWindowWidth)
{
count_diff = (x+pixel_count)-WorkWindowWidth;
c0 -= count_diff;
while(c0--)
{
*line_ptr++ =COL_TO_RGB888(*src_ptr,pal);
src_ptr++;
}
src_ptr += count_diff;
R_SCAN
}
else
{
while(c0--)
{
*line_ptr++ =COL_TO_RGB888(*src_ptr,pal);
src_ptr++;
}
}
break;
case SKIP_PIXELS:
c0 = (*src_ptr++)+1;
skip_pixels:
pixel_count += c0;
if((SLONG)(x+pixel_count)>=WorkWindowWidth)
{
R_SCAN
}
else
line_ptr += c0;
break;
case DUPLICATE_PIXELS:
c0 = (*src_ptr++)+1;
duplicate_pixels:
pixel_count += c0;
dup_pixel = COL_TO_RGB888(*src_ptr,pal);
src_ptr++;
if((SLONG)(x+pixel_count)>=WorkWindowWidth)
{
c0 -= (x+pixel_count)-WorkWindowWidth;
while(c0--)
*line_ptr++ = dup_pixel;
R_SCAN
}
else
{
while(c0--)
*line_ptr++ = dup_pixel;
}
break;
case FINISHED:
return;
}
}
}
else
{
DRAW_SPRITE32(pal)
}
}
//---------------------------------------------------------------
void SetupBSprites(BSprite *sprite_ref,UBYTE *sprite_data)
{
ULONG spr_count;
spr_count = *(ULONG*)(&sprite_ref->SpriteHeight);
sprite_ref++;
while(spr_count--)
{
sprite_ref->SpriteData += (ULONG)sprite_data;
sprite_ref++;
}
}
//---------------------------------------------------------------

View File

@ -0,0 +1,930 @@
// TextDef.c
// Guy Simmons, 7th October 1996.
// Hard coded font definition for quick text functions.
#include <MFHeader.h>
//---------------------------------------------------------------
// Byte1 - Width
// Byte2 - Height
// Byte3 - Vertical offset.
//---------------------------------------------------------------
static UBYTE Null[]=
{
0,0,0,
};
static UBYTE Space[] =
{
4,0,0,
};
static UBYTE Excl[] =
{
1,7,1,
1,
1,
1,
1,
1,
0,
1,
};
static UBYTE Dollar[] =
{
5,9,0,
0,0,1,0,0,
0,1,1,1,0,
1,0,1,0,1,
1,0,1,0,0,
0,1,1,1,0,
0,0,1,0,1,
1,0,1,0,1,
0,1,1,1,0,
0,0,1,0,0,
};
static UBYTE Percent[] =
{
8,7,1,
0,1,1,1,1,1,1,1,
1,0,0,1,0,0,1,0,
1,0,0,1,0,1,0,0,
0,1,1,0,1,1,1,0,
0,0,0,1,1,0,0,1,
0,0,1,0,1,0,0,1,
0,1,0,0,0,1,1,0,
};
static UBYTE And[] =
{
7,8,0,
0,0,1,1,0,0,0,
0,1,0,0,1,0,0,
0,1,0,1,0,0,0,
0,0,1,0,0,0,0,
0,1,0,1,0,1,0,
1,0,0,0,1,0,0,
1,0,0,1,0,1,0,
0,1,1,0,0,0,1,
};
static UBYTE Quotes[] =
{
3,2,1,
1,0,1,
1,0,1,
};
static UBYTE Astrisk[] =
{
5,5,1,
0,1,0,1,0,
0,0,1,0,0,
1,1,1,1,1,
0,0,1,0,0,
0,1,0,1,0,
};
static UBYTE BrackO[] =
{
3,9,0,
0,0,1,
0,1,0,
1,0,0,
1,0,0,
1,0,0,
1,0,0,
1,0,0,
0,1,0,
0,0,1,
};
static UBYTE BrackC[] =
{
3,9,0,
1,0,0,
0,1,0,
0,0,1,
0,0,1,
0,0,1,
0,0,1,
0,0,1,
0,1,0,
1,0,0,
};
static UBYTE Plus[] =
{
5,5,2,
0,0,1,0,0,
0,0,1,0,0,
1,1,1,1,1,
0,0,1,0,0,
0,0,1,0,0,
};
static UBYTE Comma[] =
{
2,4,6,
1,1,
1,1,
0,1,
1,0,
};
static UBYTE Minus[] =
{
5,1,4,
1,1,1,1,1
};
static UBYTE Stop[] =
{
2,2,6,
1,1,
1,1,
};
static UBYTE Zero[] =
{
5,7,1,
0,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
0,1,1,1,0,
};
static UBYTE One[] =
{
2,7,1,
0,1,
1,1,
0,1,
0,1,
0,1,
0,1,
0,1,
};
static UBYTE Two[] =
{
5,7,1,
0,1,1,1,0,
1,0,0,0,1,
0,0,0,0,1,
0,0,0,1,0,
0,0,1,0,0,
0,1,0,0,0,
1,1,1,1,1,
};
static UBYTE Three[] =
{
5,7,1,
1,1,1,1,1,
0,0,0,1,0,
0,0,1,0,0,
0,1,1,1,0,
0,0,0,0,1,
1,0,0,0,1,
0,1,1,1,0,
};
static UBYTE Four[] =
{
5,7,1,
0,0,0,1,0,
0,0,1,1,0,
0,1,0,1,0,
1,0,0,1,0,
1,1,1,1,1,
0,0,0,1,0,
0,0,0,1,0,
};
static UBYTE Five[] =
{
5,7,1,
1,1,1,1,1,
1,0,0,0,0,
1,1,1,1,0,
0,0,0,0,1,
0,0,0,0,1,
1,0,0,0,1,
0,1,1,1,0,
};
static UBYTE Six[] =
{
5,7,1,
0,0,1,1,0,
0,1,0,0,0,
1,0,0,0,0,
1,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
0,1,1,1,0,
};
static UBYTE Seven[] =
{
5,7,1,
1,1,1,1,1,
0,0,0,0,1,
0,0,0,1,0,
0,0,0,1,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
};
static UBYTE Eight[] =
{
5,7,1,
0,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
0,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
0,1,1,1,0,
};
static UBYTE Nine[] =
{
5,7,1,
0,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
0,1,1,1,1,
0,0,0,0,1,
0,0,0,1,0,
0,1,1,0,0,
};
static UBYTE Colon[] =
{
2,3,4,
0,1,
0,0,
0,1,
};
static UBYTE QMark[] =
{
5,7,1,
0,1,1,1,0,
1,0,0,0,1,
0,0,0,0,1,
0,0,0,1,0,
0,0,1,0,0,
0,0,0,0,0,
0,0,1,0,0,
};
static UBYTE At[] =
{
7,8,1,
0,0,1,1,1,0,0,
0,1,0,0,0,1,0,
1,0,0,1,1,0,1,
1,0,1,0,1,0,1,
1,0,1,0,1,0,1,
1,0,0,1,1,1,0,
0,1,0,0,0,0,0,
0,0,1,1,1,0,0,
};
static UBYTE A[] =
{
5,7,1,
0,0,1,0,0,
0,0,1,0,0,
0,1,0,1,0,
0,1,0,1,0,
1,1,1,1,1,
1,0,0,0,1,
1,0,0,0,1
};
static UBYTE B[] =
{
5,7,1,
1,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
1,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
1,1,1,1,0,
};
static UBYTE C[] =
{
5,7,1,
0,1,1,1,0,
1,0,0,0,1,
1,0,0,0,0,
1,0,0,0,0,
1,0,0,0,0,
1,0,0,0,1,
0,1,1,1,0
};
static UBYTE D[] =
{
5,7,1,
1,1,1,0,0,
1,0,0,1,0,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,1,0,
1,1,1,0,0,
};
static UBYTE E[] =
{
4,7,1,
1,1,1,1,
1,0,0,0,
1,0,0,0,
1,1,1,0,
1,0,0,0,
1,0,0,0,
1,1,1,1,
};
static UBYTE F[] =
{
4,7,1,
1,1,1,1,
1,0,0,0,
1,0,0,0,
1,1,1,0,
1,0,0,0,
1,0,0,0,
1,0,0,0,
};
static UBYTE G[] =
{
5,7,1,
0,1,1,1,0,
1,0,0,0,1,
1,0,0,0,0,
1,0,0,1,1,
1,0,0,0,1,
1,0,0,0,1,
0,1,1,1,0,
};
static UBYTE H[] =
{
5,7,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,1,1,1,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
};
static UBYTE I[] =
{
1,7,1,
1,
1,
1,
1,
1,
1,
1,
};
static UBYTE J[] =
{
5,7,1,
0,0,0,0,1,
0,0,0,0,1,
0,0,0,0,1,
0,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
0,1,1,1,0,
};
static UBYTE K[] =
{
5,7,1,
1,0,0,0,1,
1,0,0,1,0,
1,0,1,0,0,
1,1,0,0,0,
1,0,1,0,0,
1,0,0,1,0,
1,0,0,0,1,
};
static UBYTE L[] =
{
4,7,1,
1,0,0,0,
1,0,0,0,
1,0,0,0,
1,0,0,0,
1,0,0,0,
1,0,0,0,
1,1,1,1,
};
static UBYTE M[] =
{
7,7,1,
1,0,0,0,0,0,1,
1,1,0,0,0,1,1,
1,0,1,0,1,0,1,
1,0,0,1,0,0,1,
1,0,0,0,0,0,1,
1,0,0,0,0,0,1,
1,0,0,0,0,0,1,
};
static UBYTE N[] =
{
5,7,1,
1,1,0,0,1,
1,1,0,0,1,
1,0,1,0,1,
1,0,1,0,1,
1,0,0,1,1,
1,0,0,1,1,
1,0,0,0,1,
};
static UBYTE O[] =
{
5,7,1,
0,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
0,1,1,1,0,
};
static UBYTE P[] =
{
5,7,1,
1,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
1,1,1,1,0,
1,0,0,0,0,
1,0,0,0,0,
1,0,0,0,0,
};
static UBYTE Q[] =
{
5,8,1,
0,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,1,0,1,
0,1,1,1,0,
0,0,0,1,0,
};
static UBYTE R[] =
{
5,7,1,
1,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
1,1,1,1,0,
1,0,1,0,0,
1,0,0,1,0,
1,0,0,0,1,
};
static UBYTE S[] =
{
5,7,1,
0,1,1,1,0,
1,0,0,0,1,
1,0,0,0,0,
0,1,1,1,0,
0,0,0,0,1,
1,0,0,0,1,
0,1,1,1,0,
};
static UBYTE T[] =
{
5,7,1,
1,1,1,1,1,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
};
static UBYTE U[] =
{
5,7,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
0,1,1,1,0,
};
static UBYTE V[] =
{
5,7,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
0,1,0,1,0,
0,1,0,1,0,
0,0,1,0,0,
0,0,1,0,0,
};
static UBYTE W[] =
{
7,7,1,
1,0,0,0,0,0,1,
1,0,0,0,0,0,1,
0,1,0,1,0,1,0,
0,1,0,1,0,1,0,
0,0,1,0,1,0,0,
0,0,1,0,1,0,0,
0,0,1,0,1,0,0,
};
static UBYTE X[] =
{
5,7,1,
1,0,0,0,1,
1,0,0,0,1,
0,1,0,1,0,
0,0,1,0,0,
0,1,0,1,0,
1,0,0,0,1,
1,0,0,0,1,
};
static UBYTE Y[] =
{
5,7,1,
1,0,0,0,1,
1,0,0,0,1,
0,1,0,1,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
};
static UBYTE Z[] =
{
4,7,1,
1,1,1,1,
0,0,0,1,
0,0,1,0,
0,1,0,0,
1,0,0,0,
1,0,0,0,
1,1,1,1,
};
static UBYTE _a[] =
{
4,5,3,
0,1,1,0,
0,0,0,1,
0,1,1,1,
1,0,0,1,
0,1,1,1,
};
static UBYTE _b[] =
{
4,7,1,
1,0,0,0,
1,0,0,0,
1,1,1,0,
1,0,0,1,
1,0,0,1,
1,0,0,1,
1,1,1,0,
};
static UBYTE _c[] =
{
4,5,3,
0,1,1,0,
1,0,0,1,
1,0,0,0,
1,0,0,1,
0,1,1,0,
};
static UBYTE _d[] =
{
4,7,1,
0,0,0,1,
0,0,0,1,
0,1,1,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
0,1,1,1,
};
static UBYTE _e[] =
{
4,5,3,
0,1,1,0,
1,0,0,1,
1,1,1,1,
1,0,0,0,
0,1,1,0,
};
static UBYTE _f[] =
{
4,7,1,
0,0,1,1,
0,1,0,0,
1,1,1,0,
0,1,0,0,
0,1,0,0,
0,1,0,0,
0,1,0,0,
};
static UBYTE _g[] =
{
4,7,3,
0,1,1,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
0,1,1,1,
0,0,0,1,
0,1,1,0,
};
static UBYTE _h[] =
{
4,7,1,
1,0,0,0,
1,0,0,0,
1,1,1,0,
1,0,0,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
};
static UBYTE _i[] =
{
2,7,1,
0,1,
0,0,
1,1,
0,1,
0,1,
0,1,
0,1,
};
static UBYTE _j[] =
{
3,9,1,
0,0,1,
0,0,0,
0,1,1,
0,0,1,
0,0,1,
0,0,1,
0,0,1,
0,0,1,
1,1,0,
};
static UBYTE _k[] =
{
4,7,1,
1,0,0,0,
1,0,0,0,
1,0,0,1,
1,0,1,0,
1,1,0,0,
1,0,1,0,
1,0,0,1,
};
static UBYTE _l[] =
{
2,7,1,
1,1,
0,1,
0,1,
0,1,
0,1,
0,1,
0,1,
};
static UBYTE _m[] =
{
7,5,3,
1,1,1,0,1,1,0,
1,0,0,1,0,0,1,
1,0,0,1,0,0,1,
1,0,0,1,0,0,1,
1,0,0,1,0,0,1,
};
static UBYTE _n[] =
{
4,5,3,
1,1,1,0,
1,0,0,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
};
static UBYTE _o[] =
{
4,5,3,
0,1,1,0,
1,0,0,1,
1,0,0,1,
1,0,0,1,
0,1,1,0,
};
static UBYTE _p[] =
{
4,7,3,
1,1,1,0,
1,0,0,1,
1,0,0,1,
1,0,0,1,
1,1,1,0,
1,0,0,0,
1,0,0,0,
};
static UBYTE _q[] =
{
4,7,3,
0,1,1,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
0,1,1,1,
0,0,0,1,
0,0,0,1,
};
static UBYTE _r[] =
{
4,5,3,
1,0,1,1,
1,1,0,0,
1,0,0,0,
1,0,0,0,
1,0,0,0,
};
static UBYTE _s[] =
{
4,5,3,
0,1,1,1,
1,0,0,0,
0,1,1,0,
0,0,0,1,
1,1,1,0,
};
static UBYTE _t[] =
{
3,7,1,
0,1,0,
0,1,0,
1,1,1,
0,1,0,
0,1,0,
0,1,0,
0,0,1,
};
static UBYTE _u[] =
{
4,5,3,
1,0,0,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
0,1,1,1,
};
static UBYTE _v[] =
{
5,5,3,
1,0,0,0,1,
0,1,0,1,0,
0,1,0,1,0,
0,0,1,0,0,
0,0,1,0,0,
};
static UBYTE _w[] =
{
7,5,3,
1,0,0,0,0,0,1,
0,1,0,1,0,1,0,
0,1,0,1,0,1,0,
0,0,1,0,1,0,0,
0,0,1,0,1,0,0,
};
static UBYTE _x[] =
{
5,5,3,
1,0,0,0,1,
0,1,0,1,0,
0,0,1,0,0,
0,1,0,1,0,
1,0,0,0,1,
};
static UBYTE _y[] =
{
4,7,3,
1,0,0,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
0,1,1,1,
0,0,0,1,
0,1,1,0,
};
static UBYTE _z[] =
{
4,5,3,
1,1,1,1,
0,0,1,0,
0,1,0,0,
1,0,0,0,
1,1,1,1,
};
//---------------------------------------------------------------
UBYTE *CharTable[] =
{
Null, Null, Null, Null, Null, Null, Null, Null,
Null, Null, Null, Null, Null, Null, Null, Null,
Null, Null, Null, Null, Null, Null, Null, Null,
Null, Null, Null, Null, NULL, Null, Null, Null,
Space, Excl, Quotes, Null, Dollar, Percent,And, Null,
BrackO, BrackC, Astrisk,Plus, Comma, Minus, Stop, Null,
Zero, One, Two, Three, Four, Five, Six, Seven,
Eight, Nine, Colon, Null, Null, Null, Null, QMark,
At, A, B, C, D, E, F, G,
H, I, J, K, L, M, N, O,
P, Q, R, S, T, U, V, W,
X, Y, Z, Null, Null, Null, Null, Null,
Null, _a, _b, _c, _d, _e, _f, _g,
_h, _i, _j, _k, _l, _m, _n, _o,
_p, _q, _r, _s, _t, _u, _v, _w,
_x, _y, _z, Null, Null, Null, Null, Null
};
//---------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,363 @@
// Draw3D.cpp - Windows.
// Guy Simmons, 8th May 1997.
#define INITGUID
#include <MFHeader.h>
BOOL DeviceFound = FALSE,
GotD3D2 = FALSE,
HasHardware = FALSE;
ULONG RequestFlags = 0;
SLONG DeviceBitDepth;
D3DDEVICEDESC d3d_DeviceDesc;
GUID GUIDDevice;
IDirect3DDevice2 *lp_D3D_Device;
LPDIRECT3D lp_D3D = NULL;
LPDIRECT3D2 lp_D3D_2 = NULL;
LPDIRECTDRAWSURFACE lp_DD_ZBuffer;
HRESULT WINAPI EnumDeviceCallback(LPGUID,LPTSTR,LPTSTR,LPD3DDEVICEDESC,LPD3DDEVICEDESC,LPVOID);
//---------------------------------------------------------------
void SetupD3D2(void)
{
HRESULT dd_result;
if(!GotD3D2)
{
dd_result = lp_DD->QueryInterface(IID_IDirect3D,(LPVOID*)&lp_D3D);
if(dd_result==DD_OK)
{
dd_result = lp_D3D->QueryInterface(IID_IDirect3D2,(LPVOID*)&lp_D3D_2);
if(dd_result==DD_OK)
{
LogText("D3D2 installed.\n");
GotD3D2 = TRUE;
}
}
}
return;
}
//---------------------------------------------------------------
void ResetD3D2(void)
{
HRESULT dd_result;
if(lp_DD_ZBuffer)
{
dd_result = lp_DD_ZBuffer->Release();
if(dd_result!=DD_OK)
{
LogText("error: %ld - Unable to release ZBuffer\n",dd_result&0xff);
}
}
if(lp_D3D_2)
{
dd_result = lp_D3D_2->Release();
if(dd_result!=DD_OK)
{
LogText("error: %ld - Unable to release Direct3D2\n",dd_result&0xff);
}
}
if(lp_D3D)
{
dd_result = lp_D3D->Release();
if(dd_result!=DD_OK)
{
LogText("error: %ld - Unable to release Direct3D\n",dd_result&0xff);
}
}
}
//---------------------------------------------------------------
BOOL ChooseD3DDevice(ULONG flags)
{
DDSURFACEDESC dd_sd;
HRESULT dd_result;
if(GotD3D2)
{
ZeroMemory(&dd_sd,sizeof(dd_sd));
dd_sd.dwSize = sizeof(dd_sd);
dd_result = lp_DD_FrontSurface->GetSurfaceDesc(&dd_sd);
if(dd_result==DD_OK)
{
switch(dd_sd.ddpfPixelFormat.dwRGBBitCount)
{
case 1: DeviceBitDepth = DDBD_1;break;
case 2: DeviceBitDepth = DDBD_2;break;
case 4: DeviceBitDepth = DDBD_4;break;
case 8: DeviceBitDepth = DDBD_8;break;
case 16: DeviceBitDepth = DDBD_16;break;
case 24: DeviceBitDepth = DDBD_24;break;
case 32: DeviceBitDepth = DDBD_32;break;
default: DeviceBitDepth = 0;
}
DeviceFound = FALSE;
RequestFlags = flags;
dd_result = lp_D3D_2->EnumDevices(EnumDeviceCallback,NULL);
if(dd_result==D3D_OK && DeviceFound)
{
LogText("Got required device.\n");
memset(&dd_sd, 0, sizeof(DDSURFACEDESC));
dd_sd.dwSize = sizeof(DDSURFACEDESC);
dd_sd.dwFlags = DDSD_WIDTH |
DDSD_HEIGHT |
DDSD_CAPS |
DDSD_ZBUFFERBITDEPTH;
dd_sd.dwWidth = WorkScreenPixelWidth;
dd_sd.dwHeight = WorkScreenHeight;
if(HasHardware)
{
LogText("ZBuffer in Video memory\n");
dd_sd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
}
else
{
LogText("ZBuffer in System memory\n");
dd_sd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY;
}
if(d3d_DeviceDesc.dwDeviceZBufferBitDepth & DDBD_32) { dd_sd.dwZBufferBitDepth=32;LogText("32 bit zbuffer\n"); }
if(d3d_DeviceDesc.dwDeviceZBufferBitDepth & DDBD_24) { dd_sd.dwZBufferBitDepth=24;LogText("24 bit zbuffer\n"); }
if(d3d_DeviceDesc.dwDeviceZBufferBitDepth & DDBD_16) { dd_sd.dwZBufferBitDepth=16;LogText("16 bit zbuffer\n"); }
if(d3d_DeviceDesc.dwDeviceZBufferBitDepth & DDBD_8 ) { dd_sd.dwZBufferBitDepth=8;LogText("8 bit zbuffer\n"); }
/*
if(d3d_DeviceDesc.dwDeviceZBufferBitDepth&DDBD_32) { dd_sd.dwZBufferBitDepth=32; }
if(d3d_DeviceDesc.dwDeviceZBufferBitDepth&DDBD_24) { dd_sd.dwZBufferBitDepth=24; }
if(d3d_DeviceDesc.dwDeviceZBufferBitDepth&DDBD_16) { dd_sd.dwZBufferBitDepth=16; }
if(d3d_DeviceDesc.dwDeviceZBufferBitDepth&DDBD_8 ) { dd_sd.dwZBufferBitDepth=8; }
*/
dd_result = lp_DD->CreateSurface(&dd_sd,&lp_DD_ZBuffer,NULL);
if(dd_result!=DD_OK)
{
LogText("error: %ld - Can't create ZBuffer\n",dd_result&0xffff);
goto exit_false;
}
dd_result = lp_DD_BackSurface->AddAttachedSurface(lp_DD_ZBuffer);
if(dd_result!=DD_OK)
{
LogText("Can't attach ZBuffer\n");
goto exit_false;
}
dd_result = lp_D3D_2->CreateDevice(GUIDDevice,lp_DD_BackSurface,&lp_D3D_Device);
if(dd_result!=DD_OK)
{
LogText("Can't create direct draw device\n");
goto exit_false;
}
return TRUE;
}
}
}
exit_false:
return FALSE;
}
//---------------------------------------------------------------
HRESULT WINAPI EnumDeviceCallback(
LPGUID lpGUID,
LPTSTR lpszDeviceDesc,
LPTSTR lpszDeviceName,
LPD3DDEVICEDESC lpd3dHWDeviceDesc,
LPD3DDEVICEDESC lpd3dSWDeviceDesc,
LPVOID lpUserArg
)
{
LPD3DDEVICEDESC lp_d3d_device_desc;
lpUserArg = lpUserArg;
HasHardware = (lpd3dHWDeviceDesc->dcmColorModel!=0);
// Do we want hardware & do we have hardware?
if(RequestFlags&D3D_HARDWARE && !HasHardware)
return D3DENUMRET_OK;
lp_d3d_device_desc = (HasHardware ? lpd3dHWDeviceDesc : lpd3dSWDeviceDesc);
// Do we want a ramp device & do we have a ramp device?
if(!(RequestFlags&D3D_RAMP) && lp_d3d_device_desc->dcmColorModel==D3DCOLOR_MONO)
return D3DENUMRET_OK;
// Check the device supports the correct rendering depth.
if(!(lp_d3d_device_desc->dwDeviceRenderBitDepth&DeviceBitDepth))
return D3DENUMRET_OK;
// Check the device supports everything we want it to.
if(lp_d3d_device_desc->dcmColorModel==D3DCOLOR_MONO) // Ramp device.
{
if (
(RequestFlags&D3D_GOURAUD) &&
!(lp_d3d_device_desc->dpcTriCaps.dwShadeCaps&D3DPSHADECAPS_COLORGOURAUDMONO)
)
return D3DENUMRET_OK; // No Ramp gouraud shading.
}
else // RGB device.
{
if (
(RequestFlags&D3D_GOURAUD) &&
!(lp_d3d_device_desc->dpcTriCaps.dwShadeCaps&D3DPSHADECAPS_COLORGOURAUDRGB)
)
return D3DENUMRET_OK; // No RGB gouraud shading.
}
DeviceFound = TRUE;
CopyMemory(&GUIDDevice,lpGUID,sizeof(GUID));
// strcpy(DeviceDesc, lpszDeviceDesc);
// strcpy(DeviceName, lpszDeviceName);
CopyMemory(&d3d_DeviceDesc,lp_d3d_device_desc,sizeof(D3DDEVICEDESC));
LogText("DeviceDesc - %s\nDeviceName - %s\n\n",lpszDeviceDesc,lpszDeviceName);
return D3DENUMRET_CANCEL;
}
//---------------------------------------------------------------
/*
HRESULT WINAPI EnumDeviceCallback(
LPGUID lpGUID,
LPTSTR lpszDeviceDesc,
LPTSTR lpszDeviceName,
LPD3DDEVICEDESC lpd3dHWDeviceDesc,
LPD3DDEVICEDESC lpd3dSWDeviceDesc,
LPVOID lpUserArg
)
{
LPD3DDEVICEDESC lpd3dDeviceDesc;
lpUserArg = lpUserArg;
#ifdef _DEBUG
HardwareDevice = FALSE;
#else
// If there is no hardware support the color model is zero.
HardwareDevice = (0 != lpd3dHWDeviceDesc->dcmColorModel);
#endif
lpd3dDeviceDesc = (HardwareDevice ? lpd3dHWDeviceDesc :
lpd3dSWDeviceDesc);
#ifdef _DEBUG
if(HardwareDevice)
return D3DENUMRET_OK;
#else
if(!HardwareDevice)
return D3DENUMRET_OK;
#endif
LogText("DeviceDesc - %s\nDeviceName - %s\n\n",lpszDeviceDesc,lpszDeviceName);
// Does the device render at the depth we want?
if(!(lpd3dDeviceDesc->dwDeviceRenderBitDepth&device_bit_depth))
{
// If not, skip this device.
return D3DENUMRET_OK;
}
// The device must support Gouraud-shaded triangles.
if(D3DCOLOR_MONO == lpd3dDeviceDesc->dcmColorModel)
{
if (!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps &
D3DPSHADECAPS_COLORGOURAUDMONO))
{
// No Gouraud shading. Skip this device.
LogText("No Gouraud shading\n");
return D3DENUMRET_OK;
}
}
else
{
if(!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps &
D3DPSHADECAPS_COLORGOURAUDRGB))
{
// No Gouraud shading. Skip this device.
LogText("No Gouraud shading\n");
return D3DENUMRET_OK;
}
}
#ifdef _DEBUG
if (
!HardwareDevice && !DeviceFound &&
(D3DCOLOR_RGB == lpd3dDeviceDesc->dcmColorModel)
)
{
// If this is software RGB and we already have found
// a software monochromatic renderer, we are not
// interested. Skip this device.
// return D3DENUMRET_OK;
// This is a device we are interested in. Save the details.
DeviceFound = TRUE;
CopyMemory(&guid_device, lpGUID, sizeof(GUID));
strcpy(DeviceDesc, lpszDeviceDesc);
strcpy(DeviceName, lpszDeviceName);
CopyMemory(&d3d_HWDeviceDesc, lpd3dHWDeviceDesc,
sizeof(D3DDEVICEDESC));
CopyMemory(&d3d_SWDeviceDesc, lpd3dSWDeviceDesc,
sizeof(D3DDEVICEDESC));
CopyMemory(&d3d_DeviceDesc, lpd3dDeviceDesc,
sizeof(D3DDEVICEDESC));
return D3DENUMRET_CANCEL;
}
#else
// This is a device we are interested in. Save the details.
DeviceFound = TRUE;
CopyMemory(&guid_device, lpGUID, sizeof(GUID));
strcpy(DeviceDesc, lpszDeviceDesc);
strcpy(DeviceName, lpszDeviceName);
CopyMemory(&d3d_HWDeviceDesc, lpd3dHWDeviceDesc,
sizeof(D3DDEVICEDESC));
CopyMemory(&d3d_SWDeviceDesc, lpd3dSWDeviceDesc,
sizeof(D3DDEVICEDESC));
CopyMemory(&d3d_DeviceDesc, lpd3dDeviceDesc,
sizeof(D3DDEVICEDESC));
#endif
#ifdef _DEBUG
// return D3DENUMRET_CANCEL;
return D3DENUMRET_OK;
#else
// If this is a hardware device, we have found
// what we are looking for.
if(HardwareDevice)
{
LogText("We have a hardware device\n");
return D3DENUMRET_CANCEL;
}
// Otherwise, keep looking.
return D3DENUMRET_OK;
#endif
}
*/
//---------------------------------------------------------------

View File

@ -0,0 +1,926 @@
// Display.cpp - Windows.
// Guy Simmons, 1st February 1997.
#include <MFHeader.h>
#define MF_DD2
BOOL EmulateLoRes = FALSE,
Got3DFX = FALSE;
UBYTE DisplayActive = 0,
DisplayState = 0,
*WorkScreen,
WorkScreenDepth;
SLONG DisplayMode = DISPLAY_MODE_NONE,
WorkScreenHeight,
WorkScreenWidth,
WorkScreenPixelWidth;
GUID DevicePrimary,
Device3DFX;
DDSURFACEDESC DD_DisplayDesc;
LPDIRECTDRAW lp_DD = NULL; // Main DirectDraw object
LPDIRECTDRAW2 lp_DD_2 = NULL; // Main DirectDraw2 object
LPDIRECTDRAWCLIPPER lp_DD_Clipper = NULL;
LPDIRECTDRAWSURFACE lp_DD_BackSurface = NULL,
lp_DD_FrontSurface = NULL,
lp_DD_WorkSurface = NULL;
volatile UBYTE MFShellActive = 0;
SLONG CreateSurfaces(void);
SLONG DestroySurfaces(void);
void RestoreSurfaces(void);
HRESULT CALLBACK DisplayModesCallback(LPDDSURFACEDESC p_dd_sd, LPVOID ignore);
extern HANDLE hShellThread;
extern HWND hShellWindow;
extern RECT ShellRect;
extern void SetDrawFunctions(ULONG depth);
BOOL WINAPI EnumDeviceCallback(GUID FAR *lpGUID,LPSTR lpDriverDescription,LPSTR lpDriverName,LPVOID lpContext);
//---------------------------------------------------------------
SLONG OpenDisplay(ULONG width, ULONG height, ULONG depth, ULONG flags)
{
SLONG result = DisplayCreationError;
HRESULT dd_result;
WorkScreenHeight = height;
WorkScreenWidth = width;
WorkScreenPixelWidth = width;
DisplayActive = 0;
if(hShellThread)
{
// Create Direct Draw Object.
#ifdef _DEBUG
flags = flags;
dd_result = DirectDrawCreate((GUID*)DDCREATE_EMULATIONONLY,&lp_DD,NULL);
#else
dd_result = DirectDrawEnumerate(EnumDeviceCallback,NULL);
if(Got3DFX && flags&FLAGS_USE_3DFX)
dd_result = DirectDrawCreate(&Device3DFX,&lp_DD,NULL);
else
dd_result = DirectDrawCreate(NULL,&lp_DD,NULL);
#endif
if(dd_result==DD_OK)
{
#ifdef MF_DD2
dd_result = lp_DD->QueryInterface(IID_IDirectDraw2,(LPVOID *)&lp_DD_2);
#endif
if(dd_result==DD_OK)
{
DisplayState |= DS_DIRECT_DRAW_ACTIVE;
#ifdef _DEBUG
// Normal mode for Debug.
#ifdef MF_DD2
dd_result = lp_DD_2->SetCooperativeLevel(hShellWindow,DDSCL_NORMAL);
#else
dd_result = lp_DD->SetCooperativeLevel(hShellWindow,DDSCL_NORMAL);
#endif
#else
// Exclusive mode for Release.
#ifdef MF_DD2
dd_result = lp_DD_2->SetCooperativeLevel(hShellWindow,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN); //|DDSCL_ALLOWMODEX);
#else
dd_result = lp_DD->SetCooperativeLevel(hShellWindow,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN); //|DDSCL_ALLOWMODEX);
#endif
// Find all the available display modes.
#ifdef MF_DD2
lp_DD_2->EnumDisplayModes(0,NULL,0,DisplayModesCallback);
#else
lp_DD->EnumDisplayModes(0,NULL,0,DisplayModesCallback);
#endif
#endif
InitPalettes();
if(SetDisplay(width,height,depth)==NoError)
{
SetupD3D2();
return NoError;
}
}
}
}
return result;
}
//---------------------------------------------------------------
SLONG CloseDisplay(void)
{
HRESULT dd_result;
/*
if(DisplayState&DS_THREAD_ACTIVE)
{
SendMessage(hShellWindow,WM_CLOSE,0,0);
WaitForSingleObject(hShellThread,4000);
CloseHandle(hShellThread);
}
*/
DestroySurfaces();
DestroyPalettes();
#ifdef MF_DD2
if(lp_DD_2)
dd_result = lp_DD_2->SetCooperativeLevel(hShellWindow,DDSCL_NORMAL);
#else
if(lp_DD)
dd_result = lp_DD->SetCooperativeLevel(hShellWindow,DDSCL_NORMAL);
#endif
/*
ResetD3D2();
if(lp_DD_2)
{
dd_result = lp_DD_2->Release();
if(dd_result!=DD_OK)
{
LogText("error: %ld - Unable to release DirectDraw2\n",dd_result&0xff);
}
else
lp_DD_2 = NULL;
}
*/
if(lp_DD)
{
dd_result = lp_DD->Release();
if(dd_result!=DD_OK)
{
LogText("error: %ld - Unable to release DirectDraw\n",dd_result&0xff);
}
else
lp_DD = NULL;
}
return NoError;
}
//---------------------------------------------------------------
SLONG SetDisplay(ULONG width,ULONG height,ULONG depth)
{
SLONG mode = DISPLAY_MODE_NONE;
HRESULT dd_result;
if(DisplayState&DS_SCREEN_LOCKED)
{
ERROR_MSG(0,"Screen Locked");
}
if(DisplayState&DS_DIRECT_DRAW_ACTIVE)
{
mode = DisplayModeAvailable(width,height,depth);
if(mode)
{
// Clear away the old display stuff.
DestroySurfaces();
DestroyPalettes();
// Initially force
WorkScreenHeight = height;
WorkScreenWidth = width;
WorkScreenPixelWidth = width;
WorkScreenDepth = depth;
// Set display size.
#ifdef _RELEASE
if(EmulateLoRes)
{
#ifdef MF_DD2
dd_result = lp_DD_2->SetDisplayMode(640,480,8,0,0);
#else
dd_result = lp_DD->SetDisplayMode(640,480,8);
#endif
}
else
{
#ifdef MF_DD2
dd_result = lp_DD_2->SetDisplayMode(width,height,depth,0,0);
#else
dd_result = lp_DD->SetDisplayMode(width,height,depth);
#endif
}
#else
DWORD dw_style;
RECT temp_rect;
dw_style = GetWindowStyle(hShellWindow);
dw_style &= ~WS_POPUP;
dw_style |= WS_OVERLAPPED|WS_CAPTION|WS_THICKFRAME|WS_MINIMIZEBOX;
SetWindowLong(hShellWindow,GWL_STYLE,dw_style);
SetRect(&temp_rect,0,0,width,height);
AdjustWindowRectEx (
&temp_rect,
GetWindowStyle(hShellWindow),
GetMenu(hShellWindow) != NULL,
GetWindowExStyle(hShellWindow)
);
SetWindowPos(
hShellWindow,
NULL,
0,0,
temp_rect.right-temp_rect.left,
temp_rect.bottom-temp_rect.top,
SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE
);
dd_result = DD_OK;
#endif
if(dd_result==DD_OK)
{
// Create the new display stuff.
DisplayState |= DS_DISPLAY_MODE_SET;
DisplayMode = mode;
#ifdef _DEBUG
dd_result = lp_DD_2->GetDisplayMode(&DD_DisplayDesc);
#else
DD_DisplayDesc = DisplayModes[DisplayMode].DD_ModeDesc;
#endif
CreateSurfaces();
CreatePalettes();
SetWorkWindowBounds(0,0,width,height);
SetDrawFunctions(depth);
return NoError;
}
else
{
LogText("Unable to set display mode. Error: %ld\n",dd_result&0xffff);
// ERROR_MSG((dd_result==DD_OK),"Unable to set display mode.");
}
}
else
{
LogText("\nDisplay Mode not available\n");
// ERROR_MSG((dd_result==DD_OK),"Display mode unavailable.");
}
}
return -1;
}
//---------------------------------------------------------------
SLONG CreateSurfaces(void)
{
#ifdef _RELEASE
DDSCAPS dd_scaps;
#endif
DDSURFACEDESC dd_sd;
HRESULT dd_result;
ZeroMemory(&dd_sd,sizeof(dd_sd));
dd_sd.dwSize = sizeof(dd_sd);
#ifdef _DEBUG
if(lp_DD_FrontSurface==NULL)
{
// Create DEBUG front surface.
dd_sd.dwFlags = DDSD_CAPS;
dd_sd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
#ifdef MF_DD2
dd_result = lp_DD_2->CreateSurface(&dd_sd,&lp_DD_FrontSurface,NULL);
#else
dd_result = lp_DD->CreateSurface(&dd_sd,&lp_DD_FrontSurface,NULL);
#endif
ERROR_MSG((dd_result==DD_OK),"Can't create lp_DD_FrontSurface");
}
if(lp_DD_BackSurface==NULL)
{
// Create DEBUG back surface.
dd_sd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
dd_sd.dwHeight = WorkScreenHeight;
dd_sd.dwWidth = WorkScreenWidth;
dd_sd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_3DDEVICE; //|DDSCAPS_SYSTEMMEMORY;
#ifdef MF_DD2
dd_result = lp_DD_2->CreateSurface(&dd_sd,&lp_DD_BackSurface,NULL);
#else
dd_result = lp_DD->CreateSurface(&dd_sd,&lp_DD_BackSurface,NULL);
#endif
ERROR_MSG((dd_result==DD_OK),"Can't create lp_DD_BackSurface");
}
if(lp_DD_Clipper==NULL)
{
// Create DEBUG clipper.
#ifdef DD2
dd_result = lp_DD_2->CreateClipper(0,&lp_DD_Clipper,NULL);
#else
dd_result = lp_DD->CreateClipper(0,&lp_DD_Clipper,NULL);
#endif
ERROR_MSG((dd_result==DD_OK),"Can't create lp_DD_Clipper");
// Set clipper window handle.
dd_result = lp_DD_Clipper->SetHWnd(0,hShellWindow);
ERROR_MSG((dd_result==DD_OK),"Can't set lp_DD_Clipper window handle");
// Attach clipper to front surface.
lp_DD_FrontSurface->SetClipper(lp_DD_Clipper);
ERROR_MSG((dd_result==DD_OK),"Can't attach lp_DD_Clipper to lp_DD_FrontSurface");
}
#else
if(lp_DD_FrontSurface==NULL)
{
// Create RELEASE front & back Surfaces.
dd_sd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
dd_sd.ddsCaps.dwCaps = DDSCAPS_COMPLEX|DDSCAPS_FLIP|DDSCAPS_PRIMARYSURFACE|DDSCAPS_3DDEVICE;
dd_sd.dwBackBufferCount = 1;
#ifdef MF_DD2
dd_result = lp_DD_2->CreateSurface(&dd_sd,&lp_DD_FrontSurface,NULL);
#else
dd_result = lp_DD->CreateSurface(&dd_sd,&lp_DD_FrontSurface,NULL);
#endif
ERROR_MSG((dd_result==DD_OK),"Can't create lp_DD_FrontSurface");
// Extract RELEASE Back surface.
dd_scaps.dwCaps = DDSCAPS_BACKBUFFER;
dd_result = lp_DD_FrontSurface->GetAttachedSurface(&dd_scaps,&lp_DD_BackSurface);
ERROR_MSG((dd_result==DD_OK),"Can't extract lp_DD_BackSurface");
}
#endif
if(lp_DD_WorkSurface==NULL)
{
// Create work surface.
dd_sd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
dd_sd.dwHeight = WorkScreenHeight;
dd_sd.dwWidth = WorkScreenWidth;
dd_sd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
#ifdef MF_DD2
dd_result = lp_DD_2->CreateSurface(&dd_sd,&lp_DD_WorkSurface,NULL);
#else
dd_result = lp_DD->CreateSurface(&dd_sd,&lp_DD_WorkSurface,NULL);
#endif
ERROR_MSG((dd_result==DD_OK),"Can't create lp_DD_WorkSurface");
}
DisplayState |= DS_CREATED_SURFACES;
return NoError;
}
//---------------------------------------------------------------
SLONG DestroySurfaces(void)
{
HRESULT dd_result;
#ifdef _DEBUG
if(lp_DD_Clipper)
{
lp_DD_Clipper->Release();
lp_DD_Clipper = NULL;
}
if(lp_DD_BackSurface)
{
dd_result = lp_DD_BackSurface->Release();
// if(dd_result!=DD_OK)
// LogText("error: %ld - Unable to release lp_DD_BackSurface\n",dd_result&0xffff);
}
#endif
if(lp_DD_FrontSurface)
{
dd_result = lp_DD_FrontSurface->Release();
if(dd_result!=DD_OK)
LogText("error: %ld - Unable to release lp_DD_FrontSurface\n",dd_result&0xffff);
lp_DD_FrontSurface = NULL;
lp_DD_BackSurface = NULL;
}
if(lp_DD_WorkSurface)
{
dd_result = lp_DD_WorkSurface->Release();
if(dd_result!=DD_OK)
LogText("error: %ld - Unable to release lp_DD_WorkSurface\n",dd_result&0xffff);
lp_DD_WorkSurface = NULL;
}
DisplayState &= ~(DS_CREATED_SURFACES);
return NoError;
}
//---------------------------------------------------------------
void ClearDisplay(void)
{
DDBLTFX dd_bltfx;
HRESULT dd_result;
dd_bltfx.dwSize = sizeof(dd_bltfx);
dd_bltfx.dwFillColor = 0;
dd_result = lp_DD_FrontSurface->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&dd_bltfx);
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
lp_DD_FrontSurface->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&dd_bltfx);
break;
}
}
//---------------------------------------------------------------
void FadeDisplay(UBYTE mode)
{
switch(mode)
{
case FADE_IN:
break;
case FADE_OUT:
break;
}
}
//---------------------------------------------------------------
void *LockWorkScreen(void)
{
DDSURFACEDESC dd_sd;
HRESULT dd_result;
if(lp_DD_WorkSurface)
{
dd_sd.dwSize = sizeof(dd_sd);
dd_result = lp_DD_WorkSurface->Lock(NULL,&dd_sd,DDLOCK_WAIT,NULL);
switch(dd_result)
{
case DD_OK:
WorkScreenWidth = dd_sd.lPitch;
WorkScreen = (UBYTE*)dd_sd.lpSurface;
SetWorkWindow();
DisplayState |= DS_SCREEN_LOCKED;
return dd_sd.lpSurface;
case DDERR_SURFACELOST:
RestoreSurfaces();
return 0;
}
}
return 0;
}
//---------------------------------------------------------------
void UnlockWorkScreen(void)
{
HRESULT dd_result;
if(lp_DD_WorkSurface)
{
dd_result = lp_DD_WorkSurface->Unlock(NULL);
switch(dd_result)
{
case DD_OK:
DisplayState &= ~(DS_SCREEN_LOCKED);
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
break;
}
}
}
//---------------------------------------------------------------
void ShowWorkScreen(ULONG flags)
{
HRESULT dd_result;
if(lp_DD_WorkSurface==NULL)
return;
// Apparently Blt is better than BltFst for System to Display blits.
if(flags&DS_WAIT_VBI)
{
#ifdef MF_DD2
dd_result = lp_DD_2->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,NULL);
#else
dd_result = lp_DD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,NULL);
#endif
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
#ifdef MF_DD2
lp_DD_2->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,NULL);
#else
lp_DD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,NULL);
#endif
break;
}
}
if(flags&DS_DO_FLIP)
{
#ifdef _DEBUG
dd_result = lp_DD_BackSurface->Blt (
&ShellRect,
lp_DD_WorkSurface,
NULL,
DDBLT_WAIT,
NULL
);
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
break;
default:
LogText("Blt failed in ShowWorkScreen. Error: %ld\n",dd_result&0xffff);
}
/*
dd_result = lp_DD_FrontSurface->Blt (
&ShellRect,
lp_DD_BackSurface,
NULL,
DDBLT_WAIT,
NULL
);
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
break;
default:
LogText("Flip failed in ShowWorkScreen. Error: %ld\n",dd_result&0xffff);
}
*/
#else
dd_result = lp_DD_BackSurface->Blt (
NULL,
lp_DD_WorkSurface,
NULL,
DDBLT_WAIT,
NULL
);
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
break;
default:
LogText("Blt failed in ShowWorkScreen. Error: %ld\n",dd_result&0xffff);
}
/*
dd_result = lp_DD_FrontSurface->Flip(NULL, DDFLIP_WAIT);
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
break;
default:
LogText("Flip failed in ShowWorkScreen. Error: %ld\n",dd_result&0xffff);
}
*/
#endif
}
else
{
#ifdef _DEBUG
dd_result = lp_DD_FrontSurface->Blt (
&ShellRect,
lp_DD_WorkSurface,
NULL,
DDBLT_WAIT,
NULL
);
#else
dd_result = lp_DD_FrontSurface->Blt (
NULL,
lp_DD_WorkSurface,
NULL,
DDBLT_WAIT,
NULL
);
#endif
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
break;
default:
LogText("Blt failed in ShowWorkScreen. Error: %ld\n",dd_result&0xffff);
}
}
}
//---------------------------------------------------------------
void ShowWorkWindow(ULONG flags)
{
HRESULT dd_result;
RECT ww_source_rect;
#ifdef _DEBUG
SLONG x_scale,
y_scale;
RECT ww_dest_rect;
#endif
if(lp_DD_WorkSurface==NULL)
return;
ww_source_rect.left = WorkWindowRect.Left;
ww_source_rect.top = WorkWindowRect.Top;
ww_source_rect.right = WorkWindowRect.Right;
ww_source_rect.bottom = WorkWindowRect.Bottom;
// Apparently Blt is better than BltFst for System to Display blits.
if(flags&DS_WAIT_VBI)
{
#ifdef MF_DD2
dd_result = lp_DD_2->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,NULL);
#else
dd_result = lp_DD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,NULL);
#endif
switch(dd_result)
{
case DD_OK:
break;
case DDERR_WASSTILLDRAWING:
while(lp_DD_WorkSurface->GetBltStatus(DDGBS_ISBLTDONE)==DDERR_WASSTILLDRAWING);
while(lp_DD_BackSurface->GetBltStatus(DDGBS_ISBLTDONE)==DDERR_WASSTILLDRAWING);
while(lp_DD_FrontSurface->GetBltStatus(DDGBS_ISBLTDONE)==DDERR_WASSTILLDRAWING);
#ifdef MF_DD2
lp_DD_2->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,NULL);
#else
lp_DD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,NULL);
#endif
break;
}
}
if(flags&DS_DO_FLIP)
{
#ifdef _DEBUG
x_scale = ((ShellRect.right-ShellRect.left)<<16)/WorkScreenPixelWidth;
y_scale = ((ShellRect.bottom-ShellRect.top)<<16)/WorkScreenHeight;
ww_dest_rect.left = ShellRect.left+ww_source_rect.left;
ww_dest_rect.top = ShellRect.top+ww_source_rect.top;
ww_dest_rect.right = ww_dest_rect.left+((WorkWindowWidth*x_scale)>>16);
ww_dest_rect.bottom = ww_dest_rect.top+((WorkWindowHeight*y_scale)>>16);
dd_result = lp_DD_BackSurface->Blt (
&ww_source_rect,
lp_DD_WorkSurface,
&ww_source_rect,
DDBLT_WAIT,
NULL
);
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
break;
default:
LogText("Blt failed in ShowWorkScreen. Error: %ld\n",dd_result&0xffff);
}
/*
dd_result = lp_DD_FrontSurface->Blt (
&ww_dest_rect,
lp_DD_BackSurface,
&ShellRect,
DDBLT_WAIT,
NULL
);
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
break;
default:
LogText("Flip failed in ShowWorkScreen. Error: %ld\n",dd_result&0xffff);
}
*/
#else
dd_result = lp_DD_BackSurface->Blt (
&ww_source_rect,
lp_DD_WorkSurface,
&ww_source_rect,
DDBLT_WAIT,
NULL
);
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
break;
default:
LogText("Blt failed in ShowWorkScreen. Error: %ld\n",dd_result&0xffff);
}
/*
dd_result = lp_DD_FrontSurface->Flip(NULL, DDFLIP_WAIT);
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
break;
default:
LogText("Flip failed in ShowWorkScreen. Error: %ld\n",dd_result&0xffff);
}
*/
#endif
}
else
{
#ifdef _DEBUG
x_scale = ((ShellRect.right-ShellRect.left)<<16)/WorkScreenPixelWidth;
y_scale = ((ShellRect.bottom-ShellRect.top)<<16)/WorkScreenHeight;
ww_dest_rect.left = ShellRect.left+ww_source_rect.left;
ww_dest_rect.top = ShellRect.top+ww_source_rect.top;
ww_dest_rect.right = ww_dest_rect.left+((WorkWindowWidth*x_scale)>>16);
ww_dest_rect.bottom = ww_dest_rect.top+((WorkWindowHeight*y_scale)>>16);
dd_result = lp_DD_FrontSurface->Blt (
&ww_dest_rect,
lp_DD_WorkSurface,
&ww_source_rect,
DDBLT_WAIT,
NULL
);
#else
dd_result = lp_DD_FrontSurface->Blt (
&ww_source_rect,
lp_DD_WorkSurface,
&ww_source_rect,
DDBLT_WAIT,
NULL
);
#endif
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
break;
default:
LogText("Blt failed in ShowWorkScreen. Error: %ld\n",dd_result&0xffff);
}
}
}
//---------------------------------------------------------------
void ClearWorkScreen(UBYTE colour)
{
DDBLTFX dd_bltfx;
HRESULT dd_result;
if(lp_DD_WorkSurface)
{
dd_bltfx.dwSize = sizeof(dd_bltfx);
dd_bltfx.dwFillColor = colour;
dd_result = lp_DD_WorkSurface->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&dd_bltfx);
switch(dd_result)
{
case DD_OK:
break;
case DDERR_SURFACELOST:
RestoreSurfaces();
lp_DD_WorkSurface->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&dd_bltfx);
break;
}
}
}
//---------------------------------------------------------------
void RestoreSurfaces(void)
{
if(lp_DD_FrontSurface)
{
if(lp_DD_FrontSurface->IsLost() == DDERR_SURFACELOST)
{
lp_DD_FrontSurface->Restore();
RestorePalettes();
}
}
#ifdef _DEBUG
if(lp_DD_BackSurface)
{
if(lp_DD_BackSurface->IsLost() == DDERR_SURFACELOST)
{
lp_DD_BackSurface->Restore();
}
}
#endif
if(lp_DD_WorkSurface)
{
if(lp_DD_WorkSurface->IsLost() == DDERR_SURFACELOST)
{
lp_DD_WorkSurface->Restore();
}
}
}
//---------------------------------------------------------------
HRESULT CALLBACK DisplayModesCallback(LPDDSURFACEDESC p_dd_sd, LPVOID ignore)
{
ULONG c0;
ignore = ignore; // Stop the compiler whinging.
for(c0=1;c0<DISPLAY_MODE_COUNT;c0++)
{
if (
DisplayModes[c0].Width==p_dd_sd->dwWidth &&
DisplayModes[c0].Height==p_dd_sd->dwHeight &&
DisplayModes[c0].Depth==p_dd_sd->ddpfPixelFormat.dwRGBBitCount
)
{
DisplayModes[c0].DD_ModeDesc = *p_dd_sd;
DisplayModes[c0].Availability = TRUE;
break;
}
}
return DDENUMRET_OK;
}
//---------------------------------------------------------------
BOOL WINAPI EnumDeviceCallback(
GUID FAR *lpGUID,
LPSTR lpDriverDescription,
LPSTR lpDriverName,
LPVOID lpContext
)
{
CBYTE *str_ptr = lpDriverDescription;
lpDriverName = lpDriverName;
lpContext = lpContext;
while(*str_ptr!=0)
{
if(*str_ptr=='3')
{
if((*(str_ptr+1)=='D'||*(str_ptr+1)=='d') && (*(str_ptr+2)=='F'||*(str_ptr+2)=='f') && (*(str_ptr+3)=='X'||*(str_ptr+3)=='x'))
{
Device3DFX = *lpGUID;
Got3DFX = TRUE;
return DDENUMRET_CANCEL;
}
}
str_ptr++;
}
return DDENUMRET_OK;
}
//---------------------------------------------------------------

View File

@ -0,0 +1,176 @@
// File.cpp
// Guy Simmons, 10th February 1997.
#include <MFHeader.h>
//---------------------------------------------------------------
BOOL FileExists(CBYTE *file_name)
{
if(GetFileAttributes(file_name)==0xffffffff)
return FALSE;
else
return TRUE;
}
//---------------------------------------------------------------
MFFileHandle FileOpen(CBYTE *file_name)
{
MFFileHandle result = FILE_OPEN_ERROR;
if(FileExists(file_name))
{
result = CreateFile (
file_name,
(GENERIC_READ|GENERIC_WRITE),
(FILE_SHARE_READ|FILE_SHARE_WRITE),
NULL,
OPEN_EXISTING,
0,
NULL
);
if(result==INVALID_HANDLE_VALUE)
result = FILE_OPEN_ERROR;
}
return result;
}
//---------------------------------------------------------------
void FileClose(MFFileHandle file_handle)
{
CloseHandle(file_handle);
}
//---------------------------------------------------------------
MFFileHandle FileCreate(CBYTE *file_name,BOOL overwrite)
{
DWORD creation_mode;
MFFileHandle result;
if(overwrite)
{
creation_mode = CREATE_ALWAYS;
}
else
{
creation_mode = CREATE_NEW;
}
result = CreateFile (
file_name,
(GENERIC_READ|GENERIC_WRITE),
(FILE_SHARE_READ|FILE_SHARE_WRITE),
NULL,
creation_mode,
0,
NULL
);
if(result==INVALID_HANDLE_VALUE)
result = FILE_CREATION_ERROR;
return result;
}
//---------------------------------------------------------------
void FileDelete(CBYTE *file_name)
{
DeleteFile(file_name);
}
//---------------------------------------------------------------
SLONG FileSize(MFFileHandle file_handle)
{
DWORD result;
result = GetFileSize(file_handle,NULL);
if(result==0xffffffff)
return FILE_SIZE_ERROR;
else
return (SLONG)result;
}
//---------------------------------------------------------------
SLONG FileRead(MFFileHandle file_handle,void *buffer,ULONG size)
{
SLONG bytes_read;
if(ReadFile(file_handle,buffer,size,(LPDWORD)&bytes_read,NULL)==FALSE)
return FILE_READ_ERROR;
else
return bytes_read;
}
//---------------------------------------------------------------
SLONG FileWrite(MFFileHandle file_handle,void *buffer,ULONG size)
{
SLONG bytes_written;
if(WriteFile(file_handle,buffer,size,(LPDWORD)&bytes_written,NULL)==FALSE)
return FILE_WRITE_ERROR;
else
return bytes_written;
}
//---------------------------------------------------------------
SLONG FileSeek(MFFileHandle file_handle,enum SeekModes mode,SLONG offset)
{
DWORD method;
switch(mode)
{
case SEEK_MODE_BEGINNING:
method = FILE_BEGIN;
break;
case SEEK_MODE_CURRENT:
method = FILE_CURRENT;
break;
case SEEK_MODE_END:
method = FILE_END;
break;
}
if(SetFilePointer(file_handle,offset,NULL,method)==0xffffffff)
return FILE_SEEK_ERROR;
else
return 0;
}
//---------------------------------------------------------------
SLONG FileLoadAt(CBYTE *file_name,void *buffer)
{
SLONG size;
MFFileHandle handle;
handle = FileOpen(file_name);
if(handle!=FILE_OPEN_ERROR)
{
size = FileSize(handle);
if(size>0)
{
if(FileRead(handle,buffer,size)==size)
{
FileClose(handle);
return size;
}
}
FileClose(handle);
}
return FILE_LOAD_AT_ERROR;
}
//---------------------------------------------------------------

View File

@ -0,0 +1,117 @@
// Keyboard.cpp
// Guy Simmons, 11th February 1997.
#include <MFHeader.h>
volatile UBYTE AltFlag,
ControlFlag,
ShiftFlag;
volatile UBYTE Keys[256],
LastKey;
HHOOK KeyboardHook;
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam);
//---------------------------------------------------------------
BOOL SetupKeyboard(void)
{
AltFlag = 0;
ControlFlag = 0;
ShiftFlag = 0;
LastKey = 0;
memset((char*)&Keys[0],0,256);
#ifdef _RELEASE
KeyboardHook = NULL;
/*
KeyboardHook = SetWindowsHookEx(
WH_KEYBOARD,
(HOOKPROC)KeyboardProc,
NULL,
0
);
ERROR_MSG(KeyboardHook,"Can't setup the keyboard.")
if(KeyboardHook==NULL)
{
// Unable to set up keyboard.
return FALSE;
}
*/
#endif
return TRUE;
}
//---------------------------------------------------------------
void ResetKeyboard(void)
{
#ifdef _RELEASE
if(KeyboardHook)
UnhookWindowsHookEx(KeyboardHook);
#endif
}
//---------------------------------------------------------------
#define KEYMASK_REPEAT (0x0000ffff)
#define KEYMASK_SCAN (0x00ff0000)
#define KEYMASK_EXTENDED (0x01000000)
#define KEYMASK_RESERVED (0x1e000000)
#define KEYMASK_CONTEXT (0x20000000)
#define KEYMASK_PSTATE (0x40000000)
#define KEYMASK_TSTATE (0x80000000)
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
UBYTE key_code;
ULONG virtual_keycode = wParam;
if(code<0)
{
return CallNextHookEx(KeyboardHook,code,wParam,lParam);
}
// Get key scan code.
key_code = (UBYTE)((lParam&KEYMASK_SCAN)>>16);
// Extended key press?
if(lParam&KEYMASK_EXTENDED)
{
key_code += 0x80;
}
// Key up?
if(lParam&KEYMASK_TSTATE)
{
Keys[key_code] = 0;
}
// No ,down.
else
{
Keys[key_code] = 1;
LastKey = key_code;
}
if(Keys[KB_LALT] || Keys[KB_RALT])
AltFlag = 1;
else
AltFlag = 0;
if(Keys[KB_LCONTROL] || Keys[KB_RCONTROL])
ControlFlag = 1;
else
ControlFlag = 0;
if(Keys[KB_LSHIFT] || Keys[KB_RSHIFT])
ShiftFlag = 1;
else
ShiftFlag = 0;
return FALSE;
}
//---------------------------------------------------------------

View File

@ -0,0 +1,449 @@
// MFHost.cpp - Windows.
// Guy Simmons, 1st February 1997.
#include <MFHeader.h>
#define SHELL_NAME "Mucky Foot Shell"
int iGlobalCmdShow;
HANDLE hShellThread = NULL;
HINSTANCE hGlobalInstance,
hGlobalPrevInstance;
HWND hShellWindow = NULL;
LPSTR szGlobalCmdLine;
MFFileHandle log_handle = NULL;
WNDCLASS wnd_class;
RECT ShellRect;
static UWORD argc;
static LPTSTR argv[MAX_PATH];
LRESULT CALLBACK WndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam);
ULONG ShellThread(ULONG arg);
SLONG CreateShellWindow(void);
extern UBYTE DisplayState;
//---------------------------------------------------------------
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR szCmdLine, int iCmdShow)
{
#ifdef TARGET_DC
// DC doesn't have command-lines.
TCHAR *argv[2];
argv[0] = TEXT("BogusName");
argv[1] = TEXT("");
return MF_main(1,argv);
#else //#ifdef TARGET_DC
LPSTR lp_str;
szGlobalCmdLine = szCmdLine;
iGlobalCmdShow = iCmdShow;
hGlobalInstance = hInstance;
hGlobalPrevInstance = hPrevInstance;
argc = 1;
lp_str = szCmdLine;
while(*lp_str!=0)
{
while(*lp_str=='\t'||*lp_str==' ')
{
lp_str++;
}
if(*lp_str!=0)
{
argv[argc++] = lp_str;
while(*lp_str!='\t'&&*lp_str!=' '&&*lp_str!=0)
{
lp_str++;
}
if(*lp_str!=0)
{
*lp_str = 0;
lp_str++;
}
}
}
return MF_main(argc,argv);
#endif //#else //#ifdef TARGET_DC
}
//---------------------------------------------------------------
BOOL SetupHost(ULONG flags)
{
DWORD id;
if(!SetupMemory())
return FALSE;
if(!SetupKeyboard())
return FALSE;
if(flags&H_CREATE_LOG)
{
log_handle = FileCreate("debug.log",1);
if(log_handle==FILE_CREATION_ERROR)
log_handle = NULL;
}
#ifndef TARGET_DC
// Set up shell window.
wnd_class.style = 0; //CS_HREDRAW|CS_VREDRAW;
wnd_class.lpfnWndProc = WndProc;
wnd_class.cbClsExtra = 0;
wnd_class.cbWndExtra = 0;
wnd_class.hInstance = hGlobalInstance;
wnd_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW);
wnd_class.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wnd_class.lpszMenuName = NULL;
wnd_class.lpszClassName = SHELL_NAME;
#else //#ifndef TARGET_DC
// Set up shell window.
wnd_class.style = 0;
wnd_class.lpfnWndProc = WndProc;
wnd_class.cbClsExtra = 0;
wnd_class.cbWndExtra = 0;
wnd_class.hInstance = hGlobalInstance;
wnd_class.hIcon = NULL;
wnd_class.hCursor = NULL;
wnd_class.hbrBackground = NULL;
wnd_class.lpszMenuName = NULL;
wnd_class.lpszClassName = TEXT(SHELL_NAME);
#endif //#else //#ifndef TARGET_DC
RegisterClass(&wnd_class);
hShellThread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)ShellThread,
0,
0,
&id
);
ERROR_MSG(hShellThread,"Can't create the shell thread.")
if(hShellThread)
{
// Wait for shell to activate.
// This could potentially cause a problem if the shell window couldn't be created.
while(!DisplayActive)
{
#ifdef TARGET_DC
Sleep(100);
#else
SleepEx(100,FALSE);
#endif
}
}
return TRUE;
}
//---------------------------------------------------------------
void ResetHost(void)
{
if(log_handle)
FileClose(log_handle);
ResetKeyboard();
ResetMemory();
}
//---------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND h_window,UINT i_message,WPARAM w_param,LPARAM l_param)
{
switch (i_message)
{
#ifndef TARGET_DC
case WM_SIZE:
case WM_MOVE:
// LogText("WM_SIZE or WM_MOVE\n");
if (IsIconic(h_window))
{
// Shell is minimized, maybe set Pause flag?
}
#ifdef _DEBUG
GetClientRect(h_window, &ShellRect);
ClientToScreen(h_window, (LPPOINT)&ShellRect);
ClientToScreen(h_window, (LPPOINT)&ShellRect+1);
#else
SetRect(&ShellRect,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
#endif
if(lp_DD_FrontSurface)
ClearDisplay();
break;
case WM_QUERYNEWPALETTE:
// LogText("WM_QUERYNEWPALETTE\n");
RestorePalettes();
break;
case WM_PALETTECHANGED:
// LogText("WM_PALETTECHANGED\n");
RestorePalettes();
break;
case WM_MOUSEMOVE:
// LogText("WM_MOUSEMOVE:\n");
MouseX = LOWORD(l_param);
MouseY = HIWORD(l_param);
MousePoint.X = MouseX;
MousePoint.Y = MouseY;
MouseMoved = 1;
break;
#endif //#ifndef TARGET_DC
case WM_RBUTTONUP:
// LogText("WM_RBUTTONUP\n");
RightButton = 0;
break;
case WM_RBUTTONDOWN:
// LogText("WM_RBUTTONDOWN\n");
RightButton = 1;
if(!RightMouse.ButtonState)
{
RightMouse.ButtonState = 1;
RightMouse.MouseX = LOWORD(l_param);
RightMouse.MouseY = HIWORD(l_param);
RightMouse.MousePoint.X = LOWORD(l_param);
RightMouse.MousePoint.Y = HIWORD(l_param);
}
break;
case WM_RBUTTONDBLCLK:
break;
case WM_LBUTTONUP:
LogText("WM_LBUTTONUP\n");
LeftButton = 0;
break;
case WM_LBUTTONDOWN:
// LogText("WM_LBUTTONDOWN\n");
LeftButton = 1;
if(!LeftMouse.ButtonState)
{
LeftMouse.ButtonState = 1;
LeftMouse.MouseX = LOWORD(l_param);
LeftMouse.MouseY = HIWORD(l_param);
LeftMouse.MousePoint.X = LOWORD(l_param);
LeftMouse.MousePoint.Y = HIWORD(l_param);
}
break;
case WM_LBUTTONDBLCLK:
break;
case WM_MBUTTONUP:
MiddleButton = 0;
break;
case WM_MBUTTONDOWN:
// LogText("WM_MBUTTONDOWN\n");
MiddleButton = 1;
if(!MiddleMouse.ButtonState)
{
MiddleMouse.ButtonState = 1;
MiddleMouse.MouseX = LOWORD(l_param);
MiddleMouse.MouseY = HIWORD(l_param);
MiddleMouse.MousePoint.X= LOWORD(l_param);
MiddleMouse.MousePoint.Y= HIWORD(l_param);
}
break;
case WM_MBUTTONDBLCLK:
break;
//#ifdef _DEBUG
extern LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam);
case WM_KEYDOWN:
case WM_KEYUP:
// LogText("WM_KEYDOWN or WM_KEYUP\n");
KeyboardProc( 0, 0, l_param);
break;
//#endif
case WM_CLOSE:
// LogText("WM_CLOSE\n");
DisplayActive = 0;
break;
case WM_DESTROY:
// LogText("WM_DESTROY\n");
PostQuitMessage(0);
DisplayState &= ~(DS_SHELL_WINDOW_OPEN);
break;
// default:
// LogText("Unknown event - %ld\n",i_message);
}
return DefWindowProc(h_window,i_message,w_param,l_param);
}
//---------------------------------------------------------------
ULONG ShellThread(ULONG arg)
{
SLONG result;
MSG msg;
arg = arg;
DisplayState |= DS_THREAD_ACTIVE;
result = CreateShellWindow();
if(result==NoError)
{
/*
while(1)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
// if(!GetMessage(&msg,NULL,0,0))
// break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// make sure we go to sleep if we have nothing else to do
WaitMessage();
}
}
*/
while(GetMessage(&msg,NULL,0,0) && (DisplayState&DS_SHELL_WINDOW_OPEN))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
#ifdef TARGET_DC
Sleep(100);
#else
SleepEx(100,FALSE);
#endif
DisplayActive = 0;
MFShellActive = 0;
DisplayState &= ~(DS_THREAD_ACTIVE);
return EXIT_SUCCESS;
}
//---------------------------------------------------------------
SLONG CreateShellWindow(void)
{
hShellWindow = CreateWindowExA (
0,
SHELL_NAME,
SHELL_NAME,
WS_POPUP|WS_VISIBLE|WS_SYSMENU,
#ifdef _DEBUG
0,0,
640,
480,
#else
0,0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
#endif
NULL,
NULL,
hGlobalInstance,
NULL
);
ERROR_MSG(hShellWindow,"Can't create the shell window.")
if(hShellWindow)
{
DisplayState |= DS_SHELL_WINDOW_OPEN;
DisplayActive = 1;
MFShellActive = 1;
// ShowWindow(hShellWindow,SW_SHOWNORMAL);
// UpdateWindow(hShellWindow);
return NoError;
}
else
{
return -1;
}
}
//---------------------------------------------------------------
void LogText(CBYTE *error, ...)
{
CBYTE buf[512];
va_list argptr;
if(log_handle)
{
va_start(argptr,error);
vsprintf(buf, error,argptr);
va_end(argptr);
FileWrite(log_handle,buf,strlen(buf));
}
}
//---------------------------------------------------------------
extern HWND hShellWindow;
int MFMessage(const char *pMessage, const char *pFile, ULONG dwLine)
{
#ifndef TARGET_DC
char buff1[512];
char buff2[512];
ULONG flag;
LogText("Mucky Foot Message\n %s\nIn : %s\nLine : %u",pMessage,pFile,dwLine);
sprintf( buff1, "Something strange has happened!");
sprintf( buff2, "%s\n\n%s\n\nIn : %s\nline : %u", buff1, pMessage, pFile, dwLine);
strcat(buff2, "\n\nAbort=Kill Application, Retry=Debug, Ignore=Continue");
flag = MB_ABORTRETRYIGNORE|MB_ICONSTOP|MB_DEFBUTTON3;
switch(MessageBox(hShellWindow, buff2, "Mucky Foot Message", flag))
{
case IDABORT:
case IDCANCEL:
exit(1);
break;
case IDRETRY:
return TRUE;
}
#else //#ifndef TARGET_DC
LogText("Mucky Foot Message\n %s\nIn : %s\nLine : %u",pMessage,pFile,dwLine);
#endif //#else //#ifndef TARGET_DC
return FALSE;
}
//---------------------------------------------------------------
void Time(struct MFTime *the_time)
{
SYSTEMTIME new_time;
GetLocalTime(&new_time);
the_time->Hours = new_time.wHour;
the_time->Minutes = new_time.wMinute;
the_time->Seconds = new_time.wSecond;
the_time->MSeconds = new_time.wMilliseconds;
the_time->DayOfWeek = new_time.wDayOfWeek;
the_time->Day = new_time.wDay;
the_time->Month = new_time.wMonth;
the_time->Year = new_time.wYear;
the_time->Ticks = GetTickCount();
}
//---------------------------------------------------------------

View File

@ -0,0 +1,67 @@
// Mem.cpp
// Guy Simmons, 10th February 1997.
#include <MFHeader.h>
#define INITIAL_HEAP_SIZE (18*1024*1024)
#define MAXIMUM_HEAP_SIZE (24*1024*1024)
HANDLE MFHeap = NULL;
//---------------------------------------------------------------
BOOL SetupMemory(void)
{
if(MFHeap==NULL)
{
MFHeap = HeapCreate(0,INITIAL_HEAP_SIZE,MAXIMUM_HEAP_SIZE);
}
ERROR_MSG(MFHeap,"Can't setup memory.")
if(MFHeap)
return TRUE;
else
return FALSE;
}
//---------------------------------------------------------------
void ResetMemory(void)
{
if(MFHeap)
{
HeapDestroy(MFHeap);
MFHeap = NULL;
}
}
//---------------------------------------------------------------
void *MemAlloc(ULONG size)
{
size = (size+3)&0xfffffffc;
return (void*)HeapAlloc(MFHeap,HEAP_ZERO_MEMORY,size);
}
//---------------------------------------------------------------
void MemFree(void *mem_ptr)
{
HeapFree(MFHeap,0,mem_ptr);
}
//---------------------------------------------------------------
void MemClear(void *mem_ptr,ULONG size)
{
/*
ULONG c0;
for(c0=0;c0<size;c0++)
*(mem_ptr++) = 0;
*/
}
//---------------------------------------------------------------

View File

@ -0,0 +1,17 @@
// Mouse.cpp
// Guy Simmons, 19th February 1997.
#include <MFHeader.h>
volatile UBYTE MouseMoved = 0,
LeftButton = 0,
MiddleButton = 0,
RightButton = 0;
volatile SLONG MouseX,
MouseY;
volatile LastMouse LeftMouse = { 0,0,0,{ 0,0 } },
MiddleMouse = { 0,0,0,{ 0,0 } },
RightMouse = { 0,0,0,{ 0,0 } };
volatile MFPoint MousePoint = { 0,0 };

View File

@ -0,0 +1,245 @@
// Palette.cpp
// Guy Simmons, 11th February 1997.
#include <MFHeader.h>
UBYTE CurrentPalette[256*3];
LPDIRECTDRAWPALETTE lp_DD_Palette = NULL;
PALETTEENTRY ThePalette[256];
//---------------------------------------------------------------
void InitPalettes(void)
{
#if defined(_DEBUG) && !defined(TARGET_DC)
ULONG c0;
// First set up the Windows static entries.
for(c0=0;c0<10;c0++)
{
// The first 10 static entries:
ThePalette[c0].peFlags = PC_EXPLICIT;
ThePalette[c0].peRed = (UBYTE)c0;
ThePalette[c0].peGreen = 0;
ThePalette[c0].peBlue = 0;
// The last 10 static entries:
ThePalette[c0+246].peFlags = PC_EXPLICIT;
ThePalette[c0+246].peRed = (UBYTE)(c0+246);
ThePalette[c0+246].peGreen = 0;
ThePalette[c0+246].peBlue = 0;
}
// Set up private entries. Initialise to black.
for(c0=10;c0<246;c0++)
{
ThePalette[c0].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
ThePalette[c0].peRed = 0;
ThePalette[c0].peGreen = 0;
ThePalette[c0].peBlue = 0;
}
#else
// Initialise palette to black.
memset(ThePalette,0,sizeof(ThePalette));
#endif
}
//---------------------------------------------------------------
SLONG CreatePalettes(void)
{
HRESULT dd_result;
if(lp_DD_Palette==NULL )
{
#ifdef _DEBUG
dd_result = lp_DD->CreatePalette(
DDPCAPS_8BIT,
ThePalette,
&lp_DD_Palette,
NULL
);
#else
dd_result = lp_DD->CreatePalette(
DDPCAPS_8BIT|DDPCAPS_ALLOW256,
ThePalette,
&lp_DD_Palette,
NULL
);
#endif
if(dd_result!=DD_OK)
{
return -1;
}
dd_result = lp_DD_FrontSurface->SetPalette(lp_DD_Palette);
if(dd_result!=DD_OK)
{
LogText(" Unable to attach palette to lp_DD_FrontSurface\n");
return -1;
}
/*
if(dd_result!=DD_OK) dd_result = lp_DD_BackSurface->SetPalette(lp_DD_Palette);
{
LogText(" Unable to attach palette to lp_DD_BackSurface\n");
return -1;
}
*/
}
return NoError;
}
//---------------------------------------------------------------
void DestroyPalettes(void)
{
HRESULT dd_result;
if(lp_DD_Palette)
{
dd_result = lp_DD_Palette->Release();
if(dd_result==DD_OK)
{
lp_DD_Palette = NULL;
}
else
{
// CBYTE text[256];
// sprintf(text,"Unable to Release Palette. Error: %ld",dd_result&0xffff);
// ERROR_MSG(0,text)
}
}
}
//---------------------------------------------------------------
void RestorePalettes(void)
{
if(lp_DD_Palette && lp_DD_FrontSurface)
{
lp_DD_FrontSurface->SetPalette(lp_DD_Palette);
}
}
//---------------------------------------------------------------
void SetPalette(UBYTE *the_palette)
{
#ifndef TARGET_DC
ULONG c0;
HRESULT dd_result;
#ifdef _DEBUG
// First set up the Windows static entries.
for(c0=0;c0<10;c0++)
{
// The first 10 static entries:
ThePalette[c0].peFlags = PC_EXPLICIT;
ThePalette[c0].peRed = (UBYTE)c0;
ThePalette[c0].peGreen = 0;
ThePalette[c0].peBlue = 0;
// The last 10 static entries:
ThePalette[c0+246].peFlags = PC_EXPLICIT;
ThePalette[c0+246].peRed = (UBYTE)(c0+246);
ThePalette[c0+246].peGreen = 0;
ThePalette[c0+246].peBlue = 0;
}
// Set up private entries.
for(c0=10;c0<246;c0++)
{
ThePalette[c0].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
ThePalette[c0].peRed = (UBYTE)(the_palette[(c0*3)+0]);
ThePalette[c0].peGreen = (UBYTE)(the_palette[(c0*3)+1]);
ThePalette[c0].peBlue = (UBYTE)(the_palette[(c0*3)+2]);
}
#else
// Set up all entries.
for(c0=0;c0<256;c0++)
{
ThePalette[c0].peRed = (UBYTE)(the_palette[(c0*3)+0]);
ThePalette[c0].peGreen = (UBYTE)(the_palette[(c0*3)+1]);
ThePalette[c0].peBlue = (UBYTE)(the_palette[(c0*3)+2]);
}
#endif
for(c0=0;c0<256;c0++)
{
CurrentPalette[c0*3+0]=ThePalette[c0].peRed;
CurrentPalette[c0*3+1]=ThePalette[c0].peGreen;
CurrentPalette[c0*3+2]=ThePalette[c0].peBlue;
}
if(lp_DD_Palette)
dd_result = lp_DD_Palette->SetEntries(0,0,256,ThePalette);
#endif
}
//---------------------------------------------------------------
SLONG FindColour(UBYTE *the_palette,SLONG r,SLONG g,SLONG b)
{
SLONG found = -1;
if(r>255)
r=255;
if(g>255)
g=255;
if(b>255)
b=255;
switch(WorkScreenDepth)
{
case 1:
{
SLONG dist = 0x7fffffff,
c0,
dist2,
tr,
tg,
tb;
for(c0=0;c0<256;c0++)
{
tr = *the_palette++;
tg = *the_palette++;
tb = *the_palette++;
tr -= r;
tg -= g;
tb -= b;
dist2= abs(tr*tr)+abs(tg*tg)+abs(tb*tb);
if(dist2<dist)
{
found = c0;
dist = dist2;
if(dist<8)
return(c0);
}
}
break;
}
case 2:
found=(((r>>3)<<11)|((g>>2)<<5)|(b>>3));
break;
case 4:
found=((r<<16)|(g<<8)|(b));
break;
}
return(found);
}
//---------------------------------------------------------------

312
MFStdLib/Headers/MFStdLib.h Normal file
View File

@ -0,0 +1,312 @@
// MFStdLib.h
// Guy Simmons, 18th December 1997.
#ifndef MF_STD_LIB_H
#define MF_STD_LIB_H
//---------------------------------------------------------------
// Standard 'C' includes.
#if !defined(TARGET_DC)
#include <iostream.h>
#include <time.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
// Library defines.
#define _MF_WINDOWS
#ifndef _WIN32
#define _WIN32
#endif
#ifndef WIN32
#define WIN32
#endif
// Specific Windows includes.
#define D3D_OVERLOADS
#include <windows.h>
#include <windowsx.h>
#include <d3dtypes.h>
#include <ddraw.h>
#ifndef TARGET_DC
// For the DX8 headers, you need to define this to get old interfaces.
#ifndef DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION 0x0700
#endif
#endif
#include <dinput.h>
#include <dplay.h>
#include <dsound.h>
#include <d3d.h>
#ifdef TARGET_DC
#include "target.h"
#endif
//---------------------------------------------------------------
#define TRUE 1
#define FALSE 0
typedef unsigned char UBYTE;
typedef signed char SBYTE;
typedef char CBYTE;
typedef unsigned short UWORD;
typedef signed short SWORD;
typedef unsigned long ULONG;
typedef signed long SLONG;
typedef struct
{
SLONG X,
Y;
}MFPoint;
typedef struct
{
SLONG Left,
Top,
Right,
Bottom,
Width,
Height;
}MFRect;
//---------------------------------------------------------------
// MF Standard includes.
#include "StdFile.h"
#include "StdKeybd.h"
#include "StdMaths.h"
#include "StdMem.h"
#include "StdMouse.h"
//---------------------------------------------------------------
// Display
#define FLAGS_USE_3DFX (1<<0)
#define FLAGS_USE_3D (1<<1)
#define FLAGS_USE_WORKSCREEN (1<<2)
extern UBYTE WorkScreenDepth,
*WorkScreen;
extern SLONG WorkScreenHeight,
WorkScreenPixelWidth,
WorkScreenWidth;
extern SLONG DisplayWidth,
DisplayHeight,
DisplayBPP;
SLONG OpenDisplay(ULONG width, ULONG height, ULONG depth, ULONG flags);
SLONG SetDisplay(ULONG width,ULONG height,ULONG depth);
SLONG CloseDisplay(void);
SLONG ClearDisplay(UBYTE r,UBYTE g,UBYTE b);
void FadeDisplay(UBYTE mode);
void *LockWorkScreen(void);
void UnlockWorkScreen(void);
void ShowWorkScreen(ULONG flags);
void ClearWorkScreen(UBYTE colour);
//---------------------------------------------------------------
// Host
#define SHELL_NAME "Mucky Foot Shell\0"
#define H_CREATE_LOG (1<<0)
#define SHELL_ACTIVE (LibShellActive())
#define SHELL_CHANGED (LibShellChanged())
#define main(ac,av) MF_main(ac,av)
struct MFTime
{
SLONG Hours,
Minutes,
Seconds,
MSeconds;
SLONG DayOfWeek, // 0 - 6; Sunday = 0
Day,
Month, // 1 - 12; January = 1
Year;
SLONG Ticks; // Number of ticks(milliseconds) since windows started.
};
SLONG main(UWORD argc, TCHAR** argv);
BOOL SetupHost(ULONG flags);
void ResetHost(void);
//void TraceText(CBYTE *error, ...);
void TraceText(char *error, ...);
BOOL LibShellActive(void);
BOOL LibShellChanged(void);
BOOL LibShellMessage(const char *pMessage, const char *pFile, ULONG dwLine);
#define NoError 0
#ifndef NDEBUG
void DebugText(CBYTE *error, ...);
#define TRACE TraceText
#define LogText DebugText
#define MFMessage LibShellMessage
#define ERROR_MSG(e,m) {if(!(e)) {LibShellMessage(m,__FILE__,__LINE__);}}
//#define ASSERT(e) {if (!(e)) { _asm{int 3} }else{/*TRACE("file %s line %d \n",__FILE__,__LINE__);*/}}
#ifndef ASSERT
#define ASSERT(e) ERROR_MSG(e,"ASSERT TRIGGERED");
#endif
#else
#define DebugText
#define TRACE
#define LogText
#define MFMessage
#define ERROR_MSG(e,m) {}
#ifndef ASSERT
#define ASSERT(e) {}
#endif
#endif
//---------------------------------------------------------------
// Input.
#define MOUSE DIDEVTYPE_MOUSE
#define KEYBOARD DIDEVTYPE_KEYBOARD
#define JOYSTICK DIDEVTYPE_JOYSTICK
#if 0
BOOL GetInputDevice(UBYTE type,UBYTE sub_type);
BOOL ReadInputDevice(void);
#endif
//---------------------------------------------------------------
// Sound.
#define SAMPLE_VOL_MIN DSBVOLUME_MIN
#define SAMPLE_VOL_MAX DSBVOLUME_MAX
#define SAMPLE_PAN_LEFT DSBPAN_LEFT
#define SAMPLE_PAN_RIGHT DSBPAN_RIGHT
#define SAMPLE_PAN_CENTER DSBPAN_CENTER
#define SAMPLE_FREQ_MIN DSBFREQUENCY_MIN
#define SAMPLE_FREQ_MAX DSBFREQUENCY_MAX
#define SAMPLE_FREQ_ORIG DSBFREQUENCY_ORIGINAL
void LoadSampleList(CBYTE *sample_file);
void PlaySample(SLONG ref,SWORD sample_no,SLONG vol,SLONG pan,SLONG freq,SLONG pri);
//---------------------------------------------------------------
// New Sound
#define WAVE_STEREO (1<<0)
#define WAVE_POLAR (1<<1)
#define WAVE_CARTESIAN (1<<2)
#define WAVE_PAN_RATE (1<<3)
#define WAVE_DISTANCE_MAPPING (1<<4)
#define WAVE_LOOP (1<<5)
#define WAVE_SET_LOOP_POINTS (1<<6)
#define WAVE_TYPE_MASK (WAVE_STEREO|WAVE_POLAR|WAVE_CARTESIAN)
#define WAVE_PLAY_INTERUPT 0
#define WAVE_PLAY_NO_INTERUPT 1
#define WAVE_PLAY_OVERLAP 2
#define WAVE_PLAY_QUEUE 3
struct WaveParams
{
ULONG Flags,
LoopStart,
LoopEnd,
Priority;
union
{
// Stereo.
struct
{
SLONG Pan,
Volume;
}Stereo;
// Polar.
struct
{
SLONG Azimuth,
Elevation,
Range;
}Polar;
// Cartesian.
struct
{
SLONG Scale,
X,
Y,
Z;
}Cartesian;
}Mode;
};
void LoadWaveList(CBYTE *path,CBYTE *file);
void FreeWaveList(void);
void PlayWave(SLONG ref,SLONG wave_id,SLONG play_type,WaveParams *the_params);
void StopWave(SLONG ref,SLONG wave_id);
void SetListenerPosition(SLONG x,SLONG y,SLONG z,SLONG scale);
//---------------------------------------------------------------
// Standard macros.
#define sgn(a) (((a)<0) ? -1 : 1)
#define swap(a,b) {a^=b;b^=a;a^=b;}
#define in_range(a,min,max) {if(a>(max))a=(max);else if(a<(min))a=(min);}
#ifndef min
#define min(a,b) (((a)<(b)) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) (((a)>(b)) ? (a) : (b))
#endif
//---------------------------------------------------------------
//
// Stuff put in by Mark...
//
#define INFINITY 0x7fffffff
#define PI (3.14159265F)
#define WITHIN(x,a,b) ((x) >= (a) && (x) <= (b))
#define SATURATE(x,a,b) {if ((x) < (a)) {(x) = (a);} else if ((x) > (b)) {(x) = (b);}}
#define SWAP(a,b) {SLONG temp; temp = (a); (a) = (b); (b) = temp;}
#define SWAP_FL(a,b) {float temp; temp = (a); (a) = (b); (b) = temp;}
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define SIGN(x) (((x)) ? (((x) > 0) ? +1 : -1) : 0)
//
// Some maths stuff by mike
//
#define QDIST3(x,y,z) ((x)>(y) ? ((x)>(z) ? (x)+((y)>>2)+((z)>>2) : (z)+((x)>>2)+((y)>>2)) : ((y)>(z) ? ((y)+((x)>>2)+((z)>>2)) : (z)+((x)>>2)+((y)>>2) ))
#define QDIST2(x,y) ((x)>(y) ? ((x)+((y)>>1) ):((y)+((x)>>1) ))
#define SDIST3(x,y,z) (((x)*(x))+((y)*(y))+((z)*(z)))
#define SDIST2(x,y) (((x)*(x))+((y)*(y)))
#endif

View File

@ -0,0 +1,48 @@
// StdFile.h
// Guy Simmons, 18th December 1997.
#ifndef STD_FILE_H
#define STD_FILE_H
//---------------------------------------------------------------
typedef HANDLE MFFileHandle;
#define FILE_OPEN_ERROR ((MFFileHandle)-100)
#define FILE_CLOSE_ERROR ((MFFileHandle)-101)
#define FILE_CREATION_ERROR ((MFFileHandle)-102)
#define FILE_SIZE_ERROR ((SLONG)-103)
#define FILE_READ_ERROR ((SLONG)-104)
#define FILE_WRITE_ERROR ((SLONG)-105)
#define FILE_SEEK_ERROR ((SLONG)-106)
#define FILE_LOAD_AT_ERROR ((SLONG)-107)
#define SEEK_MODE_BEGINNING 0
#define SEEK_MODE_CURRENT 1
#define SEEK_MODE_END 2
BOOL FileExists(CBYTE *file_name);
MFFileHandle FileOpen(CBYTE *file_name);
void FileClose(MFFileHandle file_handle);
MFFileHandle FileCreate(CBYTE *file_name,BOOL overwrite);
void FileDelete(CBYTE *file_name);
SLONG FileSize(MFFileHandle file_handle);
SLONG FileRead(MFFileHandle file_handle,void *buffer,ULONG size);
SLONG FileWrite(MFFileHandle file_handle,void *buffer,ULONG size);
SLONG FileSeek(MFFileHandle file_handle,const int mode,SLONG offset);
SLONG FileLoadAt(CBYTE *file_name,void *buffer);
void FileSetBasePath(CBYTE *path_name);
// Plug'n'play replacements for fopen/fclose.
// Except they do something cunning on the DC.
// These can be used with sscanf() and so on,
// whereas the above can't.
FILE *MF_Fopen ( const char *file_name, const char *mode );
int MF_Fclose( FILE *stream );
//---------------------------------------------------------------
#endif

152
MFStdLib/Headers/StdKeybd.h Normal file
View File

@ -0,0 +1,152 @@
// StdKeybd.h
// Guy Simmons, 18th December 1997.
#ifndef STD_KEYBD_H
#define STD_KEYBD_H
//---------------------------------------------------------------
// Row1
#define KB_ESC 0x01
#define KB_1 0x02
#define KB_2 0x03
#define KB_3 0x04
#define KB_4 0x05
#define KB_5 0x06
#define KB_6 0x07
#define KB_7 0x08
#define KB_8 0x09
#define KB_9 0x0a
#define KB_0 0x0b
#define KB_MINUS 0x0c
#define KB_PLUS 0x0d
#define KB_BS 0x0e
// Row2
#define KB_TAB 0x0f
#define KB_Q 0x10
#define KB_W 0x11
#define KB_E 0x12
#define KB_R 0x13
#define KB_T 0x14
#define KB_Y 0x15
#define KB_U 0x16
#define KB_I 0x17
#define KB_O 0x18
#define KB_P 0x19
#define KB_LBRACE 0x1a
#define KB_RBRACE 0x1b
#define KB_ENTER 0x1c
// Row3
#define KB_LCONTROL 0x1d
#define KB_CAPSLOCK 0x3a
#define KB_A 0x1e
#define KB_S 0x1f
#define KB_D 0x20
#define KB_F 0x21
#define KB_G 0x22
#define KB_H 0x23
#define KB_J 0x24
#define KB_K 0x25
#define KB_L 0x26
#define KB_COLON 0x27
#define KB_QUOTE 0x28
#define KB_TILD 0x29
// Row4
#define KB_LSHIFT 0x2a
#define KB_BACKSLASH 0x2b
#define KB_Z 0x2c
#define KB_X 0x2d
#define KB_C 0x2e
#define KB_V 0x2f
#define KB_B 0x30
#define KB_N 0x31
#define KB_M 0x32
#define KB_COMMA 0x33
#define KB_POINT 0x34
#define KB_FORESLASH 0x35
#define KB_RSHIFT 0x36
#define KB_LALT 0x38
#define KB_SPACE 0x39
#define KB_RALT (0x38+0x80)
#define KB_RCONTROL (0x1d+0x80)
// Function key row.
#define KB_F1 0x3b
#define KB_F2 0x3c
#define KB_F3 0x3d
#define KB_F4 0x3e
#define KB_F5 0x3f
#define KB_F6 0x40
#define KB_F7 0x41
#define KB_F8 0x42
#define KB_F9 0x43
#define KB_F10 0x44
#define KB_F11 0x57
#define KB_F12 0x58
#define KB_PRTSC (0x37+0x80)
#define KB_SCROLLLOCK 0x46
//#define KB_PAUSE ????
// Edit pad.
#define KB_INS (0x52+0x80)
#define KB_HOME (0x47+0x80)
#define KB_PGUP (0x49+0x80)
#define KB_DEL (0x53+0x80)
#define KB_END (0x4f+0x80)
#define KB_PGDN (0x51+0x80)
// Cursor pad.
#define KB_LEFT (0x4b+0x80)
#define KB_UP (0x48+0x80)
#define KB_RIGHT (0x4d+0x80)
#define KB_DOWN (0x50+0x80)
// Key pad.
#define KB_NUMLOCK 0x45
#define KB_PSLASH (0x35+0x80)
#define KB_ASTERISK 0x37
#define KB_PMINUS 0x4a
#define KB_P7 0x47
#define KB_P8 0x48
#define KB_P9 0x49
#define KB_PPLUS 0x4e
#define KB_P4 0x4b
#define KB_P5 0x4c
#define KB_P6 0x4d
#define KB_P1 0x4f
#define KB_P2 0x50
#define KB_P3 0x51
#define KB_PENTER (0x1c+0x80)
#define KB_P0 0x52
#define KB_PPOINT 0x53
#ifdef TARGET_DC
// On the Dreamcast, these don't exist.
#define AltFlag 0
#define ControlFlag 0
#define ShiftFlag 0
// These don't either, but we'll leave them for now.
extern volatile UBYTE Keys[256],
LastKey;
#else
extern volatile UBYTE AltFlag,
ControlFlag,
ShiftFlag;
extern volatile UBYTE Keys[256],
LastKey;
#endif
//---------------------------------------------------------------
#endif

View File

@ -0,0 +1,44 @@
// StdMaths.h
// Guy Simmons, 18th December 1997
#ifndef STD_MATHS_H
#define STD_MATHS_H
//---------------------------------------------------------------
#define SIN(a) SinTable[a]
#define COS(a) CosTable[a]
#define SIN_F(a) SinTableF[a]
#define COS_F(a) CosTableF[a]
#define PROPTABLE_SIZE 256
#define PROP(x) Proportions[(x)+PROPTABLE_SIZE]
extern float *CosTableF,
SinTableF[];
extern SWORD AtanTable[];
extern SLONG *CosTable,
SinTable[];
extern SLONG Proportions[];
SLONG Arctan(SLONG X,SLONG Y);
SLONG Root(SLONG square);
static inline SLONG Hypotenuse(SLONG x,SLONG y)
{
x = abs(x);
y = abs(y);
if(x>y)
return((PROP((y<<8)/x)*x)>>13);
else
if(y)
return((PROP((x<<8)/y)*y)>>13);
else
return(0);
}
//---------------------------------------------------------------
#endif

42
MFStdLib/Headers/StdMem.h Normal file
View File

@ -0,0 +1,42 @@
// StdMem.h
// Guy Simmons, 18th December 1997
#ifndef STD_MEM_H
#define STD_MEM_H
//---------------------------------------------------------------
BOOL SetupMemory(void);
void ResetMemory(void);
void *MemAlloc(ULONG size);
void MemFree(void *mem_ptr);
#ifdef DEBUG
void MFnewTrace ( void *pvAddr, size_t size );
void MFdeleteTrace ( void *pvAddr );
#endif
// Some templated new and delete stand-ins.
template <class T> T *MFnew ( void )
{
T *ptr = new T;
#ifdef DEBUG
MFnewTrace ( ptr, sizeof ( ptr ) );
#endif
return ptr;
}
template<class T> void MFdelete(T *thing)
{
#ifdef DEBUG
MFdeleteTrace ( thing );
#endif
delete thing;
}
//---------------------------------------------------------------
#endif

View File

@ -0,0 +1,31 @@
// StdMouse.h
// Guy Simmons, 18th December 1997.
#ifndef STD_MOUSE_H
#define STD_MOUSE_H
//---------------------------------------------------------------
struct LastMouse
{
SLONG ButtonState,
MouseX,
MouseY;
MFPoint MousePoint;
};
extern volatile UBYTE MouseMoved,
LeftButton,
MiddleButton,
RightButton;
extern volatile SLONG MouseX,
MouseY;
extern volatile LastMouse LeftMouse,
MiddleMouse,
RightMouse;
extern volatile MFPoint MousePoint;
//---------------------------------------------------------------
#endif

View File

@ -0,0 +1,346 @@
// StdFile.cpp
// Guy Simmons, 18th December 1997.
#include <MFStdLib.h>
#define MAX_LENGTH_OF_BASE_PATH 64
CBYTE cBasePath[MAX_LENGTH_OF_BASE_PATH+1];
#ifdef DEBUG
int m_iNumOpenFiles_FileOpen = 0;
int m_iNumOpenFiles_MF_Fopen = 0;
char pcPrevFilenameOpened[256];
#endif
//---------------------------------------------------------------
#define MAX_LENGTH_OF_FULL_NAME (MAX_LENGTH_OF_BASE_PATH+128)
CBYTE cTempFilename[MAX_LENGTH_OF_FULL_NAME+1];
CBYTE *MakeFullPathName ( const CBYTE *cFilename )
{
strcpy ( cTempFilename, cBasePath );
ASSERT ( strlen ( cFilename ) < ( MAX_LENGTH_OF_FULL_NAME - MAX_LENGTH_OF_BASE_PATH ) );
strcat ( cTempFilename, cFilename );
return ( cTempFilename );
}
//---------------------------------------------------------------
BOOL FileExists( CBYTE *file_name)
{
file_name = MakeFullPathName ( file_name );
if(GetFileAttributes(file_name)==0xffffffff)
return FALSE;
else
return TRUE;
}
//---------------------------------------------------------------
MFFileHandle FileOpen(CBYTE *file_name)
{
MFFileHandle result = FILE_OPEN_ERROR;
if(FileExists(file_name))
{
file_name = MakeFullPathName ( file_name );
result = CreateFile (
file_name,
(GENERIC_READ),
(FILE_SHARE_READ),
NULL,
OPEN_EXISTING,
0,
NULL
);
if(result==INVALID_HANDLE_VALUE)
{
result = FILE_OPEN_ERROR;
}
else
{
#ifdef DEBUG
m_iNumOpenFiles_FileOpen++;
if ( m_iNumOpenFiles_FileOpen > 1 )
{
TRACE ( "FileOpen nested %i\n", m_iNumOpenFiles_FileOpen );
}
strncpy ( pcPrevFilenameOpened, file_name, 256 );
#endif
}
}
return result;
}
//---------------------------------------------------------------
void FileClose(MFFileHandle file_handle)
{
#ifdef DEBUG
if ( m_iNumOpenFiles_FileOpen > 1 )
{
TRACE ( "FileClose nested %i\n", m_iNumOpenFiles_FileOpen );
}
m_iNumOpenFiles_FileOpen--;
#endif
CloseHandle(file_handle);
}
//---------------------------------------------------------------
MFFileHandle FileCreate(CBYTE *file_name,BOOL overwrite)
{
DWORD creation_mode;
MFFileHandle result;
file_name = MakeFullPathName ( file_name );
if(overwrite)
{
creation_mode = CREATE_ALWAYS;
}
else
{
creation_mode = CREATE_NEW;
}
result = CreateFile (
file_name,
(GENERIC_READ|GENERIC_WRITE),
0,//(FILE_SHARE_READ|FILE_SHARE_WRITE),
NULL,
creation_mode,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if(result==INVALID_HANDLE_VALUE)
result = FILE_CREATION_ERROR;
return result;
}
//---------------------------------------------------------------
void FileDelete(CBYTE *file_name)
{
file_name = MakeFullPathName ( file_name );
DeleteFile(file_name);
}
//---------------------------------------------------------------
SLONG FileSize(MFFileHandle file_handle)
{
DWORD result;
result = GetFileSize(file_handle,NULL);
if(result==0xffffffff)
return FILE_SIZE_ERROR;
else
return (SLONG)result;
}
//---------------------------------------------------------------
SLONG FileRead(MFFileHandle file_handle,void *buffer,ULONG size)
{
SLONG bytes_read;
if(ReadFile(file_handle,buffer,size,(LPDWORD)&bytes_read,NULL)==FALSE)
return FILE_READ_ERROR;
else
return bytes_read;
}
//---------------------------------------------------------------
SLONG FileWrite(MFFileHandle file_handle,void *buffer,ULONG size)
{
SLONG bytes_written;
if(WriteFile(file_handle,buffer,size,(LPDWORD)&bytes_written,NULL)==FALSE)
return FILE_WRITE_ERROR;
else
return bytes_written;
}
//---------------------------------------------------------------
SLONG FileSeek(MFFileHandle file_handle,const int mode,SLONG offset)
{
DWORD method;
switch(mode)
{
case SEEK_MODE_BEGINNING:
method = FILE_BEGIN;
break;
case SEEK_MODE_CURRENT:
method = FILE_CURRENT;
break;
case SEEK_MODE_END:
method = FILE_END;
break;
}
if(SetFilePointer(file_handle,offset,NULL,method)==0xffffffff)
return FILE_SEEK_ERROR;
else
return 0;
}
//---------------------------------------------------------------
SLONG FileLoadAt(CBYTE *file_name,void *buffer)
{
SLONG size;
MFFileHandle handle;
handle = FileOpen(file_name);
if(handle!=FILE_OPEN_ERROR)
{
size = FileSize(handle);
if(size>0)
{
if(FileRead(handle,buffer,size)==size)
{
FileClose(handle);
return size;
}
}
FileClose(handle);
}
return FILE_LOAD_AT_ERROR;
}
//---------------------------------------------------------------
void TraceText(CBYTE *fmt, ...)
{
//
// Work out the real message.
//
CBYTE message[512];
va_list ap;
va_start(ap, fmt);
vsprintf(message, fmt, ap);
va_end (ap);
OutputDebugString(message);
}
//---------------------------------------------------------------
void FileSetBasePath(CBYTE *path_name)
{
ASSERT ( strlen ( path_name ) < MAX_LENGTH_OF_BASE_PATH - 1 );
strncpy ( cBasePath, path_name, MAX_LENGTH_OF_BASE_PATH - 1 );
// Add a trailing slash if need be.
CBYTE *pch = cBasePath;
if ( *pch != '\0' )
{
while ( *++pch != '\0' ){}
pch--;
if ( *pch != '\\' )
{
*pch++ = '\\';
*pch = '\0';
}
}
}
//---------------------------------------------------------------
// Do NOT mix and match MF_FOpen/MF_FClose with the above - they don't mingle.
#ifdef TARGET_DC
static TCHAR pchTcharVersion[100];
//static TCHAR pchTcharMode[5];
#endif
FILE *MF_Fopen ( const char *file_name, const char *mode )
{
if ( !FileExists ( (char *)file_name ) )
{
return NULL;
}
file_name = MakeFullPathName ( file_name );
#ifdef TARGET_DC
// Apparently fopen causes a memory leak.
#if 1
ASSERT ( mode[0] == 'r' );
ASSERT ( mode[2] == '\0' );
TCHAR *pchTcharMode;
if ( mode[1] == 't' )
{
pchTcharMode = TEXT("rt");
}
else
{
ASSERT ( mode[1] == 'b' );
pchTcharMode = TEXT("rb");
}
#else
pc1 = mode;
ASSERT ( strlen ( mode) < 3 );
pc2 = pchTcharMode;
while ( *pc1 != '\0' )
{
*pc2++ = (TCHAR)( *pc1++ );
}
*pc2++ = TEXT('\0');
#endif
const char *pc1 = file_name;
ASSERT ( strlen ( file_name) < 80 );
TCHAR *pc2 = pchTcharVersion;
while ( *pc1 != '\0' )
{
*pc2++ = (TCHAR)( *pc1++ );
}
*pc2++ = TEXT('\0');
FILE *res = _wfopen ( pchTcharVersion, pchTcharMode );
#ifdef DEBUG
if ( res != NULL )
{
m_iNumOpenFiles_MF_Fopen++;
if ( m_iNumOpenFiles_MF_Fopen > 1 )
{
TRACE ( "MF_Fopen nested %i\n", m_iNumOpenFiles_MF_Fopen );
}
strncpy ( pcPrevFilenameOpened, file_name, 256 );
}
#endif
return ( res );
#else
return ( fopen ( (char *)file_name, (char *)mode ) );
#endif
}
//---------------------------------------------------------------
int MF_Fclose( FILE *stream )
{
#ifdef DEBUG
if ( m_iNumOpenFiles_MF_Fopen > 1 )
{
TRACE ( "MF_Fclose nested %i\n", m_iNumOpenFiles_MF_Fopen );
}
m_iNumOpenFiles_MF_Fopen--;
#endif
return ( fclose ( stream ) );
}
//---------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,254 @@
// StdMem.cpp
// Guy Simmons, 18th December 1997
#include <MFStdLib.h>
#define INITIAL_HEAP_SIZE (8*1024*1024)
#define MAXIMUM_HEAP_SIZE 0
#ifdef DEBUG
// Allows heap debugging - logs interesting info, e.g. for memory leak tracking.
//#define HEAP_DEBUGGING_PLEASE_BOB defined
#endif
HANDLE MFHeap = NULL;
#ifdef HEAP_DEBUGGING_PLEASE_BOB
struct HeapDebugInfo
{
HeapDebugInfo *pPrev;
HeapDebugInfo *pNext;
ULONG ulSize; // The size of this alloc.
ULONG ulSeqNum; // The malloc number.
};
#define MAX_NUM_DELNEW_TRACES 2000
int iNumNewDelTraces = 0;
struct newdeltrace
{
void *pvAddr;
ULONG ulsize;
ULONG ulSequenceNumber;
} ndtList[MAX_NUM_DELNEW_TRACES];
HeapDebugInfo *pFirst = NULL;
ULONG ulCurrentSequenceNumber = 0;
// Set this to 1 in a debugger to dump the info.
volatile bool bDumpDebug = FALSE;
// Set this to an ID you want to track in the debugger.
volatile ULONG ulSpotted = -1;
void DumpDebug ( void )
{
bDumpDebug = FALSE;
TRACE ( "\nMemory debug dump\n" );
HeapDebugInfo *phdi = pFirst;
while ( phdi != NULL )
{
TRACE ( "ID<0x%x> size<0x%x> \n", phdi->ulSeqNum, phdi->ulSize );
phdi = phdi->pNext;
}
TRACE ( "NewDel debug bump\n" );
for ( int i = 0; i < iNumNewDelTraces; i++ )
{
TRACE ( "ID<0x%x> size<0x%x> \n", ndtList[i].ulSequenceNumber, ndtList[i].ulsize );
}
TRACE ( "\n" );
}
#endif
//---------------------------------------------------------------
BOOL SetupMemory(void)
{
#ifdef HEAP_DEBUGGING_PLEASE_BOB
pFirst = NULL;
ulCurrentSequenceNumber = 0;
#endif
if(MFHeap==NULL)
{
MFHeap = HeapCreate(0,INITIAL_HEAP_SIZE,MAXIMUM_HEAP_SIZE);
}
if(MFHeap)
return TRUE;
else
return FALSE;
}
//---------------------------------------------------------------
void ResetMemory(void)
{
if(MFHeap)
{
HeapDestroy(MFHeap);
MFHeap = NULL;
}
#ifdef HEAP_DEBUGGING_PLEASE_BOB
pFirst = NULL;
// Sequence number is not reset.
#endif
}
//---------------------------------------------------------------
void *MemAlloc(ULONG size)
{
#ifdef HEAP_DEBUGGING_PLEASE_BOB
if ( bDumpDebug )
{
DumpDebug();
}
// Set up ulSpotted in a debugger to track interesting items.
ASSERT ( ulSpotted != ulCurrentSequenceNumber );
ULONG ulOriginalSize = size;
size += sizeof ( HeapDebugInfo );
#endif
size = (size+3)&0xfffffffc;
void *ptr = (void*)HeapAlloc(MFHeap,HEAP_ZERO_MEMORY,size);
ASSERT ( ptr != NULL );
#ifdef HEAP_DEBUGGING_PLEASE_BOB
HeapDebugInfo *phdi = (HeapDebugInfo *)ptr;
ptr = (void*)( (char*)ptr + sizeof ( HeapDebugInfo ) );
phdi->ulSeqNum = ulCurrentSequenceNumber++;
phdi->ulSize = ulOriginalSize;
phdi->pNext = pFirst;
phdi->pPrev = NULL;
if ( pFirst != NULL )
{
ASSERT ( pFirst->pPrev == NULL );
pFirst->pPrev = phdi;
}
pFirst = phdi;
#endif
return ptr;
}
//---------------------------------------------------------------
void MemFree(void *mem_ptr)
{
#ifdef HEAP_DEBUGGING_PLEASE_BOB
if ( bDumpDebug )
{
DumpDebug();
}
mem_ptr = (void*)( (char*)mem_ptr - sizeof ( HeapDebugInfo ) );
HeapDebugInfo *phdi = (HeapDebugInfo *)mem_ptr;
// Set up ulSpotted in a debugger to track interesting items.
ASSERT ( ulSpotted != phdi->ulSeqNum );
if ( phdi->pPrev != NULL )
{
ASSERT ( phdi->pPrev->pNext == phdi );
phdi->pPrev->pNext = phdi->pNext;
}
else
{
ASSERT ( pFirst == phdi );
pFirst = phdi->pNext;
}
if ( phdi->pNext != NULL )
{
ASSERT ( phdi->pNext->pPrev == phdi );
phdi->pNext->pPrev = phdi->pPrev;
}
#endif
HeapFree(MFHeap,0,mem_ptr);
}
//---------------------------------------------------------------
/*
void MemClear(void *mem_ptr,ULONG size)
{
}
*/
//---------------------------------------------------------------
#ifdef DEBUG
// Support for MFnew and MFdelete
#ifndef HEAP_DEBUGGING_PLEASE_BOB
// Do nothing.
void MFnewTrace ( void *pvAddr, size_t size )
{
}
void MFdeleteTrace ( void *pvAddr )
{
}
#else //#ifndef HEAP_DEBUGGING_PLEASE_BOB
void MFnewTrace ( void *pvAddr, size_t size )
{
if ( bDumpDebug )
{
DumpDebug();
}
ASSERT ( iNumNewDelTraces < MAX_NUM_DELNEW_TRACES - 1 );
ndtList[iNumNewDelTraces].pvAddr = pvAddr;
ndtList[iNumNewDelTraces].ulsize = (ULONG)size;
ndtList[iNumNewDelTraces].ulSequenceNumber = ulCurrentSequenceNumber++;
iNumNewDelTraces++;
}
void MFdeleteTrace ( void *pvAddr )
{
if ( bDumpDebug )
{
DumpDebug();
}
// Search for this entry.
bool bFound = FALSE;
for ( int i = 0; i < iNumNewDelTraces; i++ )
{
if ( ndtList[i].pvAddr == pvAddr )
{
iNumNewDelTraces--;
ndtList[i] = ndtList[iNumNewDelTraces];
bFound = TRUE;
break;
}
}
ASSERT ( bFound );
}
#endif //#else //#ifndef HEAP_DEBUGGING_PLEASE_BOB
#endif

414
MuckyBasic/Always.h Normal file
View File

@ -0,0 +1,414 @@
#ifndef _ALWAYS_
#define _ALWAYS_
//
// Turn off the warning about [] arrays at the end of structures.
//
#pragma warning( disable : 4200 )
typedef signed long SLONG;
typedef unsigned long ULONG;
typedef signed short int SWORD;
typedef unsigned short int UWORD;
typedef signed char SBYTE;
typedef unsigned char UBYTE;
typedef char CBYTE;
//
// Standard libraries most often used.
//
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
//
// Constants.
//
#define PI (3.14159265F)
#define ROOT2 (1.41421356F)
#define INFINITY (0x7fffffff)
//
// Useful defines.
//
#define MIN(mnx,mny) (((mnx) < (mny)) ? (mnx) : (mny))
#define MAX(mnx,mny) (((mnx) > (mny)) ? (mnx) : (mny))
#define MAX3(mnx,mny,mnz) (((mnx) > (mny)) ? MAX(mnx,mnz) : MAX(mny,mnz))
#define MIN3(mnx,mny,mnz) (((mnx) < (mny)) ? MIN(mnx,mnz) : MIN(mny,mnz))
#define MIN4(a,b,c,d) (MIN(MIN(a,b), MIN(c,d)))
#define MAX4(a,b,c,d) (MAX(MAX(a,b), MAX(c,d)))
#define SWAP(x,y) {SLONG SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_UB(x,y) {UBYTE SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_UW(x,y) {UWORD SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_FL(x,y) {float SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_DB(x,y) {double SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_HF(x,y) {Pointhf SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_P3(x,y) {Point3d SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_VD(x,y) {void *SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_UWP(x,y) {UWORD *SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_UBP(x,y) {UBYTE *SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define WITHIN(x,a,b) ((x) >= (a) && (x) <= (b))
#define SATURATE(x,a,b) {if ((x) < (a)) (x) = (a); if ((x) > (b)) (x) = (b);}
#define SIGN(x) (((x)) ? (((x) > 0) ? 1 : -1) : 0)
#define QLEN(x,y) (((x) > (y)) ? (x) + ((y) >> 1) : (y) + ((x) >> 1))
#define XOR(a,b) ((!(a) && (b)) || ((a) && !(b)))
#define SQRT16(x) ((sqrt((double) (x)) * 256))
#define SHOW(a) {TRACE(#a" = %d\n", (a));}
#define SHOW_X(a) {TRACE(#a" = 0x%x\n", (a));}
#define SHOW_FL(a) {TRACE(#a" = %f\n", (a));}
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
//
// Error checking macros
//
#ifndef NDEBUG
void OS_string(CBYTE *fmt, ...);
#define ASSERT(x) {assert(x);}
#define TRACE OS_string
#define VERIFY(x) ASSERT(x)
#else
#define ASSERT(x) {__assume(x);}
#define TRACE
#define VERIFY(x) x
//
// In release build, get rid of the x == 1; warning message otherwise
// VERIFY generates it all the time!
//
#pragma warning( disable : 4553 )
#endif
//
// Assembler fixed point thingies from T.A.C.
//
static inline SLONG DIV16(SLONG a, SLONG b)
{
SLONG v;
_asm
{
mov edx,a
mov ebx,b
mov eax,edx
shl eax,16
sar edx,16
idiv ebx
mov v,eax
}
return v;
}
#pragma warning( disable : 4035 )
// stop warning of no return value : eax is valid
static inline SLONG MUL16(SLONG a, SLONG b)
// MSVC++ version, params:ecx,edx, return:eax
// this is as fast on 486/Pentium as the old version
// and 2.5* faster on Pentium Pro
{
__asm
{
mov eax, a
imul b // result in edx:eax
shl edx,16
shr eax,16
or eax,edx
// return in eax
}
}
#pragma warning( default : 4035 )
//
// Sets the precision of the floating point unit.
//
#define FPP_SINGLE 0x00 // 32-bits
#define FPP_DOUBLE 0x20 // 53-bits
#define FPP_EXTENDED 0x30 // 64-bits
static inline void fpp_set(UWORD precision)
{
short control;
__asm
{
wait
fnstcw control
wait
mov ax, control
and ax, 0xfcff
or ax, precision
mov control, ax
fldcw control
}
}
//
// For doing fast floating-point to long conversion...
//
//
// Sets the rounding to truncate automatically.
//
static inline void ftol_init(void)
{
short control;
__asm
{
wait
fnstcw control
wait
mov ax, control
or ah, 0Ch
mov control, ax
fldcw control
}
}
//
// Converts a float to an int using the current rounding. For normal
// C-style rounding, make sure you call ftol_init() at the start
// of your program.
//
static inline int ftol(float f)
{
int ans;
__asm
{
fld f
fistp ans
}
return ans;
}
//
// Finds the sign of the cross product x1y2 - x2y1 also from T.A.C.
//
static inline SBYTE CROSS_PROD_SIGN(SLONG x1, SLONG y1, SLONG x2, SLONG y2)
{
SBYTE ans;
__asm
{
mov eax, x1
mov ebx, y1
mov ecx, x2
mov edx, y2
imul edx
xchg eax,ebx
xchg edx,ecx
imul edx
sub ebx,eax
setnz al
sbb ecx,edx
jz done
setl ah
setg al
sub al,ah
done:
mov ans, al
}
return ans;
}
//
// Returns the number of the first bit set in the given value. Returns
// -1 if there is no bit set.
//
static inline first_bit(SLONG search)
{
SLONG ans;
__asm
{
mov eax, search
mov ebx, 0ffffffffh
bsf ebx, eax
mov ans, ebx
}
return ans;
}
//
// Returns the number of the last bit set in the given value. Returns
// -1 if there is no bit set.
//
static inline last_bit(SLONG search)
{
SLONG ans;
__asm
{
mov eax, search
mov ebx, 0ffffffffh
bsr ebx, eax
mov ans, ebx
}
return ans;
}
//
// Find the cross product.
//
#define CROSS_PROD(x1,y1,x2,y2) (((x1)*(y2)) - ((x2)*(y1)))
//
// Globally useful structures.
//
typedef struct {float x, y, z;} Point3d;
typedef struct {float x, y; } Point2d;
typedef struct {float x, z; } Pointhf;
typedef struct {float u, v; } Pointuv;
typedef struct
{
float yaw;
float pitch;
float roll;
} Direction;
typedef struct
{
UBYTE r;
UBYTE g;
UBYTE b;
} Colour;
//
// Fast approximation to sqrt(x*x + y*y)
//
static inline float qdist2(float x, float y)
{
float ans;
ASSERT(x >= 0.0F);
ASSERT(y >= 0.0F);
if (x > y)
{
ans = x + y * 0.5F;
}
else
{
ans = y + x * 0.5F;
}
return ans;
}
//
// Fast approximation to sqrt(x*x + y*y + z*z), x,y and z must
// be positive.
//
static inline float qdist3(float x, float y, float z)
{
float ans;
ASSERT(x >= 0.0F);
ASSERT(y >= 0.0F);
ASSERT(z >= 0.0F);
if (x > y)
{
if (x > z)
{
//
// x is the biggeset.
//
ans = x + (y + z) * 0.2941F;
return ans;
}
}
else
{
if (y > z)
{
//
// y is the biggeset.
//
ans = y + (x + z) * 0.2941F;
return ans;
}
}
//
// z is the biggeset.
//
ans = z + (x + y) * 0.2941F;
return ans;
}
//
// A floating point number between 0 and 1.0F
//
static inline float frand(void)
{
SLONG irand = rand();
float ans = float(irand) * (1.0F / float(RAND_MAX));
return ans;
}
#endif

133
MuckyBasic/Key.h Normal file
View File

@ -0,0 +1,133 @@
//
// Keyboard handling.
//
#ifndef _KEY_
#define _KEY_
//
// Every key has a byte flag to say whether it is on or off.
//
extern volatile UBYTE KEY_on[256];
extern volatile SLONG KEY_inkey; // The ASCII value of the last key pressed.
extern volatile SLONG KEY_shift;
//
// KEY shift can have the following bits set.
//
#define KEY_SHIFT (1 << 0)
#define KEY_ALT (1 << 1)
#define KEY_CONTROL (1 << 2)
//
// The scancodes of all the keys...
//
#define KEY_ESCAPE 0x01
#define KEY_1 0x02
#define KEY_2 0x03
#define KEY_3 0x04
#define KEY_4 0x05
#define KEY_5 0x06
#define KEY_6 0x07
#define KEY_7 0x08
#define KEY_8 0x09
#define KEY_9 0x0a
#define KEY_0 0x0b
#define KEY_MINUS 0x0c
#define KEY_EQUAL 0x0d
#define KEY_BACKSPACE 0x0e
#define KEY_TAB 0x0f
#define KEY_Q 0x010
#define KEY_W 0x011
#define KEY_E 0x012
#define KEY_R 0x013
#define KEY_T 0x014
#define KEY_Y 0x015
#define KEY_U 0x016
#define KEY_I 0x017
#define KEY_O 0x018
#define KEY_P 0x019
#define KEY_LSBRACKET 0x01a
#define KEY_RSBRACKET 0x01b
#define KEY_RETURN 0x01c
#define KEY_LCONTROL 0x01d
#define KEY_RCONTROL (0x01d + 0x80)
#define KEY_A 0x01e
#define KEY_S 0x01f
#define KEY_D 0x020
#define KEY_F 0x021
#define KEY_G 0x022
#define KEY_H 0x023
#define KEY_J 0x024
#define KEY_K 0x025
#define KEY_L 0x026
#define KEY_COLON 0x027
#define KEY_QUOTE 0x028
#define KEY_QUOTE2 0x029
#define KEY_LSHIFT 0x02a
#define KEY_HASH 0x02b
#define KEY_BACKSLASH 0x056
#define KEY_Z 0x02c
#define KEY_X 0x02d
#define KEY_C 0x02e
#define KEY_V 0x02f
#define KEY_B 0x030
#define KEY_N 0x031
#define KEY_M 0x032
#define KEY_COMMA 0x033
#define KEY_POINT 0x034
#define KEY_SLASH 0x035
#define KEY_RSHIFT 0x036
#define KEY_LALT 0x038
#define KEY_RALT (0x038 + 0x80)
#define KEY_SPACE 0x039
#define KEY_CAPS 0x03a
#define KEY_F1 0x03b
#define KEY_F2 0x03c
#define KEY_F3 0x03d
#define KEY_F4 0x03e
#define KEY_F5 0x03f
#define KEY_F6 0x040
#define KEY_F7 0x041
#define KEY_F8 0x042
#define KEY_F9 0x043
#define KEY_F10 0x044
#define KEY_F11 0x057
#define KEY_F12 0x058
#define KEY_HOME (0x47 + 0x80)
#define KEY_UP (0x48 + 0x80)
#define KEY_PAGEUP (0x49 + 0x80)
#define KEY_LEFT (0x4b + 0x80)
#define KEY_RIGHT (0x4d + 0x80)
#define KEY_END (0x4f + 0x80)
#define KEY_DOWN (0x50 + 0x80)
#define KEY_PAGEDOWN (0x51 + 0x80)
#define KEY_INSERT (0x52 + 0x80)
#define KEY_DELETE (0x53 + 0x80)
#define KEY_NUM_LOCK 0x045
#define KEY_PMINUS 0x04a
#define KEY_PADD 0x04e
#define KEY_PSLASH (0x035 + 0x80)
#define KEY_ASTERISK 0x037
#define KEY_PDOT 0x053
#define KEY_ENTER (0x01c + 0x80)
#define KEY_P7 0x047
#define KEY_P8 0x048
#define KEY_P9 0x049
#define KEY_P4 0x04b
#define KEY_P5 0x04c
#define KEY_P6 0x04d
#define KEY_P1 0x04f
#define KEY_P2 0x050
#define KEY_P3 0x051
#define KEY_P0 0x052
#endif

450
MuckyBasic/Matrix.cpp Normal file
View File

@ -0,0 +1,450 @@
#include "always.h"
#include "matrix.h"
//
// OPTIMISE THIS AT SOME POINT MARK! 'roll' AND 'pitch' ARE NEARLY ALWAYS 0!
//
void MATRIX_calc(float matrix[9], float yaw, float pitch, float roll)
{
float cy, cp, cr;
float sy, sp, sr;
sy = sinf(yaw);
sp = sinf(pitch);
sr = sinf(roll);
cy = cosf(yaw);
cp = cosf(pitch);
cr = cosf(roll);
//
// Jan I trust you... but only becuase I've already seen it working!
//
matrix[0] = cy * cr + sy * sp * sr;
matrix[3] = cy * sr - sy * sp * cr;
matrix[6] = sy * cp;
matrix[1] = -cp * sr;
matrix[4] = cp * cr;
matrix[7] = sp;
matrix[2] = -sy * cr + cy * sp * sr;
matrix[5] = -sy * sr - cy * sp * cr;
matrix[8] = cy * cp;
}
void MATRIX_calc_arb(
float matrix[9],
float ux,
float uy,
float uz,
float angle)
{
float sa = sinf(angle);
float ca = cosf(angle);
float ux2 = ux*ux;
float uy2 = uy*uy;
float uz2 = uz*uz;
float uxuy = ux*uy;
float uxuz = ux*uz;
float uyuz = uy*uz;
matrix[0] = ux2 + ca*(1 - ux2);
matrix[1] = uxuy*(1 - ca) - uz*sa;
matrix[2] = uxuz*(1 - ca) + uy*sa;
matrix[3] = uxuy*(1 - ca) + uz*sa;
matrix[4] = uy2 + ca*(1 - uy2);
matrix[5] = uyuz*(1 - ca) - ux*sa;
matrix[6] = uxuz*(1 - ca) - uy*sa;
matrix[7] = uy*uz*(1 - ca) + ux*sa;
matrix[8] = uz2 + ca*(1 - uz2);
}
void MATRIX_vector(float vector[3], float yaw, float pitch)
{
float cy, cp;
float sy, sp;
sy = sin(yaw);
sp = sin(pitch);
cy = cos(yaw);
cp = cos(pitch);
vector[0] = sy * cp;
vector[1] = sp;
vector[2] = cy * cp;
}
void MATRIX_skew(float matrix[9], float skew, float zoom, float scale)
{
//
// Squish up the matrix according to the aspect ratio of the screen.
//
matrix[0] = matrix[0] * skew;
matrix[1] = matrix[1] * skew;
matrix[2] = matrix[2] * skew;
//
// Create a lens by multiplying the x and y rows by the zoom factor...
//
matrix[0] = zoom * matrix[0];
matrix[1] = zoom * matrix[1];
matrix[2] = zoom * matrix[2];
matrix[3] = zoom * matrix[3];
matrix[4] = zoom * matrix[4];
matrix[5] = zoom * matrix[5];
//
// Scale the whole matrix.
//
matrix[0] *= scale;
matrix[1] *= scale;
matrix[2] *= scale;
matrix[3] *= scale;
matrix[4] *= scale;
matrix[5] *= scale;
matrix[6] *= scale;
matrix[7] *= scale;
matrix[8] *= scale;
}
void MATRIX_3x3mul(float a[9], float m[9], float n[9])
{
float result[9];
result[0] = m[0] * n[0] + m[1] * n[3] + m[2] * n[6];
result[1] = m[0] * n[1] + m[1] * n[4] + m[2] * n[7];
result[2] = m[0] * n[2] + m[1] * n[5] + m[2] * n[8];
result[3] = m[3] * n[0] + m[4] * n[3] + m[5] * n[6];
result[4] = m[3] * n[1] + m[4] * n[4] + m[5] * n[7];
result[5] = m[3] * n[2] + m[4] * n[5] + m[5] * n[8];
result[6] = m[6] * n[0] + m[7] * n[3] + m[8] * n[6];
result[7] = m[6] * n[1] + m[7] * n[4] + m[8] * n[7];
result[8] = m[6] * n[2] + m[7] * n[5] + m[8] * n[8];
a[0] = result[0];
a[1] = result[1];
a[2] = result[2];
a[3] = result[3];
a[4] = result[4];
a[5] = result[5];
a[6] = result[6];
a[7] = result[7];
a[8] = result[8];
}
//
// Rotates the matrix by angle. You don't have to pass the 3rd row of the
// matrix, because it will be unchanged.
//
#define MATRIX_ROTATE_ABOUT_Z(ax, ay, az, bx, by, bz, cx, cy, cz, angle) \
{ \
float c = cos(angle); \
float s = sin(angle); \
\
float px; \
float py; \
float pz; \
\
float qx; \
float qy; \
float qz; \
\
if (angle) \
{ \
px = c * (ax) + s * (bx); \
py = c * (ay) + s * (by); \
pz = c * (az) + s * (bz); \
\
qx = -s * (ax) + c * (bx); \
qy = -s * (ay) + c * (by); \
qz = -s * (az) + c * (bz); \
\
(ax) = px; (ay) = py; (az) = pz; \
(bx) = qx; (by) = qy; (bz) = qz; \
} \
}
void MATRIX_rotate_about_its_x(float *matrix, float angle)
{
MATRIX_ROTATE_ABOUT_Z(
matrix[1], matrix[4], matrix[7],
matrix[2], matrix[5], matrix[8],
matrix[0], matrix[3], matrix[6],
-angle);
}
void MATRIX_rotate_about_its_y(float *matrix, float angle)
{
MATRIX_ROTATE_ABOUT_Z(
matrix[2], matrix[5], matrix[8],
matrix[0], matrix[3], matrix[6],
matrix[1], matrix[4], matrix[7],
-angle);
}
void MATRIX_rotate_about_its_z(float *matrix, float angle)
{
MATRIX_ROTATE_ABOUT_Z(
matrix[0], matrix[3], matrix[6],
matrix[1], matrix[4], matrix[7],
matrix[2], matrix[5], matrix[8],
-angle);
}
#define MATRIX_FA_VECTOR_TOO_SMALL (0.001F)
#define MATRIX_FA_ANGLE_TOO_SMALL (PI * 2.0F / 180.0F)
Direction MATRIX_find_angles_old(float matrix[9])
{
float x;
float y;
float z;
float xz;
Direction ans;
//
// Look from above at the z-vector to work out the yaw.
//
x = matrix[6];
y = matrix[7];
z = matrix[8];
if (fabsf(x) + fabsf(z) < MATRIX_FA_VECTOR_TOO_SMALL)
{
//
// Try using the x-vector instead.
//
float x1 = matrix[0];
float y1 = matrix[1];
float z1 = matrix[2];
ans.yaw = atan2f(-z1, x1);
//ans.yaw = 0.0F;
}
else
{
ans.yaw = atan2f(x, z);
}
//
// Look down the x vector to at the z-vector to work out the pitch.
//
xz = sqrtf(x*x + z*z);
if (fabsf(xz) + fabsf(y) < MATRIX_FA_VECTOR_TOO_SMALL)
{
if (y < 0) {ans.pitch = -PI;} else {ans.pitch = +PI;}
}
else
{
ans.pitch = atan2(y, xz);
}
//
// Now... matrix[4] = cos(pitch) * cos(roll)
// matrix[1] = -cos(pitch) * sin(roll)
//
// so... cos(roll) = matrix[4] / cos(pitch)
// sin(roll) = matrix[1] / -cos(pitch)
//
float cos_roll;
float sin_roll;
float cos_pitch;
cos_pitch = cosf(ans.pitch);
if (fabsf(cos_pitch) < MATRIX_FA_ANGLE_TOO_SMALL)
{
ans.roll = 0.0F;
}
else
{
cos_roll = matrix[4] / cos_pitch;
sin_roll = matrix[1] / -cos_pitch;
ans.roll = atan2f(sin_roll, cos_roll);
}
return ans;
}
Direction MATRIX_find_angles(float matrix[9])
{
Direction ans;
//
// matrix[7] is the sin(pitch)
//
ans.pitch = asinf(matrix[7]);
//
// Work out yaw differently depending on how much we are looking
// down or up.
//
if (fabsf(ans.pitch) > (PI / 4.0F))
{
if (fabsf(matrix[0]) + fabsf(matrix[2]) < 0.1F)
{
}
ans.yaw = atan2f(matrix[0], matrix[2]) - (PI / 2.0F);
}
else
{
ans.yaw = atan2f(matrix[6], matrix[8]);
}
//
// Now... matrix[4] = cos(pitch) * cos(roll)
// matrix[1] = -cos(pitch) * sin(roll)
//
// so... cos(roll) = matrix[4] / cos(pitch)
// sin(roll) = matrix[1] / -cos(pitch)
//
float cos_roll;
float sin_roll;
float cos_pitch;
cos_pitch = cosf(ans.pitch);
if (fabsf(cos_pitch) < 0.0001F)
{
ans.roll = 0.0F;
}
else
{
cos_roll = matrix[4] / cos_pitch;
sin_roll = matrix[1] / -cos_pitch;
ans.roll = atan2f(sin_roll, cos_roll);
}
return ans;
}
void MATRIX_scale(float matrix[9], float mulby)
{
matrix[0] *= mulby;
matrix[1] *= mulby;
matrix[2] *= mulby;
matrix[3] *= mulby;
matrix[4] *= mulby;
matrix[5] *= mulby;
matrix[6] *= mulby;
matrix[7] *= mulby;
matrix[8] *= mulby;
}
void MATRIX_construct(float matrix[9], float dx, float dy, float dz)
{
float cx;
float cy;
float cz;
float len;
float overlen;
len = sqrtf(dx*dx + dy*dy + dz*dz);
overlen = 1.0F / len;
dx *= overlen;
dy *= overlen;
dz *= overlen;
//
// We've got the z-row of the matrix now.
//
matrix[6] = dx;
matrix[7] = dy;
matrix[8] = dz;
cx = 0.0F;
cy = 1.0F;
cz = 0.0F;
matrix[0] = cy*dz - cz*dy;
matrix[1] = cz*dx - cx*dz;
matrix[2] = cx*dy - cy*dx;
len =
matrix[0]*matrix[0] +
matrix[1]*matrix[1] +
matrix[2]*matrix[2];
if (len < 0.001F)
{
//
// Oh dear... too small!
//
MATRIX_calc(
matrix,
0.0F,
-PI * 0.5F,
0.0F);
return;
}
MATRIX_NORMALISE(
matrix[0],
matrix[1],
matrix[2]);
matrix[3] = -matrix[1]*matrix[8] + matrix[2]*matrix[7];
matrix[4] = -matrix[2]*matrix[6] + matrix[0]*matrix[8];
matrix[5] = -matrix[0]*matrix[7] + matrix[1]*matrix[6];
MATRIX_NORMALISE(
matrix[3],
matrix[4],
matrix[5]);
}

167
MuckyBasic/Matrix.h Normal file
View File

@ -0,0 +1,167 @@
//
// Matrix stuff...
//
#ifndef _MATRIX_
#define _MATRIX_
//
// ALL ANGLES ARE IN RADIANS.
//
//
// Fills in the matrix appropriately given the three angles (yaw, pitch, roll)
// for the eye along the z-axis.
//
void MATRIX_calc(float matrix[9], float yaw, float pitch, float roll);
//
// Makes a rotation matrix that rotates 'angle' radians about thie given unit vector
//
void MATRIX_calc_arb(
float matrix[9],
float ux,
float uy,
float uz,
float angle);
//
// Calculates a vector from yaw and pitch...
//
void MATRIX_vector(float vector[3], float yaw, float pitch);
//
// Skews the view matrix so that it is correct for 3d clipping.
//
// The skew value should be one over the horizontal view-window resolution
// divided by the vertical view-window resolution.
//
// The x and y vectors are multiplied by the zoom.
//
// The whole matrix is scaled by scale.
//
void MATRIX_skew(float matrix[9], float skew, float zoom, float scale);
//
// Normalises the vector.
//
#define MATRIX_NORMALISE(x,y,z) \
{ \
float len2; \
float len; \
float overlen; \
\
len2 = (x)*(x) + (y)*(y) + (z)*(z); \
len = sqrtf(len2); \
overlen = 1.0F / len; \
\
(x) *= overlen; \
(y) *= overlen; \
(z) *= overlen; \
}
//
// Multiplies points x,y,z by matrix m.
//
#define MATRIX_MUL(m,x,y,z) \
{ \
float xnew, ynew, znew; \
\
xnew = (x) * (m)[0]; \
ynew = (x) * (m)[3]; \
znew = (x) * (m)[6]; \
\
xnew += (y) * (m)[1]; \
ynew += (y) * (m)[4]; \
znew += (y) * (m)[7]; \
\
xnew += (z) * (m)[2]; \
ynew += (z) * (m)[5]; \
znew += (z) * (m)[8]; \
\
(x) = xnew; (y) = ynew; (z) = znew; \
}
//
// Multiplies points x,y,z by the transpose of matrix m.
//
#define MATRIX_MUL_BY_TRANSPOSE(m,x,y,z) \
{ \
float xnew, ynew, znew; \
\
xnew = (x) * (m)[0]; \
ynew = (x) * (m)[1]; \
znew = (x) * (m)[2]; \
\
xnew += (y) * (m)[3]; \
ynew += (y) * (m)[4]; \
znew += (y) * (m)[5]; \
\
xnew += (z) * (m)[6]; \
ynew += (z) * (m)[7]; \
znew += (z) * (m)[8]; \
\
(x) = xnew; (y) = ynew; (z) = znew; \
}
//
// Multiplies two 3x3 together. A = MN.
//
void MATRIX_3x3mul(float a[9], float m[9], float n[9]);
//
// Transposes the matrix m.
//
#define MATRIX_TRANSPOSE(m) {SWAP_FL(m[1], m[3]); SWAP_FL(m[2], m[6]); SWAP_FL(m[5], m[7]);}
//
// Rotates a matrix about its x,y or z vector.
//
void MATRIX_rotate_about_its_x(float *matrix, float angle);
void MATRIX_rotate_about_its_y(float *matrix, float angle);
void MATRIX_rotate_about_its_z(float *matrix, float angle);
//
// Convert a matrix into its equivalent yaw, pitch and roll.
//
Direction MATRIX_find_angles(float matrix[9]);
//
// Scales the given vector.
//
void MATRIX_scale(float matrix[9], float mulby);
//
// Constructs an orthonormal matrix from a vector whose [6][7][8] is the normalised
// vector (dx,dy,dz). It return a matrix without any 'roll'. (dx,dy,dz) does not
// have to be normalised.
//
void MATRIX_construct(float matrix[9], float dx, float dy, float dz);
#endif

343
MuckyBasic/Tga.cpp Normal file
View File

@ -0,0 +1,343 @@
//
// Loads in 32-bit RGBA uncompressed TGAs.
//
#include "always.h"
#include "tga.h"
TGA_Info TGA_load(
const CBYTE *file,
SLONG max_width,
SLONG max_height,
TGA_Pixel *data)
{
SLONG i;
SLONG j;
UBYTE red;
UBYTE green;
UBYTE blue;
SLONG tga_width;
SLONG tga_height;
SLONG tga_pixel_depth;
SLONG tga_image_type;
SLONG tga_id_length;
UBYTE header[18];
UBYTE rubbish;
UBYTE no_alpha;
FILE *handle;
TGA_Info ans;
//
// Open the file.
//
handle = fopen(file, "rb");
if (handle == NULL)
{
TRACE("Could not open TGA file %s", file);
ans.valid = FALSE;
return ans;
}
//
// Read the header.
//
if (fread(header, sizeof(UBYTE), 18, handle) != 18) goto file_error;
//
// Extract info from the header.
//
tga_id_length = header[0x0];
tga_image_type = header[0x2];
tga_width = header[0xc] + header[0xd] * 256;
tga_height = header[0xe] + header[0xf] * 256;
tga_pixel_depth = header[0x10];
//
// Is this a valid tga file?
//
ans.valid = FALSE;
ans.width = tga_width;
ans.height = tga_height;
ans.flag = 0;
if (tga_image_type != 2)
{
TRACE("Tga must be true colour and uncompressed.\n");
fclose(handle);
return ans;
}
if (tga_pixel_depth != 32 && tga_pixel_depth != 24)
{
TRACE("Tga must be 32-bit or 24-bit (24-bit + 8-bit alpha channel)\n");
fclose(handle);
return ans;
}
if (tga_width > max_width ||
tga_height > max_height)
{
TRACE("Invalid dimensions:\n\tWanted <= %d x %d\n\tGot %d x %d\n", max_width, max_height, tga_width, tga_height);
fclose(handle);
return ans;
}
//
// The tga file is valid...
//
ans.valid = TRUE;
//
// Skip past the image identification field.
//
for (i = 0; i < tga_id_length; i++)
{
if (fread(&rubbish, sizeof(UBYTE), 1, handle) != 1) goto file_error;
}
//
// Load in the data upside down (because the TGA's themselves are stored upside down!)
//
if (tga_pixel_depth == 32)
{
for (i = tga_height - 1; i >= 0; i--)
{
if (fread(data + tga_width * i, sizeof(TGA_Pixel), tga_width, handle) != tga_width) goto file_error;
}
no_alpha = FALSE;
}
else
{
//
// We have to load a pixel in at a time to add the NULL alpha channel.
//
for (i = tga_height - 1; i >= 0; i--)
{
for (j = 0; j < tga_width; j++)
{
if (fread(&blue, sizeof(UBYTE), 1, handle) != 1) goto file_error;
if (fread(&green, sizeof(UBYTE), 1, handle) != 1) goto file_error;
if (fread(&red, sizeof(UBYTE), 1, handle) != 1) goto file_error;
data[i * tga_width + j].red = red;
data[i * tga_width + j].green = green;
data[i * tga_width + j].blue = blue;
data[i * tga_width + j].alpha = 255;
}
}
no_alpha = TRUE;
}
fclose(handle);
//
// Loaded in the tga. Sets the flags- is it grayscale?
//
if (!no_alpha)
{
ans.flag |= TGA_FLAG_ONE_BIT_ALPHA;
for (i = 0; i < tga_width * tga_height; i++)
{
if (data[i].alpha != 255)
{
//
// Found alpha channel data.
//
ans.flag |= TGA_FLAG_CONTAINS_ALPHA;
if (ans.flag != 0)
{
ans.flag &= ~TGA_FLAG_ONE_BIT_ALPHA;
break;
}
}
}
if (!(ans.flag & TGA_FLAG_CONTAINS_ALPHA))
{
ans.flag &= ~TGA_FLAG_ONE_BIT_ALPHA;
}
}
//
// Is it grayscale?
//
ans.flag |= TGA_FLAG_GRAYSCALE;
for (i = 0; i < tga_width * tga_height; i++)
{
if (data[i].red != data[i].green ||
data[i].red != data[i].blue ||
data[i].green != data[i].blue)
{
ans.flag &= ~TGA_FLAG_GRAYSCALE;
break;
}
}
return ans;
file_error:;
//
// Error!
//
TRACE("File error loading TGA file %s\n", file);
fclose(handle);
ans.valid = FALSE;
return ans;
}
UBYTE TGA_header[18] =
{
0, 0, 2, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 1, // Width LSB:MSB
0, 1, // Height LSB:MSB
24, // Pixel depth
0
};
void TGA_save(
const CBYTE *file,
SLONG width,
SLONG height,
TGA_Pixel *data,
SLONG contains_alpha)
{
SLONG x;
SLONG y;
SLONG num_pixels;
UBYTE header[18];
SLONG bpp;
FILE *handle;
handle = fopen(file, "wb");
if (handle == NULL)
{
TRACE("Cannot open TGA file %s\n", file);
return;
}
//
// Create the header.
//
SLONG i;
for (i = 0; i < 18; i++)
{
header[i] = TGA_header[i];
}
header[0xc] = width & 0xff;
header[0xd] = width >> 8;
header[0xe] = height & 0xff;
header[0xf] = height >> 8;
header[0x10] = (contains_alpha) ? 32 : 24;
//
// Write out the header.
//
fwrite(&header, sizeof(UBYTE), 18, handle);
//
// Write out the pixel data.
//
for (y = height - 1; y >= 0; y--)
for (x = 0; x < width; x++)
{
if (contains_alpha)
{
fwrite(&data[x + y * width].alpha, sizeof(UBYTE), 1, handle);
}
fwrite(&data[x + y * width].blue, sizeof(UBYTE), 1, handle);
fwrite(&data[x + y * width].green, sizeof(UBYTE), 1, handle);
fwrite(&data[x + y * width].red, sizeof(UBYTE), 1, handle);
}
fclose(handle);
}
SLONG TGA_colour(TGA_Pixel tp)
{
if (abs(tp.red - tp.green) < 24 &&
abs(tp.red - tp.blue ) < 24 &&
abs(tp.green - tp.blue ) < 24)
{
//
// All the colours are roughly in the same proportions.
// The colour is a shade of grey.
//
if (tp.red < 64) {return TGA_COLOUR_BLACK;}
if (tp.red < 192) {return TGA_COLOUR_GREY ;}
return TGA_COLOUR_WHITE;
}
if (tp.red > tp.green && tp.green > tp.blue && tp.blue < (tp.red >> 1))
{
//
// Red green blue in descending order and not much blue.
// This must be a brown pixel.
//
return TGA_COLOUR_BROWN;
}
if (tp.red > (tp.green << 1) && tp.red > (tp.blue << 1))
{
return TGA_COLOUR_RED;
}
if (tp.green > (tp.red << 1) && tp.red > (tp.blue << 1))
{
return TGA_COLOUR_GREEN;
}
return TGA_COLOUR_DONTKNOW;
}

80
MuckyBasic/Tga.h Normal file
View File

@ -0,0 +1,80 @@
//
// Loads in 32-bit RGBA uncompressed TGAs.
//
#ifndef _TGA_
#define _TGA_
//
// The format of a TGA pixel.
//
typedef struct
{
UBYTE blue;
UBYTE green;
UBYTE red;
UBYTE alpha;
} TGA_Pixel;
//
// Info describing the tga.
//
#define TGA_FLAG_CONTAINS_ALPHA (1 << 0)
#define TGA_FLAG_ONE_BIT_ALPHA (1 << 1) // Alpha is only 255 or 0
#define TGA_FLAG_GRAYSCALE (1 << 2) // For all pixels r == g == b.
typedef struct
{
SLONG valid;
SLONG width;
SLONG height;
ULONG flag;
} TGA_Info;
//
// If the width and height of the tga exceed the maximums, then the tga is not loaded.
//
TGA_Info TGA_load(
const CBYTE *file,
SLONG max_width,
SLONG max_height,
TGA_Pixel *data);
//
// Saves out a tga.
//
void TGA_save(
const CBYTE *file,
SLONG width,
SLONG height,
TGA_Pixel *data,
SLONG contains_alpha); // FALSE => Save without the alpha data.
//
// Returns the colour of the given pixel.
//
#define TGA_COLOUR_DONTKNOW 0
#define TGA_COLOUR_BLACK 1
#define TGA_COLOUR_GREEN 2
#define TGA_COLOUR_BROWN 3
#define TGA_COLOUR_WHITE 4
#define TGA_COLOUR_RED 5
#define TGA_COLOUR_GREY 6
SLONG TGA_colour(TGA_Pixel tp);
#endif

2727
MuckyBasic/cg.cpp Normal file

File diff suppressed because it is too large Load Diff

32
MuckyBasic/cg.h Normal file
View File

@ -0,0 +1,32 @@
//
// The code generator and linker. Converts the output of the parse into
// an executable.
//
#ifndef _CG_
#define _CG_
//
// Takes the output of the PARSE module and spews out
// code to the given filename. Returns FALSE on failure.
// CG_output[] hold the errors/warnings/status of the
// code generation phase.
//
extern CBYTE *CG_output;
extern SLONG CG_num_errors;
extern SLONG CG_num_warnings;
#define CG_OUTPUT_EXECUTABLE (1 << 0)
#define CG_OUTPUT_OBJECT_FILE (1 << 1)
#define CG_OUTPUT_DEBUG_INFO (1 << 2)
SLONG CG_do(CBYTE *fname, SLONG output = CG_OUTPUT_EXECUTABLE);
#endif

155
MuckyBasic/clip.cpp Normal file
View File

@ -0,0 +1,155 @@
//
// A general clipper.
//
#include "always.h"
//
// The buffer in which we create new points.
//
#define CLIP_BUFFER_SIZE 2048
UBYTE CLIP_buffer[CLIP_BUFFER_SIZE];
UBYTE *CLIP_buffer_upto = CLIP_buffer;
//
// Returns the address of a block of memory of the
// given size.
//
inline void *CLIP_malloc(ULONG size)
{
void *ans;
ASSERT(size < CLIP_BUFFER_SIZE);
if (CLIP_buffer_upto + size * 2 > &CLIP_buffer[CLIP_BUFFER_SIZE])
{
CLIP_buffer_upto = CLIP_buffer;
}
ans = CLIP_buffer_upto;
CLIP_buffer_upto += size * 2;
return ans;
}
void CLIP_do(
void ***polygon,
SLONG *polygon_num_points,
SLONG sizeof_polygon_point,
void (*interpolate)(void *new_point, void *point1, void *point2, float amount_along_from_1_to_2),
float (*signed_distance_from_edge)(void *point))
{
SLONG i;
SLONG i_p1;
SLONG i_p2;
void *p1;
void *p2;
float along;
//
// The output buffer.
//
void **output = (void **) CLIP_malloc(2 * sizeof(void *) * *polygon_num_points);
SLONG output_upto = 0;
//
// Work out the signed distance of each point from the edge.
//
float *distance = (float *) CLIP_malloc(sizeof(float) * *polygon_num_points);
for (i = 0; i < *polygon_num_points; i++)
{
distance[i] = signed_distance_from_edge((*polygon)[i]);
}
//
// Go through the lines of the poly and build up the output polygon.
//
for (i = 0; i < *polygon_num_points; i++)
{
//
// The two points of the line.
//
i_p1 = i + 0;
i_p2 = i + 1;
if (i_p2 == *polygon_num_points)
{
i_p2 = 0;
}
p1 = (*polygon)[i_p1];
p2 = (*polygon)[i_p2];
if (distance[i_p1] >= 0)
{
//
// This point is on the 'good' positive side of the line... add
// it to the output polygon.
//
output[output_upto++] = p1;
if (distance[i_p2] >= 0)
{
//
// The other end of the line is also on the right side of the line...
// no need to create a clipped point.
//
continue;
}
}
else
{
if (distance[i_p2] < 0)
{
//
// Both points are offscreen, so don't create a clipped point between them.
//
continue;
}
}
along = distance[i_p1] / (distance[i_p1] - distance[i_p2]);
//
// Create a clipped point 'along' the way from point 1 to point 2.
//
output[output_upto] = CLIP_malloc(sizeof_polygon_point);
interpolate(
output[output_upto],
p1,
p2,
along);
output_upto += 1;
}
//
// Return the new polygon.
//
*polygon = output;
*polygon_num_points = output_upto;
}

22
MuckyBasic/clip.h Normal file
View File

@ -0,0 +1,22 @@
//
// A general clipper.
//
#ifndef _CLIP_
#define _CLIP_
//
// Clips a polygon against an edge. On exit *polygon is an array of points and
// *polygon_num_points gives the length of the array.
//
void CLIP_do(
void ***polygon, // Points to an array of (point *)s of length (*polygon_num_points)
SLONG *polygon_num_points,
SLONG sizeof_polygon_point,
void (*interpolate)(void *new_point, void *point1, void *point2, float amount_along_from_1_to_2),
float signed_distance_from_edge(void *point)); // +'ve => On the good side of the edge.
#endif

62
MuckyBasic/comp.cpp Normal file
View File

@ -0,0 +1,62 @@
#include "always.h"
#include "cg.h"
#include "lex.h"
#include "parse.h"
#include "st.h"
#include "vm.h"
#define COMP_MAX_PROGRAM (512 * 1024) // Huge buffer!
CBYTE COMP_program[COMP_MAX_PROGRAM];
SLONG COMP_do(CBYTE *fname_input, CBYTE *fname_output)
{
//
// Load program.
//
FILE *handle = fopen(fname_input, "rb");
if (!handle)
{
//
// Could not open input file.
//
return FALSE;
}
//
// Load in the source.
//
SLONG bytes_read;
bytes_read = fread(COMP_program, sizeof(CBYTE), COMP_MAX_PROGRAM, handle);
if (bytes_read == 0)
{
//
// No data read?
//
return FALSE;
}
if (bytes_read >= COMP_MAX_PROGRAM)
{
//
// Our source buffer isn't large enough!
//
return FALSE;
}
ST_init();
PARSE_do(COMP_program);
CG_do(fname_output);
return TRUE;
}

18
MuckyBasic/comp.h Normal file
View File

@ -0,0 +1,18 @@
//
// The compiler.
//
#ifndef _COMP_
#define _COMP_
//
// Compiles the input file to produce the output file.
//
SLONG COMP_do(CBYTE *fname_input, CBYTE *fname_output);
#endif

300
MuckyBasic/console.cpp Normal file
View File

@ -0,0 +1,300 @@
//
// Provides a PRINT and INPUT for our graphical display.
// Uses the FONT module and takes control of the display.
//
#include "always.h"
#include "console.h"
#include "font.h"
#include "key.h"
#include "os.h"
//
// Each line of text.
//
#define CONSOLE_MAX_TEXT_PER_LINE 512
typedef struct
{
CBYTE text[CONSOLE_MAX_TEXT_PER_LINE];
SLONG cursor;
} CONSOLE_Line;
#define CONSOLE_MAX_LINES 35
CONSOLE_Line CONSOLE_line[CONSOLE_MAX_LINES];
SLONG CONSOLE_line_upto; // Just keeps going up beyond CONSOLE_MAX_LINES...
//
// Line height...
//
#define CONSOLE_LINE_HEIGHT (1.0F / (CONSOLE_MAX_LINES + 1))
void CONSOLE_init()
{
memset(CONSOLE_line, 0, sizeof(CONSOLE_line));
CONSOLE_line_upto = 0;
}
//
// Draws the current console.
//
void CONSOLE_draw()
{
SLONG i;
SLONG first;
SLONG last;
SLONG num;
float ypos;
OS_clear_screen();
if (CONSOLE_line_upto <= CONSOLE_MAX_LINES)
{
first = 0;
last = CONSOLE_line_upto - 1;
}
else
{
first = CONSOLE_line_upto - CONSOLE_MAX_LINES;
last = CONSOLE_line_upto - 1;
}
num = last - first + 1;
ypos = 0.009F + (num - 1) * CONSOLE_LINE_HEIGHT;
for (i = last; i >= first; i--)
{
FONT_draw(
0.013F,
ypos,
0xffffff,
FONT_FLAG_JUSTIFY_LEFT,
1.0F,
CONSOLE_line[i % CONSOLE_MAX_LINES].cursor,
CONSOLE_line[i % CONSOLE_MAX_LINES].text);
ypos -= CONSOLE_LINE_HEIGHT;
}
OS_show();
}
void CONSOLE_print(CBYTE *fmt, ...)
{
//
// Work out the real message.
//
CBYTE message[2048]; // Real long... just in case!
va_list ap;
va_start(ap, fmt);
vsprintf(message, fmt, ap);
va_end (ap);
//
// Create a new line on the console.
//
CONSOLE_Line *cl;
cl = &CONSOLE_line[CONSOLE_line_upto++ % CONSOLE_MAX_LINES];
memcpy(cl->text, message, CONSOLE_MAX_TEXT_PER_LINE - 1);
cl->cursor = -1;
//
// Draw the console.
//
CONSOLE_draw();
}
CBYTE *CONSOLE_input()
{
CBYTE *ch;
CONSOLE_Line *cl;
SLONG flash = OS_ticks();
SLONG draw = TRUE;
SLONG cursor = 0;
//
// Create a new line on the console that we will use as our input.
//
cl = &CONSOLE_line[CONSOLE_line_upto++ % CONSOLE_MAX_LINES];
memset(cl->text, 0, sizeof(cl->text));
cl->cursor = -1;
//
// Process keyboard input...
//
KEY_inkey = 0;
while(1)
{
if (KEY_on[KEY_BACKSPACE])
{
KEY_on[KEY_BACKSPACE] = 0;
if (cursor > 0)
{
cursor -= 1;
ch = &cl->text[cursor];
while(1)
{
ch[0] = ch[1];
if (ch[0] == '\000')
{
break;
}
ch++;
}
}
flash = OS_ticks();
draw = TRUE;
}
if (KEY_on[KEY_DELETE])
{
KEY_on[KEY_DELETE] = 0;
}
if (KEY_on[KEY_RETURN])
{
KEY_on[KEY_RETURN] = 0;
cl->cursor = -1;
return cl->text;
}
if (KEY_on[KEY_LEFT])
{
KEY_on[KEY_LEFT] = 0;
if (cursor > 0)
{
cursor -= 1;
}
flash = OS_ticks();
draw = TRUE;
}
if (KEY_on[KEY_RIGHT])
{
KEY_on[KEY_RIGHT] = 0;
if (cl->text[cursor])
{
cursor += 1;
}
flash = OS_ticks();
draw = TRUE;
}
if (KEY_on[KEY_END])
{
KEY_on[KEY_END] = 0;
while(cl->text[cursor])
{
cursor++;
}
flash = OS_ticks();
draw = TRUE;
}
if (KEY_on[KEY_HOME])
{
KEY_on[KEY_HOME] = 0;
cursor = 0;
flash = OS_ticks();
draw = TRUE;
}
if (KEY_inkey)
{
if (isprint(KEY_inkey))
{
if (WITHIN(cursor, 0, CONSOLE_MAX_TEXT_PER_LINE - 2))
{
//
// Insert a character at the cursor position.
//
for (ch = &cl->text[cursor]; *ch; ch++);
while(ch > &cl->text[cursor])
{
ch[0] = ch[-1];
ch--;
}
cl->text[cursor] = KEY_inkey;
cl->text[CONSOLE_MAX_TEXT_PER_LINE - 1] = '\000';
cursor += 1;
}
}
flash = OS_ticks();
draw = TRUE;
KEY_inkey = 0;
}
if (OS_ticks() > flash + 500)
{
flash = OS_ticks();
draw ^= TRUE;
}
if (draw)
{
cl->cursor = cursor;
}
else
{
cl->cursor = -1;
}
CONSOLE_draw();
}
}

33
MuckyBasic/console.h Normal file
View File

@ -0,0 +1,33 @@
//
// Provides a PRINT and INPUT for our graphical display.
// Uses the FONT module and takes control of the display.
//
#ifndef _CONSOLE_
#define _CONSOLE_
//
// Iniailises the CONSOLE output.
//
void CONSOLE_init(void);
//
// Prints the text.
//
void CONSOLE_print(CBYTE *fmt, ...);
//
// Gets a line of input from the user.
//
CBYTE *CONSOLE_input(void);
#endif

643
MuckyBasic/d3denum.cpp Normal file
View File

@ -0,0 +1,643 @@
//-----------------------------------------------------------------------------
// File: D3DEnum.cpp
//
// Desc: Class enumerate through the DirectDraw drivers, Direct3D devices,
// and the display modes available to each device.
//
//
// Copyright (c) 1997-1998 Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
#define STRICT
#include <stdio.h>
// HACK!!!!!
#include <windows.h>
#ifndef SM_CMONITORS
#define SM_CMONITORS
DECLARE_HANDLE(HMONITOR);
#define HMONITOR_DECLARED
#endif
#include "D3DEnum.h"
#include "D3DUtil.h"
//-----------------------------------------------------------------------------
// Constants and function prototypes for the user select driver dialog
//-----------------------------------------------------------------------------
DLGTEMPLATE* _BuildDriverSelectTemplate();
BOOL CALLBACK _DriverSelectProc( HWND, UINT, WPARAM, LPARAM );
//-----------------------------------------------------------------------------
// Global data for the enumerator functions
//-----------------------------------------------------------------------------
static LPDIRECTDRAW4 g_pDD = NULL; // Used for callbacks
static BOOL g_bRefRastEnumerated = FALSE; // For the reference rast
static BOOL g_bDevicesEnumerated = FALSE; // Used during enumeration
D3DEnum_DriverInfo* g_pFirstDriver = NULL; // List of DD drivers
D3DEnum_DriverInfo* g_pDefaultDriver = NULL; // Default driver
D3DEnum_DriverInfo* g_pCurrentDriver = NULL; // The selected DD driver
static HRESULT (*g_fnAppConfirmFn)(DDCAPS*, D3DDEVICEDESC*) = NULL;
//-----------------------------------------------------------------------------
// Local callback functions used during enumeration
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Name: EnumDisplayModesCallback()
// Desc: Callback function called for each display mode. Each available
// display mode is added to a list for further choosing from the app.
//-----------------------------------------------------------------------------
static HRESULT WINAPI EnumDisplayModesCallback( DDSURFACEDESC2* pddsd,
VOID* pvContext )
{
// Check parameters
if( NULL==pddsd || NULL==pvContext )
return DDENUMRET_CANCEL;
D3DEnum_DeviceInfo* pDevice = (D3DEnum_DeviceInfo*)pvContext;
D3DEnum_ModeInfo* pNewMode;
DWORD dwBitDepth = pDevice->ddDesc.dwDeviceRenderBitDepth;
DWORD dwModeDepth = pddsd->ddpfPixelFormat.dwRGBBitCount;
// Check mode for compatability with device. Skip 8-bit modes.
if( (32==dwModeDepth) && (0==(dwBitDepth&DDBD_32)) ) return DDENUMRET_OK;
if( (24==dwModeDepth) && (0==(dwBitDepth&DDBD_24)) ) return DDENUMRET_OK;
if( (16==dwModeDepth) && (0==(dwBitDepth&DDBD_16)) ) return DDENUMRET_OK;
if( ( 8==dwModeDepth) ) return DDENUMRET_OK;
// Create a new mode structure
if( NULL == ( pNewMode = new D3DEnum_ModeInfo ) )
return DDENUMRET_CANCEL;
// Initialize the new mode structure
ZeroMemory( pNewMode, sizeof(D3DEnum_ModeInfo) );
memcpy( &pNewMode->ddsd, pddsd, sizeof(DDSURFACEDESC2) );
sprintf( pNewMode->strDesc, TEXT("%ld x %ld x %ld"), pddsd->dwWidth,
pddsd->dwHeight, dwModeDepth );
// Link the new mode struct in the list of other display modes
D3DEnum_ModeInfo** pMode = &pDevice->pFirstMode;
while( *pMode )
pMode = &((*pMode)->pNext);
(*pMode) = pNewMode;
// If this is a 640x480x16 mode, save it as the default mode
if( ( 640 == pddsd->dwWidth ) && ( 480 == pddsd->dwHeight ) &&
( 16 == pddsd->ddpfPixelFormat.dwRGBBitCount ) )
pDevice->pCurrentMode = pNewMode;
if( NULL == pDevice->pCurrentMode )
pDevice->pCurrentMode = pNewMode;
return DDENUMRET_OK;
}
//-----------------------------------------------------------------------------
// Name: Enum3DDevicesCallback()
// Desc: Callback function called for each DirectX 3D device. The driver's
// attributes are added to the list of available drivers.
//-----------------------------------------------------------------------------
static HRESULT WINAPI Enum3DDevicesCallback( GUID* pGUID, LPSTR strDesc,
LPSTR strName, LPD3DDEVICEDESC pHALDesc,
LPD3DDEVICEDESC pHELDesc, LPVOID pvContext )
{
D3DEnum_DriverInfo* pDriver = (D3DEnum_DriverInfo*)pvContext;
D3DEnum_DeviceInfo* pNewDevice;
// Check params
if( NULL==pGUID || NULL==pHALDesc || NULL==pHELDesc || NULL==pDriver )
return D3DENUMRET_CANCEL;
// Handle specific device GUIDs. NullDevice renders nothing
if( IsEqualGUID( *pGUID, IID_IDirect3DNullDevice ) )
return D3DENUMRET_OK;
// Set a flag so we know enumeration is working. This is just a feature to
// help return more informative return codes later on.
g_bDevicesEnumerated = TRUE;
// Get info about this device.
BOOL bIsHardware = ( 0 != pHALDesc->dwFlags );
D3DDEVICEDESC* pDesc = bIsHardware ? pHALDesc : pHELDesc;
// Only enumerate software rasterizers for the primary device (which has
// a NULL GUID). This is to avoid duplicates
if( pDriver->pGUID != NULL )
if( FALSE == bIsHardware )
return D3DENUMRET_OK;
// Give the app a chance to accept or reject this device, based on
// what feature set it supports
if( g_fnAppConfirmFn )
if( FAILED( g_fnAppConfirmFn( &pDriver->ddDriverCaps, pDesc ) ) )
return D3DENUMRET_OK;
// Create a new D3D Driver struct
if( NULL == ( pNewDevice = new D3DEnum_DeviceInfo ) )
return D3DENUMRET_CANCEL;
ZeroMemory( pNewDevice, sizeof(D3DEnum_DeviceInfo) );
// Copy remaining device attributes
memcpy( &pNewDevice->guid, pGUID, sizeof(GUID) );
pNewDevice->pGUID = &pNewDevice->guid;
strncpy( pNewDevice->strName, strName, 39 );
memcpy( &pNewDevice->ddDesc, pDesc, sizeof(D3DDEVICEDESC) );
pNewDevice->bIsHardware = bIsHardware;
if( pNewDevice->bIsHardware )
pDriver->pCurrentDevice = pNewDevice;
else
{
if( NULL == pDriver->pCurrentDevice )
if( D3DCOLOR_RGB & pHELDesc->dcmColorModel )
pDriver->pCurrentDevice = pNewDevice;
}
// Enumerate the display modes
g_pDD->EnumDisplayModes( 0, NULL, pNewDevice, EnumDisplayModesCallback );
// Get the display mode's depth
DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(DDSURFACEDESC2);
g_pDD->GetDisplayMode( &ddsd );
DWORD dwDisplayBPP = ddsd.ddpfPixelFormat.dwRGBBitCount;
// Set the initial bWindowed flag if the device can render in a window and
// supports the current display mode
if( pDriver->ddDriverCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED )
{
for( D3DEnum_ModeInfo* pMode=pNewDevice->pFirstMode; pMode;
pMode = pMode->pNext )
{
if( pMode->ddsd.ddpfPixelFormat.dwRGBBitCount == dwDisplayBPP )
{
pNewDevice->bCompatbileWithDesktop = TRUE;
if( NULL == pDriver->pGUID )
pNewDevice->bWindowed = TRUE;
}
}
}
if( pNewDevice->pFirstMode )
{
// Link it with the other D3D drivers in the DD Driver struct
D3DEnum_DeviceInfo** pDevice = &pDriver->pFirstDevice;
while( *pDevice )
pDevice = &((*pDevice)->pNext);
(*pDevice) = pNewDevice;
}
else
// Device has no modes, so delete it
delete pNewDevice;
if( IsEqualGUID( *pGUID, IID_IDirect3DRefDevice ) )
g_bRefRastEnumerated = TRUE;
return D3DENUMRET_OK;
}
//-----------------------------------------------------------------------------
// Name: DirectDrawEnumCallbackEx()
// Desc: Callback function called for each DirectDraw driver. Unless we have
// multimon or a type of card which uses a separate 2D card in
// conjunction with the 3D card, this is only done once.
//-----------------------------------------------------------------------------
static BOOL WINAPI DirectDrawEnumCallbackEx( GUID FAR* pGUID, LPSTR strDesc,
LPSTR strName, VOID*,
HMONITOR hMonitor )
{
// Use the GUID to create the DirectDraw object, so that information
// can be extracted from it.
LPDIRECTDRAW pDD;
if( FAILED( DirectDrawCreate( pGUID, &pDD, 0L ) ) )
{
DEBUG_MSG( TEXT("Can't create DDraw during enumeration!") );
return D3DENUMRET_OK;
}
// Query the DirectDraw driver for access to Direct3D.
if( FAILED( pDD->QueryInterface( IID_IDirectDraw4, (VOID**)&g_pDD ) ) )
{
DEBUG_MSG( TEXT("Can't query IDirectDraw4 during enumeration!") );
pDD->Release();
return D3DENUMRET_OK;
}
pDD->Release();
// Query the DirectDraw driver for access to Direct3D.
LPDIRECT3D3 pD3D;
if( FAILED( g_pDD->QueryInterface( IID_IDirect3D3, (VOID**)&pD3D ) ) )
{
DEBUG_MSG( TEXT("Can't query IDirect3D3 during enumeration!") );
g_pDD->Release();
return D3DENUMRET_OK;
}
// Copy the DDDriver info into a new DriverInfo struct
D3DEnum_DriverInfo* pNewDriver = new D3DEnum_DriverInfo;
if( NULL == pNewDriver )
return D3DENUMRET_CANCEL;
ZeroMemory( pNewDriver, sizeof(D3DEnum_DriverInfo) );
// Copy the GUID (if specified) and the driver name
if( NULL != pGUID )
{
memcpy( &pNewDriver->guid, pGUID, sizeof(GUID) );
pNewDriver->pGUID = &pNewDriver->guid;
}
strncpy( pNewDriver->strDesc, strDesc, 39 );
strncpy( pNewDriver->strName, strName, 39 );
pNewDriver->hMonitor = hMonitor;
// Get the caps bits for the driver
pNewDriver->ddDriverCaps.dwSize = sizeof(DDCAPS);
pNewDriver->ddHELCaps.dwSize = sizeof(DDCAPS);
g_pDD->GetCaps( &pNewDriver->ddDriverCaps, &pNewDriver->ddHELCaps );
// Now, enumerate all the 3D devices
pD3D->EnumDevices( Enum3DDevicesCallback, pNewDriver );
if( pNewDriver->pFirstDevice )
{
// Link the new DDDriver with the global list
D3DEnum_DriverInfo** pDriver = &g_pFirstDriver;
while( *pDriver )
pDriver = &((*pDriver)->pNext);
(*pDriver) = pNewDriver;
// Decide if this is a good default driver
if( NULL == pGUID )
g_pCurrentDriver = pNewDriver;
}
else
// Driver has no devices, so delete it
delete pNewDriver;
pD3D->Release();
g_pDD->Release();
return DDENUMRET_OK;
}
//-----------------------------------------------------------------------------
// Name: DirectDrawEnumCallback()
// Desc: Non-mulitmon version of the ddraw enumeration callback
//-----------------------------------------------------------------------------
static BOOL WINAPI DirectDrawEnumCallback( GUID FAR* pGUID, LPSTR strDesc,
LPSTR strName, VOID* )
{
return DirectDrawEnumCallbackEx( pGUID, strDesc, strName, NULL, NULL );
}
//-----------------------------------------------------------------------------
// Name: D3DEnum_FreeResources()
// Desc: Frees all resources used for driver enumeration
//-----------------------------------------------------------------------------
VOID D3DEnum_FreeResources()
{
// Loop through each driver, and delete everything
while( g_pFirstDriver )
{
D3DEnum_DriverInfo* pDriverVictim = g_pFirstDriver;
g_pFirstDriver = g_pFirstDriver->pNext;
while( pDriverVictim->pFirstDevice )
{
D3DEnum_DeviceInfo* pDeviceVictim = pDriverVictim->pFirstDevice;
pDriverVictim->pFirstDevice = pDeviceVictim->pNext;
while( pDeviceVictim->pFirstMode )
{
D3DEnum_ModeInfo* pModeVictim = pDeviceVictim->pFirstMode;
pDeviceVictim->pFirstMode = pModeVictim->pNext;
delete pModeVictim;
}
delete pDeviceVictim;
}
delete pDriverVictim;
}
}
//-----------------------------------------------------------------------------
// Name: RefreshListForDesktopCompatibility()
// Desc: Loops through list of devices, and marks a flag for whether the device
// is compatible with the desktop bit depth.
//-----------------------------------------------------------------------------
static VOID RefreshListForDesktopCompatibility()
{
// Get the currect display mode description
LPDIRECTDRAW pDD;
DDSURFACEDESC ddsd;
if( FAILED( DirectDrawCreate( NULL, &pDD, NULL ) ) )
return;
ddsd.dwSize = sizeof(DDSURFACEDESC);
pDD->GetDisplayMode( &ddsd );
pDD->Release();
// Get the display mode's depth
DWORD dwDisplayBPP = ddsd.ddpfPixelFormat.dwRGBBitCount;
// Loop through the devices, and check if any modes works with the current
// display setting
for( D3DEnum_DriverInfo* pDriver = g_pFirstDriver; pDriver;
pDriver = pDriver->pNext )
{
for( D3DEnum_DeviceInfo* pDevice=pDriver->pFirstDevice; pDevice;
pDevice = pDevice->pNext )
{
pDevice->bCompatbileWithDesktop = FALSE;
for( D3DEnum_ModeInfo* pMode=pDevice->pFirstMode; pMode;
pMode = pMode->pNext )
{
if( pMode->ddsd.ddpfPixelFormat.dwRGBBitCount == dwDisplayBPP )
pDevice->bCompatbileWithDesktop = TRUE;
}
}
}
}
//-----------------------------------------------------------------------------
// Name: D3DEnum_EnumerateDevices()
// Desc: Enumerates all drivers, devices, and modes. The optional app-supplied
// callback is called for each enumerated device, to confirm that the
// device supports the feature set required by the app.
//-----------------------------------------------------------------------------
HRESULT D3DEnum_EnumerateDevices(
HRESULT (*AppConfirmFn)(DDCAPS*, D3DDEVICEDESC*) )
{
g_fnAppConfirmFn = AppConfirmFn;
g_bRefRastEnumerated = FALSE;
// We need to manually get the procedure address for the DDrawEnumEx()
// function.
HMODULE hDDrawDLL = GetModuleHandle("DDRAW.DLL");
if( NULL == hDDrawDLL )
{
DEBUG_MSG( TEXT("Can't load DDRAW.DLL!") );
return D3DENUMERR_NODIRECTDRAW;
}
// Find the DDraw enumeration function, and call it
LPDIRECTDRAWENUMERATEEX pDDrawEnumFn = (LPDIRECTDRAWENUMERATEEX)
GetProcAddress( hDDrawDLL, "DirectDrawEnumerateExA" );
if( pDDrawEnumFn )
pDDrawEnumFn( DirectDrawEnumCallbackEx, NULL,
DDENUM_ATTACHEDSECONDARYDEVICES |
DDENUM_DETACHEDSECONDARYDEVICES |
DDENUM_NONDISPLAYDEVICES );
else
DirectDrawEnumerate( DirectDrawEnumCallback, NULL );
// Select a driver. Ask for a hardware device that renders in a window
return D3DEnum_SelectDefaultDriver( NULL );
}
//-----------------------------------------------------------------------------
// Name: D3DEnum_SelectDefaultDriver()
// Desc: Picks a default driver according to the passed in flags.
//-----------------------------------------------------------------------------
HRESULT D3DEnum_SelectDefaultDriver( DWORD dwFlags )
{
// Refresh the list of devices to mark which devices (if any) are
// compatible with the current desktop (ie. can render in a window).
RefreshListForDesktopCompatibility();
// If a specific driver was requested, perform that search here
if( dwFlags & 0x0000003c )
{
for( D3DEnum_DriverInfo* pDriver = g_pFirstDriver; pDriver;
pDriver = pDriver->pNext )
{
for( D3DEnum_DeviceInfo* pDevice = pDriver->pFirstDevice; pDevice;
pDevice = pDevice->pNext )
{
BOOL bFound = FALSE;
if( IsEqualGUID( *pDevice->pGUID, IID_IDirect3DRGBDevice ) )
{
if( dwFlags & D3DENUM_RGBEMULATION )
bFound = TRUE;
}
else if( IsEqualGUID( *pDevice->pGUID, IID_IDirect3DRefDevice ) )
{
if( dwFlags & D3DENUM_REFERENCERAST )
bFound = TRUE;
}
else
{
if( dwFlags & D3DENUM_PRIMARYHAL )
if( pDriver == g_pFirstDriver )
bFound = TRUE;
if( dwFlags & D3DENUM_SECONDARYHAL )
if( pDriver != g_pFirstDriver )
bFound = TRUE;
}
if( bFound )
{
g_pCurrentDriver = pDriver;
g_pCurrentDriver->pCurrentDevice = pDevice;
return S_OK;
}
}
}
return D3DENUMERR_NOTFOUND;
}
// Do 4 passes, looping through drivers, devices and modes. The 1st pass
// searches for hardware. The 2nd pass looks for software devices. The
// final two passes allow fullscreen modes.
for( WORD pass=0; pass<4; pass++ )
{
BOOL bSeekHardware = ( pass & 0x1 ) ? FALSE : TRUE;
BOOL bSeekWindowed = ( pass & 0x2 ) ? FALSE : TRUE;
// Skip the passes we aren't allowing
if( (TRUE==bSeekHardware) && (dwFlags&D3DENUM_SOFTWAREONLY) )
continue;
if( (TRUE==bSeekWindowed) && (dwFlags&D3DENUM_FULLSCREENONLY) )
continue;
for( D3DEnum_DriverInfo* pDriver = g_pFirstDriver; pDriver;
pDriver = pDriver->pNext )
{
DDCAPS* pCaps = &pDriver->ddDriverCaps;
if( bSeekWindowed )
if( 0 == ( pCaps->dwCaps2 & DDCAPS2_CANRENDERWINDOWED ) )
continue;
for( D3DEnum_DeviceInfo* pDevice = pDriver->pFirstDevice; pDevice;
pDevice = pDevice->pNext )
{
if( bSeekHardware != pDevice->bIsHardware )
continue;
if( bSeekWindowed && FALSE == pDevice->bCompatbileWithDesktop )
continue;
pDevice->bWindowed = bSeekWindowed;
g_pCurrentDriver = pDriver;
g_pCurrentDriver->pCurrentDevice = pDevice;
return S_OK;
}
}
}
// No compatible devices were found. Return an error code
if( FALSE == g_bDevicesEnumerated )
return D3DENUMERR_ENUMERATIONFAILED; // Enumeration really did fail
if( FALSE == g_bRefRastEnumerated )
return D3DENUMERR_SUGGESTREFRAST; // Suggest enabling the RefRast
return D3DENUMERR_NOCOMPATIBLEDEVICES;
}
//-----------------------------------------------------------------------------
// Name: D3DEnum_UserDlgSelectDriver()
// Desc: Displays a dialog box for the user to select a driver/device/mode.
// The return values are akin to the Windows DialogBox() function.
//-----------------------------------------------------------------------------
INT D3DEnum_UserDlgSelectDriver( HWND hwndParent, BOOL bCurrentlyWindowed )
{
INT nResult = -1;
// Check in case drivers weren't properly enumerated beforehand.
if( NULL == g_pCurrentDriver )
return -1;
// Refresh the list of devices to mark which devices (if any) are
// compatible with the current desktop (ie. can render in a window).
RefreshListForDesktopCompatibility();
// Match the current windowed-vs-fullscreen state
g_pCurrentDriver->pCurrentDevice->bWindowed = bCurrentlyWindowed;
// Pop up a dialog box for the user's choice of driver/device/mode
HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndParent,
GWL_HINSTANCE );
// Create dynamic dialog template
DLGTEMPLATE* pDlgSelect = _BuildDriverSelectTemplate();
if( pDlgSelect )
{
// Create dialog box from template
nResult = DialogBoxIndirectParam( hInstance, pDlgSelect, hwndParent,
(DLGPROC)_DriverSelectProc, 0L );
delete pDlgSelect;
}
return nResult;
}
//-----------------------------------------------------------------------------
// Name: D3DEnum_GetSelectedDriver()
// Desc: Returns the currently selected driver, device, and display mode
//-----------------------------------------------------------------------------
HRESULT D3DEnum_GetSelectedDriver( LPGUID* ppDriverGUID, LPGUID* ppDeviceGUID,
LPDDSURFACEDESC2* ppddsd, BOOL* pbWindowed,
BOOL* pbIsHardware )
{
// Check parans
if( (!ppDriverGUID) || (!ppDeviceGUID) )
return E_INVALIDARG;
// Abort if things weren't setup correctly
if( NULL == g_pCurrentDriver )
return D3DENUMERR_ENUMERATIONFAILED;
// Copy the driver and device GUID ptrs
(*ppDriverGUID) = g_pCurrentDriver->pGUID;
(*ppDeviceGUID) = g_pCurrentDriver->pCurrentDevice->pGUID;
if( ppddsd )
(*ppddsd) = &g_pCurrentDriver->pCurrentDevice->pCurrentMode->ddsd;
if( pbWindowed )
(*pbWindowed) = g_pCurrentDriver->pCurrentDevice->bWindowed;
if( pbIsHardware )
(*pbIsHardware) = g_pCurrentDriver->pCurrentDevice->bIsHardware;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DEnum_GetSelectedDriver()
// Desc: Returns the currently selected driver, device, and display mode
//-----------------------------------------------------------------------------
HRESULT D3DEnum_GetSelectedDriver( D3DEnum_DriverInfo** ppDriverInfo,
D3DEnum_DeviceInfo** ppDeviceInfo )
{
// Abort if things weren't setup correctly
if( NULL == g_pCurrentDriver )
return D3DENUMERR_ENUMERATIONFAILED;
// Copy the driver and device info ptrs
if( ppDriverInfo ) *ppDriverInfo = g_pCurrentDriver;
if( ppDeviceInfo ) *ppDeviceInfo = g_pCurrentDriver->pCurrentDevice;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DEnum_GetFirstDriver()
// Desc: Returns a ptr to the first DriverInfo structure in the list.
//-----------------------------------------------------------------------------
D3DEnum_DriverInfo* D3DEnum_GetFirstDriver()
{
return g_pFirstDriver;
}

180
MuckyBasic/d3denum.h Normal file
View File

@ -0,0 +1,180 @@
//-----------------------------------------------------------------------------
// File: D3DEnum.h
//
// Desc: Functions which enumerate through the DirectDraw drivers, Direct3D
// devices, and the display modes available to each device.
//
//
// Copyright (C) 1997 Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
#ifndef D3DENUM_H
#define D3DENUM_H
#include <ddraw.h>
#include <d3d.h>
//-----------------------------------------------------------------------------
// Name: D3DEnum_ModeInfo
// Desc: Linked-list structure to hold information about a display mode. This
// info is stored as a width, height, bpp, and pixelformat within a
// DDSURFACEDESC2.
//-----------------------------------------------------------------------------
struct D3DEnum_ModeInfo
{
DDSURFACEDESC2 ddsd;
CHAR strDesc[40];
D3DEnum_ModeInfo* pNext;
};
//-----------------------------------------------------------------------------
// Name: D3DEnum_DeviceInfo
// Desc: Linked-list structure to hold information about a Direct3D device. The
// primary information recorded here is the D3DDEVICEDESC and a ptr to a
// linked-list of valid display modes.
//-----------------------------------------------------------------------------
struct D3DEnum_DeviceInfo
{
GUID guid;
GUID* pGUID;
CHAR strName[40];
D3DDEVICEDESC ddDesc;
BOOL bIsHardware;
BOOL bCompatbileWithDesktop;
BOOL bWindowed;
D3DEnum_ModeInfo* pCurrentMode;
D3DEnum_ModeInfo* pFirstMode;
D3DEnum_DeviceInfo* pNext;
};
//-----------------------------------------------------------------------------
// Name: D3DEnum_DriverInfo
// Desc: Linked-list structure to hold information about a DirectX driver. The
// info stored is the capability bits for the driver plus a linked-list
// of valid Direct3D devices for the driver. Note: most systems will only
// have one driver. The exception are multi-monitor systems, and systems
// with non-GDI 3D video cards.
//-----------------------------------------------------------------------------
struct D3DEnum_DriverInfo
{
GUID guid;
GUID* pGUID;
CHAR strDesc[40];
CHAR strName[40];
DDCAPS ddDriverCaps;
DDCAPS ddHELCaps;
HANDLE hMonitor;
D3DEnum_DeviceInfo* pCurrentDevice;
D3DEnum_DeviceInfo* pFirstDevice;
D3DEnum_DriverInfo* pNext;
};
//-----------------------------------------------------------------------------
// Name: D3DEnum_EnumerateDevices()
// Desc: Enumerates all drivers, devices, and modes. The optional app-supplied
// callback is called for each enumerated device, to confirm that the
// device supports the feature set required by the app.
//-----------------------------------------------------------------------------
HRESULT D3DEnum_EnumerateDevices(
HRESULT (*AppConfirmFn)(DDCAPS*, D3DDEVICEDESC*) );
//-----------------------------------------------------------------------------
// Name: D3DEnum_FreeResources()
// Desc: Frees all resources used for driver enumeration
//-----------------------------------------------------------------------------
VOID D3DEnum_FreeResources();
//-----------------------------------------------------------------------------
// Name: D3DEnum_SelectDefaultDriver()
// Desc: Picks a driver based on a set of passed in criteria.
//-----------------------------------------------------------------------------
HRESULT D3DEnum_SelectDefaultDriver( DWORD dwFlags );
#define D3DENUM_SOFTWAREONLY 0x00000001
#define D3DENUM_FULLSCREENONLY 0x00000002
#define D3DENUM_RGBEMULATION 0x00000004
#define D3DENUM_REFERENCERAST 0x00000008
#define D3DENUM_PRIMARYHAL 0x00000010
#define D3DENUM_SECONDARYHAL 0x00000020
//-----------------------------------------------------------------------------
// Name: D3DEnum_UserDlgSelectDriver()
// Desc: Prompts the user with a dialog box, from which to choose a DD driver,
// D3D device, and compatible display mode. The function will return
// IDOK if a new driver/device/mode was selected, or IDCANCEL if not.
// Any error will result in a -1 for a return code.
//-----------------------------------------------------------------------------
INT D3DEnum_UserDlgSelectDriver( HWND hwndParent, BOOL bCurrentlyWindowed );
//-----------------------------------------------------------------------------
// Name: D3DEnum_GetSelectedDriver()
// Desc: Returns the currently selected driver, device, and display mode.
//-----------------------------------------------------------------------------
HRESULT D3DEnum_GetSelectedDriver( LPGUID* ppDriverGUID, LPGUID* ppDeviceGuid,
LPDDSURFACEDESC2* pddsdDisplayMode = NULL,
BOOL* pbWindowed = NULL,
BOOL* pbIsHardware = NULL );
//-----------------------------------------------------------------------------
// Name: D3DEnum_GetSelectedDriver()
// Desc: Returns the currently selected driver, device, and display mode.
//-----------------------------------------------------------------------------
HRESULT D3DEnum_GetSelectedDriver( D3DEnum_DriverInfo** ppDriverInfo,
D3DEnum_DeviceInfo** ppDeviceInfo );
//-----------------------------------------------------------------------------
// Name: D3DEnum_GetFirstDriver()
// Desc: Returns a ptr to the first DriverInfo structure in the tree holding
// the device/driver/mode enumeration information.
//-----------------------------------------------------------------------------
D3DEnum_DriverInfo* D3DEnum_GetFirstDriver();
//-----------------------------------------------------------------------------
// Error codes
//-----------------------------------------------------------------------------
#define D3DENUMERR_ENUMERATIONFAILED 0x81000001 // Enumeration failed
#define D3DENUMERR_SUGGESTREFRAST 0x81000002 // Suggest using the RefRast
#define D3DENUMERR_NOCOMPATIBLEDEVICES 0x81000003 // No devices were found that
// meet the app's desired
// capabilities
#define D3DENUMERR_NODIRECTDRAW 0x81000004 // DDraw couldn't initialize
#define D3DENUMERR_NOTFOUND 0x81000005 // Requested device not found
#endif // D3DENUM_H

755
MuckyBasic/d3dframe.cpp Normal file
View File

@ -0,0 +1,755 @@
//-----------------------------------------------------------------------------
// File: D3DFrame.cpp
//
// Desc: Class to manage the Direct3D environment objects such as buffers,
// viewports, and 3D devices.
//
// The class is initialized with the Initialize() function, after which
// the Get????() functions can be used to access the objects needed for
// rendering. If the device or display needs to be changed, the
// ChangeDevice() function can be called. If the display window is moved
// the changes need to be reported with the Move() function.
//
// After rendering a frame, the ShowFrame() function filps or blits the
// backbuffer contents to the primary. If surfaces are lost, they can be
// restored with the RestoreSurfaces() function. Finally, if normal
// Windows output is needed, the FlipToGDISurface() provides a GDI
// surface to draw on.
//
//
// Copyright (c) 1995-1998 by Microsoft, all rights reserved
//-----------------------------------------------------------------------------
#define STRICT
#include <windows.h>
#include "D3DFrame.h"
#include "D3DUtil.h"
//-----------------------------------------------------------------------------
// Name: EnumZBufferFormatsCallback()
// Desc: Enumeration function to report valid pixel formats for z-buffers.
//-----------------------------------------------------------------------------
static HRESULT WINAPI EnumZBufferFormatsCallback( DDPIXELFORMAT* pddpf,
VOID* pddpfDesired )
{
if( NULL==pddpf || NULL==pddpfDesired )
return D3DENUMRET_CANCEL;
// If the current pixel format's match the desired ones (DDPF_ZBUFFER and
// possibly DDPF_STENCILBUFFER), lets copy it and return. This function is
// not choosy...it accepts the first valid format that comes along.
if( pddpf->dwFlags == ((DDPIXELFORMAT*)pddpfDesired)->dwFlags )
{
memcpy( pddpfDesired, pddpf, sizeof(DDPIXELFORMAT) );
// We're happy with a 16-bit z-buffer. Otherwise, keep looking.
if( pddpf->dwZBufferBitDepth == 16 )
return D3DENUMRET_CANCEL;
}
return D3DENUMRET_OK;
}
//-----------------------------------------------------------------------------
// Name: CD3DFramework()
// Desc: The constructor. Clears static variables
//-----------------------------------------------------------------------------
CD3DFramework::CD3DFramework()
{
m_hWnd = NULL;
m_bIsFullscreen = FALSE;
m_dwRenderWidth = 0L;
m_dwRenderHeight = 0L;
m_pddsFrontBuffer = NULL;
m_pddsBackBuffer = NULL;
m_pddsRenderTarget = NULL;
m_pddsZBuffer = NULL;
m_pd3dDevice = NULL;
m_pvViewport = NULL;
m_pDD = NULL;
m_pD3D = NULL;
m_dwDeviceMemType = NULL;
}
//-----------------------------------------------------------------------------
// Name: ~CD3DFramework()
// Desc: The destructor. Deletes all objects
//-----------------------------------------------------------------------------
CD3DFramework::~CD3DFramework()
{
DestroyObjects();
}
//-----------------------------------------------------------------------------
// Name: DestroyObjects()
// Desc: Cleans everything up upon deletion. This code returns an error
// if any of the objects have remaining reference counts.
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::DestroyObjects()
{
LONG nDD = 0L; // Number of outstanding DDraw references
LONG nD3D = 0L; // Number of outstanding D3DDevice references
SAFE_RELEASE( m_pvViewport );
// Do a safe check for releasing the D3DDEVICE. RefCount must be zero.
if( m_pd3dDevice )
if( 0 < ( nD3D = m_pd3dDevice->Release() ) )
DEBUG_MSG( TEXT("Error: D3DDevice object is still referenced!") );
m_pd3dDevice = NULL;
// In windowed mode, release the explicity created backbuffer.
if( FALSE == m_bIsFullscreen )
SAFE_RELEASE( m_pddsBackBuffer );
SAFE_RELEASE( m_pddsRenderTarget ); //Note: release before frontbuffer
SAFE_RELEASE( m_pddsZBuffer );
SAFE_RELEASE( m_pddsFrontBuffer );
SAFE_RELEASE( m_pD3D );
// Do a safe check for releasing DDRAW. RefCount must be zero.
if( m_pDD )
{
m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL );
if( 0 < ( nDD = m_pDD->Release() ) )
DEBUG_MSG( TEXT("Error: DDraw object is still referenced!") );
}
m_pDD = NULL;
// Return successful, unless there are outstanding DD or D3DDevice refs.
return ( nDD==0 && nD3D==0 ) ? S_OK : D3DFWERR_NONZEROREFCOUNT;
}
//-----------------------------------------------------------------------------
// Name: Initialize()
// Desc: Creates the internal objects for the framework
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::Initialize( HWND hWnd, GUID* pDriverGUID,
GUID* pDeviceGUID, DDSURFACEDESC2* pMode,
DWORD dwFlags )
{
HRESULT hr;
// Check params. A NULL mode is valid for windowed modes only. A NULL
// device GUID is legal for apps that only want 2D support.
if( NULL==hWnd || ( NULL==pMode && (dwFlags&D3DFW_FULLSCREEN) ) )
return E_INVALIDARG;
// Setup state for windowed/fullscreen mode
m_hWnd = hWnd;
m_bIsFullscreen = ( dwFlags & D3DFW_FULLSCREEN ) ? TRUE : FALSE;
// Create the D3D rendering environment (surfaces, device, viewport, etc.)
if( FAILED( hr = CreateEnvironment( pDriverGUID, pDeviceGUID, pMode,
dwFlags ) ) )
{
DestroyObjects();
if( E_FAIL == hr )
hr = D3DFWERR_INITIALIZATIONFAILED;
}
return hr;
}
//-----------------------------------------------------------------------------
// Name: CreateEnvironment()
// Desc: Creates the internal objects for the framework
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::CreateEnvironment( GUID* pDriverGUID, GUID* pDeviceGUID,
DDSURFACEDESC2* pMode, DWORD dwFlags )
{
HRESULT hr;
// Create the DDraw object
if( FAILED( hr = CreateDirectDraw( pDriverGUID, dwFlags ) ) )
return hr;
// Create the Direct3D object
if( pDeviceGUID )
if( FAILED( hr = CreateDirect3D( pDeviceGUID, dwFlags ) ) )
return hr;
// Create the front and back buffers, and attach a clipper
if( FAILED( hr = CreateBuffers( pMode, dwFlags ) ) )
return hr;
// If there is no device GUID, then the app only wants 2D, so we're done
if( NULL == pDeviceGUID )
return S_OK;
// Create and attach the zbuffer
if( dwFlags & D3DFW_ZBUFFER )
if( FAILED( hr = CreateZBuffer() ) )
return hr;
// Query the render buffer for the 3ddevice
if( FAILED( hr = Create3DDevice( pDeviceGUID ) ) )
return hr;
// Create and set the viewport
if( FAILED( hr = CreateViewport() ) )
return hr;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CreateDirectDraw()
// Desc: Create the DirectDraw interface
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::CreateDirectDraw( GUID* pDriverGUID, DWORD dwFlags )
{
// Create the DirectDraw interface, and query for the DD4 interface
LPDIRECTDRAW pDD;
if( FAILED( DirectDrawCreate( pDriverGUID, &pDD, NULL ) ) )
{
DEBUG_MSG( TEXT("Could not create DirectDraw") );
return D3DFWERR_NODIRECTDRAW;
}
if( FAILED( pDD->QueryInterface( IID_IDirectDraw4, (VOID**)&m_pDD ) ) )
{
pDD->Release();
DEBUG_MSG( TEXT("Couldn't query for DirectDraw4") );
return D3DFWERR_NODIRECTDRAW;
}
pDD->Release();
// Set the Windows cooperative level
DWORD dwCoopFlags = DDSCL_NORMAL;
if( m_bIsFullscreen )
dwCoopFlags = DDSCL_ALLOWREBOOT|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN;
// By defualt, set the flag to allow D3D to optimize floating point calcs
if( 0L == ( dwFlags & D3DFW_NO_FPUSETUP ) )
dwCoopFlags |= DDSCL_FPUSETUP;
if( FAILED( m_pDD->SetCooperativeLevel( m_hWnd, dwCoopFlags ) ) )
{
DEBUG_MSG( TEXT("Couldn't set coop level") );
return D3DFWERR_COULDNTSETCOOPLEVEL;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CreateDirect3D()
// Desc: Create the Direct3D interface
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::CreateDirect3D( GUID* pDeviceGUID, DWORD dwFlags )
{
// Query DirectDraw for access to Direct3D
if( FAILED( m_pDD->QueryInterface( IID_IDirect3D3, (VOID**)&m_pD3D ) ) )
{
DEBUG_MSG( TEXT("Couldn't query the Direct3D interface") );
return D3DFWERR_NODIRECT3D;
}
// Use the FindDevice() method to test if the requested device
// exists, and if so, take note of what memory type it takes.
D3DFINDDEVICERESULT devResult;
D3DFINDDEVICESEARCH devSearch;
ZeroMemory( &devResult, sizeof(D3DFINDDEVICERESULT) );
ZeroMemory( &devSearch, sizeof(D3DFINDDEVICESEARCH) );
devResult.dwSize = sizeof(D3DFINDDEVICERESULT);
devSearch.dwSize = sizeof(D3DFINDDEVICESEARCH);
devSearch.dwFlags = D3DFDS_GUID;
CopyMemory( &devSearch.guid, pDeviceGUID, sizeof(GUID) );
if( FAILED( m_pD3D->FindDevice( &devSearch, &devResult ) ) )
{
DEBUG_MSG( TEXT("Couldn't find the specified device") );
return D3DFWERR_NODIRECT3D;
}
// Whether device is SW or HW, get the devicedesc, and the defualt memtype
if( 0L == devResult.ddHwDesc.dwFlags )
{
m_dwDeviceMemType = DDSCAPS_SYSTEMMEMORY;
memcpy( &m_ddDeviceDesc, &devResult.ddSwDesc, sizeof(D3DDEVICEDESC) );
}
else
{
m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
memcpy( &m_ddDeviceDesc, &devResult.ddHwDesc, sizeof(D3DDEVICEDESC) );
}
// Using the device GUID, let's enumerate a format for our z-buffer, in
// case we later decide to create one.
ZeroMemory( &m_ddpfZBuffer, sizeof(DDPIXELFORMAT) );
if( dwFlags & D3DFW_STENCILBUFFER )
m_ddpfZBuffer.dwFlags = DDPF_ZBUFFER | DDPF_STENCILBUFFER;
else
m_ddpfZBuffer.dwFlags = DDPF_ZBUFFER;
// Get an appropiate pixel format from enumeration of the formats.
m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
(VOID*)&m_ddpfZBuffer );
if( sizeof(DDPIXELFORMAT) != m_ddpfZBuffer.dwSize )
{
DEBUG_MSG( TEXT("Device doesn't support requested zbuffer format") );
return D3DFWERR_NOZBUFFER;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CreateBuffers()
// Desc: Creates the primary and (optional) backbuffer for rendering.
// Windowed mode and fullscreen mode are handled differently.
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::CreateBuffers( DDSURFACEDESC2* pddsd, DWORD dwFlags )
{
HRESULT hr;
if( dwFlags & D3DFW_FULLSCREEN )
{
// Get the dimensions of the viewport and screen bounds
// Store the rectangle which contains the renderer
SetRect( &m_rcViewportRect, 0, 0, pddsd->dwWidth, pddsd->dwHeight );
memcpy( &m_rcScreenRect, &m_rcViewportRect, sizeof(RECT) );
m_dwRenderWidth = m_rcViewportRect.right;
m_dwRenderHeight = m_rcViewportRect.bottom;
// Set the display mode to the requested dimensions. Check for
// 320x200x8 modes, and set flag to avoid using ModeX
DWORD dwModeFlags = 0;
if( (320==m_dwRenderWidth) && (200==m_dwRenderHeight) &&
(8==pddsd->ddpfPixelFormat.dwRGBBitCount) )
dwModeFlags |= DDSDM_STANDARDVGAMODE;
if( FAILED( m_pDD->SetDisplayMode( m_dwRenderWidth, m_dwRenderHeight,
pddsd->ddpfPixelFormat.dwRGBBitCount,
pddsd->dwRefreshRate, dwModeFlags ) ) )
{
DEBUG_MSG( TEXT("Can't set display mode") );
return D3DFWERR_BADDISPLAYMODE;
}
// Create the primary surface
DDSURFACEDESC2 ddsd;
D3DUtil_InitSurfaceDesc( ddsd, DDSD_CAPS );
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
// With no backbuffer, the primary becomes the render target
if( dwFlags & D3DFW_BACKBUFFER )
{
ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
}
if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
{
DEBUG_MSG( TEXT("Error: Can't create primary surface") );
if( hr != DDERR_OUTOFVIDEOMEMORY )
return D3DFWERR_NOPRIMARY;
DEBUG_MSG( TEXT("Error: Out of video memory") );
return DDERR_OUTOFVIDEOMEMORY;
}
// Get the backbuffer. For fullscreen mode, the backbuffer was created
// along with the primary, but windowed mode still needs to create one.
if( dwFlags & D3DFW_BACKBUFFER )
{
// Get a ptr to the back buffer, which will be our render target
DDSCAPS2 ddscaps;
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps,
&m_pddsBackBuffer ) ) )
{
DEBUG_MSG( TEXT("Error: Can't get/create the backbuffer") );
if( hr != DDERR_OUTOFVIDEOMEMORY )
return D3DFWERR_NOBACKBUFFER;
DEBUG_MSG( TEXT("Error: Out of video memory") );
return DDERR_OUTOFVIDEOMEMORY;
}
}
}
else // Set up buffers for windowed rendering
{
// Get the dimensions of the viewport and screen bounds
GetClientRect( m_hWnd, &m_rcViewportRect );
GetClientRect( m_hWnd, &m_rcScreenRect );
ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.left );
ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.right );
m_dwRenderWidth = m_rcViewportRect.right;
m_dwRenderHeight = m_rcViewportRect.bottom;
// Create the primary surface
DDSURFACEDESC2 ddsd;
D3DUtil_InitSurfaceDesc( ddsd, DDSD_CAPS );
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
// With no backbuffer, the primary becomes the render target
if( 0L == ( dwFlags & D3DFW_BACKBUFFER ) )
ddsd.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
{
DEBUG_MSG( TEXT("Error: Can't create primary surface") );
if( hr != DDERR_OUTOFVIDEOMEMORY )
return D3DFWERR_NOPRIMARY;
DEBUG_MSG( TEXT("Error: Out of video memory") );
return DDERR_OUTOFVIDEOMEMORY;
}
// If in windowed-mode, create a clipper object
LPDIRECTDRAWCLIPPER pcClipper;
if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) )
{
DEBUG_MSG( TEXT("Error: Couldn't create clipper") );
return D3DFWERR_NOCLIPPER;
}
// Associate the clipper with the window
pcClipper->SetHWnd( 0, m_hWnd );
m_pddsFrontBuffer->SetClipper( pcClipper );
SAFE_RELEASE( pcClipper );
// Get the backbuffer. For fullscreen mode, the backbuffer was created
// along with the primary, but windowed mode still needs to create one.
if( dwFlags & D3DFW_BACKBUFFER )
{
// Create the back buffer (the render target)
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
ddsd.dwWidth = m_dwRenderWidth;
ddsd.dwHeight = m_dwRenderHeight;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) )
{
DEBUG_MSG( TEXT("Error: Couldn't create the backbuffer") );
if( hr != DDERR_OUTOFVIDEOMEMORY )
return D3DFWERR_NOBACKBUFFER;
DEBUG_MSG( TEXT("Error: Out of video memory") );
return DDERR_OUTOFVIDEOMEMORY;
}
}
else // For rendering without a backbuffer
{
ClientToScreen( m_hWnd, (POINT*)&m_rcViewportRect.left );
ClientToScreen( m_hWnd, (POINT*)&m_rcViewportRect.right );
}
}
// Set up backbuffer ptr and ref counts
if( dwFlags & D3DFW_BACKBUFFER )
m_pddsRenderTarget = m_pddsBackBuffer;
else
m_pddsRenderTarget = m_pddsFrontBuffer;
m_pddsRenderTarget->AddRef();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CreateZBuffer()
// Desc: Internal function called by Create() to make and attach a zbuffer
// to the renderer
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::CreateZBuffer()
{
HRESULT hr;
// Check if the device supports z-bufferless hidden surface removal. If so,
// we don't really need a z-buffer
DWORD dwRasterCaps = m_ddDeviceDesc.dpcTriCaps.dwRasterCaps;
if( dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )
return S_OK;
// Get z-buffer dimensions from the render target
// Setup the surface desc for the z-buffer.
DDSURFACEDESC2 ddsd;
D3DUtil_InitSurfaceDesc( ddsd, DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS |
DDSD_PIXELFORMAT );
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | m_dwDeviceMemType;
ddsd.dwWidth = m_dwRenderWidth;
ddsd.dwHeight = m_dwRenderHeight;
memcpy( &ddsd.ddpfPixelFormat, &m_ddpfZBuffer, sizeof(DDPIXELFORMAT) );
// Create and attach a z-buffer
if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsZBuffer, NULL ) ) )
{
DEBUG_MSG( TEXT("Error: Couldn't create a ZBuffer surface") );
if( hr != DDERR_OUTOFVIDEOMEMORY )
return D3DFWERR_NOZBUFFER;
DEBUG_MSG( TEXT("Error: Out of video memory") );
return DDERR_OUTOFVIDEOMEMORY;
}
if( FAILED( m_pddsRenderTarget->AddAttachedSurface( m_pddsZBuffer ) ) )
{
DEBUG_MSG( TEXT("Error: Couldn't attach zbuffer to render surface") );
return D3DFWERR_NOZBUFFER;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Create3DDevice()
// Desc: Creates the 3D device for the render target
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::Create3DDevice( GUID* pDeviceGUID )
{
// Check that we are NOT in a palettized display. That case will fail,
// since the framework doesn't use palettes.
DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(DDSURFACEDESC2);
m_pDD->GetDisplayMode( &ddsd );
if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 )
return D3DFWERR_INVALIDMODE;
// Create the device
if( FAILED( m_pD3D->CreateDevice( *pDeviceGUID, m_pddsRenderTarget,
&m_pd3dDevice, NULL ) ) )
{
DEBUG_MSG( TEXT("Couldn't create the D3DDevice") );
return D3DFWERR_NO3DDEVICE;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CreateViewport()
// Desc: Create the D3D viewport used by the renderer.
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::CreateViewport()
{
// Set up the viewport data parameters
HRESULT hr;
D3DVIEWPORT2 vdData;
D3DUtil_InitViewport( vdData, m_dwRenderWidth, m_dwRenderHeight );
// Create the viewport
if( FAILED( m_pD3D->CreateViewport( &m_pvViewport, NULL ) ) )
{
DEBUG_MSG( TEXT("Error: Couldn't create a viewport") );
return D3DFWERR_NOVIEWPORT;
}
// Associate the viewport with the D3DDEVICE object
if( FAILED( hr = m_pd3dDevice->AddViewport( m_pvViewport ) ) )
{
DEBUG_MSG( TEXT("Error: Couldn't add the viewport") );
return D3DFWERR_NOVIEWPORT;
}
// Set the parameters to the new viewport
if( FAILED( m_pvViewport->SetViewport2( &vdData ) ) )
{
DEBUG_MSG( TEXT("Error: Couldn't set the viewport data") );
return D3DFWERR_NOVIEWPORT;
}
// Finally, set the current viewport for the current device
if( FAILED( m_pd3dDevice->SetCurrentViewport( m_pvViewport ) ) )
{
DEBUG_MSG( TEXT("Error: Couldn't set current viewport to device") );
return D3DFWERR_NOVIEWPORT;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: ShowFrame()
// Desc: Show the frame on the primary surface, via a blt or a flip.
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::ShowFrame()
{
if( NULL == m_pddsFrontBuffer )
return D3DFWERR_NOTINITIALIZED;
// Check for a backbuffer. If no backbuffer exists, then we have nothing to
// do. However, to be consistent let's check for lost surfaces
if( NULL == m_pddsBackBuffer )
return m_pddsFrontBuffer->IsLost();
// If we are in fullscreen mode perform a flip.
if( m_bIsFullscreen )
return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT );
// Else, we are in windowed mode, so perform a blit.
return m_pddsFrontBuffer->Blt( &m_rcScreenRect, m_pddsBackBuffer,
&m_rcViewportRect, DDBLT_WAIT, NULL );
}
//-----------------------------------------------------------------------------
// Name: FlipToGDISurface()
// Desc: Puts the GDI surface in front of the primary, so that dialog
// boxes and other windows drawing funcs may happen.
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::FlipToGDISurface( BOOL bDrawFrame )
{
if( m_pDD && m_bIsFullscreen )
{
m_pDD->FlipToGDISurface();
if( bDrawFrame )
{
DrawMenuBar( m_hWnd );
RedrawWindow( m_hWnd, NULL, NULL, RDW_FRAME );
}
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: RestoreSurfaces()
// Desc: Checks for lost surfaces and restores them if lost. Note: Don't
// restore render surface, since it's just a duplicate ptr.
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::RestoreSurfaces()
{
// Check/restore the primary surface
if( m_pddsFrontBuffer )
if( m_pddsFrontBuffer->IsLost() )
m_pddsFrontBuffer->Restore();
// Check/restore the back buffer
if( m_pddsBackBuffer )
if( m_pddsBackBuffer->IsLost() )
m_pddsBackBuffer->Restore();
// Check/restore the z-buffer surface
if( m_pddsZBuffer )
if( m_pddsZBuffer->IsLost() )
m_pddsZBuffer->Restore();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Move()
// Desc: Moves the screen rect for windowed renderers
//-----------------------------------------------------------------------------
VOID CD3DFramework::Move( INT x, INT y )
{
if( FALSE == m_bIsFullscreen )
{
SetRect( &m_rcScreenRect, x, y,
x + m_dwRenderWidth, y + m_dwRenderHeight );
// If we have no backbuffer, then update viewport rect as well
if( NULL == m_pddsBackBuffer )
CopyMemory( &m_rcViewportRect, &m_rcScreenRect, sizeof(RECT) );
}
}
//-----------------------------------------------------------------------------
// Name: ChangeRenderTarget()
// Desc: Wrapper for the IDirect3DDevice::SetRenderTarget() function, which
// adds functionality to handle an attached z-buffer. Note that this
// function does NOT alter the current viewport
//-----------------------------------------------------------------------------
HRESULT CD3DFramework::ChangeRenderTarget( LPDIRECTDRAWSURFACE4 pddsNewTarget )
{
if( NULL == pddsNewTarget )
return E_INVALIDARG;
// Get the new render target dimensions
DDSURFACEDESC2 ddsd;
D3DUtil_InitSurfaceDesc( ddsd );
pddsNewTarget->GetSurfaceDesc( &ddsd );
m_dwRenderWidth = ddsd.dwWidth;
m_dwRenderHeight = ddsd.dwHeight;
// If a z-buffer is attached, delete and recreate it
if( NULL != m_pddsZBuffer )
{
// Remove the old z-buffer
m_pddsRenderTarget->DeleteAttachedSurface( 0, m_pddsZBuffer );
SAFE_RELEASE( m_pddsZBuffer );
// Keep track of reference counts
SAFE_RELEASE( m_pddsRenderTarget );
m_pddsRenderTarget = pddsNewTarget;
m_pddsRenderTarget->AddRef();
// Create the new z-buffer
if( FAILED( CreateZBuffer() ) )
{
DEBUG_MSG( TEXT("ChangeRenderTarget() - zbuffer create failed") );
return D3DFWERR_NOZBUFFER;
}
}
else
{
// With no z-buffer, we just do accounting on the reference counts
SAFE_RELEASE( m_pddsRenderTarget );
m_pddsRenderTarget = pddsNewTarget;
m_pddsRenderTarget->AddRef();
}
// Finally, perform the set render target call
if( FAILED( m_pd3dDevice->SetRenderTarget( m_pddsRenderTarget, 0 ) ) )
{
return D3DFWERR_NORENDERTARGET;
}
return S_OK;
}

135
MuckyBasic/d3dframe.h Normal file
View File

@ -0,0 +1,135 @@
//-----------------------------------------------------------------------------
// File: D3DFrame.h
//
// Desc: Class to manage the Direct3D environment objects such as buffers,
// viewports, and 3D devices.
//
// The class is initialized with the Initialize() function, after which
// the Get????() functions can be used to access the objects needed for
// rendering. If the device or display needs to be changed, the
// ChangeDevice() function can be called. If the display window is moved
// the changes need to be reported with the Move() function.
//
// After rendering a frame, the ShowFrame() function filps or blits the
// backbuffer contents to the primary. If surfaces are lost, they can be
// restored with the RestoreSurfaces() function. Finally, if normal
// Windows output is needed, the FlipToGDISurface() provides a GDI
// surface to draw on.
//
//
// Copyright (C) 1997 Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
#ifndef D3DFRAME_H
#define D3DFRAME_H
#include <ddraw.h>
#include <d3d.h>
//-----------------------------------------------------------------------------
// Name: CD3DFramework
// Desc: The Direct3D sample framework class. Maintains the D3D surfaces,
// device, and viewport used for 3D rendering.
//-----------------------------------------------------------------------------
class CD3DFramework
{
// Internal variables for the framework class
HWND m_hWnd; // The window object
BOOL m_bIsFullscreen; // Fullscreen vs. windowed
DWORD m_dwRenderWidth; // Dimensions of the render target
DWORD m_dwRenderHeight;
RECT m_rcScreenRect; // Screen rect for window
RECT m_rcViewportRect; // Offscreen rect for VPort
LPDIRECTDRAWSURFACE4 m_pddsFrontBuffer; // The primary surface
LPDIRECTDRAWSURFACE4 m_pddsBackBuffer; // The backbuffer surface
LPDIRECTDRAWSURFACE4 m_pddsRenderTarget; // The render target surface
LPDIRECTDRAWSURFACE4 m_pddsZBuffer; // The zbuffer surface
LPDIRECT3DDEVICE3 m_pd3dDevice; // The D3D device
LPDIRECT3DVIEWPORT3 m_pvViewport; // The D3D viewport
LPDIRECTDRAW4 m_pDD; // The DirectDraw object
LPDIRECT3D3 m_pD3D; // The Direct3D object
D3DDEVICEDESC m_ddDeviceDesc;
DWORD m_dwDeviceMemType;
DDPIXELFORMAT m_ddpfZBuffer; // Enumerated zbuffer format
// Internal functions for the framework class
HRESULT CreateViewport();
HRESULT Create3DDevice( GUID* );
HRESULT CreateZBuffer();
HRESULT CreateBuffers( DDSURFACEDESC2*, DWORD );
HRESULT CreateDirectDraw( GUID*, DWORD );
HRESULT CreateDirect3D( GUID*, DWORD );
HRESULT CreateEnvironment( GUID*, GUID*, DDSURFACEDESC2*, DWORD );
public:
// Access functions for DirectX objects
LPDIRECTDRAW4 GetDirectDraw() { return m_pDD; }
LPDIRECT3D3 GetDirect3D() { return m_pD3D; }
LPDIRECT3DDEVICE3 GetD3DDevice() { return m_pd3dDevice; }
LPDIRECT3DVIEWPORT3 GetViewport() { return m_pvViewport; }
LPDIRECTDRAWSURFACE4 GetFrontBuffer() { return m_pddsFrontBuffer; }
LPDIRECTDRAWSURFACE4 GetBackBuffer() { return m_pddsBackBuffer; }
LPDIRECTDRAWSURFACE4 GetRenderSurface() { return m_pddsRenderTarget; }
// Functions to aid rendering
HRESULT RestoreSurfaces();
HRESULT ShowFrame();
HRESULT FlipToGDISurface( BOOL bDrawFrame );
// Functions for managing screen and viewport bounds
BOOL IsFullscreen() { return m_bIsFullscreen; }
RECT* GetViewportRect() { return &m_rcViewportRect; }
VOID Move( INT x, INT y );
// Functions to support sprite-based rendering
HRESULT ChangeRenderTarget( LPDIRECTDRAWSURFACE4 pddsNewTarget );
// Creates the Framework
HRESULT Initialize( HWND hWnd, GUID* pDriverGUID, GUID* pDeviceGUID,
DDSURFACEDESC2* pddsd, DWORD dwFlags );
HRESULT DestroyObjects();
CD3DFramework();
~CD3DFramework();
};
//-----------------------------------------------------------------------------
// Flags used for the Initialize() method of a CD3DFramework object
//-----------------------------------------------------------------------------
#define D3DFW_FULLSCREEN 0x00000001 // Use fullscreen mode
#define D3DFW_BACKBUFFER 0x00000002 // Create and use a backbuffer
#define D3DFW_ZBUFFER 0x00000004 // Create and use a zbuffer
#define D3DFW_STENCILBUFFER 0x00000008 // Use a z-buffer w/stenciling
#define D3DFW_NO_FPUSETUP 0x00000010 // Don't use default DDSCL_FPUSETUP flag
//-----------------------------------------------------------------------------
// Errors that the Initialize() and ChangeDriver() calls may return
//-----------------------------------------------------------------------------
#define D3DFWERR_INITIALIZATIONFAILED 0x82000000
#define D3DFWERR_NODIRECTDRAW 0x82000001
#define D3DFWERR_COULDNTSETCOOPLEVEL 0x82000002
#define D3DFWERR_NODIRECT3D 0x82000003
#define D3DFWERR_NO3DDEVICE 0x82000004
#define D3DFWERR_NOZBUFFER 0x82000005
#define D3DFWERR_NOVIEWPORT 0x82000006
#define D3DFWERR_NOPRIMARY 0x82000007
#define D3DFWERR_NOCLIPPER 0x82000008
#define D3DFWERR_BADDISPLAYMODE 0x82000009
#define D3DFWERR_NOBACKBUFFER 0x8200000a
#define D3DFWERR_NONZEROREFCOUNT 0x8200000b
#define D3DFWERR_NORENDERTARGET 0x8200000c
#define D3DFWERR_INVALIDMODE 0x8200000d
#define D3DFWERR_NOTINITIALIZED 0x8200000e
#endif // D3DFRAME_H

394
MuckyBasic/d3dutil.cpp Normal file
View File

@ -0,0 +1,394 @@
//-----------------------------------------------------------------------------
// File: D3DUtil.cpp
//
// Desc: Shortcut macros and functions for using DX objects
//
//
// Copyright (c) 1997-1998 Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
#define D3D_OVERLOADS
#define STRICT
#include <math.h>
#include <stdio.h>
#include "D3DUtil.h"
//-----------------------------------------------------------------------------
// Name: D3DUtil_InitDeviceDesc()
// Desc: Helper function called to initialize a D3DDEVICEDESC structure,
//-----------------------------------------------------------------------------
VOID D3DUtil_InitDeviceDesc( D3DDEVICEDESC& ddDevDesc )
{
ZeroMemory( &ddDevDesc, sizeof(D3DDEVICEDESC) );
ddDevDesc.dwSize = sizeof(D3DDEVICEDESC);
ddDevDesc.dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
ddDevDesc.dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
ddDevDesc.dpcLineCaps.dwSize = sizeof(D3DPRIMCAPS);
ddDevDesc.dpcTriCaps.dwSize = sizeof(D3DPRIMCAPS);
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_InitSurfaceDesc()
// Desc: Helper function called to build a DDSURFACEDESC2 structure,
// typically before calling CreateSurface() or GetSurfaceDesc()
//-----------------------------------------------------------------------------
VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags,
DWORD dwCaps )
{
ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddsd.dwFlags = dwFlags;
ddsd.ddsCaps.dwCaps = dwCaps;
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_InitViewport()
// Desc: Helper function called to build a D3DVIEWPORT3 structure
//-----------------------------------------------------------------------------
VOID D3DUtil_InitViewport( D3DVIEWPORT2& vp, DWORD dwWidth, DWORD dwHeight )
{
ZeroMemory( &vp, sizeof(D3DVIEWPORT2) );
vp.dwSize = sizeof(D3DVIEWPORT2);
vp.dwX = 0;
vp.dwY = 0;
vp.dwWidth = dwWidth;
vp.dwHeight = dwHeight;
vp.dvMaxZ = 1.0f;
vp.dvClipX = -1.0f;
vp.dvClipWidth = 2.0f;
vp.dvClipY = 1.0f;
vp.dvClipHeight = 2.0f;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_InitMaterial()
// Desc: Helper function called to build a D3DMATERIAL structure
//-----------------------------------------------------------------------------
VOID D3DUtil_InitMaterial( D3DMATERIAL& mtrl, FLOAT r, FLOAT g, FLOAT b )
{
ZeroMemory( &mtrl, sizeof(D3DMATERIAL) );
mtrl.dwSize = sizeof(D3DMATERIAL);
mtrl.dcvDiffuse.r = mtrl.dcvAmbient.r = r;
mtrl.dcvDiffuse.g = mtrl.dcvAmbient.g = g;
mtrl.dcvDiffuse.b = mtrl.dcvAmbient.b = b;
mtrl.dwRampSize = 16L; // A default ramp size
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_InitLight()
// Desc: Initializes a D3DLIGHT structure
//-----------------------------------------------------------------------------
VOID D3DUtil_InitLight( D3DLIGHT& light, D3DLIGHTTYPE ltType,
FLOAT x, FLOAT y, FLOAT z )
{
ZeroMemory( &light, sizeof(D3DLIGHT) );
light.dwSize = sizeof(D3DLIGHT);
light.dltType = ltType;
light.dcvColor.r = 1.0f;
light.dcvColor.g = 1.0f;
light.dcvColor.b = 1.0f;
light.dvPosition.x = light.dvDirection.x = x;
light.dvPosition.y = light.dvDirection.y = y;
light.dvPosition.z = light.dvDirection.z = z;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_GetDirectDrawFromDevice()
// Desc: Get the DDraw interface from a D3DDevice.
//-----------------------------------------------------------------------------
LPDIRECTDRAW4 D3DUtil_GetDirectDrawFromDevice( LPDIRECT3DDEVICE3 pd3dDevice )
{
LPDIRECTDRAW4 pDD = NULL;
LPDIRECTDRAWSURFACE4 pddsRender;
if( pd3dDevice )
{
// Get the current render target
if( SUCCEEDED( pd3dDevice->GetRenderTarget( &pddsRender ) ) )
{
// Get the DDraw4 interface from the render target
pddsRender->GetDDInterface( (VOID**)&pDD );
pddsRender->Release();
}
}
return pDD;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_GetDeviceMemoryType()
// Desc: Retreives the default memory type used for the device.
//-----------------------------------------------------------------------------
DWORD D3DUtil_GetDeviceMemoryType( LPDIRECT3DDEVICE3 pd3dDevice )
{
D3DDEVICEDESC ddHwDesc, ddSwDesc;
ddHwDesc.dwSize = sizeof(D3DDEVICEDESC);
ddSwDesc.dwSize = sizeof(D3DDEVICEDESC);
if( FAILED( pd3dDevice->GetCaps( &ddHwDesc, &ddSwDesc ) ) )
return 0L;
if( ddHwDesc.dwFlags )
return DDSCAPS_VIDEOMEMORY;
return DDSCAPS_SYSTEMMEMORY;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetViewMatrix()
// Desc: Given an eye point, a lookat point, and an up vector, this
// function builds a 4x4 view matrix.
//-----------------------------------------------------------------------------
HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
D3DVECTOR& vAt, D3DVECTOR& vWorldUp )
{
// Get the z basis vector, which points straight ahead. This is the
// difference from the eyepoint to the lookat point.
D3DVECTOR vView = vAt - vFrom;
FLOAT fLength = Magnitude( vView );
if( fLength < 1e-6f )
return E_INVALIDARG;
// Normalize the z basis vector
vView /= fLength;
// Get the dot product, and calculate the projection of the z basis
// vector onto the up vector. The projection is the y basis vector.
FLOAT fDotProduct = DotProduct( vWorldUp, vView );
D3DVECTOR vUp = vWorldUp - fDotProduct * vView;
// If this vector has near-zero length because the input specified a
// bogus up vector, let's try a default up vector
if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
{
vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView;
// If we still have near-zero length, resort to a different axis.
if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
{
vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView;
if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
return E_INVALIDARG;
}
}
// Normalize the y basis vector
vUp /= fLength;
// The x basis vector is found simply with the cross product of the y
// and z basis vectors
D3DVECTOR vRight = CrossProduct( vUp, vView );
// Start building the matrix. The first three rows contains the basis
// vectors used to rotate the view to point at the lookat point
D3DUtil_SetIdentityMatrix( mat );
mat._11 = vRight.x; mat._12 = vUp.x; mat._13 = vView.x;
mat._21 = vRight.y; mat._22 = vUp.y; mat._23 = vView.y;
mat._31 = vRight.z; mat._32 = vUp.z; mat._33 = vView.z;
// Do the translation values (rotations are still about the eyepoint)
mat._41 = - DotProduct( vFrom, vRight );
mat._42 = - DotProduct( vFrom, vUp );
mat._43 = - DotProduct( vFrom, vView );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetProjectionMatrix()
// Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built
// from the field-of-view (fov, in y), aspect ratio, near plane (D),
// and far plane (F). Note that the projection matrix is normalized for
// element [3][4] to be 1.0. This is performed so that W-based range fog
// will work correctly.
//-----------------------------------------------------------------------------
HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV, FLOAT fAspect,
FLOAT fNearPlane, FLOAT fFarPlane )
{
if( fabs(fFarPlane-fNearPlane) < 0.01f )
return E_INVALIDARG;
if( fabs(sin(fFOV/2)) < 0.01f )
return E_INVALIDARG;
FLOAT w = fAspect * (FLOAT)( cos(fFOV/2)/sin(fFOV/2) );
FLOAT h = 1.0f * (FLOAT)( cos(fFOV/2)/sin(fFOV/2) );
FLOAT Q = fFarPlane / ( fFarPlane - fNearPlane );
ZeroMemory( &mat, sizeof(D3DMATRIX) );
mat._11 = w;
mat._22 = h;
mat._33 = Q;
mat._34 = 1.0f;
mat._43 = -Q*fNearPlane;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotateXMatrix()
// Desc: Create Rotation matrix about X axis
//-----------------------------------------------------------------------------
VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads )
{
D3DUtil_SetIdentityMatrix( mat );
mat._22 = (FLOAT)cos( fRads );
mat._23 = (FLOAT)sin( fRads );
mat._32 = -(FLOAT)sin( fRads );
mat._33 = (FLOAT)cos( fRads );
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotateYMatrix()
// Desc: Create Rotation matrix about Y axis
//-----------------------------------------------------------------------------
VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads )
{
D3DUtil_SetIdentityMatrix( mat );
mat._11 = (FLOAT)cos( fRads );
mat._13 = -(FLOAT)sin( fRads );
mat._31 = (FLOAT)sin( fRads );
mat._33 = (FLOAT)cos( fRads );
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotateZMatrix()
// Desc: Create Rotation matrix about Z axis
//-----------------------------------------------------------------------------
VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads )
{
D3DUtil_SetIdentityMatrix( mat );
mat._11 = (FLOAT)cos( fRads );
mat._12 = (FLOAT)sin( fRads );
mat._21 = -(FLOAT)sin( fRads );
mat._22 = (FLOAT)cos( fRads );
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotationMatrix
// Desc: Create a Rotation matrix about vector direction
//-----------------------------------------------------------------------------
VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, FLOAT fRads )
{
FLOAT fCos = (FLOAT)cos( fRads );
FLOAT fSin = (FLOAT)sin( fRads );
D3DVECTOR v = Normalize( vDir );
mat._11 = ( v.x * v.x ) * ( 1.0f - fCos ) + fCos;
mat._12 = ( v.x * v.y ) * ( 1.0f - fCos ) - (v.z * fSin);
mat._13 = ( v.x * v.z ) * ( 1.0f - fCos ) + (v.y * fSin);
mat._21 = ( v.y * v.x ) * ( 1.0f - fCos ) + (v.z * fSin);
mat._22 = ( v.y * v.y ) * ( 1.0f - fCos ) + fCos ;
mat._23 = ( v.y * v.z ) * ( 1.0f - fCos ) - (v.x * fSin);
mat._31 = ( v.z * v.x ) * ( 1.0f - fCos ) - (v.y * fSin);
mat._32 = ( v.z * v.y ) * ( 1.0f - fCos ) + (v.x * fSin);
mat._33 = ( v.z * v.z ) * ( 1.0f - fCos ) + fCos;
mat._14 = mat._24 = mat._34 = 0.0f;
mat._41 = mat._42 = mat._43 = 0.0f;
mat._44 = 1.0f;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_GetDisplayDepth()
// Desc: Returns the depth of the current display mode.
//-----------------------------------------------------------------------------
DWORD D3DUtil_GetDisplayDepth( LPDIRECTDRAW4 pDD4 )
{
// If the caller did not supply a DDraw object, just create a temp one.
if( NULL == pDD4 )
{
LPDIRECTDRAW pDD1;
if( FAILED( DirectDrawCreate( NULL, &pDD1, NULL ) ) )
return 0L;
HRESULT hr = pDD1->QueryInterface( IID_IDirectDraw4, (VOID**)&pDD4 );
pDD1->Release();
if( FAILED(hr) )
return 0L;
}
else
pDD4->AddRef();
// Get the display mode description
DDSURFACEDESC2 ddsd;
ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
pDD4->GetDisplayMode( &ddsd );
pDD4->Release();
// Return the display mode's depth
return ddsd.ddpfPixelFormat.dwRGBBitCount;
}
//-----------------------------------------------------------------------------
// Name: _DbgOut()
// Desc: Outputs a message to the debug stream
//-----------------------------------------------------------------------------
HRESULT _DbgOut( TCHAR* strFile, DWORD dwLine, HRESULT hr, TCHAR* strMsg )
{
TCHAR buffer[256];
sprintf( buffer, "%s(%ld): ", strFile, dwLine );
OutputDebugString( buffer );
OutputDebugString( strMsg );
if( hr )
{
sprintf( buffer, "(hr=%08lx)\n", hr );
OutputDebugString( buffer );
}
OutputDebugString( "\n" );
return hr;
}

110
MuckyBasic/d3dutil.h Normal file
View File

@ -0,0 +1,110 @@
//-----------------------------------------------------------------------------
// File: D3DUtil.h
//
// Desc: Helper functions and typing shortcuts for Direct3D programming.
//
//
// Copyright (C) 1997 Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
#ifndef D3DUTIL_H
#define D3DUTIL_H
#include <ddraw.h>
#include <d3d.h>
//-----------------------------------------------------------------------------
// Typing shortcuts for deleting and freeing objects.
//-----------------------------------------------------------------------------
#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
//-----------------------------------------------------------------------------
// Short cut functions for creating and using DX structures
//-----------------------------------------------------------------------------
VOID D3DUtil_InitDeviceDesc( D3DDEVICEDESC& ddDevDesc );
VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags=0,
DWORD dwCaps=0 );
VOID D3DUtil_InitViewport( D3DVIEWPORT2& vdViewData, DWORD dwWidth=0,
DWORD dwHeight=0 );
VOID D3DUtil_InitMaterial( D3DMATERIAL& mdMtrlData, FLOAT r=0.0f, FLOAT g=0.0f,
FLOAT b=0.0f );
VOID D3DUtil_InitLight( D3DLIGHT& ldLightData, D3DLIGHTTYPE ltType,
FLOAT x=0.0f, FLOAT y=0.0f, FLOAT z=0.0f );
//-----------------------------------------------------------------------------
// Miscellaneous helper functions
//-----------------------------------------------------------------------------
LPDIRECTDRAW4 D3DUtil_GetDirectDrawFromDevice( LPDIRECT3DDEVICE3 pd3dDevice );
DWORD D3DUtil_GetDeviceMemoryType( LPDIRECT3DDEVICE3 pd3dDevice );
DWORD D3DUtil_GetDisplayDepth( LPDIRECTDRAW4 pDD4=NULL );
//-----------------------------------------------------------------------------
// D3D Matrix functions. For performance reasons, some functions are inline.
//-----------------------------------------------------------------------------
HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
D3DVECTOR& vAt, D3DVECTOR& vUp );
HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV = 1.570795f,
FLOAT fAspect = 1.0f,
FLOAT fNearPlane = 1.0f,
FLOAT fFarPlane = 1000.0f );
inline VOID D3DUtil_SetIdentityMatrix( D3DMATRIX& m )
{
m._12 = m._13 = m._14 = m._21 = m._23 = m._24 = 0.0f;
m._31 = m._32 = m._34 = m._41 = m._42 = m._43 = 0.0f;
m._11 = m._22 = m._33 = m._44 = 1.0f;
}
inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, FLOAT tx, FLOAT ty,
FLOAT tz )
{ D3DUtil_SetIdentityMatrix( m ); m._41 = tx; m._42 = ty; m._43 = tz; }
inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, D3DVECTOR& v )
{ D3DUtil_SetTranslateMatrix( m, v.x, v.y, v.z ); }
inline VOID D3DUtil_SetScaleMatrix( D3DMATRIX& m, FLOAT sx, FLOAT sy,
FLOAT sz )
{ D3DUtil_SetIdentityMatrix( m ); m._11 = sx; m._22 = sy; m._33 = sz; }
inline VOID SetScaleMatrix( D3DMATRIX& m, D3DVECTOR& v )
{ D3DUtil_SetScaleMatrix( m, v.x, v.y, v.z ); }
VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads );
VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads );
VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads );
VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir,
FLOAT fRads );
//-----------------------------------------------------------------------------
// Debug printing support
//-----------------------------------------------------------------------------
HRESULT _DbgOut( TCHAR*, DWORD, HRESULT, TCHAR* );
#if defined(DEBUG) | defined(_DEBUG)
#define DEBUG_MSG(str) _DbgOut( __FILE__, (DWORD)__LINE__, 0, str )
#define DEBUG_ERR(hr,str) _DbgOut( __FILE__, (DWORD)__LINE__, hr, str )
#else
#define DEBUG_MSG(str) (0L)
#define DEBUG_ERR(hr,str) (hr)
#endif
#endif // D3DUTIL_H

480
MuckyBasic/font.cpp Normal file
View File

@ -0,0 +1,480 @@
//
// A font! That's all there is to it.
//
#include "always.h"
#include "font.h"
#include "os.h"
#include "tga.h"
//
// Each of the letters
//
typedef struct
{
float u;
float v;
float uwidth;
} FONT_Letter;
#define FONT_LETTER_HEIGHT 20
#define FONT_LOWERCASE 0
#define FONT_UPPERCASE 26
#define FONT_NUMBERS 52
#define FONT_PUNCT_PLING 62
#define FONT_PUNCT_DQUOTE 63
#define FONT_PUNCT_POUND 64
#define FONT_PUNCT_DOLLAR 65
#define FONT_PUNCT_PERCENT 66
#define FONT_PUNCT_POWER 67
#define FONT_PUNCT_AMPERSAND 68
#define FONT_PUNCT_ASTERISK 69
#define FONT_PUNCT_OPEN 70
#define FONT_PUNCT_CLOSE 71
#define FONT_PUNCT_COPEN 72
#define FONT_PUNCT_CCLOSE 73
#define FONT_PUNCT_SOPEN 74
#define FONT_PUNCT_SCLOSE 75
#define FONT_PUNCT_LT 76
#define FONT_PUNCT_GT 77
#define FONT_PUNCT_BSLASH 78
#define FONT_PUNCT_FSLASH 79
#define FONT_PUNCT_SEMICOLON 80
#define FONT_PUNCT_COLON 81
#define FONT_PUNCT_QUOTE 82
#define FONT_PUNCT_AT 83
#define FONT_PUNCT_HASH 84
#define FONT_PUNCT_TILDE 85
#define FONT_PUNCT_QMARK 86
#define FONT_PUNCT_MINUS 87
#define FONT_PUNCT_EQUALS 88
#define FONT_PUNCT_PLUS 89
#define FONT_PUNCT_DOT 90
#define FONT_PUNCT_COMMA 91
#define FONT_PUNCT_UNDERSCORE 92
#define FONT_NUM_FOREIGN 66
#define FONT_NUM_LETTERS (93 + FONT_NUM_FOREIGN)
FONT_Letter FONT_letter[FONT_NUM_LETTERS];
//
// This is the order the punctuation characters come in.
//
CBYTE FONT_punct[] =
{
"!\"£$%^&*(){}[]<>\\/;:'@#~?-=+.,_"
"©ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüüýþÿ"
};
//
// The texture and another place where we store the font data
// apart from the texture!
//
OS_Texture *FONT_ot;
TGA_Pixel FONT_data[256][256];
//
// Returns TRUE if it finds pixel data at (x,y)
//
SLONG FONT_found_data(SLONG x, SLONG y)
{
SLONG dy;
SLONG px;
SLONG py;
ASSERT(WITHIN(x, 0, 255));
for (dy = -15; dy <= 4; dy++)
{
px = x;
py = y + dy;
if (WITHIN(py, 0, 255))
{
if (FONT_data[py][px].alpha)
{
return TRUE;
}
}
}
return FALSE;
}
void FONT_init()
{
SLONG i;
SLONG y;
SLONG x;
SLONG line;
FONT_Letter *fl;
//
// Load the texture.
//
FONT_ot = OS_texture_create("font_system.tga");
//
// Load in the font bitmap.
//
TGA_Info ti;
ti = TGA_load(
"Textures\\System\\Fonts\\font_system.tga",
256,
256,
&FONT_data[0][0]);
ASSERT(ti.valid);
ASSERT(ti.width == 256);
ASSERT(ti.height == 256);
//
// Work out the position of each of the letters.
//
x = 0;
y = 19;
line = 0;
for (i = 0; i < FONT_NUM_LETTERS; i++)
{
fl = &FONT_letter[i];
//
// Look for the start of the letter.
//
while(!FONT_found_data(x,y))
{
x += 1;
if (x >= 256)
{
x = 0;
line += 1;
y += 22;
if (y > 256)
{
return;
}
}
}
fl->u = float(x);
fl->v = float(y);
//
// Look for the end of the letter.
//
x += 3;
while(FONT_found_data(x,y))
{
x += 1;
}
fl->uwidth = (x - fl->u) * (1.0F / 256.0F);
//
// Convert the (u,v)s
//
fl->u *= 1.0F / 256.0F;
fl->v *= 1.0F / 256.0F;
fl->v -= 16.0F / 256.0F;
}
}
//
// Returns the index of the given character
//
SLONG FONT_get_index(CBYTE chr)
{
SLONG letter;
//
// Find our letter index.
//
if (WITHIN(chr, 'a', 'z'))
{
letter = FONT_LOWERCASE + chr - 'a';
}
else
if (WITHIN(chr, 'A', 'Z'))
{
letter = FONT_UPPERCASE + chr - 'A';
}
else
if (WITHIN(chr, '0', '9'))
{
letter = FONT_NUMBERS + chr - '0';
}
else
{
//
// Look for the punctuation letter.
//
letter = FONT_PUNCT_PLING;
for (CBYTE *ch = FONT_punct; *ch && *ch != chr; ch++, letter++);
}
if (!WITHIN(letter, 0, FONT_NUM_LETTERS - 1))
{
letter = FONT_PUNCT_QMARK;
}
return letter;
}
SLONG FONT_char_is_valid(CBYTE ch)
{
if (FONT_get_index(ch) == FONT_PUNCT_QMARK && ch != '?')
{
return FALSE;
}
else
{
return TRUE;
}
}
float FONT_get_letter_width(CBYTE chr)
{
SLONG letter;
if (chr == ' ')
{
return 8.0F / 256.0F;
}
letter = FONT_get_index(chr);
ASSERT(WITHIN(letter, 0, FONT_NUM_LETTERS - 1));
return FONT_letter[letter].uwidth + (1.0F / 256.0F);
}
float FONT_draw_letter(
OS_Buffer *ob,
CBYTE chr,
float x,
float y,
ULONG colour = 0xffffffff,
ULONG flag = 0,
float scale = 1.0F)
{
SLONG letter;
float width;
FONT_Letter *fl;
if (flag & FONT_FLAG_DROP_SHADOW)
{
FONT_draw_letter(
ob,
chr,
x + 0.008F * scale,
y + 0.008F * scale,
(~colour) | (colour & 0xff000000),
flag & ~FONT_FLAG_DROP_SHADOW,
scale);
}
//
// Space is a special case!
//
if (chr == ' ')
{
width = (8.0F / 256.0F) * scale;
}
else
{
letter = FONT_get_index(chr);
ASSERT(WITHIN(letter, 0, FONT_NUM_LETTERS - 1));
fl = &FONT_letter[letter];
width = fl->uwidth;
OS_buffer_add_sprite(
ob,
x,
y,
x + fl->uwidth * scale,
y + (FONT_LETTER_HEIGHT * 1.33F / 256.0F) * scale,
fl->u,
fl->v,
fl->u + fl->uwidth,
fl->v + (FONT_LETTER_HEIGHT / 256.0F),
0.0F,
colour);
}
return (width + 1.0F / 256.0F) * scale;
}
//
// Returns the width of the given string.
//
float FONT_get_width(CBYTE *str, float scale)
{
float ans = 0.0F;
for (CBYTE *ch = str; *ch; ch++)
{
ans += FONT_get_letter_width(*ch) * scale;
}
return ans;
}
void FONT_draw(float start_x, float start_y, ULONG colour, ULONG flag, float scale, SLONG cursor, CBYTE *fmt, ...)
{
CBYTE message[4096];
va_list ap;
if (fmt == NULL)
{
sprintf(message, "<NULL>");
}
else
{
va_start(ap, fmt);
vsprintf(message, fmt, ap);
va_end (ap);
}
//
// So that a scale of 1.0F is normal size.
//
scale *= 0.26F;
//
// The buffer we use to hold the sprites.
//
OS_Buffer *ob = OS_buffer_new();
//
// Make sure the colour component has alpha- otherwise the
// font will be invisible!
//
colour |= 0xff000000;
float x = start_x;
float y = start_y;
if (flag & FONT_FLAG_JUSTIFY_CENTRE)
{
x -= FONT_get_width(message, scale) * 0.5F;
}
else
if (flag & FONT_FLAG_JUSTIFY_RIGHT)
{
x -= FONT_get_width(message, scale);
}
CBYTE *ch = message;
while(*ch)
{
if (iscntrl(*ch))
{
if (*ch == '\n')
{
x = start_x;
y += (FONT_LETTER_HEIGHT * 1.4F / 256.0F) * scale;
}
}
else
{
if (cursor-- == 0)
{
//
// Draw a cursor here.
//
{
OS_Buffer *ob = OS_buffer_new();
OS_buffer_add_sprite(
ob,
x, y, x + 0.01F * scale, y + (FONT_LETTER_HEIGHT * 1.33F / 256.0F) * scale,
0.0F, 0.0F,
1.0F, 1.0F,
0.0F,
0xeeeeeff);
OS_buffer_draw(ob, NULL, NULL, OS_DRAW_DOUBLESIDED | OS_DRAW_ZALWAYS | OS_DRAW_NOZWRITE);
}
}
x += FONT_draw_letter(ob, *ch, x, y, colour, flag, scale);
}
ch += 1;
}
if (cursor-- == 0)
{
//
// Draw a cursor here.
//
{
OS_Buffer *ob = OS_buffer_new();
OS_buffer_add_sprite(
ob,
x, y, x + 0.01F * scale, y + (FONT_LETTER_HEIGHT * 1.33F / 256.0F) * scale,
0.0F, 0.0F,
1.0F, 1.0F,
0.0F,
0xeeeeeff);
OS_buffer_draw(ob, NULL, NULL, OS_DRAW_DOUBLESIDED | OS_DRAW_ZALWAYS | OS_DRAW_NOZWRITE);
}
}
OS_buffer_draw(ob, FONT_ot, NULL, OS_DRAW_DOUBLESIDED | OS_DRAW_ZALWAYS | OS_DRAW_NOZWRITE | OS_DRAW_ALPHABLEND);
}

37
MuckyBasic/font.h Normal file
View File

@ -0,0 +1,37 @@
//
// A font! That's all there is to it.
//
#ifndef _FONT_
#define _FONT_
//
// Loads in the font texture and calculates the uv's of the letters.
//
void FONT_init(void);
//
// Returns TRUE if the FONT module can draw the ASCII character.
//
SLONG FONT_char_is_valid(CBYTE ch);
//
// Draws some text. A scale of 1.0F is normal! If cursor is >= 0, then a cursor
// draw after the 'cursor'th character.
//
#define FONT_FLAG_JUSTIFY_LEFT (1 << 0)
#define FONT_FLAG_JUSTIFY_CENTRE (1 << 1)
#define FONT_FLAG_JUSTIFY_RIGHT (1 << 2)
#define FONT_FLAG_DROP_SHADOW (1 << 3)
void FONT_draw(float start_x, float start_y, ULONG colour, ULONG flag, float scale, SLONG cursor, CBYTE *fmt, ...);
#endif

BIN
MuckyBasic/icon1.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

820
MuckyBasic/lex.cpp Normal file
View File

@ -0,0 +1,820 @@
//
// A lexical analyser
//
#include "always.h"
#include "lex.h"
//
// The input stream we are analysing.
// The cursor in the stream upto where we have done.
// The current line we are on.
//
CBYTE *LEX_stream_buffer;
CBYTE *LEX_stream_upto;
SLONG LEX_stream_line;
//
// We can push upto one token onto the stack!
//
SLONG LEX_stack_valid;
LEX_Token LEX_stack;
//
// The last token we read.
//
SLONG LEX_top_valid;
LEX_Token LEX_top;
//
// TRUE if the last token found was a NEWLINE
//
SLONG LEX_last_token_newline;
//
// A buffer for returning string constants in.
//
CBYTE LEX_string_buffer[LEX_MAX_STRING_LENGTH + 32];
//
// Eats up the input stream and finds the next token.
//
void LEX_find_next_token(void)
{
SLONG i;
CBYTE *dest;
//
// Initailise the answer.
//
LEX_top_valid = TRUE;
LEX_top.line = LEX_stream_line;
//
// Skip whitespace.
//
while(isspace(*LEX_stream_upto))
{
if (*LEX_stream_upto == '\n')
{
//
// A new line character.
//
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_NEWLINE;
LEX_last_token_newline = TRUE;
return;
}
LEX_stream_upto++;
}
//
// End of the input stream?
//
if (*LEX_stream_upto == '\000')
{
//
// Only return an EOF after a NEWLINE
//
if (LEX_last_token_newline)
{
LEX_top.type = LEX_TOKEN_TYPE_EOF;
}
else
{
LEX_top.type = LEX_TOKEN_TYPE_NEWLINE;
LEX_last_token_newline = TRUE;
}
return;
}
LEX_last_token_newline = FALSE;
//
// Arithmetic characters..
//
switch(*LEX_stream_upto)
{
case '=':
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_EQUALS;
return;
case '-':
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_MINUS;
return;
case '+':
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_PLUS;
return;
case '*':
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_TIMES;
return;
case '%':
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_MOD;
return;
case '/':
if (LEX_stream_upto[1] == '/')
{
//
// This is the C++ comment system- bin the rest of the line.
//
while(1)
{
if (*LEX_stream_upto == '\n')
{
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_NEWLINE;
LEX_last_token_newline = TRUE;
return;
}
if (*LEX_stream_upto == '\000')
{
LEX_top.type = LEX_TOKEN_TYPE_NEWLINE;
LEX_last_token_newline = TRUE;
return;
}
LEX_stream_upto++;
}
//
// Never gets here
//
ASSERT(0);
}
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_DIVIDE;
return;
case ':':
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_COLON;
return;
case '(':
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_OPEN;
return;
case ')':
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_CLOSE;
return;
case '[':
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_OSQUARE;
return;
case ']':
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_CSQUARE;
return;
case ',':
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_COMMA;
return;
case '>':
if (LEX_stream_upto[1] == '=')
{
LEX_stream_upto += 2;
LEX_top.type = LEX_TOKEN_TYPE_GTEQ;
}
else
{
LEX_stream_upto += 1;
LEX_top.type = LEX_TOKEN_TYPE_GT;
}
return;
case '<':
if (LEX_stream_upto[1] == '=')
{
LEX_stream_upto += 2;
LEX_top.type = LEX_TOKEN_TYPE_LTEQ;
}
else
if (LEX_stream_upto[1] == '>')
{
LEX_stream_upto += 2;
LEX_top.type = LEX_TOKEN_TYPE_NOTEQUAL;
}
else
{
LEX_stream_upto += 1;
LEX_top.type = LEX_TOKEN_TYPE_LT;
}
return;
case '!':
if (LEX_stream_upto[1] == '=')
{
LEX_stream_upto += 2;
LEX_top.type = LEX_TOKEN_TYPE_NOTEQUAL;
return;
}
break;
case '.':
if (isdigit(LEX_stream_upto[1]))
{
//
// This dot is part of a number.
//
break;
}
else
{
LEX_stream_upto += 1;
LEX_top.type = LEX_TOKEN_TYPE_DOT;
return;
}
case '"':
LEX_stream_upto += 1;
dest = LEX_string_buffer;
while(1)
{
if (!WITHIN(dest, LEX_string_buffer, LEX_string_buffer + LEX_MAX_STRING_LENGTH - 1))
{
LEX_top.type = LEX_TOKEN_TYPE_ERROR;
LEX_top.error = "String constant is too long";
return;
}
if (*LEX_stream_upto == '"')
{
*dest = '\000';
LEX_stream_upto += 1;
LEX_top.type = LEX_TOKEN_TYPE_STRING;
LEX_top.string = LEX_string_buffer;
return;
}
else
if (*LEX_stream_upto == '\n')
{
LEX_top.type = LEX_TOKEN_TYPE_ERROR;
LEX_top.error = "Newline in string constant (did you miss out a close quote on a string!)";
return;
}
else
if (*LEX_stream_upto == '\000')
{
LEX_top.type = LEX_TOKEN_TYPE_ERROR;
LEX_top.error = "End of file found during string constant (did you miss out a close quote on a string!)";
return;
}
else
{
*dest++ = *LEX_stream_upto++;
}
}
//
// Never gets here...
//
ASSERT(0);
case '\'':
//
// Character constant?
//
LEX_stream_upto += 1;
if (iscntrl(*LEX_stream_upto))
{
LEX_top.type = LEX_TOKEN_TYPE_ERROR;
LEX_top.error = "Bad character in character constant";
return;
}
LEX_top.type = LEX_TOKEN_TYPE_SLUMBER;
LEX_top.slumber = *LEX_stream_upto++;
if (*LEX_stream_upto != '\'')
{
LEX_top.type = LEX_TOKEN_TYPE_ERROR;
LEX_top.error = "Character constant isn't terminated with an end quote";
return;
}
LEX_stream_upto++;
break;
default:
break;
}
//
// Number constant?
//
if (LEX_stream_upto[0] == '0' && (LEX_stream_upto[1] == 'x' || LEX_stream_upto[1] == 'X'))
{
//
// This is a HEX number.
//
SLONG number = 0;
SLONG num_digits = 0;
LEX_stream_upto += 2;
if (!isxdigit(*LEX_stream_upto))
{
LEX_top.type = LEX_TOKEN_TYPE_ERROR;
LEX_top.error = "Unfinished hexadecimal constant";
return;
}
while(1)
{
if (isxdigit(*LEX_stream_upto))
{
number <<= 4;
if (isdigit(*LEX_stream_upto))
{
number |= *LEX_stream_upto - '0';
}
else
{
if (isupper(*LEX_stream_upto))
{
number |= *LEX_stream_upto - 'A' + 10;
}
else
{
number |= *LEX_stream_upto - 'a' + 10;
}
}
num_digits += 1;
LEX_stream_upto += 1;
}
else
{
break;
}
}
if (num_digits > 8)
{
LEX_top.type = LEX_TOKEN_TYPE_ERROR;
LEX_top.error = "Too many digits in hexadecimal constant";
return;
}
LEX_top.type = LEX_TOKEN_TYPE_SLUMBER;
LEX_top.slumber = number;
return;
}
else
if (isdigit(*LEX_stream_upto) || *LEX_stream_upto == '.')
{
SLONG doing_fraction = FALSE;
double number = 0.0F;
double frac = 0.1F;
while(1)
{
if (isdigit(*LEX_stream_upto))
{
if (doing_fraction)
{
//
// We are doing the fractional part of a floating point number.
//
number += float(*LEX_stream_upto - '0') * frac;
frac *= 0.1F;
}
else
{
//
// We are doing the integer part.
//
number *= 10.0F;
number += float(*LEX_stream_upto - '0');
}
}
else
if (*LEX_stream_upto == '.')
{
//
// A floating point number.
//
if (doing_fraction)
{
//
// We've already come across one decimal point!
//
LEX_top.type = LEX_TOKEN_TYPE_ERROR;
LEX_top.error = "Found two decimal points in a floating point number!";
return;
}
else
{
doing_fraction = TRUE;
}
}
else
{
if (doing_fraction)
{
LEX_top.type = LEX_TOKEN_TYPE_FLUMBER;
LEX_top.flumber = (float) number;
}
else
{
LEX_top.type = LEX_TOKEN_TYPE_SLUMBER;
LEX_top.slumber = (SLONG) number;
}
return;
}
LEX_stream_upto += 1;
}
}
//
// A word of some sort?
//
if (isalpha(*LEX_stream_upto))
{
//
// Copy the variable into the string buffer.
//
dest = LEX_string_buffer;
while(1)
{
if (!WITHIN(dest, LEX_string_buffer, LEX_string_buffer + LEX_MAX_STRING_LENGTH - 1))
{
LEX_top.type = LEX_TOKEN_TYPE_ERROR;
LEX_top.error = "Variable name or label is too long";
return;
}
if (isalnum(*LEX_stream_upto) || *LEX_stream_upto == '_')
{
*dest++ = *LEX_stream_upto++;
}
else
{
*dest = '\000';
break;
}
}
//
// Have we found a keyword?
//
struct
{
CBYTE *keyword;
SLONG token;
} keyword[] =
{
{"IF", LEX_TOKEN_TYPE_IF },
{"THEN", LEX_TOKEN_TYPE_THEN },
{"GOTO", LEX_TOKEN_TYPE_GOTO },
{"AND", LEX_TOKEN_TYPE_AND },
{"OR", LEX_TOKEN_TYPE_OR },
{"NOT", LEX_TOKEN_TYPE_NOT },
{"REM", NULL }, // This is a special case, LEX removes the rest of the line
{"CALL", LEX_TOKEN_TYPE_CALL },
{"FUNC", LEX_TOKEN_TYPE_FUNC },
{"LOCAL", LEX_TOKEN_TYPE_LOCAL },
{"PRINT", LEX_TOKEN_TYPE_PRINT },
{"ELSE", LEX_TOKEN_TYPE_ELSE },
{"TRUE", LEX_TOKEN_TYPE_TRUE },
{"FALSE", LEX_TOKEN_TYPE_FALSE },
{"SQRT", LEX_TOKEN_TYPE_SQRT },
{"ABS", LEX_TOKEN_TYPE_ABS },
{"INPUT", LEX_TOKEN_TYPE_INPUT },
{"UNDEFINED", LEX_TOKEN_TYPE_UNDEFINED},
{"EXIT", LEX_TOKEN_TYPE_EXIT },
{"GOSUB", LEX_TOKEN_TYPE_GOSUB },
{"RETURN", LEX_TOKEN_TYPE_RETURN },
{"XOR", LEX_TOKEN_TYPE_XOR },
{"FOR", LEX_TOKEN_TYPE_FOR },
{"TO", LEX_TOKEN_TYPE_TO },
{"STEP", LEX_TOKEN_TYPE_STEP },
{"NEXT", LEX_TOKEN_TYPE_NEXT },
{"RANDOM", LEX_TOKEN_TYPE_RANDOM },
{"SWAP", LEX_TOKEN_TYPE_SWAP },
{"MOD", LEX_TOKEN_TYPE_MOD },
{"ENDIF", LEX_TOKEN_TYPE_ENDIF },
{"WHILE", LEX_TOKEN_TYPE_WHILE },
{"LOOP", LEX_TOKEN_TYPE_LOOP },
{"FUNCTION", LEX_TOKEN_TYPE_FUNCTION },
{"ENDFUNC", LEX_TOKEN_TYPE_ENDFUNC },
{"TEXTURE", LEX_TOKEN_TYPE_TEXTURE },
{"BUFFER", LEX_TOKEN_TYPE_BUFFER },
{"DRAW", LEX_TOKEN_TYPE_DRAW },
{"CLS", LEX_TOKEN_TYPE_CLS },
{"FLIP", LEX_TOKEN_TYPE_FLIP },
{"KEY", LEX_TOKEN_TYPE_KEY },
{"INKEY", LEX_TOKEN_TYPE_INKEY },
{"TIMER", LEX_TOKEN_TYPE_TIMER },
{"SIN", LEX_TOKEN_TYPE_SIN },
{"COS", LEX_TOKEN_TYPE_COS },
{"TAN", LEX_TOKEN_TYPE_TAN },
{"ASIN", LEX_TOKEN_TYPE_ASIN },
{"ACOS", LEX_TOKEN_TYPE_ACOS },
{"ATAN", LEX_TOKEN_TYPE_ATAN },
{"ATAN2", LEX_TOKEN_TYPE_ATAN2 },
{"EXPORT", LEX_TOKEN_TYPE_EXPORT },
{"LEFT", LEX_TOKEN_TYPE_LEFT },
{"MID", LEX_TOKEN_TYPE_MID },
{"RIGHT", LEX_TOKEN_TYPE_RIGHT },
{"LEN", LEX_TOKEN_TYPE_LEN },
{"!"}
};
for (i = 0; keyword[i].keyword[0] != '!'; i++)
{
if (strcmp(keyword[i].keyword, LEX_string_buffer) == 0)
{
if (strcmp(keyword[i].keyword, "REM") == 0)
{
//
// This is a REM statement. Skip to the end of the line
// and return a NEWLINE.
//
while(1)
{
if (*LEX_stream_upto == '\n')
{
LEX_stream_upto++;
LEX_top.type = LEX_TOKEN_TYPE_NEWLINE;
LEX_last_token_newline = TRUE;
return;
}
if (*LEX_stream_upto == '\000')
{
LEX_top.type = LEX_TOKEN_TYPE_NEWLINE;
LEX_last_token_newline = TRUE;
return;
}
LEX_stream_upto++;
}
//
// Never gets here
//
ASSERT(0);
}
if (LEX_last_token_newline)
{
//
// If the next character is a ':', then it's an error because
// you can't have a keyword as a label.
//
if (*LEX_stream_upto == ':')
{
LEX_top.type = LEX_TOKEN_TYPE_ERROR;
LEX_top.error = "You can't have a keyword as a label";
return;
}
}
LEX_top.type = keyword[i].token;
return;
}
}
//
// Is this a label? Is the next character a ':'?
//
if (*LEX_stream_upto == ':')
{
if (LEX_last_token_newline)
{
//
// Labels only at the beginning of a line.
//
strcat(LEX_string_buffer, ":");
LEX_stream_upto += 1;
LEX_top.type = LEX_TOKEN_TYPE_LABEL;
LEX_top.label = LEX_string_buffer;
return;
}
else
{
//
// Otherwise it's a variable followed by a COLON separator.
//
}
}
//
// Must be a variable.
//
LEX_top.type = LEX_TOKEN_TYPE_VARIABLE;
LEX_top.variable = LEX_string_buffer;
return;
}
//
// Strange character.
//
sprintf(LEX_string_buffer, "Found a strange character: '%c'", *LEX_stream_upto);
LEX_top.type = LEX_TOKEN_TYPE_ERROR;
LEX_top.error = LEX_string_buffer;
return;
}
void LEX_start(CBYTE *string)
{
LEX_stream_buffer = string;
LEX_stream_upto = string;
LEX_top_valid = FALSE;
LEX_last_token_newline = FALSE;
}
LEX_Token LEX_get()
{
if (!LEX_top_valid)
{
LEX_find_next_token();
}
return LEX_top;
}
LEX_Token LEX_pop()
{
LEX_Token ans;
if (!LEX_top_valid)
{
LEX_find_next_token();
}
LEX_top_valid = FALSE;
ans = LEX_top;
if (LEX_stack_valid)
{
LEX_stack_valid = FALSE;
LEX_top_valid = TRUE;
LEX_top = LEX_stack;
}
return ans;
}
void LEX_push(LEX_Token lt)
{
if (LEX_top_valid)
{
ASSERT(!LEX_stack_valid);
LEX_stack_valid = TRUE;
LEX_stack = LEX_top;
LEX_top = lt;
}
else
{
LEX_top_valid = TRUE;
LEX_top = lt;
}
}
void LEX_next_line()
{
LEX_Token lt;
while(1)
{
lt = LEX_pop();
if (lt.type == LEX_TOKEN_TYPE_NEWLINE)
{
return;
}
if (lt.type == LEX_TOKEN_TYPE_EOF)
{
//
// Push the token back on the stack...
//
LEX_top_valid = TRUE;
return;
}
}
}

161
MuckyBasic/lex.h Normal file
View File

@ -0,0 +1,161 @@
//
// A lexical analyser
//
#ifndef _LEX_
#define _LEX_
#define LEX_TOKEN_TYPE_EQUALS 0
#define LEX_TOKEN_TYPE_PLUS 1
#define LEX_TOKEN_TYPE_MINUS 2
#define LEX_TOKEN_TYPE_TIMES 3
#define LEX_TOKEN_TYPE_DIVIDE 4
#define LEX_TOKEN_TYPE_SLUMBER 5
#define LEX_TOKEN_TYPE_FLUMBER 6
#define LEX_TOKEN_TYPE_STRING 7
#define LEX_TOKEN_TYPE_VARIABLE 8
#define LEX_TOKEN_TYPE_IF 9
#define LEX_TOKEN_TYPE_THEN 10
#define LEX_TOKEN_TYPE_GOTO 11
#define LEX_TOKEN_TYPE_LABEL 12
#define LEX_TOKEN_TYPE_ERROR 13
#define LEX_TOKEN_TYPE_NEWLINE 14
#define LEX_TOKEN_TYPE_EOF 15
#define LEX_TOKEN_TYPE_GT 16
#define LEX_TOKEN_TYPE_LT 17
#define LEX_TOKEN_TYPE_GTEQ 18
#define LEX_TOKEN_TYPE_LTEQ 19
#define LEX_TOKEN_TYPE_AND 20
#define LEX_TOKEN_TYPE_OR 21
#define LEX_TOKEN_TYPE_NOT 22
#define LEX_TOKEN_TYPE_DOT 23
#define LEX_TOKEN_TYPE_OPEN 24
#define LEX_TOKEN_TYPE_CLOSE 25
#define LEX_TOKEN_TYPE_CALL 26
#define LEX_TOKEN_TYPE_FUNC 27
#define LEX_TOKEN_TYPE_LOCAL 28
#define LEX_TOKEN_TYPE_OSQUARE 29 // Open square bracket [
#define LEX_TOKEN_TYPE_CSQUARE 30 // Close square bracket ]
#define LEX_TOKEN_TYPE_PRINT 31
#define LEX_TOKEN_TYPE_MOD 32
#define LEX_TOKEN_TYPE_ELSE 33
#define LEX_TOKEN_TYPE_TRUE 34
#define LEX_TOKEN_TYPE_FALSE 35
#define LEX_TOKEN_TYPE_SQRT 36
#define LEX_TOKEN_TYPE_ABS 37
#define LEX_TOKEN_TYPE_COMMA 38
#define LEX_TOKEN_TYPE_INPUT 39
#define LEX_TOKEN_TYPE_UNDEFINED 40 // The actual word "UNDEFINED"
#define LEX_TOKEN_TYPE_COLON 41
#define LEX_TOKEN_TYPE_EXIT 42
#define LEX_TOKEN_TYPE_GOSUB 43
#define LEX_TOKEN_TYPE_RETURN 44
#define LEX_TOKEN_TYPE_XOR 45
#define LEX_TOKEN_TYPE_FOR 46
#define LEX_TOKEN_TYPE_TO 47
#define LEX_TOKEN_TYPE_STEP 48
#define LEX_TOKEN_TYPE_NEXT 49
#define LEX_TOKEN_TYPE_NOTEQUAL 50
#define LEX_TOKEN_TYPE_RANDOM 51
#define LEX_TOKEN_TYPE_SWAP 52
#define LEX_TOKEN_TYPE_ENDIF 53
#define LEX_TOKEN_TYPE_WHILE 54
#define LEX_TOKEN_TYPE_LOOP 55
#define LEX_TOKEN_TYPE_FUNCTION 56
#define LEX_TOKEN_TYPE_ENDFUNC 57
#define LEX_TOKEN_TYPE_TEXTURE 58
#define LEX_TOKEN_TYPE_BUFFER 59
#define LEX_TOKEN_TYPE_DRAW 60
#define LEX_TOKEN_TYPE_CLS 61
#define LEX_TOKEN_TYPE_FLIP 62
#define LEX_TOKEN_TYPE_KEY 63
#define LEX_TOKEN_TYPE_INKEY 64
#define LEX_TOKEN_TYPE_TIMER 65
#define LEX_TOKEN_TYPE_SIN 66
#define LEX_TOKEN_TYPE_COS 67
#define LEX_TOKEN_TYPE_TAN 68
#define LEX_TOKEN_TYPE_ASIN 69
#define LEX_TOKEN_TYPE_ACOS 70
#define LEX_TOKEN_TYPE_ATAN 71
#define LEX_TOKEN_TYPE_ATAN2 72
#define LEX_TOKEN_TYPE_EXPORT 73
#define LEX_TOKEN_TYPE_LEFT 74
#define LEX_TOKEN_TYPE_MID 75
#define LEX_TOKEN_TYPE_RIGHT 76
#define LEX_TOKEN_TYPE_LEN 77
#define LEX_TOKEN_TYPE_MATRIX 78
#define LEX_TOKEN_TYPE_VECTOR 79
#define LEX_TOKEN_TYPE_DPROD 80
#define LEX_TOKEN_TYPE_CPROD 81
#define LEX_TOKEN_TYPE_NORMALISE 82
#define LEX_TOKEN_TYPE_TRANSPOSE 83
typedef struct
{
SLONG type;
SLONG line;
union
{
SLONG slumber;
float flumber;
CBYTE *string;
CBYTE *variable;
CBYTE *label;
CBYTE *error;
};
} LEX_Token;
//
// The maximum length of a string constant, variable name or label.
//
#define LEX_MAX_STRING_LENGTH 1024
//
// Starts reading token from the given string.
//
void LEX_start(CBYTE *string);
//
// Returns the next token in the input stream without
// taking it out of the stream.
//
LEX_Token LEX_get(void);
//
// Pops the next token from the input stream.
//
LEX_Token LEX_pop(void);
//
// Pushes the given token back onto the input stream.
//
void LEX_push(LEX_Token lt);
//
// Skips to the next line and eats up all the input. Helpful
// for error recovery.
//
void LEX_next_line(void);
#endif

975
MuckyBasic/link.cpp Normal file
View File

@ -0,0 +1,975 @@
//
// The linker
//
#include "always.h"
#include "ml.h"
#include "link.h"
#include "sysvar.h"
#include "st.h"
//
// The data we accumulate as we link.
//
SLONG *LINK_instruction;
SLONG LINK_instruction_max;
SLONG LINK_instruction_upto;
CBYTE *LINK_table_data;
SLONG LINK_table_data_max;
SLONG LINK_table_data_upto;
LINK_Global *LINK_global;
SLONG LINK_global_max;
SLONG LINK_global_upto;
LINK_Function *LINK_function;
SLONG LINK_function_max;
SLONG LINK_function_upto;
LINK_Line *LINK_line;
SLONG LINK_line_max;
SLONG LINK_line_upto;
LINK_Jump *LINK_jump;
SLONG LINK_jump_max;
SLONG LINK_jump_upto;
LINK_Field *LINK_field;
SLONG LINK_field_max;
SLONG LINK_field_upto;
LINK_Globalref *LINK_global_ref;
SLONG LINK_global_ref_max;
SLONG LINK_global_ref_upto;
LINK_Undefref *LINK_undef_ref;
SLONG LINK_undef_ref_max;
SLONG LINK_undef_ref_upto;
LINK_Fieldref *LINK_field_ref;
SLONG LINK_field_ref_max;
SLONG LINK_field_ref_upto;
LINK_Datatableref *LINK_data_table_ref;
SLONG LINK_data_table_ref_max;
SLONG LINK_data_table_ref_upto;
CBYTE *LINK_debug_data;
SLONG LINK_debug_data_max;
SLONG LINK_debug_data_upto;
//
// Each file.
//
typedef struct
{
SLONG first_instruction;
SLONG num_instructions;
SLONG first_table_datum;
SLONG num_table_data;
SLONG first_global;
SLONG num_globals;
SLONG first_function;
SLONG num_functions;
SLONG first_line;
SLONG num_lines;
SLONG first_jump;
SLONG num_jumps;
SLONG first_field;
SLONG num_fields;
SLONG first_global_ref;
SLONG num_global_refs;
SLONG first_undef_ref;
SLONG num_undef_refs;
SLONG first_field_ref;
SLONG num_field_refs;
SLONG first_data_table_ref;
SLONG num_data_table_refs;
SLONG first_debug_datum;
SLONG num_debug_data;
} LINK_File;
LINK_File *LINK_file;
SLONG LINK_file_max;
SLONG LINK_file_upto;
//
// The number of globals and fields in the executable.
//
SLONG LINK_global_id_upto;
SLONG LINK_field_id_upto;
//
// Allocates initial memory.
//
void LINK_allocate_memory(void)
{
LINK_instruction_max = 1;
LINK_instruction_upto = 0;
LINK_instruction = (SLONG *) malloc(sizeof(SLONG) * LINK_instruction_max);
LINK_table_data_max = 1;
LINK_table_data_upto = 0;
LINK_table_data = (CBYTE *) malloc(sizeof(CBYTE) * LINK_table_data_max);
LINK_global_max = 1;
LINK_global_upto = 0;
LINK_global = (LINK_Global *) malloc(sizeof(LINK_Global) * LINK_global_max);
LINK_function_max = 1;
LINK_function_upto = 0;
LINK_function = (LINK_Function *) malloc(sizeof(LINK_Function) * LINK_function_max);
LINK_line_max = 1;
LINK_line_upto = 0;
LINK_line = (LINK_Line *) malloc(sizeof(LINK_Line) * LINK_line_max);
LINK_jump_max = 1;
LINK_jump_upto = 0;
LINK_jump = (LINK_Jump *) malloc(sizeof(LINK_Jump) * LINK_jump_max);
LINK_field_max = 1;
LINK_field_upto = 0;
LINK_field = (LINK_Field *) malloc(sizeof(LINK_Field) * LINK_field_max);
LINK_global_ref_max = 1;
LINK_global_ref_upto = 0;
LINK_global_ref = (LINK_Globalref *) malloc(sizeof(LINK_Globalref) * LINK_global_ref_max);
LINK_undef_ref_max = 1;
LINK_undef_ref_upto = 0;
LINK_undef_ref = (LINK_Undefref *) malloc(sizeof(LINK_Undefref) * LINK_undef_ref_max);
LINK_field_ref_max = 1;
LINK_field_ref_upto = 0;
LINK_field_ref = (LINK_Fieldref *) malloc(sizeof(LINK_Fieldref) * LINK_field_ref_max);
LINK_data_table_ref_max = 1;
LINK_data_table_ref_upto = 0;
LINK_data_table_ref = (LINK_Datatableref *) malloc(sizeof(LINK_Datatableref) * LINK_data_table_ref_max);
LINK_debug_data_max = 1;
LINK_debug_data_upto = 0;
LINK_debug_data = (CBYTE *) malloc(sizeof(CBYTE) * LINK_debug_data_max);
LINK_file_max = 1;
LINK_file_upto = 0;
LINK_file = (LINK_File *) malloc(sizeof(LINK_File) * LINK_file_max);
}
//
// Frees all memory.
//
void LINK_free_memory(void)
{
free(LINK_instruction );
free(LINK_table_data );
free(LINK_global );
free(LINK_function );
free(LINK_line );
free(LINK_jump );
free(LINK_field );
free(LINK_global_ref );
free(LINK_undef_ref );
free(LINK_field_ref );
free(LINK_data_table_ref);
free(LINK_debug_data );
free(LINK_file );
LINK_instruction = NULL;
LINK_table_data = NULL;
LINK_global = NULL;
LINK_function = NULL;
LINK_line = NULL;
LINK_jump = NULL;
LINK_field = NULL;
LINK_global_ref = NULL;
LINK_undef_ref = NULL;
LINK_field_ref = NULL;
LINK_data_table_ref = NULL;
LINK_debug_data = NULL;
LINK_file = NULL;
}
SLONG LINK_do(CBYTE *object_fname[], SLONG num_object_files, CBYTE *exec_fname)
{
SLONG i;
SLONG j;
SLONG instruction;
SLONG magic;
LINK_Header lh;
LINK_File *lf;
LINK_Function *lc;
LINK_Jump *lj;
LINK_Global *lg;
LINK_Field *ld;
LINK_Undefref *lu;
LINK_Datatableref *lt;
FILE *handle;
#define LINK_MAGIC_CHECK() {if (fread(&magic, sizeof(SLONG), 1, handle) != 1) goto file_error; ASSERT(magic == 12345678);}
//
// Initialise all data.
//
LINK_allocate_memory();
//
// Load in each file.
//
for (i = 0; i < num_object_files; i++)
{
//
// Open the file.
//
handle = fopen(object_fname[i], "rb");
if (handle == NULL)
{
//
// ERROR! Can't open object file...
//
goto file_error;
}
//
// Load in the header.
//
if (fread(&lh, sizeof(LINK_Header), 1, handle) != 1) goto file_error;
//
// Correct version number?
//
if (lh.version != 1)
{
//
// ERROR!
//
}
//
// Get another LINK_File.
//
if (LINK_file_upto >= LINK_file_max)
{
LINK_file_max *= 2;
LINK_file = (LINK_File *) realloc(LINK_file, sizeof(LINK_File) * LINK_file_max);
}
lf = &LINK_file[LINK_file_upto++];
//
// Initialise.
//
memset(lf, 0, sizeof(LINK_File));
//
// Instructions.
//
lf->first_instruction = LINK_instruction_upto;
lf->num_instructions = lh.num_instructions;
while(LINK_instruction_upto + lh.num_instructions > LINK_instruction_max)
{
LINK_instruction_max *= 2;
LINK_instruction = (SLONG *) realloc(LINK_instruction, sizeof(SLONG) * LINK_instruction_max);
}
if (fread(LINK_instruction + LINK_instruction_upto, sizeof(SLONG), lh.num_instructions, handle) != lh.num_instructions) goto file_error;
LINK_instruction_upto += lh.num_instructions;
LINK_MAGIC_CHECK();
//
// The data table.
//
lf->first_table_datum = LINK_table_data_upto;
lf->num_table_data = lh.data_table_length_in_bytes;
while(LINK_table_data_upto + lh.data_table_length_in_bytes > LINK_table_data_max)
{
LINK_table_data_max *= 2;
LINK_table_data = (CBYTE *) realloc(LINK_table_data, sizeof(CBYTE) * LINK_table_data_max);
}
if (fread(LINK_table_data + LINK_table_data_upto, sizeof(CBYTE), lh.data_table_length_in_bytes, handle) != lh.data_table_length_in_bytes) goto file_error;
LINK_table_data_upto += lh.data_table_length_in_bytes;
LINK_MAGIC_CHECK();
//
// Globals.
//
lf->first_global = LINK_global_upto;
lf->num_globals = lh.num_globals;
while(LINK_global_upto + lh.num_globals > LINK_global_max)
{
LINK_global_max *= 2;
LINK_global = (LINK_Global *) realloc(LINK_global, sizeof(LINK_Global) * LINK_global_max);
}
if (fread(LINK_global + LINK_global_upto, sizeof(LINK_Global), lh.num_globals, handle) != lh.num_globals) goto file_error;
LINK_global_upto += lh.num_globals;
LINK_MAGIC_CHECK();
//
// Functions.
//
lf->first_function = LINK_function_upto;
lf->num_functions = lh.num_functions;
while(LINK_function_upto + lh.num_functions > LINK_function_max)
{
LINK_function_max *= 2;
LINK_function = (LINK_Function *) realloc(LINK_function, sizeof(LINK_Function) * LINK_function_max);
}
if (fread(LINK_function + LINK_function_upto, sizeof(LINK_Function), lh.num_functions, handle) != lh.num_functions) goto file_error;
LINK_function_upto += lh.num_functions;
LINK_MAGIC_CHECK();
//
// Lines.
//
lf->first_line = LINK_line_upto;
lf->num_lines = lh.num_lines;
while(LINK_line_upto + lh.num_lines > LINK_line_max)
{
LINK_line_max *= 2;
LINK_line = (LINK_Line *) realloc(LINK_line, sizeof(LINK_Line) * LINK_line_max);
}
if (fread(LINK_line + LINK_line_upto, sizeof(LINK_Line), lh.num_lines, handle) != lh.num_lines) goto file_error;
LINK_line_upto += lh.num_lines;
LINK_MAGIC_CHECK();
//
// Jumps.
//
lf->first_jump = LINK_jump_upto;
lf->num_jumps = lh.num_jumps;
while(LINK_jump_upto + lh.num_jumps > LINK_jump_max)
{
LINK_jump_max *= 2;
LINK_jump = (LINK_Jump *) realloc(LINK_jump, sizeof(LINK_Jump) * LINK_jump_max);
}
if (fread(LINK_jump + LINK_jump_upto, sizeof(LINK_Jump), lh.num_jumps, handle) != lh.num_jumps) goto file_error;
LINK_jump_upto += lh.num_jumps;
LINK_MAGIC_CHECK();
//
// Fields.
//
lf->first_field = LINK_field_upto;
lf->num_fields = lh.num_fields;
while(LINK_field_upto + lh.num_fields > LINK_field_max)
{
LINK_field_max *= 2;
LINK_field = (LINK_Field *) realloc(LINK_field, sizeof(LINK_Field) * LINK_field_max);
}
if (fread(LINK_field + LINK_field_upto, sizeof(LINK_Field), lh.num_fields, handle) != lh.num_fields) goto file_error;
LINK_field_upto += lh.num_fields;
LINK_MAGIC_CHECK();
//
// Globalrefs.
//
lf->first_global_ref = LINK_global_ref_upto;
lf->num_global_refs = lh.num_global_refs;
while(LINK_global_ref_upto + lh.num_global_refs > LINK_global_ref_max)
{
LINK_global_ref_max *= 2;
LINK_global_ref = (LINK_Globalref *) realloc(LINK_global_ref, sizeof(LINK_Globalref) * LINK_global_ref_max);
}
if (fread(LINK_global_ref + LINK_global_ref_upto, sizeof(LINK_Globalref), lh.num_global_refs, handle) != lh.num_global_refs) goto file_error;
LINK_global_ref_upto += lh.num_global_refs;
LINK_MAGIC_CHECK();
//
// Undefined function references.
//
lf->first_undef_ref = LINK_undef_ref_upto;
lf->num_undef_refs = lh.num_undef_refs;
while(LINK_undef_ref_upto + lh.num_undef_refs > LINK_undef_ref_max)
{
LINK_undef_ref_max *= 2;
LINK_undef_ref = (LINK_Undefref *) realloc(LINK_undef_ref, sizeof(LINK_Undefref) * LINK_undef_ref_max);
}
if (fread(LINK_undef_ref + LINK_undef_ref_upto, sizeof(LINK_Undefref), lh.num_undef_refs, handle) != lh.num_undef_refs) goto file_error;
LINK_undef_ref_upto += lh.num_undef_refs;
LINK_MAGIC_CHECK();
//
// Fieldrefs.
//
lf->first_field_ref = LINK_field_ref_upto;
lf->num_field_refs = lh.num_field_refs;
while(LINK_field_ref_upto + lh.num_field_refs > LINK_field_ref_max)
{
LINK_field_ref_max *= 2;
LINK_field_ref = (LINK_Fieldref *) realloc(LINK_field_ref, sizeof(LINK_Fieldref) * LINK_field_ref_max);
}
if (fread(LINK_field_ref + LINK_field_ref_upto, sizeof(LINK_Fieldref), lh.num_field_refs, handle) != lh.num_field_refs) goto file_error;
LINK_field_ref_upto += lh.num_field_refs;
LINK_MAGIC_CHECK();
//
// Data table refs.
//
lf->first_data_table_ref = LINK_data_table_ref_upto;
lf->num_data_table_refs = lh.num_data_table_refs;
while(LINK_data_table_ref_upto + lh.num_data_table_refs > LINK_data_table_ref_max)
{
LINK_data_table_ref_max *= 2;
LINK_data_table_ref = (LINK_Datatableref *) realloc(LINK_data_table_ref, sizeof(LINK_Datatableref) * LINK_data_table_ref_max);
}
if (fread(LINK_data_table_ref + LINK_data_table_ref_upto, sizeof(LINK_Datatableref), lh.num_data_table_refs, handle) != lh.num_data_table_refs) goto file_error;
LINK_data_table_ref_upto += lh.num_data_table_refs;
LINK_MAGIC_CHECK();
//
// Load in the debug data.
//
lf->first_debug_datum = LINK_debug_data_upto;
if (fread(&lf->num_debug_data, sizeof(SLONG), 1, handle) != 1) goto file_error;
while(LINK_debug_data_upto + lf->num_debug_data > LINK_debug_data_max)
{
LINK_debug_data_max *= 2;
LINK_debug_data = (CBYTE *) realloc(LINK_debug_data, sizeof(CBYTE) * LINK_debug_data_max);
}
if (fread(LINK_debug_data + LINK_debug_data_upto, sizeof(CBYTE), lf->num_debug_data, handle) != lf->num_debug_data) goto file_error;
LINK_debug_data_upto += lf->num_debug_data;
//
// Finished. We should have read the entire file.
//
#ifdef _DEBUG
//
// Make sure there is no file left!
//
{
UBYTE junk[1024];
SLONG read;
read = fread(junk, 1, 1024, handle);
ASSERT(read == 0);
}
#endif
//
// Finished reading the file.
//
fclose(handle);
}
//
// Add all exported globals, fields and exported functions
// to the symbol table. This helps us allocate global_ids
// and field_ids and resolve calls to functions across files.
//
ST_clear_all();
SYSVAR_init();
LINK_global_id_upto = 0;
LINK_field_id_upto = SYSVAR_FIELD_NUMBER;
for (i = 0; i < LINK_file_upto; i++)
{
lf = &LINK_file[i];
//
// Overwrite each global's index field with the new global_id.
//
for (j = 0; j < lf->num_globals; j++)
{
lg = &LINK_global[lf->first_global + j];
if (lg->export)
{
ASSERT(WITHIN(lg->name + lf->first_debug_datum, 0, LINK_debug_data_upto - 1));
//
// Is this global already in the symbol table?
//
if (ST_find(LINK_debug_data + lg->name + lf->first_debug_datum))
{
//
// ERROR! Multiply defined exported global.
//
ASSERT(0);
}
else
{
//
// The global wasn't found. Allocate a new global_id and add
// this global to the symbol table.
//
lg->index = LINK_global_id_upto++;
ST_add(ST_TABLE_GLOBAL, LINK_debug_data + lg->name + lf->first_debug_datum, lg->index, 0);
}
}
else
{
ASSERT(WITHIN(lg->name + lf->first_debug_datum, 0, LINK_debug_data_upto - 1));
if (lg->local)
{
//
// This global is local for sure, so it needs it's own ID.
//
lg->index = LINK_global_id_upto++;
}
else
{
//
// Is this global already in the symbol table?
//
if (ST_find(LINK_debug_data + lg->name + lf->first_debug_datum))
{
//
// Use the same global id.
//
lg->index = ST_found_value;
}
else
{
//
// Allocate a new global_id.
//
lg->index = LINK_global_id_upto++;
}
}
}
}
//
// Overwrite each field's index field with the new field_id.
//
for (j = 0; j < lf->num_fields; j++)
{
ld = &LINK_field[lf->first_field + j];
ASSERT(WITHIN(ld->name + lf->first_debug_datum, 0, LINK_debug_data_upto - 1));
//
// Is this field already in the symbol table?
//
if (ST_find(LINK_debug_data + ld->name + lf->first_debug_datum))
{
//
// Use the same field_id.
//
ld->index = ST_found_value;
}
else
{
//
// Allocate a new field_id and add it to the symbol table.
//
ld->index = LINK_field_id_upto++;
ST_add(ST_TABLE_GLOBAL, LINK_debug_data + ld->name + lf->first_debug_datum, ld->index, 0);
}
}
//
// Add all the exported functions to the symbol table.
//
for (j = 0; j < lf->num_functions; j++)
{
lc = &LINK_function[lf->first_function + j];
if (lc->export)
{
ASSERT(WITHIN(lc->name + lf->first_debug_datum, 0, LINK_debug_data_upto - 1));
//
// The value associated with the function is the first instruction
// of the function body.
//
if (ST_find(LINK_debug_data + lc->name + lf->first_debug_datum))
{
//
// ERROR! Multiply defined function!
//
ASSERT(0);
}
else
{
//
// What is the first instruction of the function body?
//
ASSERT(WITHIN(lc->line_start, 0, lf->num_lines - 1));
ASSERT(WITHIN(lc->line_start + lf->first_line, 0, LINK_line_upto - 1));
instruction = LINK_line[lf->first_line + lc->line_start].instruction;
ASSERT(WITHIN(instruction, 0, lf->num_instructions - 1));
instruction += lf->first_instruction;
ASSERT(WITHIN(instruction, 0, LINK_instruction_upto - 1));
//
// The first two instructions of a function are a GOTO to the
// end of the funciton. This is so that execution will jump
// over the function instead of leaking into it accidentally.
//
instruction += 2;
//
// Add the function to the symbol table.
//
ST_add(
ST_TABLE_GLOBAL,
LINK_debug_data + lc->name + lf->first_debug_datum,
instruction,
0);
}
}
}
}
//
// Do the actual linking.
//
for (i = 0; i < LINK_file_upto; i++)
{
lf = &LINK_file[i];
//
// Fix instructions that refer to globals.
//
for (j = 0; j < lf->num_global_refs; j++)
{
ASSERT(WITHIN(lf->first_global_ref + j, 0, LINK_global_ref_upto - 1));
instruction = LINK_global_ref[lf->first_global_ref + j].instruction;
instruction += lf->first_instruction;
ASSERT(WITHIN(instruction, 0, LINK_instruction_upto - 1));
//
// We have the instruction that contains the old global_id.
// Overwrite it with the new one.
//
ASSERT(WITHIN(LINK_instruction[instruction], 0, lf->num_globals - 1));
LINK_instruction[instruction] = LINK_global[lf->first_global + LINK_instruction[instruction]].index;
}
//
// Fix instructions that refer to fields.
//
for (j = 0; j < lf->num_field_refs; j++)
{
ASSERT(WITHIN(lf->first_field_ref + j, 0, LINK_field_ref_upto - 1));
instruction = LINK_field_ref[lf->first_field_ref + j].instruction;
instruction += lf->first_instruction;
ASSERT(WITHIN(instruction, 0, LINK_instruction_upto - 1));
//
// We have the instruction that contains the old field_id.
// Overwrite it with the new one.
//
ASSERT(WITHIN(LINK_instruction[instruction], 0, lf->num_fields - 1));
LINK_instruction[instruction] = LINK_field[lf->first_field + LINK_instruction[instruction]].index;
}
//
// Fix calls to functions across files.
//
for (j = 0; j < lf->num_undef_refs; j++)
{
ASSERT(WITHIN(lf->first_undef_ref + j, 0, LINK_undef_ref_upto - 1));
lu = &LINK_undef_ref[lf->first_undef_ref + j];
//
// Look for this undefined function in the symbol table.
//
ASSERT(WITHIN(lu->name + lf->first_debug_datum, 0, LINK_debug_data_upto - 1));
if (!ST_find(LINK_debug_data + lu->name + lf->first_debug_datum))
{
//
// ERROR! Undefined function.
//
ASSERT(0);
}
else
{
//
// Write the address of the function into the instructions.
//
ASSERT(WITHIN(lu->instruction, 0, lf->num_instructions - 1));
ASSERT(WITHIN(lf->first_instruction + lu->instruction, 0, LINK_instruction_upto - 1));
ASSERT(WITHIN(ST_found_value, 0, LINK_instruction_upto - 1));
LINK_instruction[lf->first_instruction + lu->instruction] = ST_found_value;
}
}
//
// Fix jumps.
//
for (j = 0; j < lf->num_jumps; j++)
{
ASSERT(WITHIN(lf->first_jump + j, 0, LINK_jump_upto - 1));
lj = &LINK_jump[lf->first_jump + j];
ASSERT(WITHIN(lj->instruction, 0, lf->num_instructions - 1));
ASSERT(WITHIN(lj->instruction + lf->first_instruction, 0, LINK_instruction_upto - 1));
LINK_instruction[lf->first_instruction + lj->instruction] += lf->first_instruction;
}
//
// Fix references into the data table.
//
for (j = 0; j < lf->num_data_table_refs; j++)
{
ASSERT(WITHIN(lf->first_data_table_ref + j, 0, LINK_data_table_ref_upto - 1));
lt = &LINK_data_table_ref[lf->first_data_table_ref + j];
ASSERT(WITHIN(lt->instruction, 0, lf->num_instructions - 1));
ASSERT(WITHIN(lt->instruction + lf->first_instruction, 0, LINK_instruction_upto - 1));
ASSERT(WITHIN(LINK_instruction[lt->instruction + lf->first_instruction], 0, lf->num_table_data - 1));
LINK_instruction[lt->instruction + lf->first_instruction] += lf->first_table_datum;
ASSERT(WITHIN(LINK_instruction[lt->instruction + lf->first_instruction], 0, LINK_table_data_upto - 1));
}
//
// The last instruction of any file is an EXIT. Replace all these
// EXIT instrucitons with NOPs except for the last one.
//
if (i == LINK_file_upto - 1)
{
//
// This is the last file.
//
}
else
{
ASSERT(WITHIN(lf->first_instruction + lf->num_instructions - 1, 0, LINK_instruction_upto - 1));
ASSERT(LINK_instruction[lf->first_instruction + lf->num_instructions - 1] == ML_DO_EXIT);
LINK_instruction[lf->first_instruction + lf->num_instructions - 1] = ML_DO_NOP;
}
}
//
// Ready to write out the executable now. Create the
// header of an executable.
//
ML_Header mh;
mh.version = ML_VERSION_NUMBER;
mh.instructions_memory_in_bytes = LINK_instruction_upto * sizeof(SLONG);
mh.data_table_length_in_bytes = LINK_table_data_upto;
mh.num_globals = LINK_global_upto;
//
// Open the executable file.
//
handle = fopen(exec_fname, "wb");
if (handle == NULL)
{
//
// ERROR!
//
goto file_error;
}
if (fwrite(&mh, sizeof(mh), 1, handle) != 1) goto file_error;
//
// The instructions.
//
if (fwrite(LINK_instruction, sizeof(SLONG), LINK_instruction_upto, handle) != LINK_instruction_upto) goto file_error;
//
// The string table.
//
if (fwrite(LINK_table_data, sizeof(UBYTE), LINK_table_data_upto, handle) != LINK_table_data_upto) goto file_error;
fclose(handle);
//
// All done.
//
LINK_free_memory();
return TRUE;
file_error:;
//
// ERROR!
//
if (handle)
{
fclose(handle);
}
LINK_free_memory();
return FALSE;
}

139
MuckyBasic/link.h Normal file
View File

@ -0,0 +1,139 @@
//
// The linker
//
#ifndef _LINK_
#define _LINK_
// ========================================================
//
// STRUCTURES IN THE OBJECT FILE.
//
// ========================================================
typedef struct
{
UWORD index; // This is the number of the global.
UBYTE export; // TRUE => This global is exported
UBYTE local; // TRUE => This global is local to the file.
SLONG name; // Index into the debug data
} LINK_Global;
typedef struct
{
SLONG name;
SLONG export; // TRUE => this function is exported.
SLONG line_start; // The first and last line of the function body
SLONG line_end;
SLONG num_args; // The number of arguments to the function
} LINK_Function;
typedef struct
{
SLONG instruction; // The first instruction generated for this line of code.
} LINK_Line;
typedef struct
{
SLONG instruction; // Index into instruction memory (SLONG *..) that contains a jump address.
} LINK_Jump;
typedef struct
{
SLONG index; // This is the number of the field.
SLONG name; // Index into the debug data.
} LINK_Field;
typedef struct
{
SLONG instruction; // Index into instruction memory that contains a global index.
} LINK_Globalref;
typedef struct
{
SLONG name; // Index into debug data for the name of the undefined function.
SLONG instruction; // Index into instruction memory that should contain the GOSUB jump to the function.
} LINK_Undefref;
typedef struct
{
SLONG instruction; // Index into the instruction memory for which field.
} LINK_Fieldref;
typedef struct
{
SLONG instruction;
} LINK_Datatableref;
typedef struct
{
SLONG version;
SLONG num_instructions; // Each instruction is a SLONG
SLONG data_table_length_in_bytes;
SLONG num_globals;
SLONG num_functions;
SLONG num_lines;
SLONG num_jumps;
SLONG num_fields;
SLONG num_global_refs;
SLONG num_undef_refs;
SLONG num_field_refs;
SLONG num_data_table_refs;
} LINK_Header;
// ========================================================
//
// THE FORMAT OF THE OBJECT FILE.
//
// ========================================================
//
// LINK_Header lh
//
// SLONG Instructions [lh.num_instructions ] Followed by MAGIC SLONG(12345678)
// CBYTE Data table [lh.data_table_length_in_bytes] Followed by MAGIC SLONG(12345678)
// LINK_Global Globals [lh.num_globals ] Followed by MAGIC SLONG(12345678)
// LINK_Function Functions [lh.num_functions ] Followed by MAGIC SLONG(12345678)
// LINK_Line Lines [lh.num_lines ] Followed by MAGIC SLONG(12345678)
// LINK_Jump Jumps [lh.num_jumps ] Followed by MAGIC SLONG(12345678)
// LINK_Field Fields [lh.num_fields ] Followed by MAGIC SLONG(12345678)
// LINK_Globalref Gobal refs [lh.num_global_refs ] Followed by MAGIC SLONG(12345678)
// LINK_Undefref Undefined function refs[lh.num_undefined_funcion_refs] Followed by MAGIC SLONG(12345678)
// LINK_Fieldref Field refs [lh.num_field_refs ] Followed by MAGIC SLONG(12345678)
// LINK_Datatableref Data table refs [lh.num_data_table_refs ] Followed by MAGIC SLONG(12345678)
//
// SLONG debug_data_length_in_bytes
// CBYTE debug data[debug_data_length_in_bytes]
//
// ========================================================
//
// THE LINKER
//
// ========================================================
//
// Links all the object files into an executable. Returns FALSE on failure.
//
SLONG LINK_do(CBYTE *object_fname[], SLONG num_object_files, CBYTE *exec_fname);
#endif

405
MuckyBasic/ll.cpp Normal file
View File

@ -0,0 +1,405 @@
//
// An interface between the low level D3D drawing and
// the virtual machine.
//
#include "always.h"
#include "ll.h"
#include "mem.h"
#include "os.h"
//
// All the textures.
//
#define LL_MAX_TEXTURES 4096
LL_Texture *LL_texture[LL_MAX_TEXTURES];
//
// All the sounds.
//
#define LL_MAX_SOUNDS 4096
LL_Sound *LL_sound[LL_MAX_SOUNDS];
LL_Texture *LL_create_texture(CBYTE *fname)
{
SLONG i;
//
// Create the OS texture.
//
OS_Texture *ot = OS_texture_create(fname);
//
// Do we already have this texture?
//
for (i = 0; i < LL_MAX_TEXTURES; i++)
{
if (LL_texture[i] && LL_texture[i]->ot == ot)
{
//
// We already have this texture!
//
LL_texture[i]->ref_count += 1;
return LL_texture[i];
}
}
//
// Create a new texture.
//
LL_Texture *lt;
lt = (LL_Texture *) MEM_alloc(sizeof(LL_Texture));
lt->ot = ot;
lt->width = OS_texture_width (ot);
lt->height = OS_texture_height(ot);
lt->ref_count = 1;
//
// Add it to our list of textures.
//
for (i = 0; i < LL_MAX_TEXTURES; i++)
{
if (LL_texture[i] == NULL)
{
LL_texture[i] = lt;
return lt;
}
}
//
// No more textures!
//
ASSERT(0);
return NULL;
}
void LL_free_texture(LL_Texture *lt)
{
//
// Free everything! We can't free OS_Textures!
//
MEM_free(lt);
//
// Get rid of the reference in the LL_texture[] array.
//
SLONG i;
for (i = 0; i < LL_MAX_TEXTURES; i++)
{
if (LL_texture[i] == lt)
{
LL_texture[i] = NULL;
return;
}
}
ASSERT(0);
}
LL_Sound *LL_create_sound(CBYTE *fname)
{
SLONG i;
//
// Create the OS sound.
//
OS_Sound *os = OS_sound_create(fname, OS_SOUND_TYPE_2D);
//
// Do we already have this sound?
//
for (i = 0; i < LL_MAX_SOUNDS; i++)
{
if (LL_sound[i] && LL_sound[i]->os == os)
{
//
// We already have this sound!
//
LL_sound[i]->ref_count += 1;
return LL_sound[i];
}
}
//
// Create a new sound.
//
LL_Sound *ls;
ls = (LL_Sound *) MEM_alloc(sizeof(LL_Sound));
ls->os = os;
ls->ref_count = 1;
//
// Add it to our list of sounds.
//
for (i = 0; i < LL_MAX_SOUNDS; i++)
{
if (LL_sound[i] == NULL)
{
LL_sound[i] = ls;
return ls;
}
}
//
// No more sounds!
//
ASSERT(0);
return NULL;
}
void LL_free_sound(LL_Sound *ls)
{
//
// Free everything! We can't free OS_Sounds!
//
MEM_free(ls);
//
// Get rid of the reference in the LL_sound[] array.
//
SLONG i;
for (i = 0; i < LL_MAX_SOUNDS; i++)
{
if (LL_sound[i] == ls)
{
LL_sound[i] = NULL;
return;
}
}
ASSERT(0);
}
LL_Buffer *LL_create_buffer(
SLONG type,
void *vert,
SLONG num_verts,
UWORD *index,
SLONG num_indices)
{
ASSERT(
type == LL_BUFFER_TYPE_TLV ||
type == LL_BUFFER_TYPE_LV);
//
// Create a new buffer.
//
LL_Buffer *lb = (LL_Buffer *) MEM_alloc(sizeof(LL_Buffer));
lb->type = type;
lb->vert_data = vert;
lb->index = index;
lb->num_verts = num_verts;
lb->num_indices = num_indices;
lb->ref_count = 1;
return lb;
}
void LL_free_buffer(LL_Buffer *lb)
{
//
// Free up data.
//
MEM_free(lb->vert);
if (lb->index)
{
MEM_free(lb->index);
}
//
// Now free up the actual buffer.
//
MEM_free(lb);
}
//
// Draws a buffer
//
OS_Vert LL_vert[OS_MAX_TRANS];
void LL_draw_buffer(
LL_Buffer *lb,
LL_Texture *lt, // NULL => Draw untextured
ULONG rs) // The LL_RS_* renderstates ORed together.
{
SLONG i;
OS_Buffer *ob;
OS_Trans *ot;
OS_Vert *ov;
LL_Tlvert *tl;
ob = OS_buffer_new();
//
// Are there too many points in this buffer?
//
ASSERT(lb->num_verts <= OS_MAX_TRANS);
//
// Build the OS_trans and OS_vert buffers.
//
switch(lb->type)
{
case LL_BUFFER_TYPE_TLV:
//
// These are already transformed, so we can write
// directly into the OS_trans[] array.
//
for (i = 0; i < lb->num_verts; i++)
{
ot = &OS_trans [i];
ov = &LL_vert [i];
tl = &lb->vert_tl[i];
ot->X = tl->x;
ot->Y = tl->y;
ot->Z = tl->rhw;
ot->z = tl->z;
ot->clip = OS_CLIP_TRANSFORMED;
ov->trans = i;
ov->index = 0;
ov->colour = tl->colour;
ov->specular = tl->specular;
ov->u1 = tl->u;
ov->v1 = tl->v;
ov->u2 = 0.0F;
ov->v2 = 0.0F;
}
if (lb->index)
{
ASSERT(lb->num_indices % 3 == 0);
for (i = 0; i < lb->num_indices; i += 3)
{
OS_buffer_add_triangle(
ob,
&LL_vert[lb->index[i + 0]],
&LL_vert[lb->index[i + 1]],
&LL_vert[lb->index[i + 2]]);
}
}
else
{
for (i = 0; i < lb->num_verts; i += 3)
{
OS_buffer_add_triangle(
ob,
&LL_vert[i + 0],
&LL_vert[i + 1],
&LL_vert[i + 2]);
}
}
break;
default:
ASSERT(0);
break;
}
//
// Now draw the buffer.
//
OS_buffer_draw(ob, (lt) ? lt->ot : NULL, NULL, rs | OS_DRAW_DOUBLESIDED | OS_DRAW_ZALWAYS | OS_DRAW_NOZWRITE);
}
void LL_cls(ULONG colour, float z)
{
SLONG r = (colour >> 16) & 0xff;
SLONG g = (colour >> 8) & 0xff;
SLONG b = (colour >> 0) & 0xff;
ASSERT(WITHIN(z, 0.0F, 1.0F));
OS_clear_screen(r,g,b,z);
}
void LL_flip()
{
OS_show();
}

220
MuckyBasic/ll.h Normal file
View File

@ -0,0 +1,220 @@
//
// An interface between the low level D3D drawing and
// the virtual machine.
//
#ifndef _LL_
#define _LL_
#include "os.h"
//
// A texture.
//
typedef struct
{
OS_Texture *ot;
SLONG width;
SLONG height;
SLONG ref_count; // This is up to you! It is set to 1 when you create the texture.
} LL_Texture;
//
// The different types of points we can pass to LL_create_buffer.
//
typedef struct
{
float x;
float y;
float z;
float rhw;
ULONG colour;
ULONG specular;
float u;
float v;
} LL_Tlvert;
typedef struct
{
float x;
float y;
float z;
ULONG reserved;
ULONG colour;
ULONG specular;
float u;
float v;
} LL_Lvert;
typedef struct
{
float x;
float y;
float z;
float nx;
float ny;
float nz;
float u;
float v;
} LL_Vert;
//
// A buffer.
//
#define LL_BUFFER_TYPE_TLV 0 // Transformed and lit
#define LL_BUFFER_TYPE_LV 0 // Just lit
#define LL_BUFFER_TYPE_V 0 // Neither lit nor transformed
typedef struct
{
SLONG type;
union
{
void *vert_data;
LL_Tlvert *vert_tl;
LL_Lvert *vert_l;
LL_Vert *vert;
};
UWORD *index;
SLONG num_verts;
SLONG num_indices;
SLONG ref_count; // This is up to you! It is set to 1 when you create the buffer.
} LL_Buffer;
//
// A sound
//
typedef struct
{
OS_Sound *os;
SLONG ref_count;
} LL_Sound;
//
// Creates a texture from a file. Returns NULL on failure.
//
LL_Texture *LL_create_texture(CBYTE *fname);
//
// Deletes the texture.
//
void LL_free_texture(LL_Texture *lt);
//
// Loads a sound from a file. Returns NULL on failure.
//
LL_Sound *LL_create_sound(CBYTE *fname);
//
// Deletes the sound.
//
void LL_free_sound(LL_Sound *ls);
//
// Creates a buffer. The vertex and index memory should be
// allocated with the MEM module.
//
LL_Buffer *LL_create_buffer(
SLONG type,
void *vert,
SLONG num_verts,
UWORD *index, // If NULL then this is a LIST buffer rather than an INDEXED buffer.
SLONG num_indices);
//
// Deletes the buffer.
//
void LL_free_buffer(LL_Buffer *lb);
//
// The renderstates you can OR together.
//
#define LL_RS_NORMAL OS_DRAW_NORMAL
#define LL_RS_ADD OS_DRAW_ADD
#define LL_RS_MULTIPLY OS_DRAW_MULTIPLY
#define LL_RS_CLAMP OS_DRAW_CLAMP
#define LL_RS_DECAL OS_DRAW_DECAL
#define LL_RS_TRANSPARENT OS_DRAW_TRANSPARENT
#define LL_RS_DOUBLESIDED OS_DRAW_DOUBLESIDED
#define LL_RS_NOZWRITE OS_DRAW_NOZWRITE
#define LL_RS_ALPHAREF OS_DRAW_ALPHAREF
#define LL_RS_ZREVERSE OS_DRAW_ZREVERSE
#define LL_RS_ZALWAYS OS_DRAW_ZALWAYS
#define LL_RS_CULLREVERSE OS_DRAW_CULLREVERSE
#define LL_RS_NODITHER OS_DRAW_NODITHER
#define LL_RS_ALPHABLEND OS_DRAW_ALPHABLEND
#define LL_RS_TEX_NONE OS_DRAW_TEX_NONE
#define LL_RS_NOFILTER OS_DRAW_NOFILTER
#define LL_RS_MULBYONE OS_DRAW_MULBYONE
//
// Draws a buffer
//
void LL_draw_buffer(
LL_Buffer *lb,
LL_Texture *lt, // NULL => Draw untextured
ULONG rs); // The LL_RS_* renderstates ORed together.
void LL_cls(ULONG colour, float z);
//
// Flips the screen- actually does a blit or a FLIP depending
// on whether we are running in a window or not.
//
void LL_flip(void);
#endif

113
MuckyBasic/main.cpp Normal file
View File

@ -0,0 +1,113 @@
//
// The entrypoint for muckyBASIC
//
#include "always.h"
#include "cg.h"
#include "console.h"
#include "font.h"
#include "key.h"
#include "link.h"
#include "mem.h"
#include "parse.h"
#include "os.h"
#include "st.h"
#include "sysvar.h"
#include "vm.h"
//
// Compiles the given file. Returns TRUE on success.
//
SLONG MAIN_compile(CBYTE *input, CBYTE *output)
{
FILE *handle;
PARSE_do(input);
if (PARSE_error_upto)
{
//
// There are errors!
//
SLONG i;
for (i = 0; i < PARSE_error_upto; i++)
{
OS_string("%s\n", PARSE_error[i]);
}
return FALSE;
}
CG_do(output, CG_OUTPUT_OBJECT_FILE);
return TRUE;
}
void MAIN_main()
{
FONT_init();
ST_init();
//
// Compile.
//
if (!MAIN_compile("test.mbs", "MuckyBASIC objects\\test.mbo" )) return;
if (!MAIN_compile("test2.mbs", "MuckyBASIC objects\\test2.mbo")) return;
//
// Link.
//
CBYTE *link[] =
{
"MuckyBASIC objects\\test.mbo",
"MuckyBASIC objects\\test2.mbo",
};
LINK_do(link, 2, "MuckyBASIC executables\\test.mbe");
//
// Run.
//
VM_run("MuckyBASIC executables\\test.mbe");
//
// Wait for a key...
//
while(1)
{
if (KEY_on[KEY_ESCAPE])
{
KEY_on[KEY_ESCAPE] = 0;
break;
}
}
}

55
MuckyBasic/mem.cpp Normal file
View File

@ -0,0 +1,55 @@
//
// Memory allocation for the virtual machine.
//
#include "always.h"
#include "mem.h"
#include <malloc.h>
//
// The number of bytes of memory allocated by malloc() - not
// neccessarily the same number as that passed to MEM_alloc()
//
SLONG MEM_bytes_used;
void *MEM_alloc(SLONG num_bytes)
{
void *ans;
ans = malloc(num_bytes);
ASSERT(ans);
MEM_bytes_used += _msize(ans);
return ans;
}
void MEM_free(void *memory)
{
ASSERT(memory);
MEM_bytes_used -= _msize(memory);
free(memory);
}
SLONG MEM_block_size(void *memory)
{
ASSERT(memory);
return _msize(memory);
}
SLONG MEM_total_bytes_allocated()
{
return MEM_bytes_used;
}

40
MuckyBasic/mem.h Normal file
View File

@ -0,0 +1,40 @@
//
// Memory allocation for the virtual machine.
//
#ifndef _MEM_
#define _MEM_
//
// Allocates an area of memory.
//
void *MEM_alloc(SLONG num_bytes);
//
// Frees an area of memory allocated with MEM_alloc();
//
void MEM_free(void *memory);
//
// Returns the length in bytes of the given block.
//
SLONG MEM_block_size(void *memory);
//
// Returns the total amount of memory allocated in bytes.
//
SLONG MEM_total_bytes_allocated(void);
#endif

243
MuckyBasic/ml.h Normal file
View File

@ -0,0 +1,243 @@
//
// The language of our virtual machine and the executable
// file format.
//
#ifndef _ML_
#define _ML_
#include "ll.h"
//
// A memory location in the machine is 8-bytes long and contains
// an ML_Data. There is main memory where globals are held and a
// stack where computations are peformed and local variables are stored.
// There is also a string table (CBYTE[]) where string constants are
// stored. When an ML_Data must store a variable that is more than an
// SLONG it just malloc()s the required memory and then stores a pointer
// to it.
//
//
// Each instruction...
//
#define ML_DO_PUSH_CONSTANT 0 // Followed by an 8-byte constant.
#define ML_DO_ADD 1 // Adds the last two items on the stack and replaces them with the answer.
#define ML_DO_PRINT 2 // Pops the last item of the stack and prints it.
#define ML_DO_EXIT 3 // Exits.
#define ML_DO_GOTO 4 // Followed by the instruction to go to. In SLONGs from the beginning of the program.
#define ML_DO_UMINUS 5 // 'Minuses' the last item on the stack.
#define ML_DO_PUSH_GLOBAL_VALUE 6 // Followed by the number of the global to push.
#define ML_DO_MINUS 7 // Does stack[-2] = stack[-2] - stack[-1]; stack -= 1...
#define ML_DO_TIMES 8 // Does stack[-2] = stack[-2] * stack[-1]; stack -= 1...
#define ML_DO_DIVIDE 9 // Does stack[-2] = stack[-2] / stack[-1]; stack -= 1...
#define ML_DO_MOD 10 // Does stack[-2] = stack[-2] % stack[-1]; stack -= 1...
#define ML_DO_IF_FALSE_GOTO 11 // Pops the stack. If it is FALSE then it does a GOTO (next instruction holds address)
#define ML_DO_AND 12 // etc...!
#define ML_DO_OR 13
#define ML_DO_EQUALS 14
#define ML_DO_GT 15
#define ML_DO_LT 16
#define ML_DO_GTEQ 17
#define ML_DO_LTEQ 18
#define ML_DO_NOT 19
#define ML_DO_SQRT 20
#define ML_DO_NEWLINE 21 // A PRINT without anything produces a NEWLINE instruction...
#define ML_DO_ABS 22
#define ML_DO_PUSH_GLOBAL_ADDRESS 23 // Pushes an 'ML_TYPE_POINTER' onto the stack containing the address of the given global.
#define ML_DO_ASSIGN 24 // stack[-2] is a value, stack[-1] is a pointer. Assigns the value to the ML_Data pointed to by stack[-1]
#define ML_DO_PUSH_FIELD_ADDRESS 25 // The next instruction contains the field_id. This function pops off a pointer to a data and pushes on the address of the given field of that bit of data.
#define ML_DO_PUSH_FIELD_VALUE 26
#define ML_DO_PUSH_ARRAY_ADDRESS 27 // The next instruction contains the dimensions of the array and the indices will already be on the stack
#define ML_DO_PUSH_ARRAY_VALUE 28
#define ML_DO_PUSH_INPUT 29 // Gets user input as a string and pushes it onto the stack
#define ML_DO_GOSUB 30
#define ML_DO_RETURN 31
#define ML_DO_XOR 32
#define ML_DO_PUSH_GLOBAL_QUICK 33
#define ML_DO_PUSH_FIELD_QUICK 34 // Pushes the actual field onto the stack- not a copy of it.
#define ML_DO_PUSH_ARRAY_QUICK 35 // Pushes the actual array onto the stack- not a copy of it.
#define ML_DO_NOTEQUAL 36
#define ML_DO_IF_TRUE_GOTO 37
#define ML_DO_PUSH_RANDOM_SLUMBER 38 // Pushes a random SLUMBER onto the stack.
#define ML_DO_SWAP 39 // Swaps the contents of the last two ML_TYPE_POINTERs on the stack.
#define ML_DO_ENTERFUNC 40 // Followed by the number of arguments passed to the function.
#define ML_DO_ENDFUNC 41 // Followed by the number of arguments passed to the function.
#define ML_DO_POP 42 // Throws away the value at the top of the stack.
#define ML_DO_PUSH_LOCAL_VALUE 43
#define ML_DO_PUSH_LOCAL_ADDRESS 44
#define ML_DO_PUSH_LOCAL_QUICK 45
#define ML_DO_JNEQ_POP_1 46 // For switch statements. Compares two values on the stack. If not equal it pops one value and jumps otherwise it pops both values. The next SLONG hold where to jump to.
#define ML_DO_TEXTURE 47
#define ML_DO_BUFFER 48
#define ML_DO_DRAW 49
#define ML_DO_CLS 50
#define ML_DO_FLIP 51
#define ML_DO_KEY_VALUE 52
#define ML_DO_KEY_ASSIGN 53
#define ML_DO_INKEY_VALUE 54
#define ML_DO_INKEY_ASSIGN 55
#define ML_DO_TIMER 56
#define ML_DO_SIN 57
#define ML_DO_COS 58
#define ML_DO_TAN 59
#define ML_DO_ASIN 60
#define ML_DO_ACOS 61
#define ML_DO_ATAN 62
#define ML_DO_ATAN2 63
#define ML_DO_NOP 64
#define ML_DO_LEFT 65
#define ML_DO_MID 66
#define ML_DO_RIGHT 67
#define ML_DO_LEN 68
#define ML_DO_PUSH_IDENTITY_MATRIX 69 // Pushes an identity matrix onto the stack
#define ML_DO_PUSH_ZERO_VECTOR 70 // Pushes a zero vector onto the stack
#define ML_DO_MATRIX 71 // Constructs a matrix from three vectors on the stack
#define ML_DO_VECTOR 72 // Constructs a vector from three numbers on the stack
#define ML_DO_PUSH_UP 73 // Push vector ( 0,+1, 0)
#define ML_DO_PUSH_DOWN 74 // Push vector ( 0,-1, 0)
#define ML_DO_PUSH_LEFT 75 // Push vector (-1, 0, 0)
#define ML_DO_PUSH_RIGHT 76 // Push vector (+1, 0, 0)
#define ML_DO_PUSH_FORWARDS 77 // Push vector ( 0, 0,+1)
#define ML_DO_PUSH_BACKWARDS 78 // Push vector ( 0, 0,-1)
#define ML_DO_DOT 79 // The dot product of two vectors on the stack
#define ML_DO_CROSS 80 // The cross product of two vectors on the stack
//
// The basic types.
//
#define ML_TYPE_UNDEFINED 0
#define ML_TYPE_SLUMBER 1
#define ML_TYPE_FLUMBER 2
#define ML_TYPE_STRCONST 3 // A string constant located in the string data segment.
#define ML_TYPE_STRVAR 4
#define ML_TYPE_BOOLEAN 5
#define ML_TYPE_POINTER 6 // Pointer to an ML_Data in the 'data' field.
#define ML_TYPE_STRUCTURE 7 // Pointer to an ML_Structure on the heap.
#define ML_TYPE_ARRAY 8 // Pointer to an ML_Array on the heap.
#define ML_TYPE_CODE_POINTER 9 // Instruction address
#define ML_TYPE_STACK_BASE 10 // The previous stack frame base pointer.
#define ML_TYPE_TEXTURE 11
#define ML_TYPE_BUFFER 12
#define ML_TYPE_NUM_ARGS 13 // The number of argument passed in a function call.
#define ML_TYPE_MATRIX 14
#define ML_TYPE_VECTOR 15
#define ML_TYPE_FLOINTER 16 // A pointer to a float inside a vector
#define ML_TYPE_VOINTER 17 // A pointer to a vector
//
// A memory location.
//
typedef struct ml_data ML_Data;
typedef struct ml_structure ML_Structure;
typedef struct ml_array ML_Array;
typedef struct ml_vector ML_Vector;
typedef struct ml_matrix ML_Matrix;
typedef struct ml_data
{
SLONG type;
union
{
SLONG value;
SLONG slumber;
float flumber;
SLONG strconst; // Index into the data table.
SLONG local; // Index into the current stackframe.
CBYTE *strvar; // Pointer to some MEM_alloc()ed memory.
SLONG boolean;
ML_Data *data; // Pointer to an ML_Data.
ML_Structure *structure; // Pointer to an ML_Structure on the heap.
ML_Array *array;
SLONG *code_pointer; // Index into instruction memory.
ML_Data *stack_base;
LL_Texture *lt;
LL_Buffer *lb;
CBYTE character;
SLONG args;
ML_Vector *vector;
ML_Matrix *matrix;
float *flointer;
};
} ML_Data;
typedef struct
{
SLONG field_id;
ML_Data data;
} ML_Field;
typedef struct ml_structure
{
SLONG num_fields;
ML_Field field[];
} ML_Structure;
typedef struct
{
SLONG size;
SLONG stride; // How many ML_Datas between two array members with consecutive indices in this dimension.
} ML_Dimension;
typedef struct ml_array
{
SLONG length; // Total number of ML_Datas in the data[] array.
SLONG num_dimensions;
ML_Data *data; // The actual data on the heap.
ML_Dimension dimension[];
} ML_Array;
typedef struct ml_vector
{
float x;
float y;
float z;
} ML_Vector;
typedef struct ml_matrix
{
ML_Vector vector[3];
} ML_Matrix;
//
// This is the header for the executable file.
//
#define ML_VERSION_NUMBER 1
typedef struct
{
SLONG version;
SLONG instructions_memory_in_bytes;
SLONG data_table_length_in_bytes;
SLONG num_globals;
//
// The instructions...
//
//
// The data table...
//
} ML_Header;
#endif

291
MuckyBasic/muckyBASIC.dsp Normal file
View File

@ -0,0 +1,291 @@
# Microsoft Developer Studio Project File - Name="muckyBASIC" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=muckyBASIC - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "muckyBASIC.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "muckyBASIC.mak" CFG="muckyBASIC - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "muckyBASIC - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "muckyBASIC - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""$/muckyBASIC", XXDAAAAA"
# PROP Scc_LocalPath "."
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "muckyBASIC - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W2 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ddraw.lib d3d8.lib dinput.lib dxguid.lib dsound.lib winmm.lib msacm32.lib /nologo /subsystem:windows /machine:I386
!ELSEIF "$(CFG)" == "muckyBASIC - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W2 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ddraw.lib d3d8.lib dinput.lib dxguid.lib dsound.lib winmm.lib msacm32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "muckyBASIC - Win32 Release"
# Name "muckyBASIC - Win32 Debug"
# Begin Group "D3DFrame"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\d3denum.cpp
# End Source File
# Begin Source File
SOURCE=.\d3denum.h
# End Source File
# Begin Source File
SOURCE=.\d3dframe.cpp
# End Source File
# Begin Source File
SOURCE=.\d3dframe.h
# End Source File
# Begin Source File
SOURCE=.\d3dutil.cpp
# End Source File
# Begin Source File
SOURCE=.\d3dutil.h
# End Source File
# Begin Source File
SOURCE=.\userdlg.cpp
# End Source File
# Begin Source File
SOURCE=.\wave.c
# End Source File
# Begin Source File
SOURCE=.\wave.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\Always.h
# End Source File
# Begin Source File
SOURCE=.\cg.cpp
# End Source File
# Begin Source File
SOURCE=.\cg.h
# End Source File
# Begin Source File
SOURCE=.\clip.cpp
# End Source File
# Begin Source File
SOURCE=.\clip.h
# End Source File
# Begin Source File
SOURCE=.\comp.cpp
# End Source File
# Begin Source File
SOURCE=.\comp.h
# End Source File
# Begin Source File
SOURCE=.\console.cpp
# End Source File
# Begin Source File
SOURCE=.\console.h
# End Source File
# Begin Source File
SOURCE=.\font.cpp
# End Source File
# Begin Source File
SOURCE=.\font.h
# End Source File
# Begin Source File
SOURCE=.\icon1.ico
# End Source File
# Begin Source File
SOURCE=.\Key.h
# End Source File
# Begin Source File
SOURCE=.\lex.cpp
# End Source File
# Begin Source File
SOURCE=.\lex.h
# End Source File
# Begin Source File
SOURCE=.\link.cpp
# End Source File
# Begin Source File
SOURCE=.\link.h
# End Source File
# Begin Source File
SOURCE=.\ll.cpp
# End Source File
# Begin Source File
SOURCE=.\ll.h
# End Source File
# Begin Source File
SOURCE=.\main.cpp
# End Source File
# Begin Source File
SOURCE=.\Matrix.cpp
# End Source File
# Begin Source File
SOURCE=.\Matrix.h
# End Source File
# Begin Source File
SOURCE=.\mem.cpp
# End Source File
# Begin Source File
SOURCE=.\mem.h
# End Source File
# Begin Source File
SOURCE=.\ml.h
# End Source File
# Begin Source File
SOURCE=.\muckyBASIC.rc
# End Source File
# Begin Source File
SOURCE=.\os.cpp
# End Source File
# Begin Source File
SOURCE=.\os.h
# End Source File
# Begin Source File
SOURCE=.\parse.cpp
# End Source File
# Begin Source File
SOURCE=.\parse.h
# End Source File
# Begin Source File
SOURCE=.\st.cpp
# End Source File
# Begin Source File
SOURCE=.\st.h
# End Source File
# Begin Source File
SOURCE=.\sysvar.cpp
# End Source File
# Begin Source File
SOURCE=.\sysvar.h
# End Source File
# Begin Source File
SOURCE=.\test.mbs
# End Source File
# Begin Source File
SOURCE=.\test2.mbs
# End Source File
# Begin Source File
SOURCE=.\Tga.cpp
# End Source File
# Begin Source File
SOURCE=.\Tga.h
# End Source File
# Begin Source File
SOURCE=.\vm.cpp
# End Source File
# Begin Source File
SOURCE=.\vm.h
# End Source File
# End Target
# End Project

37
MuckyBasic/muckyBASIC.dsw Normal file
View File

@ -0,0 +1,37 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "muckyBASIC"=.\muckyBASIC.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/muckyBASIC", XXDAAAAA
.
end source code control
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
begin source code control
"$/muckyBASIC", XXDAAAAA
.
end source code control
}}}
Package=<3>
{{{
}}}
###############################################################################

116
MuckyBasic/muckyBASIC.rc Normal file
View File

@ -0,0 +1,116 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DRIVERS DIALOG DISCARDABLE 0, 0, 208, 111
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "muckyBASIC Virtual Machine"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "Start",IDOK,50,86,50,16
PUSHBUTTON "Exit",IDCANCEL,105,86,50,16
LTEXT "Driver",IDC_STATIC,8,24,32,8
COMBOBOX IDC_COMBO_DRIVER,40,24,160,88,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
LTEXT "Mode",IDC_STATIC,8,48,32,8
COMBOBOX IDC_COMBO_MODE,40,48,160,77,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
LTEXT "Choose your driver and screen mode...",IDC_STATIC,8,8,
192,8
CTEXT "(Detected a 166MHz processor)",IDC_PROCESSOR,5,70,194,
10,SS_CENTERIMAGE
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_DRIVERS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 201
TOPMARGIN, 7
BOTTOMMARGIN, 104
END
END
#endif // APSTUDIO_INVOKED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "icon1.ico"
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

5945
MuckyBasic/os.cpp Normal file

File diff suppressed because it is too large Load Diff

664
MuckyBasic/os.h Normal file
View File

@ -0,0 +1,664 @@
//
// Interface to all the OS functions.
//
#ifndef _OS_
#define _OS_
// ========================================================
//
// WINDOWS AND MISCELLANEOUS STUFF
//
// ========================================================
//
// The command line passed to the program.
//
extern CBYTE *OS_command_line;
//
// Outputs a debug string.
// Returns the number of milliseconds since MAIN_main was called. It is very accurate.
// Resets OS_ticks()
// Returns the Mhz of the current processor.
//
void OS_string (CBYTE *fmt, ...);
void OS_reset_ticks (void);
SLONG OS_ticks (void);
void OS_ticks_reset (void);
SLONG OS_processor_mhz(void);
//
// In windowed mode it puts up an error message. In release build or
// fullscreen mode, it return and does nothing.
//
void OS_error(CBYTE *fmt, ...);
//
// Returns TRUE if the given file has its archive bit set. Returns
// FALSE if the file is not found.
//
SLONG OS_is_archive_bit_set(CBYTE *fname);
void OS_clear_archive_bit (CBYTE *fname);
// ========================================================
//
// TEXTURE STUFF
//
// ========================================================
typedef struct os_texture OS_Texture;
//
// You can create a texture either from a TGA file or just by
// specifying a size and format. If the file could not be loaded
// then a blank texture is used instead. If you try and create
// a texture from the same TGA file twice, the same pointer will
// be returned both times.
//
// It looks for the file in the "Textures\" directory and then
// in any directory its find in it's texture path. It loads
// additional texture paths from the "data\texurepaths.txt" file
//
#define OS_TEXTURE_FORMAT_RGB 0 // RGB
#define OS_TEXTURE_FORMAT_1555 1 // ARGB
#define OS_TEXTURE_FORMAT_4444 2 // ARGB
#define OS_TEXTURE_FORMAT_8 3 // Grayscale
#define OS_TEXTURE_FORMAT_SCREEN 4 // The same format that the back buffer is in.
#define OS_TEXTURE_FORMAT_NUMBER 5
#define OS_TEXTURE_MAX_SIZE 512
OS_Texture *OS_texture_create(CBYTE *fname, SLONG invert = FALSE);
OS_Texture *OS_texture_create(SLONG width, SLONG height, SLONG format);
//
// Call this function once you have loaded all textures. It ensures that
// as many of the textures as possible start off on the card instead of
// only in the texture cache in system memory.
//
void OS_texture_finished_creating(void);
//
// Returns the size of the texture.
//
SLONG OS_texture_width (OS_Texture *ot);
SLONG OS_texture_height(OS_Texture *ot);
//
// To updating a texture yourself, lock the texture and write
// into the bitmap. When you unlock it, the new texture will
// be blitted to the hardware.
//
// You're not allowed to READ from the texture! Only write.
//
// On success one of OS_bitmap_uword_screen or OS_bitmap_ubyte_screen will
// point to the screen memory.
//
void OS_texture_lock (OS_Texture *ot); // OS_bitmap_screen == NULL => lock failed.
void OS_texture_unlock(OS_Texture *ot);
//
// The bitmap returned by OS_texture_lock. To create a pixel, use the masks and
// shifts like this:
//
// pixel = (r >> mask_r) << shift_r;
// pixel |= (g >> mask_g) << shift_g;
// pixel |= (b >> mask_b) << shift_b;
//
// Include alpha only if the original texture had alpha.
//
extern SLONG OS_bitmap_format; // OS_TEXTURE_FORMAT_*
extern UWORD *OS_bitmap_uword_screen; // For 16-bit formats.
extern SLONG OS_bitmap_uword_pitch; // Pitch in UWORDS
extern UBYTE *OS_bitmap_ubyte_screen; // For the grayscale format.
extern SLONG OS_bitmap_ubyte_pitch; // Pitch in UBYTES
extern SLONG OS_bitmap_width;
extern SLONG OS_bitmap_height;
extern SLONG OS_bitmap_mask_r;
extern SLONG OS_bitmap_mask_g;
extern SLONG OS_bitmap_mask_b;
extern SLONG OS_bitmap_mask_a;
extern SLONG OS_bitmap_shift_r;
extern SLONG OS_bitmap_shift_g;
extern SLONG OS_bitmap_shift_b;
extern SLONG OS_bitmap_shift_a;
//
// Writes a pixel to a 16-bit bitmap.
//
#define OS_BITMAP_UWORD_PIXEL(x,y) (OS_bitmap_uword_screen + (x) + (y) * OS_bitmap_uword_pitch)
#define OS_BITMAP_UWORD_COLOUR(r,g,b) ((((r) >> OS_bitmap_mask_r) << OS_bitmap_shift_r) | (((g) >> OS_bitmap_mask_g) << OS_bitmap_shift_g) | (((b) >> OS_bitmap_mask_b) << OS_bitmap_shift_b))
#define OS_BITMAP_UWORD_PLOT(x,y,r,g,b) {*OS_BITMAP_UWORD_PIXEL(x,y) = OS_BITMAP_UWORD_COLOUR(r,g,b);}
//
// Write a pixel to an 8-bit bitmap
//
#define OS_BITMAP_UBYTE_PIXEL(x,y) (OS_bitmap_ubyte_screen + (x) + (y) * OS_bitmap_ubyte_pitch)
#define OS_BITMAP_UBYTE_PLOT(x,y,c) {*OS_BITMAP_UBYTE_PIXEL(x,y) = (c);}
//
// Blitting a portion of the backbuffer onto the texture.
// This will fail if the backbuffer and the texture are in
// different formats. Returns TRUE on success.
//
// The (x,y) is the upper left hand corner of the texture and
// the size of the region is given by the size of the texture.
//
// The texture can't be locked!
//
SLONG OS_texture_blit_from_backbuffer(OS_Texture *ot, SLONG x, SLONG y);
//
// Searches the "Textures\\" directory for the given file and returns
// the fullpath name. Returns the address from inside the same static
// array each time it is called. Returns NULL if it can't find the
// file inside the "Textures\\" directory.
//
CBYTE *OS_texture_full_path(CBYTE *fname);
// ========================================================
//
// THE CAMERA
//
// ========================================================
//
// Sets up the camera used to transform points added to the OS_Buffers.
//
void OS_camera_set(
float world_x,
float world_y,
float world_z,
float view_dist,
float yaw,
float pitch,
float roll,
float lens,
float screen_x1 = 0.0F,
float screen_y1 = 0.0F,
float screen_x2 = 1.0F,
float screen_y2 = 1.0F);
void OS_camera_set(
float world_x,
float world_y,
float world_z,
float view_dist,
float matrix[9],
float lens,
float screen_x1 = 0.0F,
float screen_y1 = 0.0F,
float screen_x2 = 1.0F,
float screen_y2 = 1.0F);
extern float OS_cam_x; // For reference only! Use the function above to set the camera
extern float OS_cam_y;
extern float OS_cam_z;
extern float OS_cam_lens;
extern float OS_cam_view_matrix [9];
extern float OS_cam_view_matrix_plus_local_rot[9]; // For when using OS_transform_local()
//
// The clipping flags.
//
#define OS_CLIP_TOP (1 << 0)
#define OS_CLIP_BOTTOM (1 << 1)
#define OS_CLIP_LEFT (1 << 2)
#define OS_CLIP_RIGHT (1 << 3)
#define OS_CLIP_FAR (1 << 4)
#define OS_CLIP_NEAR (1 << 5)
#define OS_CLIP_ROTATED (1 << 6)
#define OS_CLIP_TRANSFORMED (1 << 7)
#define OS_CLIP_OFFSCREEN (OS_CLIP_TOP|OS_CLIP_BOTTOM|OS_CLIP_LEFT|OS_CLIP_RIGHT)
#define OS_ZCLIP_PLANE (128.0F / 65536.0F)
//
// Transformed points.
//
typedef struct
{
float x;
float y;
float z;
float X;
float Y;
float Z;
ULONG clip;
} OS_Trans;
#define OS_MAX_TRANS 16384
extern OS_Trans OS_trans[OS_MAX_TRANS];
extern SLONG OS_trans_upto;
//
// Transforming points.
//
void OS_transform(
float world_x,
float world_y,
float world_z,
OS_Trans *os);
//
// Sets the local position and orientation for OS_transform_local().
//
void OS_local_position_and_rotation(
float world_x,
float world_y,
float world_z,
float local_rotation_matrix[9]);
//
// Transforms a point, but first puts it through the local rotation
// and position given by OS_local_position_and_rotation().
//
void OS_transform_local(
float local_x,
float local_y,
float local_z,
OS_Trans *os);
// ========================================================
//
// BUFFERS FOR COLLECTING TOGETHER POINTS AND TRIANGLES
//
// ========================================================
typedef struct os_buffer OS_Buffer;
typedef struct
{
UWORD trans; // Index into the OS_trans array for the transformed point.
UWORD index; // Before you add any OS_Verts to a buffer make sure they all have this field set to NULL
float u1;
float v1;
float u2; // For multitexturing.
float v2;
ULONG colour;
ULONG specular;
} OS_Vert;
//
// The number of poly's drawn last frame.
//
extern SLONG OS_poly_count_transformed;
extern SLONG OS_poly_count_drawn;
//
// Returns a new buffer to which you can add triangles.
//
OS_Buffer *OS_buffer_new(void);
//
// Adds a triangle to the buffer. The triangle is given by three vertices
// into an OS_Vert array whose tlvert field is all set to zero.
//
void OS_buffer_add_triangle(
OS_Buffer *ob,
OS_Vert *ov1,
OS_Vert *ov2,
OS_Vert *ov3);
//
// Adds a 2D sprite to the buffer.
//
#define OS_FADE_TOP (1 << 0)
#define OS_FADE_BOTTOM (1 << 1)
#define OS_FADE_LEFT (1 << 2)
#define OS_FADE_RIGHT (1 << 3)
void OS_buffer_add_sprite(
OS_Buffer *ob,
float x1, // Normalised to 0.0F - 1.0F
float y1, // Normalised to 0.0F - 1.0F
float x2, // Normalised to 0.0F - 1.0F
float y2, // Normalised to 0.0F - 1.0F
float u1 = 0.0F, float v1 = 0.0F,
float u2 = 1.0F, float v2 = 1.0F,
float z = 0.0F,
ULONG colour = 0xffffffff,
ULONG specular = 0x00000000,
ULONG fade = 0);
void OS_buffer_add_multitex_sprite(
OS_Buffer *ob,
float x1, // Normalised to 0.0F - 1.0F
float y1, // Normalised to 0.0F - 1.0F
float x2, // Normalised to 0.0F - 1.0F
float y2, // Normalised to 0.0F - 1.0F
float u11 = 0.0F, float v11 = 0.0F,
float u12 = 1.0F, float v12 = 1.0F,
float u21 = 0.0F, float v21 = 0.0F,
float u22 = 1.0F, float v22 = 1.0F,
float z = 0.0F,
ULONG colour = 0xffffffff,
ULONG specular = 0x00000000,
ULONG fade = 0);
//
// Adds a rotated 2D sprite to the buffer.
//
void OS_buffer_add_sprite_rot(
OS_Buffer *ob,
float x_mid,
float y_mid,
float radius, // As a percentage of the width of the screen.
float angle,
float u1 = 0.0F, float v1 = 0.0F,
float u2 = 1.0F, float v2 = 1.0F,
float z = 0.0F,
ULONG colour = 0xffffffff,
ULONG specular = 0x00000000,
float tu1 = 0.0F, float tv1 = 0.0F, // For the second pass...
float tu2 = 1.0F, float tv2 = 1.0F);
//
// Adds an arbitrary-shaped sprite to the buffer. The points are
// given in this order.
//
// 0-------1
// / \
// 2-----------3
void OS_buffer_add_sprite_arbitrary(
OS_Buffer *ob,
float x1, // Normalised to 0.0F - 1.0F
float y1, // Normalised to 0.0F - 1.0F
float x2, // Normalised to 0.0F - 1.0F
float y2, // Normalised to 0.0F - 1.0F
float x3, // Normalised to 0.0F - 1.0F
float y3, // Normalised to 0.0F - 1.0F
float x4, // Normalised to 0.0F - 1.0F
float y4, // Normalised to 0.0F - 1.0F
float u1 = 0.0F, float v0 = 0.0F,
float u2 = 1.0F, float v2 = 0.0F,
float u3 = 0.0F, float v3 = 1.0F,
float u4 = 1.0F, float v4 = 1.0F,
float z = 0.0F,
ULONG colour = 0xffffffff,
ULONG specular = 0x00000000);
void OS_buffer_add_sprite_arbitrary(
OS_Buffer *ob,
float x1, // Normalised to 0.0F - 1.0F
float y1, // Normalised to 0.0F - 1.0F
float x2, // Normalised to 0.0F - 1.0F
float y2, // Normalised to 0.0F - 1.0F
float x3, // Normalised to 0.0F - 1.0F
float y3, // Normalised to 0.0F - 1.0F
float x4, // Normalised to 0.0F - 1.0F
float y4, // Normalised to 0.0F - 1.0F
float u1 = 0.0F, float v0 = 0.0F,
float u2 = 1.0F, float v2 = 0.0F,
float u3 = 0.0F, float v3 = 1.0F,
float u4 = 1.0F, float v4 = 1.0F,
float z1 = 0.0F,
float z2 = 0.0F,
float z3 = 0.0F,
float z4 = 0.0F,
ULONG colour = 0xffffffff,
ULONG specular = 0x00000000);
//
// Adds a line.
//
void OS_buffer_add_line_2d(
OS_Buffer *ob,
float x1, // Normalised to 0.0F - 1.0F
float y1, // Normalised to 0.0F - 1.0F
float x2, // Normalised to 0.0F - 1.0F
float y2, // Normalised to 0.0F - 1.0F
float width = 0.01F, // As a percentage of the width of the screen.
float u1 = 0.0F, float v1 = 0.0F,
float u2 = 1.0F, float v2 = 1.0F,
float z = 0.0F,
ULONG colour = 0xffffffff,
ULONG specular = 0x00000000);
void OS_buffer_add_line_3d(
OS_Buffer *ob,
float X1, // These are in REAL SCREEN COORDINATES!
float Y1, // These are in REAL SCREEN COORDINATES!
float X2, // These are in REAL SCREEN COORDINATES!
float Y2, // These are in REAL SCREEN COORDINATES!
float width = 0.01F, // As a percentage of the width of the screen.
float u1 = 0.0F, float v1 = 0.0F,
float u2 = 1.0F, float v2 = 1.0F,
float z1 = 0.0F,
float z2 = 0.0F,
ULONG colour = 0xffffffff,
ULONG specular = 0x00000000);
//
// Draws the buffer in the way defined by the OS_DRAW_* flags and the texture. After
// drawing a buffer it becomes invalid. You can't add triangles to it anymore.
//
#define OS_DRAW_NORMAL 0 // Normal zbuffered gouraud textured triangle
#define OS_DRAW_ADD (1 << 0) // Pixel = source + dest
#define OS_DRAW_MULTIPLY (1 << 1) // Pixel = source * dest * 2
#define OS_DRAW_CLAMP (1 << 2) // No texture wrapping
#define OS_DRAW_DECAL (1 << 3) // No gouraud
#define OS_DRAW_TRANSPARENT (1 << 4) // Just the zbuffer written to (Pixel = dest)
#define OS_DRAW_DOUBLESIDED (1 << 5) // Don't backface cull
#define OS_DRAW_NOZWRITE (1 << 6) // Don't write to the zbuffer
#define OS_DRAW_ALPHAREF (1 << 7) // Don't draw if alpha channel is zero
#define OS_DRAW_ZREVERSE (1 << 8) // Reverses the order or the zbuffer
#define OS_DRAW_ZALWAYS (1 << 9) // Never z-reject.
#define OS_DRAW_CULLREVERSE (1 << 10) // Flip the direction of backface culling
#define OS_DRAW_NODITHER (1 << 11) // Turn of gouraud-shade dithering
#define OS_DRAW_ALPHABLEND (1 << 12) // Alphablending
#define OS_DRAW_TEX_NONE (1 << 13) // No texture mapping
#define OS_DRAW_TEX_MUL (1 << 14) // Two textures multiplied together
#define OS_DRAW_NOFILTER (1 << 15) // No filtering
#define OS_DRAW_MULBYONE (1 << 16) // Pixel = source * dest * 1
void OS_buffer_draw(
OS_Buffer *ob,
OS_Texture *ot1, // NULL => No texture mapping
OS_Texture *ot2 = NULL,
ULONG draw = OS_DRAW_NORMAL);
// ========================================================
//
// RENDER LOOP STUFF
//
// ========================================================
//
// A couple of BOOLs to tell you how the screen is setup.
//
extern UBYTE OS_frame_is_fullscreen;
extern UBYTE OS_frame_is_hardware;
extern float OS_screen_width;
extern float OS_screen_height;
//
// Clears the screen.
//
void OS_clear_screen(
UBYTE r = 0,
UBYTE g = 0,
UBYTE b = 0,
float z = 1.0F);
//
// Draws the FPS onto the screen. Call ONCE a frame!
//
void OS_fps_draw(void);
SLONG OS_fps_get (void);
//
// Flips the screen.
//
void OS_show(void);
//
// Saves out a screenshot. If the filename is NULL then
// it saves out shot<n>.tga where n is the lowest available
// number.
//
void OS_screenshot(CBYTE *fname = NULL);
// ========================================================
//
// MOUSE STUFF
//
// ========================================================
void OS_mouse_get(SLONG *x, SLONG *y);
void OS_mouse_set(SLONG x, SLONG y);
// ========================================================
//
// SOUND STUFF
//
// ========================================================
//
// A sound identifier, so you can change a sounds attributes.
//
typedef struct os_sound OS_Sound;
//
// Creates a new sound.
//
#define OS_SOUND_TYPE_UNUSED 0
#define OS_SOUND_TYPE_2D 1
#define OS_SOUND_TYPE_3D 2
OS_Sound *OS_sound_create(CBYTE *fname, SLONG type);
//
// Assumes the sound to be mono at 22050 samples per second.
//
OS_Sound *OS_sound_create(UWORD *data, SLONG num_samples, SLONG type);
//
// Plays a sound. If OS_SOUND_FLAG_LOOP then the sound will play until
// it is stopped with OS_sound_stop().
//
#define OS_SOUND_FLAG_INTERRUPT (1 << 0) // If this sample is already playing- it will start again.
#define OS_SOUND_FLAG_LOOP (1 << 1) // Continue playing until OS_sound_stop() is called.
void OS_sound_play(OS_Sound *sound, SLONG flag = 0);
void OS_sound_stop(OS_Sound *sound);
//
// For 2D sounds.
//
void OS_sound_2d_set_volume(OS_Sound *sound, float volume); // volume is between 0.0F and 1.0F
//
// For 3D sounds. The new setting take effect from the next
// time you call OS_process_messages().
//
void OS_sound_3d_set_range (OS_Sound *sound, float min, float max);
void OS_sound_3d_set_position(
OS_Sound *sound,
float x,
float y,
float z,
float dx = 0.0F,
float dy = 0.0F,
float dz = 0.0F);
//
// Setup the listener for 3D sounds.
//
void OS_sound_listener_set(
float x,
float y,
float z,
float dx = 0.0F,
float dy = 0.0F,
float dz = 0.0F,
float yaw = 0.0F,
float pitch = 0.0F,
float roll = 0.0F);
// ========================================================
//
// JOYSTICK INPUT
//
// ========================================================
//
// These values are updated after each call to OS_process_messages()
//
extern float OS_joy_x; // -1.0F to +1.0F
extern float OS_joy_y; // -1.0F to +1.0F
extern ULONG OS_joy_button; // The buttons that are currently down
extern ULONG OS_joy_button_down; // The buttons that have just been pressed
extern ULONG OS_joy_button_up; // The buttons that have just been released
#endif

3994
MuckyBasic/parse.cpp Normal file

File diff suppressed because it is too large Load Diff

196
MuckyBasic/parse.h Normal file
View File

@ -0,0 +1,196 @@
//
// A recursive descent parser.
//
#ifndef _PARSE_
#define _PARSE_
//
// Each line produces a node. A node is a tree structure.
//
#define PARSE_NODE_TYPE_NOP 0 // For a blank line
#define PARSE_NODE_TYPE_EQUALS 1
#define PARSE_NODE_TYPE_PLUS 2
#define PARSE_NODE_TYPE_MINUS 3
#define PARSE_NODE_TYPE_UMINUS 4 // Unary minus
#define PARSE_NODE_TYPE_TIMES 5
#define PARSE_NODE_TYPE_DIVIDE 6
#define PARSE_NODE_TYPE_SLUMBER 7
#define PARSE_NODE_TYPE_FLUMBER 8
#define PARSE_NODE_TYPE_STRING 9
#define PARSE_NODE_TYPE_VAR_VALUE 10
#define PARSE_NODE_TYPE_IF 11
#define PARSE_NODE_TYPE_GOTO 12
#define PARSE_NODE_TYPE_LABEL 13 // Child1 is the rest of the statement for the line
#define PARSE_NODE_TYPE_GT 14
#define PARSE_NODE_TYPE_LT 15
#define PARSE_NODE_TYPE_GTEQ 16
#define PARSE_NODE_TYPE_LTEQ 17
#define PARSE_NODE_TYPE_AND 18
#define PARSE_NODE_TYPE_OR 19
#define PARSE_NODE_TYPE_NOT 20
#define PARSE_NODE_TYPE_DOT 21 // A fullstop that isn't part of a number
#define PARSE_NODE_TYPE_CALL 22
#define PARSE_NODE_TYPE_LOCAL 23 // Child1 may point to another local node...
#define PARSE_NODE_TYPE_PRINT 24
#define PARSE_NODE_TYPE_ASSIGN 25 // Equals := , assignment...
#define PARSE_NODE_TYPE_VAR_ADDRESS 26
#define PARSE_NODE_TYPE_MOD 27
#define PARSE_NODE_TYPE_BOOLEAN 28
#define PARSE_NODE_TYPE_SQRT 29
#define PARSE_NODE_TYPE_NEWLINE 30 // A PRINT without anything else...
#define PARSE_NODE_TYPE_ABS 31
#define PARSE_NODE_TYPE_PUSH_FIELD_ADDRESS 32
#define PARSE_NODE_TYPE_FIELD 33
#define PARSE_NODE_TYPE_PUSH_FIELD_VALUE 34
#define PARSE_NODE_TYPE_EXP_LIST 35
#define PARSE_NODE_TYPE_PUSH_ARRAY_ADDRESS 36
#define PARSE_NODE_TYPE_PUSH_ARRAY_VALUE 37
#define PARSE_NODE_TYPE_INPUT 38
#define PARSE_NODE_TYPE_UNDEFINED 39 // The constant value <UNDEFINED>
#define PARSE_NODE_TYPE_STATEMENT_LIST 40
#define PARSE_NODE_TYPE_EXIT 41
#define PARSE_NODE_TYPE_RETURN 42
#define PARSE_NODE_TYPE_GOSUB 43
#define PARSE_NODE_TYPE_XOR 44
#define PARSE_NODE_TYPE_FOR 45
#define PARSE_NODE_TYPE_NEXT 46
#define PARSE_NODE_TYPE_NOTEQUAL 47
#define PARSE_NODE_TYPE_RANDOM 48
#define PARSE_NODE_TYPE_SWAP 49
#define PARSE_NODE_TYPE_MIF 50 // A multi-line IF
#define PARSE_NODE_TYPE_MELSE 51 // The ELSE of a multi-line IF
#define PARSE_NODE_TYPE_MENDIF 52 // THE ENDIF of a multi-line IF
#define PARSE_NODE_TYPE_WHILE 53
#define PARSE_NODE_TYPE_LOOP 54
#define PARSE_NODE_TYPE_FUNCTION 55
#define PARSE_NODE_TYPE_ARGUMENT 56
#define PARSE_NODE_TYPE_ENDFUNC 57
#define PARSE_NODE_TYPE_TEXTURE 58
#define PARSE_NODE_TYPE_BUFFER 59
#define PARSE_NODE_TYPE_DRAW 60
#define PARSE_NODE_TYPE_CLS 61
#define PARSE_NODE_TYPE_FLIP 62
#define PARSE_NODE_TYPE_KEY_ASSIGN 63
#define PARSE_NODE_TYPE_KEY_VALUE 64
#define PARSE_NODE_TYPE_INKEY_ASSIGN 65
#define PARSE_NODE_TYPE_INKEY_VALUE 66
#define PARSE_NODE_TYPE_TIMER 67
#define PARSE_NODE_TYPE_SIN 68
#define PARSE_NODE_TYPE_COS 69
#define PARSE_NODE_TYPE_TAN 70
#define PARSE_NODE_TYPE_ASIN 71
#define PARSE_NODE_TYPE_ACOS 72
#define PARSE_NODE_TYPE_ATAN 73
#define PARSE_NODE_TYPE_ATAN2 74
#define PARSE_NODE_TYPE_EXPORT 75
#define PARSE_NODE_TYPE_LEFT 76
#define PARSE_NODE_TYPE_MID 77
#define PARSE_NODE_TYPE_RIGHT 78
#define PARSE_NODE_TYPE_LEN 79
#define PARSE_NODE_TYPE_MATRIX 80 // Child1 is an expression list or NULL
#define PARSE_NODE_TYPE_VECTOR 81 // Child1 is an expression list or NULL
#define PARSE_NODE_TYPE_DPROD 82
#define PARSE_NODE_TYPE_CPROD 83
#define PARSE_NODE_TYPE_NORMALISE 84
#define PARSE_NODE_TYPE_TRANSPOSE 85
#define PARSE_NODE_FLAG_EXTRACT (1 << 0) // If this node is the 'child1' of a PUSH_ARRAY_VALUE, PUSH_FIELD_VALUE, PUSH_ARRAY_ADDRESS or PUSH_FIELD_ADDRESS node.
#define PARSE_NODE_FLAG_CONDITIONAL (1 << 1) // This node is in the THEN or ELSE part of an IF statement.
#define PARSE_NODE_FLAG_EXPRESSION (1 << 2) // This node is part of an expression.
typedef struct parse_node PARSE_Node;
typedef struct parse_node
{
UWORD type;
UWORD flag;
union
{
SLONG slumber;
float flumber;
CBYTE *string;
CBYTE *label;
CBYTE *variable;
SLONG boolean;
CBYTE *field; // A string whose first character is '.' to indicate this is a field.
SLONG dimensions; // For a PUSHARRAYADDRESS or PUSHARRAYVALUE node, this gives the number of dimensions
PARSE_Node *lvalue; // A FOR node has the lvalue by which it is recognised in here.
CBYTE character; // For a CHAR_CONST
};
union
{
SLONG forcode; // A unique, non-zero, random code that pairs up FOR parse nodes with corresponding FAKE_ENDFOR nodes.
SLONG ifcode; // IF nodes have a unique, non-zero random code. This code is used by the 'pretend' node types in PARSE_traverse()...
SLONG whilecode; // Unique, non-zero and random. Matched up while nodes with corresponding FAKE_WHILE_COND nodes.
SLONG args; // The number of arguments in a PARSE_NODE_TYPE_CALL node (depth of child1) or the number of initialisers to a MATRIX or VECTOR
};
struct parse_node *child1;
struct parse_node *child2;
struct parse_node *child3;
} PARSE_Node;
//
// Returns an array of PARSE_Nodes that describes the program.
// It also returns a string table that contains all the strings
// and labels used in the program. Errors/warnings/status are
// returned in the PARSE_output variable.
//
extern PARSE_Node *PARSE_line[]; // NULL value means that line was blank.
extern SLONG PARSE_line_upto;
extern SLONG PARSE_string_table_upto;
extern CBYTE PARSE_string_table[];
extern CBYTE *PARSE_error[];
extern SLONG PARSE_error_upto;
void PARSE_do(CBYTE *fname);
//
// Traverses the given parse tree and called the user_function on
// each node of the tree. It traverses through the tree in a
// cunning order- to help out the CG module. It also inserts
// the pretend nodes...
//
#define PARSE_NODE_TYPE_FAKE_THEN 10000
#define PARSE_NODE_TYPE_FAKE_ELSE 10001
#define PARSE_NODE_TYPE_FAKE_END_ELSE 10002
#define PARSE_NODE_TYPE_FAKE_END_FOR 10003
#define PARSE_NODE_TYPE_FAKE_FOR_COND 10004
#define PARSE_NODE_TYPE_FAKE_WHILE_COND 10005
// That have their 'ifcode' field set to the IF instruction
// that they correspond to. The function should return FALSE
// to abort.
//
void PARSE_traverse(PARSE_Node *pn, SLONG (*user_function)(PARSE_Node *pn));
//
// Returns TRUE if the two PARSE trees are the same.
//
SLONG PARSE_trees_the_same(PARSE_Node *tree1, PARSE_Node *tree2);
#endif

85
MuckyBasic/resource.h Normal file
View File

@ -0,0 +1,85 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by muckyBASIC.rc
//
#define IDD_DRIVERS 101
#define IDI_ICON1 103
#define IDR_MAIN_MENU 106
#define IDR_POPUPS 110
#define IDC_COMBO1 1000
#define IDC_COMBO_DRIVER 1000
#define IDC_COMBO2 1001
#define IDC_COMBO_MODE 1001
#define IDC_BUTTON1 1002
#define IDC_MINFRAMERATE 1006
#define IDC_CONSTRES 1018
#define IDC_PROCESSOR 1022
#define IDC_RUN_DRIVING_GAME 1030
#define IDC_RUN_MY_GAME 1031
#define IDC_RUN_MIKES_GAME 1032
#define IDC_RUN_LIQUID_METAL 1033
#define IDC_RUN_ANIMATION_TEST 1034
#define IDC_RUN_TOON_TEST 1064
#define IDC_RUN_EGG_PHYSICS 1065
#define IDC_RUN_PATCH_TEST 1066
#define ID_MODE_BRUSH 40003
#define ID_BRUSH_TREE 40005
#define ID_MODE_SELECT 40009
#define ID_CAMERA_FOLLOWCAR 40010
#define ID_CAMERA_LOCKEDAROUNDPOINT 40011
#define ID_CAMERA_RESET 40013
#define ID_BRUSH_GRASS 40014
#define ID_BRUSH_OB 40015
#define ID_FILE_RESET 40016
#define ID_FILE_OPENMAP 40017
#define ID_FILE_SAVEMAP 40018
#define ID_FILE_SAVEMAPAS 40019
#define ID_FILE_LOADTRACKMESH 40020
#define ID_BRUSH_CAR 40024
#define ID_EDIT_DELETE 40027
#define ID_CAMERA_1STPERSON 40028
#define ID_CAMERA_DIFFERENTCAR 40030
#define ID_DRAW_TRACK 40031
#define ID_DRAW_OBS 40032
#define ID_DRAW_LINES 40033
#define ID_DRAW_CARS 40034
#define ID_CAR_MOVETO_POLEPOSITION 40044
#define ID_CAR_MOVETO_2NDPLACE 40046
#define ID_CAR_MOVETO_3RDPLACE 40047
#define ID_CAR_MOVETO_4THPLACE 40048
#define ID_CAR_MOVETO_5THPLACE 40049
#define ID_CAR_MOVETO_6THPLACE 40050
#define ID_SPLINE_STARTINGLINE 40051
#define ID_SPLINE_TRACKSEGMENT_1 40053
#define ID_SPLINE_TRACKSEGMENT_2 40054
#define ID_SPLINE_TRACKSEGMENT_3 40055
#define ID_SPLINE_TRACKSEGMENT_4 40056
#define ID_SPLINE_TRACKSEGMENT_5 40057
#define ID_SPLINE_TRACKSEGMENT_6 40058
#define ID_SPLINE_TRACKSEGMENT_7 40059
#define ID_SPLINE_TRACKSEGMENT_8 40060
#define ID_SPLINE_TRACKSEGMENT_9 40061
#define ID_SPLINE_TRACKSEGMENT_10 40062
#define ID_SPLINE_TRACKSEGMENT_11 40063
#define ID_SPLINE_TRACKSEGMENT_12 40064
#define ID_SPLINE_TRACKSEGMENT_13 40065
#define ID_SPLINE_TRACKSEGMENT_14 40066
#define ID_SPLINE_TRACKSEGMENT_15 40067
#define ID_SPLINE_TRACKSEGMENT_16 40068
#define ID_CAR_DEF_POLEPOSITION 40069
#define ID_CAR_DEF_2NDPLACE 40070
#define ID_CAR_DEF_3RDPLACE 40071
#define ID_CAR_DEF_4THPLACE 40072
#define ID_CAR_DEF_5THPLACE 40073
#define ID_CAR_DEF_6THPLACE 40074
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 112
#define _APS_NEXT_COMMAND_VALUE 40075
#define _APS_NEXT_CONTROL_VALUE 1066
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

400
MuckyBasic/st.cpp Normal file
View File

@ -0,0 +1,400 @@
//
// A symbol table.
//
#include "always.h"
#include "st.h"
//
// A symbol.
//
typedef struct
{
ULONG hash;
SLONG value;
SLONG flag;
UWORD string; // Offset into the buffer
UWORD next;
} ST_Symbol;
//
// A symbol table.
//
typedef struct
{
//
// Where we store strings.
//
CBYTE *buffer;
SLONG buffer_upto;
SLONG buffer_max;
//
// Where we store symbols.
//
ST_Symbol *symbol;
SLONG symbol_upto;
SLONG symbol_max;
//
// A hash table. Each entry is the start of a linked list.
//
#define ST_HASH_SIZE 512
UWORD hash[ST_HASH_SIZE];
} ST_Table;
ST_Table ST_table[ST_TABLE_NUMBER];
//
// Computes the hash value of a string.
//
ULONG ST_hash_value(CBYTE *string)
{
ULONG ans = 0;
SLONG rot = 0;
CBYTE *ch;
for (ch = string; *ch; ch++)
{
ans ^= _lrotl(*ch, rot);
rot += 7;
}
ans ^= ans >> 16; // So more letters count...
return ans;
}
void ST_init()
{
SLONG i;
ST_Table *st;
//
// Clear all data.
//
memset(ST_table, 0, sizeof(ST_table));
//
// Initialise each table.
//
for (i = 0; i < ST_TABLE_NUMBER; i++)
{
st = &ST_table[i];
st->buffer_max = 8192;
st->buffer_upto = 0;
st->buffer = (CBYTE *) malloc(sizeof(CBYTE) * st->buffer_max);
st->symbol_max = 1024;
st->symbol_upto = 1; // The 0th element is the NULL index...
st->symbol = (ST_Symbol *) malloc(sizeof(ST_Symbol) * st->symbol_max);
}
}
void ST_add(SLONG table, CBYTE *string, SLONG value, SLONG flag)
{
ST_Table *st;
ST_Symbol *ss;
SLONG symbol;
ASSERT(WITHIN(table, 0, ST_TABLE_NUMBER - 1));
st = &ST_table[table];
//
// Compute the hash value.
//
ULONG hash = ST_hash_value(string);
#ifdef _DEBUG
//
// Do we already have this symbol?
//
#endif
//
// Get a new symbol. Is there enough room?
//
if (st->symbol_upto >= st->symbol_max)
{
st->symbol_max *= 2;
st->symbol = (ST_Symbol *) realloc(st->symbol, sizeof(ST_Symbol) * st->symbol_max);
}
//
// The index of our new symbol.
//
symbol = st->symbol_upto++;
//
// Initialise the symbol.
//
ss = &st->symbol[symbol];
ss->hash = hash;
ss->value = value;
ss->flag = flag;
ss->string = (UWORD) st->buffer_upto;
ss->next = NULL;
//
// Enough room to add the string?
//
SLONG length = strlen(string) + 1; // + 1 to include the terminating NULL.
if (st->buffer_upto + length > st->buffer_max)
{
//
// Must allocate a bigger string buffer.
//
st->buffer_max *= 2;
st->buffer = (CBYTE *) realloc(st->buffer, sizeof(CBYTE) * st->buffer_max);
}
//
// Add the string to the buffer.
//
strcpy(st->buffer + st->buffer_upto, string);
st->buffer_upto += length;
//
// Insert the symbol into the hash table.
//
ss->next = st->hash[ss->hash & (ST_HASH_SIZE - 1)];
st->hash[ss->hash & (ST_HASH_SIZE - 1)] = (UWORD) symbol;
}
//
// Looks for the string in the given table. Returns TRUE if it
// finds one. Sets the ST_found_table and ST_found_value variables
// if it finds the string.
//
SLONG ST_found_table;
SLONG ST_found_value;
SLONG ST_found_flag;
CBYTE *ST_found_string;
ST_Symbol *ST_found_ss;
SLONG ST_find_in_table(SLONG table, CBYTE *string)
{
ST_Table *st;
ST_Symbol *ss;
SLONG symbol;
ASSERT(WITHIN(table, 0, ST_TABLE_NUMBER - 1));
st = &ST_table[table];
//
// Compute the hash value.
//
ULONG hash = ST_hash_value(string);
for (symbol = st->hash[hash & (ST_HASH_SIZE - 1)]; symbol; symbol = ss->next)
{
ASSERT(WITHIN(symbol, 1, st->symbol_upto - 1));
ss = &st->symbol[symbol];
if (ss->hash == hash)
{
//
// This is probably our symbol. We have to check though.
//
if (strcmp(st->buffer + ss->string, string) == 0)
{
//
// This is our symbol.
//
ST_found_table = table;
ST_found_value = ss->value;
ST_found_flag = ss->flag;
ST_found_ss = ss;
ST_found_string = string;
return TRUE;
}
}
}
return FALSE;
}
SLONG ST_find(CBYTE *string)
{
SLONG table;
//
// Look in the tables.
//
for (table = ST_TABLE_NUMBER - 1; table >= 0; table--)
{
if (ST_find_in_table(
table,
string))
{
return TRUE;
}
}
return FALSE;
}
void ST_update_flag(CBYTE *string, SLONG new_flag)
{
SLONG table;
//
// Look in the tables.
//
for (table = ST_TABLE_NUMBER - 1; table >= 0; table--)
{
if (ST_find_in_table(
table,
string))
{
ST_found_ss->flag = new_flag;
return;
}
}
//
// Symbol not found!
//
ASSERT(0);
return;
}
SLONG ST_find_all_table;
SLONG ST_find_all_symbol;
void ST_find_all_start()
{
ST_find_all_table = 0;
ST_find_all_symbol = 1;
}
SLONG ST_find_all_next()
{
ST_Table *st;
ST_Symbol *ss;
while(1)
{
ASSERT(WITHIN(ST_find_all_table, 0, ST_TABLE_NUMBER - 1));
st = &ST_table[ST_find_all_table];
if (ST_find_all_symbol >= st->symbol_upto)
{
ST_find_all_table += 1;
ST_find_all_symbol = 1;
if (ST_find_all_table >= ST_TABLE_NUMBER)
{
return FALSE;
}
}
else
{
ASSERT(WITHIN(ST_find_all_symbol, 0, st->symbol_upto - 1));
ss = &st->symbol[ST_find_all_symbol++];
ASSERT(WITHIN(ss->string, 0, st->buffer_upto - 2));
ST_found_string = &st->buffer[ss->string];
ST_found_table = ST_find_all_table;
ST_found_value = ss->value;
ST_found_flag = ss->flag;
return TRUE;
}
}
}
void ST_clear(SLONG table)
{
ST_Table *st;
ASSERT(WITHIN(table, 0, ST_TABLE_NUMBER - 1));
st = &ST_table[table];
//
// Zero length the arrays and clear the hash table.
//
st->symbol_upto = 1; // 1 because the 0'th index is reserved for NULL.
st->buffer_upto = 0;
memset(st->hash, 0, sizeof(st->hash));
}
void ST_clear_all()
{
SLONG i;
for (i = 0; i < ST_TABLE_NUMBER; i++)
{
ST_clear(i);
}
}

85
MuckyBasic/st.h Normal file
View File

@ -0,0 +1,85 @@
//
// A symbol table.
//
#ifndef _ST_
#define _ST_
//
// There is a stack of symbol tables. The bottom one contains
// system defined variables and doesn't change. The next one
// contains variables from the libraries that you the program
// uses. The one above that contains globals and all the others
// above that are for function definitions.
//
#define ST_TABLE_SYSTEM 0
#define ST_TABLE_LIBRARY 1
#define ST_TABLE_GLOBAL 2
#define ST_TABLE_LOCAL 3
#define ST_TABLE_NUMBER 4 // The number of symbol tables in the stack.
//
// Initialises all the symbol tables. Call once at the start
// of the whole program.
//
void ST_init(void);
//
// Adds a symbol value pair to the given symbol table.
//
// DONT ADD THE SAME SYMBOL TWICE TO THE SAME TABLE!
//
void ST_add(SLONG table, CBYTE *string, SLONG value, SLONG flag);
//
// Finds the symbol. It checks the CALL,LOCAL,GLOBAL,LIBRRARY,SYSTEM
// symbol tables in that order. Returns TRUE if it found the symbol.
//
extern SLONG ST_found_table; // The table the symbol was in.
extern SLONG ST_found_value; // The value associated with that symbol.
extern SLONG ST_found_flag;
extern CBYTE *ST_found_string;
SLONG ST_find(CBYTE *string);
//
// Changes the flag variable associated with the given string.
// It is an error if the symbol is not found.
//
void ST_update_flag(CBYTE *string, SLONG new_flag);
//
// Finds everything in the symbol tables. Call ST_find_all_start(),
// then every call to ST_find_all_next() that returns TRUE fills in
// the ST_found_* variables. When a call to ST_find_all_next() returns
// FALSE there is nothing left to find.
//
void ST_find_all_start(void);
SLONG ST_find_all_next (void);
//
// Clears all the symbols tables or a particular one.
//
void ST_clear (SLONG table);
void ST_clear_all(void);
#endif

37
MuckyBasic/sysvar.cpp Normal file
View File

@ -0,0 +1,37 @@
//
// System variables.
//
#include "always.h"
#include "mem.h"
#include "ml.h"
#include "st.h"
#include "sysvar.h"
#include "vm.h"
//
// The names of the system fields.
//
CBYTE *SYSVAR_field[SYSVAR_FIELD_NUMBER] =
{
".x",
".y",
".z",
".rhw",
".colour",
".specular",
".u",
".v"
};
void SYSVAR_init()
{
SLONG i;
for (i = 0; i < SYSVAR_FIELD_NUMBER; i++)
{
ST_add(ST_TABLE_SYSTEM, SYSVAR_field[i], i, 0);
}
}

33
MuckyBasic/sysvar.h Normal file
View File

@ -0,0 +1,33 @@
//
// System variables.
//
#ifndef _SYSVAR_
#define _SYSVAR_
//
// The fields that are used by the system and therefore constants.
//
#define SYSVAR_FIELD_X 0
#define SYSVAR_FIELD_Y 1
#define SYSVAR_FIELD_Z 2
#define SYSVAR_FIELD_RHW 3
#define SYSVAR_FIELD_COLOUR 4
#define SYSVAR_FIELD_SPECULAR 5
#define SYSVAR_FIELD_U 6
#define SYSVAR_FIELD_V 7
#define SYSVAR_FIELD_NUMBER 8
//
// Adds all the system variables to the SYSTEM symbol table.
// Call this function after calling ST_init()
//
void SYSVAR_init(void);
#endif

23
MuckyBasic/test.mbs Normal file
View File

@ -0,0 +1,23 @@
//
// TODO next is the get . working for MATRIXes and VECTORs
// There are already ML_TYPE_* for floats and vectors...
//
//
//
//
//
//
right = VECTOR(1,0,0)
up = VECTOR(0,1,0)
forwards = VECTOR(0,0,1)
direction = MATRIX(right,up,forwards)
pos = right * 2
PRINT pos.x

32
MuckyBasic/test2.mbs Normal file
View File

@ -0,0 +1,32 @@
LOCAL x
FUNCTION isprime(n)
LOCAL i,j
FOR i = 2 TO SQRT(n)
IF n MOD i = 0 THEN RETURN FALSE
NEXT i
j = 55
RETURN TRUE
ENDFUNC
i = 100
PRINT "i = " + i
PRINT "j = " + j
PRINT "127 is prime ? " + isprime(127)
PRINT "i = " + i
PRINT "j = " + j
PRINT "x = " + x

384
MuckyBasic/userdlg.cpp Normal file
View File

@ -0,0 +1,384 @@
//-----------------------------------------------------------------------------
// File: UserDlg.cpp
//
// Desc: Support functions for the user select driver dialog.
// Note: Since this code is destined for a static link library, the
// dialog dox is constructed manually. Otherwise, we would use a resource
// and save many lines of code. Manually constructing dialog boxes is not
// trivial and there are many issues (unicode, dword alignment, etc.)
// involved.
//
//
// Copyright (c) 1997-1998 Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#define STRICT
#include <tchar.h>
#include "D3DEnum.h"
#include <stdio.h>
#include "d3dutil.h"
//-----------------------------------------------------------------------------
// Constants and function prototypes for the user select driver dialog
//-----------------------------------------------------------------------------
#define IDC_STATIC 0xffff
#define IDC_DRIVER_COMBO 1000
#define IDC_DEVICE_COMBO 1001
#define IDC_MODE_COMBO 1002
//-----------------------------------------------------------------------------
// External variables (declared in the D3DEnum.cpp file)
//-----------------------------------------------------------------------------
extern D3DEnum_DriverInfo* g_pCurrentDriver; // The selected DD driver
//-----------------------------------------------------------------------------
// Name: CopyToWideChar
//-----------------------------------------------------------------------------
static VOID CopyToWideChar( WCHAR** pstrOut, LPTSTR strIn )
{
DWORD dwLen = lstrlen( strIn );
WCHAR* strOut = *pstrOut;
#ifdef UNICODE // Copy Unicode to Unicode
_wcsncpy( strOut, strIn, dwLen );
strOut[dwLen] = L'\0';
#else // Copy Ansi to Unicode
dwLen = MultiByteToWideChar( CP_ACP, 0, strIn, dwLen, strOut, dwLen );
strOut[dwLen++] = L'\0'; // Add the null terminator
#endif
*pstrOut += dwLen;
}
//-----------------------------------------------------------------------------
// Name: AddDialogControl()
// Desc: Internal function to help build the user select dialog
//-----------------------------------------------------------------------------
static VOID AddDialogControl( WORD** pp, DWORD dwStyle, SHORT x, SHORT y,
SHORT cx, SHORT cy, WORD id,
LPTSTR strClassName, LPTSTR strTitle )
{
// DWORD align the current ptr
DLGITEMTEMPLATE* p = (DLGITEMTEMPLATE*)(((((ULONG)(*pp))+3)>>2)<<2);
p->style = dwStyle | WS_CHILD | WS_VISIBLE;
p->dwExtendedStyle = 0L;
p->x = x;
p->y = y;
p->cx = cx;
p->cy = cy;
p->id = id;
*pp = (WORD*)(++p); // Advance ptr
CopyToWideChar( (WCHAR**)pp, strClassName ); // Set Class name
CopyToWideChar( (WCHAR**)pp, strTitle ); // Set Title
(*pp)++; // Skip Extra Stuff
}
//-----------------------------------------------------------------------------
// Name: _BuildUserSelectDialog()
// Desc: Internal function to build the user select dialog
//-----------------------------------------------------------------------------
DLGTEMPLATE* _BuildDriverSelectTemplate()
{
// Allocate ample memory for building the template
DLGTEMPLATE* pDlgTemplate = new DLGTEMPLATE[50];
if( NULL == pDlgTemplate )
return NULL;
ZeroMemory( pDlgTemplate, 50*sizeof(DLGTEMPLATE) );
// Fill in the DLGTEMPLATE info
DLGTEMPLATE* pdt = pDlgTemplate;
pdt->style = DS_MODALFRAME | DS_NOIDLEMSG | DS_SETFOREGROUND |
DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE |
WS_CAPTION | WS_SYSMENU | DS_SETFONT;
pdt->dwExtendedStyle = 0L;
pdt->cdit = 8;
pdt->x = 0;
pdt->y = 0;
pdt->cx = 179;
pdt->cy = 84;
// Add menu array, class array, dlg title, font size and font name
WORD* pw = (WORD*)(++pdt);
*pw++ = L'\0'; // Set Menu array to nothing
*pw++ = L'\0'; // Set Class array to nothing
CopyToWideChar( (WCHAR**)&pw, TEXT( "Select New Direct3D Driver" ) ); // Dlg title
*pw++ = 8; // Font Size
CopyToWideChar( (WCHAR**)&pw, TEXT("Arial") ); // Font Name
// Add the okay button
AddDialogControl( &pw, BS_PUSHBUTTON | WS_TABSTOP, 65, 65, 51, 14,
IDOK, TEXT("BUTTON"), TEXT("OK") );
// Add the cancel button
AddDialogControl( &pw, BS_PUSHBUTTON | WS_TABSTOP, 123, 65, 51, 14,
IDCANCEL, TEXT("BUTTON"), TEXT("Cancel") );
// Add the driver select combobox
AddDialogControl( &pw, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,
36, 5, 138, 45,
IDC_DRIVER_COMBO, TEXT("COMBOBOX"), TEXT("") );
// Add the device select combobox
AddDialogControl( &pw, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,
36, 24, 138, 45,
IDC_DEVICE_COMBO, TEXT("COMBOBOX"), TEXT("") );
// Add the mode select combobox
AddDialogControl( &pw, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,
36, 44, 138, 45,
IDC_MODE_COMBO, TEXT("COMBOBOX"), TEXT("") );
// Add the "Driver:" text
AddDialogControl( &pw, SS_LEFT, 5, 5, 22, 13,
IDC_STATIC, TEXT("STATIC"), TEXT("Driver:") );
// Add the "Device:" text
AddDialogControl( &pw, SS_LEFT, 5, 24, 25, 13,
IDC_STATIC, TEXT("STATIC"), TEXT("Device:") );
// Add the "Mode:" text
AddDialogControl( &pw, SS_LEFT, 5, 44, 22, 13,
IDC_STATIC, TEXT("STATIC"), TEXT("Mode:") );
return pDlgTemplate;
}
//-----------------------------------------------------------------------------
// Name: UpdateComboBoxesContent()
// Desc: Builds the list of drivers, devices and modes for the combo boxes
// in the driver select dialog box.
//-----------------------------------------------------------------------------
static VOID UpdateComboBoxesContent( HWND hDlg,
D3DEnum_DriverInfo** ppCurrentDriver,
D3DEnum_DeviceInfo** ppCurrentDevice,
D3DEnum_ModeInfo** ppCurrentMode,
BOOL bWindowed )
{
// Check the parameters
if( (NULL==ppCurrentDriver) || (NULL==ppCurrentDevice) ||
(NULL==ppCurrentMode) )
return;
// If the specified driver is NULL, use the first one in the list
if( NULL == *ppCurrentDriver)
(*ppCurrentDriver) = D3DEnum_GetFirstDriver();
// If the specified device is NULL, use the first one in the list
if( NULL == *ppCurrentDevice)
(*ppCurrentDevice) = (*ppCurrentDriver)->pFirstDevice;
// Reset the content in each of the combo boxes
SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO, CB_RESETCONTENT, 0, 0 );
SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO, CB_RESETCONTENT, 0, 0 );
SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_RESETCONTENT, 0, 0 );
// Build the list of drivers for the combo box
for( D3DEnum_DriverInfo* pDriver = D3DEnum_GetFirstDriver(); pDriver;
pDriver = pDriver->pNext )
{
// Add driver desc to the combo box
DWORD dwItem = SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO,
CB_ADDSTRING, 0, (LPARAM)pDriver->strDesc );
// Associate DriverInfo ptr with the item in the combo box
SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO, CB_SETITEMDATA,
(WPARAM)dwItem, (LPARAM)pDriver );
// If this is the current driver, set is as the current selection
if( pDriver == (*ppCurrentDriver) )
SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO, CB_SETCURSEL,
(WPARAM)dwItem, 0L );
}
// Build the list of devices for the combo box
for( D3DEnum_DeviceInfo* pDevice = (*ppCurrentDriver)->pFirstDevice; pDevice;
pDevice = pDevice->pNext )
{
// Add device name to the combo box
DWORD dwItem = SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO,
CB_ADDSTRING, 0, (LPARAM)pDevice->strName );
// Associate DeviceInfo ptr with the item in the combo box
SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO, CB_SETITEMDATA,
(WPARAM)dwItem, (LPARAM)pDevice );
// If this is the current device, set this as the current selection
if( pDevice == (*ppCurrentDevice) )
SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO, CB_SETCURSEL,
(WPARAM)dwItem, 0L );
}
if( (*ppCurrentDriver)->ddDriverCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED
&& ( NULL == (*ppCurrentDriver)->pGUID )
&& (*ppCurrentDevice)->bCompatbileWithDesktop )
{
// Add windowed mode to the combo box of available modes
DWORD dwItem = SendDlgItemMessage( hDlg, IDC_MODE_COMBO,
CB_ADDSTRING, 0, (LPARAM)TEXT("Windowed mode") );
// Associate ModeInfo ptr with the item in the combo box
SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETITEMDATA,
(WPARAM)dwItem, (LPARAM)NULL );
// If the current device is windowed, set this as current
if( bWindowed )
SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETCURSEL,
(WPARAM)dwItem, 0L );
}
// Build the list of modes for the combo box
for( D3DEnum_ModeInfo* pMode = (*ppCurrentDevice)->pFirstMode; pMode;
pMode = pMode->pNext )
{
// Add mode desc to the combo box
DWORD dwItem = SendDlgItemMessage( hDlg, IDC_MODE_COMBO,
CB_ADDSTRING, 0,
(LPARAM)pMode->strDesc );
// Associate ModeInfo ptr with the item in the combo box
SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETITEMDATA,
(WPARAM)dwItem, (LPARAM)pMode );
// If this is the current mode, set is as the current selection
if( !bWindowed && ( pMode == (*ppCurrentMode) ) )
SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETCURSEL,
(WPARAM)dwItem, 0L );
}
}
//-----------------------------------------------------------------------------
// Name: _DriverSelectProc()
// Desc: Windows message handling function for the driver select dialog
//-----------------------------------------------------------------------------
BOOL CALLBACK _DriverSelectProc( HWND hDlg, UINT uiMsg, WPARAM wParam,
LPARAM lParam )
{
static D3DEnum_DriverInfo *pOldDriver, *pNewDriver;
static D3DEnum_DeviceInfo *pOldDevice, *pNewDevice;
static D3DEnum_ModeInfo *pOldMode, *pNewMode;
static BOOL bOldWindowed, bNewWindowed;
// Handle the initialization message
if( WM_INITDIALOG == uiMsg )
{
// Setup temp storage pointers for dialog
pNewDriver = pOldDriver = g_pCurrentDriver;
pNewDevice = pOldDevice = pOldDriver->pCurrentDevice;
pNewMode = pOldMode = pOldDevice->pCurrentMode;
bNewWindowed = bOldWindowed = pOldDevice->bWindowed;
UpdateComboBoxesContent( hDlg, &pOldDriver, &pOldDevice,
&pOldMode, bOldWindowed );
return TRUE;
}
if( WM_COMMAND == uiMsg )
{
// Handle the case when the user hits the OK button
if( IDOK == LOWORD(wParam) )
{
// Check if any of the options were changed
if( ( pOldDriver != pNewDriver ) || ( pOldDevice != pNewDevice ) ||
( pOldMode != pNewMode ) || ( bOldWindowed != bNewWindowed ) )
{
// Set actual ptrs from the temp ptrs used for the dialog
g_pCurrentDriver = pNewDriver;
g_pCurrentDriver->pCurrentDevice = pNewDevice;
g_pCurrentDriver->pCurrentDevice->pCurrentMode = pNewMode;
g_pCurrentDriver->pCurrentDevice->bWindowed = bNewWindowed;
EndDialog( hDlg, IDOK );
return TRUE;
}
else
{
EndDialog( hDlg, IDCANCEL );
return TRUE;
}
}
// Handle the case when the user hits the Cancel button
else if( IDCANCEL == LOWORD(wParam) )
{
EndDialog( hDlg, IDCANCEL );
return TRUE;
}
// Handle the case when the user chooses an item in the combo boxes.
else if( CBN_SELENDOK == HIWORD(wParam) )
{
DWORD dwIndex = SendMessage( (HWND)lParam, CB_GETCURSEL,
0, 0 );
LONG pNewObject = SendMessage( (HWND)lParam, CB_GETITEMDATA,
dwIndex, 0 );
if( (CB_ERR==dwIndex) )
return TRUE;
// Handle the case where one of these may have changed. The
// combo boxes will need to be updated to reflect the changes.
switch( LOWORD( wParam ) )
{
case IDC_DRIVER_COMBO:
if( pNewObject && pNewObject != (LONG)pNewDriver )
{
pNewDriver = (D3DEnum_DriverInfo*)pNewObject;
pNewDevice = pNewDriver->pCurrentDevice;;
pNewMode = pNewDevice->pCurrentMode;
bNewWindowed = pNewDevice->bWindowed;
}
break;
case IDC_DEVICE_COMBO:
if( pNewObject && pNewObject != (LONG)pNewDevice )
{
pNewDevice = (D3DEnum_DeviceInfo*)pNewObject;
pNewMode = pNewDevice->pCurrentMode;
bNewWindowed = pNewDevice->bWindowed;
}
break;
case IDC_MODE_COMBO:
if( pNewObject )
{
pNewMode = (D3DEnum_ModeInfo*)pNewObject;
bNewWindowed = FALSE;
}
else
bNewWindowed = TRUE;
break;
}
UpdateComboBoxesContent( hDlg, &pNewDriver, &pNewDevice,
&pNewMode, bNewWindowed );
return TRUE;
}
}
return FALSE;
}

4435
MuckyBasic/vm.cpp Normal file

File diff suppressed because it is too large Load Diff

17
MuckyBasic/vm.h Normal file
View File

@ -0,0 +1,17 @@
//
// The virtual machine to run our basic programs.
//
#ifndef _VM_
#define _VM_
//
// Loads the given MuckyBASIC program into memory and runs it!
//
void VM_run(CBYTE *fname);
#endif

896
MuckyBasic/wave.c Normal file
View File

@ -0,0 +1,896 @@
/*==========================================================================
*
* Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
*
* File: wave.c
* Content: Wave library routines.
* This file is used for loading/saving waves, and reading and
* writing waves in smaller blocks.
* Uses WaveOpenFile, WaveReadFile and WaveCloseReadFile for
* single block access to reading wave files.
* Uses WaveCreateFile, WaveWriteFile, WaveCloseWriteFile for
* single block access for writing wave files.
* Uses WaveLoadFile to load a whole wave file into memory.
* Uses WaveSaveFile to save a whole wave file into memory.
*
***************************************************************************/
/* PROTOTYPES */
#include <windows.h>
#include <mmsystem.h>
#include "wave.h"
//#include "debug.h"
#include "windowsx.h"
#define ASSERT(x)
/* ROUTINES */
/* -------------------------------------------------------*/
/* This function will open a wave input file and prepare it for reading,
* so the data can be easily
* read with WaveReadFile. Returns 0 if successful, the error code if not.
* pszFileName - Input filename to load.
* phmmioIn - Pointer to handle which will be used
* for further mmio routines.
* ppwfxInfo - Ptr to ptr to WaveFormatEx structure
* with all info about the file.
*
*/
int WaveOpenFile(
TCHAR*pszFileName, // (IN)
HMMIO *phmmioIn, // (OUT)
WAVEFORMATEX **ppwfxInfo, // (OUT)
MMCKINFO *pckInRIFF // (OUT)
)
{
HMMIO hmmioIn;
MMCKINFO ckIn; // chunk info. for general use.
PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in.
WORD cbExtraAlloc; // Extra bytes for waveformatex
int nError; // Return value.
// Initialization...
*ppwfxInfo = NULL;
nError = 0;
hmmioIn = NULL;
if ((hmmioIn = mmioOpen(pszFileName, NULL, MMIO_ALLOCBUF | MMIO_READ)) == NULL)
{
nError = ER_CANNOTOPEN;
goto ERROR_READING_WAVE;
}
if ((nError = (int)mmioDescend(hmmioIn, pckInRIFF, NULL, 0)) != 0)
{
goto ERROR_READING_WAVE;
}
if ((pckInRIFF->ckid != FOURCC_RIFF) || (pckInRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E')))
{
nError = ER_NOTWAVEFILE;
goto ERROR_READING_WAVE;
}
/* Search the input file for for the 'fmt ' chunk. */
ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
if ((nError = (int)mmioDescend(hmmioIn, &ckIn, pckInRIFF, MMIO_FINDCHUNK)) != 0)
{
goto ERROR_READING_WAVE;
}
/* Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>;
* if there are extra parameters at the end, we'll ignore them */
if (ckIn.cksize < (long) sizeof(PCMWAVEFORMAT))
{
nError = ER_NOTWAVEFILE;
goto ERROR_READING_WAVE;
}
/* Read the 'fmt ' chunk into <pcmWaveFormat>.*/
if (mmioRead(hmmioIn, (HPSTR) &pcmWaveFormat, (long) sizeof(pcmWaveFormat)) != (long) sizeof(pcmWaveFormat))
{
nError = ER_CANNOTREAD;
goto ERROR_READING_WAVE;
}
// Ok, allocate the waveformatex, but if its not pcm
// format, read the next word, and thats how many extra
// bytes to allocate.
if (pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM)
cbExtraAlloc = 0;
else
{
// Read in length of extra bytes.
if (mmioRead(hmmioIn, (LPTSTR) &cbExtraAlloc,
(long) sizeof(cbExtraAlloc)) != (long) sizeof(cbExtraAlloc))
{
nError = ER_CANNOTREAD;
goto ERROR_READING_WAVE;
}
}
// Ok, now allocate that waveformatex structure.
if ((*ppwfxInfo = GlobalAlloc(GMEM_FIXED, sizeof(WAVEFORMATEX)+cbExtraAlloc)) == NULL)
{
nError = ER_MEM;
goto ERROR_READING_WAVE;
}
// Copy the bytes from the pcm structure to the waveformatex structure
memcpy(*ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat));
(*ppwfxInfo)->cbSize = cbExtraAlloc;
// Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
if (cbExtraAlloc != 0)
{
if (mmioRead(hmmioIn, (LPTSTR) (((BYTE*)&((*ppwfxInfo)->cbSize))+sizeof(cbExtraAlloc)),
(long) (cbExtraAlloc)) != (long) (cbExtraAlloc))
{
nError = ER_NOTWAVEFILE;
goto ERROR_READING_WAVE;
}
}
/* Ascend the input file out of the 'fmt ' chunk. */
if ((nError = mmioAscend(hmmioIn, &ckIn, 0)) != 0)
{
goto ERROR_READING_WAVE;
}
goto TEMPCLEANUP;
ERROR_READING_WAVE:
if (*ppwfxInfo != NULL)
{
GlobalFree(*ppwfxInfo);
*ppwfxInfo = NULL;
}
if (hmmioIn != NULL)
{
mmioClose(hmmioIn, 0);
hmmioIn = NULL;
}
TEMPCLEANUP:
*phmmioIn = hmmioIn;
return(nError);
}
/* This routine has to be called before WaveReadFile as it searchs for the chunk to descend into for
reading, that is, the 'data' chunk. For simplicity, this used to be in the open routine, but was
taken out and moved to a separate routine so there was more control on the chunks that are before
the data chunk, such as 'fact', etc... */
int WaveStartDataRead(
HMMIO *phmmioIn,
MMCKINFO *pckIn,
MMCKINFO *pckInRIFF
)
{
int nError;
nError = 0;
// Do a nice little seek...
if ((nError = mmioSeek(*phmmioIn, pckInRIFF->dwDataOffset + sizeof(FOURCC), SEEK_SET)) == -1)
{
ASSERT(FALSE);
}
nError = 0;
// Search the input file for for the 'data' chunk.
pckIn->ckid = mmioFOURCC('d', 'a', 't', 'a');
if ((nError = mmioDescend(*phmmioIn, pckIn, pckInRIFF, MMIO_FINDCHUNK)) != 0)
{
goto ERROR_READING_WAVE;
}
goto CLEANUP;
ERROR_READING_WAVE:
CLEANUP:
return(nError);
}
/* This will read wave data from the wave file. Makre sure we're descended into
the data chunk, else this will fail bigtime!
hmmioIn - Handle to mmio.
cbRead - # of bytes to read.
pbDest - Destination buffer to put bytes.
cbActualRead- # of bytes actually read.
*/
int WaveReadFile(
HMMIO hmmioIn, // IN
UINT cbRead, // IN
BYTE *pbDest, // IN
MMCKINFO *pckIn, // IN.
UINT *cbActualRead // OUT.
)
{
MMIOINFO mmioinfoIn; // current status of <hmmioIn>
int nError;
UINT cT, cbDataIn;
nError = 0;
if (nError = mmioGetInfo(hmmioIn, &mmioinfoIn, 0) != 0)
{
goto ERROR_CANNOT_READ;
}
cbDataIn = cbRead;
if (cbDataIn > pckIn->cksize)
cbDataIn = pckIn->cksize;
pckIn->cksize -= cbDataIn;
for (cT = 0; cT < cbDataIn; cT++)
{
/* Copy the bytes from the io to the buffer. */
if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead)
{
if ((nError = mmioAdvance(hmmioIn, &mmioinfoIn, MMIO_READ)) != 0)
{
goto ERROR_CANNOT_READ;
}
if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead)
{
nError = ER_CORRUPTWAVEFILE;
goto ERROR_CANNOT_READ;
}
}
// Actual copy.
*((BYTE*)pbDest+cT) = *((BYTE*)mmioinfoIn.pchNext)++;
}
if ((nError = mmioSetInfo(hmmioIn, &mmioinfoIn, 0)) != 0)
{
goto ERROR_CANNOT_READ;
}
*cbActualRead = cbDataIn;
goto FINISHED_READING;
ERROR_CANNOT_READ:
*cbActualRead = 0;
FINISHED_READING:
return(nError);
}
/* This will close the wave file openned with WaveOpenFile.
phmmioIn - Pointer to the handle to input MMIO.
ppwfxSrc - Pointer to pointer to WaveFormatEx structure.
Returns 0 if successful, non-zero if there was a warning.
*/
int WaveCloseReadFile(
HMMIO *phmmio, // IN
WAVEFORMATEX **ppwfxSrc // IN
)
{
if (*ppwfxSrc != NULL)
{
GlobalFree(*ppwfxSrc);
*ppwfxSrc = NULL;
}
if (*phmmio != NULL)
{
mmioClose(*phmmio, 0);
*phmmio = NULL;
}
return(0);
}
/* This routine will create a wave file for writing. This will automatically overwrite any
existing file with the same name, so be careful and check before hand!!!
pszFileName - Pointer to filename to write.
phmmioOut - Pointer to HMMIO handle that is used for further writes
pwfxDest - Valid waveformatex destination structure.
pckOut - Pointer to be set with the MMCKINFO.
pckOutRIFF - Pointer to be set with the RIFF info.
*/
int WaveCreateFile(
TCHAR*pszFileName, // (IN)
HMMIO *phmmioOut, // (OUT)
WAVEFORMATEX *pwfxDest, // (IN)
MMCKINFO *pckOut, // (OUT)
MMCKINFO *pckOutRIFF // (OUT)
)
{
int nError; // Return value.
DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile.
MMCKINFO ckOut1;
dwFactChunk = (DWORD)-1;
nError = 0;
*phmmioOut = mmioOpen(pszFileName, NULL,
MMIO_ALLOCBUF | MMIO_READWRITE|MMIO_CREATE);
if (*phmmioOut == NULL)
{
nError = ER_CANNOTWRITE;
goto ERROR_CANNOT_WRITE; // cannot save WAVE file
}
/* Create the output file RIFF chunk of form type 'WAVE'.
*/
pckOutRIFF->fccType = mmioFOURCC('W', 'A', 'V', 'E');
pckOutRIFF->cksize = 0;
if ((nError = mmioCreateChunk(*phmmioOut, pckOutRIFF, MMIO_CREATERIFF)) != 0)
{
goto ERROR_CANNOT_WRITE; // cannot write file, probably
}
/* We are now descended into the 'RIFF' chunk we just created.
* Now create the 'fmt ' chunk. Since we know the size of this chunk,
* specify it in the MMCKINFO structure so MMIO doesn't have to seek
* back and set the chunk size after ascending from the chunk.
*/
pckOut->ckid = mmioFOURCC('f', 'm', 't', ' ');
pckOut->cksize = sizeof(PCMWAVEFORMAT); // we know the size of this ck.
if ((nError = mmioCreateChunk(*phmmioOut, pckOut, 0)) != 0)
{
goto ERROR_CANNOT_WRITE; // cannot write file, probably
}
/* Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. */
if (pwfxDest->wFormatTag == WAVE_FORMAT_PCM)
{
if (mmioWrite(*phmmioOut, (HPSTR) pwfxDest, sizeof(PCMWAVEFORMAT))
!= sizeof(PCMWAVEFORMAT))
{
nError = ER_CANNOTWRITE;
goto ERROR_CANNOT_WRITE; // cannot write file, probably
}
}
else
{
// Write the variable length size.
if ((UINT)mmioWrite(*phmmioOut, (HPSTR) pwfxDest, sizeof(*pwfxDest)+pwfxDest->cbSize)
!= (sizeof(*pwfxDest)+pwfxDest->cbSize))
{
nError = ER_CANNOTWRITE;
goto ERROR_CANNOT_WRITE; // cannot write file, probably
}
}
/* Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk.
*/
if ((nError = mmioAscend(*phmmioOut, pckOut, 0)) != 0)
{
goto ERROR_CANNOT_WRITE; // cannot write file, probably
}
// Now create the fact chunk, not required for PCM but nice to have. This is filled
// in when the close routine is called.
ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't');
ckOut1.cksize = 0;
if ((nError = mmioCreateChunk(*phmmioOut, &ckOut1, 0)) != 0)
{
goto ERROR_CANNOT_WRITE; // cannot write file, probably
}
if (mmioWrite(*phmmioOut, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != sizeof(dwFactChunk))
{
nError = ER_CANNOTWRITE;
goto ERROR_CANNOT_WRITE;
}
// Now ascend out of the fact chunk...
if ((nError = mmioAscend(*phmmioOut, &ckOut1, 0)) != 0)
{
nError = ER_CANNOTWRITE; // cannot write file, probably
goto ERROR_CANNOT_WRITE;
}
goto DONE_CREATE;
ERROR_CANNOT_WRITE:
// Maybe delete the half-written file? Ah forget it for now, its good to leave the
// file there for debugging...
DONE_CREATE:
return(nError);
}
/* This routine has to be called before any data is written to the wave output file, via wavewritefile. This
sets up the data to write, and creates the data chunk.
*/
int WaveStartDataWrite(
HMMIO *phmmioOut, // (IN)
MMCKINFO *pckOut, // (IN)
MMIOINFO *pmmioinfoOut // (OUT)
)
{
int nError;
nError = 0;
/* Create the 'data' chunk that holds the waveform samples. */
pckOut->ckid = mmioFOURCC('d', 'a', 't', 'a');
pckOut->cksize = 0;
if ((nError = mmioCreateChunk(*phmmioOut, pckOut, 0)) != 0)
{
goto ERROR_CANNOT_WRITE; // cannot write file, probably
}
if ((nError = mmioGetInfo(*phmmioOut, pmmioinfoOut, 0)) != 0)
{
goto ERROR_CANNOT_WRITE;
}
goto CLEANUP;
ERROR_CANNOT_WRITE:
CLEANUP:
return(nError);
}
/* This routine will write out data to a wave file.
hmmioOut - Handle to hmmioOut filled by WaveCreateFile
cbWrite - # of bytes to write out.
pbSrc - Pointer to source.
pckOut - pointer to ckOut filled by WaveCreateFile
cbActualWrite - # of actual bytes written.
pmmioinfoOut - Pointer to mmioinfoOut filled by WaveCreateFile.
Returns 0 if successful, else the error code.
*/
int WaveWriteFile(
HMMIO hmmioOut, // (IN)
UINT cbWrite, // (IN)
BYTE *pbSrc, // (IN)
MMCKINFO *pckOut, // (IN)
UINT *cbActualWrite, // (OUT)
MMIOINFO *pmmioinfoOut // (IN)
)
{
int nError;
UINT cT;
nError = 0;
*cbActualWrite = 0;
for (cT=0; cT < cbWrite; cT++)
{
if (pmmioinfoOut->pchNext == pmmioinfoOut->pchEndWrite)
{
pmmioinfoOut->dwFlags |= MMIO_DIRTY;
if ((nError = mmioAdvance(hmmioOut, pmmioinfoOut, MMIO_WRITE)) != 0)
{
goto ERROR_CANNOT_WRITE;
}
}
*((BYTE*)pmmioinfoOut->pchNext)++ = *((BYTE*)pbSrc+cT);
(*cbActualWrite)++;
}
ERROR_CANNOT_WRITE:
// What to do here? Well, for now, nothing, just return that error. (maybe delete the
// file later?
return(nError);
}
/* This routine will close a wave file used for writing. Returns 0 if successful, else
the error code.
phmmioOut - Pointer to mmio handle for saving.
pckOut - Pointer to the MMCKINFO for saving.
pckOutRiff - Pointer to the riff MMCKINFO for saving.
pmmioinfoOut- Pointer to mmioinfo for saving.
cSamples - # of samples saved, for the fact chunk. For PCM, this isn't used but
will be written anyway, so this can be zero as long as programs ignore
this field when they load PCM formats.
*/
int WaveCloseWriteFile(
HMMIO *phmmioOut, // (IN)
MMCKINFO *pckOut, // (IN)
MMCKINFO *pckOutRIFF, // (IN)
MMIOINFO *pmmioinfoOut, // (IN)
DWORD cSamples // (IN)
)
{
int nError;
nError = 0;
if (*phmmioOut == NULL)
return(0);
pmmioinfoOut->dwFlags |= MMIO_DIRTY;
if ((nError = mmioSetInfo(*phmmioOut, pmmioinfoOut, 0)) != 0)
{
// cannot flush, probably...
goto ERROR_CANNOT_WRITE;
}
/* Ascend the output file out of the 'data' chunk -- this will cause
* the chunk size of the 'data' chunk to be written.
*/
if ((nError = mmioAscend(*phmmioOut, pckOut, 0)) != 0)
goto ERROR_CANNOT_WRITE; // cannot write file, probably
// Do this here instead...
if ((nError = mmioAscend(*phmmioOut, pckOutRIFF, 0)) != 0)
goto ERROR_CANNOT_WRITE; // cannot write file, probably
nError = mmioSeek(*phmmioOut, 0, SEEK_SET);
if ((nError = (int)mmioDescend(*phmmioOut, pckOutRIFF, NULL, 0)) != 0)
{
goto ERROR_CANNOT_WRITE;
}
nError = 0;
pckOut->ckid = mmioFOURCC('f', 'a', 'c', 't');
if ((nError = mmioDescend(*phmmioOut, pckOut, pckOutRIFF, MMIO_FINDCHUNK)) == 0)
{
// If it didn't fail, write the fact chunk out, if it failed, not critical, just
// assert (below).
nError = mmioWrite(*phmmioOut, (HPSTR)&cSamples, sizeof(DWORD));
nError = mmioAscend(*phmmioOut, pckOut, 0);
nError = 0;
}
else
{
nError = 0;
ASSERT(FALSE);
}
// CANTWRITEFACT:
/* Ascend the output file out of the 'RIFF' chunk -- this will cause
* the chunk size of the 'RIFF' chunk to be written.
*/
if ((nError = mmioAscend(*phmmioOut, pckOutRIFF, 0)) != 0)
goto ERROR_CANNOT_WRITE; // cannot write file, probably
ERROR_CANNOT_WRITE:
if (*phmmioOut != NULL)
{
mmioClose(*phmmioOut, 0);
*phmmioOut = NULL;
}
return(nError);
}
/* This routine will copy from a source wave file to a destination wave file all those useless chunks
(well, the ones useless to conversions, etc --> apparently people use them!). The source will be
seeked to the begining, but the destination has to be at a current pointer to put the new chunks.
This will also seek back to the start of the wave riff header at the end of the routine.
phmmioIn - Pointer to input mmio file handle.
pckIn - Pointer to a nice ckIn to use.
pckInRiff - Pointer to the main riff.
phmmioOut - Pointer to output mmio file handle.
pckOut - Pointer to nice ckOut to use.
pckOutRiff - Pointer to the main riff.
Returns 0 if successful, else the error code. If this routine fails, it still attemps to seek back to
the start of the wave riff header, though this too could be unsuccessful.
*/
int WaveCopyUselessChunks(
HMMIO *phmmioIn,
MMCKINFO *pckIn,
MMCKINFO *pckInRiff,
HMMIO *phmmioOut,
MMCKINFO *pckOut,
MMCKINFO *pckOutRiff)
{
int nError;
nError = 0;
// First seek to the stinking start of the file, not including the riff header...
if ((nError = mmioSeek(*phmmioIn, pckInRiff->dwDataOffset + sizeof(FOURCC), SEEK_SET)) == -1)
{
nError = ER_CANNOTREAD;
goto ERROR_IN_PROC;
}
nError = 0;
while (mmioDescend(*phmmioIn, pckIn, pckInRiff, 0) == 0)
{
// quickly check for corrupt RIFF file--don't ascend past end!
if ((pckIn->dwDataOffset + pckIn->cksize) > (pckInRiff->dwDataOffset + pckInRiff->cksize))
goto ERROR_IN_PROC;
switch (pckIn->ckid)
{
// explicitly skip these...
case mmioFOURCC('f', 'm', 't', ' '):
break;
case mmioFOURCC('d', 'a', 't', 'a'):
break;
case mmioFOURCC('f', 'a', 'c', 't'):
break;
case mmioFOURCC('J', 'U', 'N', 'K'):
break;
case mmioFOURCC('P', 'A', 'D', ' '):
break;
case mmioFOURCC('c', 'u', 'e', ' '):
break;
// copy chunks that are OK to copy
case mmioFOURCC('p', 'l', 's', 't'):
// although without the 'cue' chunk, it doesn't make much sense
riffCopyChunk(*phmmioIn, *phmmioOut, pckIn);
break;
case mmioFOURCC('D', 'I', 'S', 'P'):
riffCopyChunk(*phmmioIn, *phmmioOut, pckIn);
break;
// don't copy unknown chunks
default:
break;
}
// step up to prepare for next chunk..
mmioAscend(*phmmioIn, pckIn, 0);
}
ERROR_IN_PROC:
{
int nErrorT;
// Seek back to riff header
nErrorT = mmioSeek(*phmmioIn, pckInRiff->dwDataOffset + sizeof(FOURCC), SEEK_SET);
}
return(nError);
}
/** BOOL RIFFAPI riffCopyChunk(HMMIO hmmioSrc, HMMIO hmmioDst, const LPMMCKINFO lpck)
*
* DESCRIPTION:
*
*
* ARGUMENTS:
* (LPWAVECONVCB lpwc, LPMMCKINFO lpck)
*
* RETURN (BOOL NEAR PASCAL):
*
*
* NOTES:
*
** */
BOOL riffCopyChunk(HMMIO hmmioSrc, HMMIO hmmioDst, const LPMMCKINFO lpck)
{
MMCKINFO ck;
HPSTR hpBuf;
//
//
//
hpBuf = (HPSTR)GlobalAllocPtr(GHND, lpck->cksize);
if (!hpBuf)
return (FALSE);
ck.ckid = lpck->ckid;
ck.cksize = lpck->cksize;
if (mmioCreateChunk(hmmioDst, &ck, 0))
goto rscc_Error;
if (mmioRead(hmmioSrc, hpBuf, lpck->cksize) != (LONG)lpck->cksize)
goto rscc_Error;
if (mmioWrite(hmmioDst, hpBuf, lpck->cksize) != (LONG)lpck->cksize)
goto rscc_Error;
if (mmioAscend(hmmioDst, &ck, 0))
goto rscc_Error;
if (hpBuf)
GlobalFreePtr(hpBuf);
return (TRUE);
rscc_Error:
if (hpBuf)
GlobalFreePtr(hpBuf);
return (FALSE);
} /* RIFFSupCopyChunk() */
/* This routine loads a full wave file into memory. Be careful, wave files can get
pretty big these days :).
szFileName - sz Filename
cbSize - Size of loaded wave (returned)
cSamples - # of samples loaded.
ppwfxInfo - Pointer to pointer to waveformatex structure. The wfx structure
IS ALLOCATED by this routine! Make sure to free it!
ppbData - Pointer to a byte pointer (globalalloc) which is allocated by this
routine. Make sure to free it!
Returns 0 if successful, else the error code.
*/
int WaveLoadFile(
TCHAR*pszFileName, // (IN)
UINT *cbSize, // (OUT)
WAVEFORMATEX **ppwfxInfo, // (OUT)
BYTE **ppbData // (OUT)
)
{
HMMIO hmmioIn;
MMCKINFO ckInRiff;
MMCKINFO ckIn;
int nError;
UINT cbActualRead;
*ppbData = NULL;
*ppwfxInfo = NULL;
*cbSize = 0;
if ((nError = WaveOpenFile(pszFileName, &hmmioIn, ppwfxInfo, &ckInRiff)) != 0)
{
goto ERROR_LOADING;
}
if ((nError = WaveStartDataRead(&hmmioIn, &ckIn, &ckInRiff)) != 0)
{
goto ERROR_LOADING;
}
// Ok, size of wave data is in ckIn, allocate that buffer.
if ((*ppbData = (BYTE *)GlobalAlloc(GMEM_FIXED, ckIn.cksize)) == NULL)
{
nError = ER_MEM;
goto ERROR_LOADING;
}
if ((nError = WaveReadFile(hmmioIn, ckIn.cksize, *ppbData, &ckIn, &cbActualRead)) != 0)
{
goto ERROR_LOADING;
}
*cbSize = cbActualRead;
goto DONE_LOADING;
ERROR_LOADING:
if (*ppbData != NULL)
{
GlobalFree(*ppbData);
*ppbData = NULL;
}
if (*ppwfxInfo != NULL)
{
GlobalFree(*ppwfxInfo);
*ppwfxInfo = NULL;
}
DONE_LOADING:
// Close the wave file.
if (hmmioIn != NULL)
{
mmioClose(hmmioIn, 0);
hmmioIn = NULL;
}
return(nError);
}
/* This routine saves a wave file in currently in memory.
pszFileName - FileName to save to. Automatically overwritten, be careful!
cbSize - Size in bytes to write.
cSamples - # of samples to write, used to make the fact chunk. (if !PCM)
pwfxDest - Pointer to waveformatex structure.
pbData - Pointer to the data.
*/
int WaveSaveFile(
TCHAR*pszFileName, // (IN)
UINT cbSize, // (IN)
DWORD cSamples, // (IN)
WAVEFORMATEX *pwfxDest, // (IN)
BYTE *pbData // (IN)
)
{
HMMIO hmmioOut;
MMCKINFO ckOut;
MMCKINFO ckOutRIFF;
MMIOINFO mmioinfoOut;
UINT cbActualWrite;
int nError;
if ((nError = WaveCreateFile(pszFileName, &hmmioOut, pwfxDest, &ckOut, &ckOutRIFF)) != 0)
{
goto ERROR_SAVING;
}
if ((nError = WaveStartDataWrite(&hmmioOut, &ckOut, &mmioinfoOut)) != 0)
{
goto ERROR_SAVING;
}
if ((nError = WaveWriteFile(hmmioOut, cbSize, pbData, &ckOut, &cbActualWrite, &mmioinfoOut)) != 0)
{
goto ERROR_SAVING;
}
if ((nError = WaveCloseWriteFile(&hmmioOut, &ckOut, &ckOutRIFF, &mmioinfoOut, cSamples)) != 0)
{
goto ERROR_SAVING;
}
ERROR_SAVING:
return(nError);
}

68
MuckyBasic/wave.h Normal file
View File

@ -0,0 +1,68 @@
/*==========================================================================
*
* Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
*
* File: wave.h
* Content: wave header
*
***************************************************************************/
#ifndef __WAVE_INCLUDED__
#define __WAVE_INCLUDED__
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
#define WAVEVERSION 1
#ifndef ER_MEM
#define ER_MEM 0xe000
#endif
#ifndef ER_CANNOTOPEN
#define ER_CANNOTOPEN 0xe100
#endif
#ifndef ER_NOTWAVEFILE
#define ER_NOTWAVEFILE 0xe101
#endif
#ifndef ER_CANNOTREAD
#define ER_CANNOTREAD 0xe102
#endif
#ifndef ER_CORRUPTWAVEFILE
#define ER_CORRUPTWAVEFILE 0xe103
#endif
#ifndef ER_CANNOTWRITE
#define ER_CANNOTWRITE 0xe104
#endif
int WaveOpenFile(TCHAR*, HMMIO *, WAVEFORMATEX **, MMCKINFO *);
int WaveStartDataRead(HMMIO *, MMCKINFO *, MMCKINFO *);
int WaveReadFile(HMMIO, UINT, BYTE *, MMCKINFO *, UINT *);
int WaveCloseReadFile(HMMIO *, WAVEFORMATEX **);
int WaveCreateFile(TCHAR*, HMMIO *, WAVEFORMATEX *, MMCKINFO *, MMCKINFO *);
int WaveStartDataWrite(HMMIO *, MMCKINFO *, MMIOINFO *);
int WaveWriteFile(HMMIO, UINT, BYTE *, MMCKINFO *, UINT *, MMIOINFO *);
int WaveCloseWriteFile(HMMIO *, MMCKINFO *, MMCKINFO *, MMIOINFO *, DWORD);
int WaveLoadFile(TCHAR*, UINT *, WAVEFORMATEX **, BYTE **);
int WaveSaveFile(TCHAR*, UINT, DWORD, WAVEFORMATEX *, BYTE *);
int WaveCopyUselessChunks(HMMIO *, MMCKINFO *, MMCKINFO *, HMMIO *, MMCKINFO *, MMCKINFO *);
BOOL riffCopyChunk(HMMIO, HMMIO, const LPMMCKINFO);
#ifdef __cplusplus
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More