first commit
This commit is contained in:
commit
f9e2faf45a
125
MFLib1/Headers/Display.h
Normal file
125
MFLib1/Headers/Display.h
Normal 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
101
MFLib1/Headers/Draw2d.h
Normal 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
|
8
MFLib1/Headers/DrawPoly.h
Normal file
8
MFLib1/Headers/DrawPoly.h
Normal 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
142
MFLib1/Headers/Keyboard.h
Normal 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
26
MFLib1/Headers/MFD3D.h
Normal 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
46
MFLib1/Headers/MFErrors.h
Normal 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
41
MFLib1/Headers/MFFile.h
Normal 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
81
MFLib1/Headers/MFHeader.h
Normal 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
36
MFLib1/Headers/MFHost.h
Normal 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
133
MFLib1/Headers/MFLbType.h
Normal 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
70
MFLib1/Headers/MFMaths.h
Normal 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
12
MFLib1/Headers/MFMem.h
Normal 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
16
MFLib1/Headers/MFStd.h
Normal 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
26
MFLib1/Headers/MFTypes.h
Normal 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
23
MFLib1/Headers/MFUtils.h
Normal 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
32
MFLib1/Headers/Mouse.h
Normal 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
24
MFLib1/Headers/Palette.h
Normal 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
41
MFLib1/Headers/Sprites.h
Normal 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
242
MFLib1/MFLib1.dsp
Normal 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
|
101
MFLib1/Source/C/Common/DModes.cpp
Normal file
101
MFLib1/Source/C/Common/DModes.cpp
Normal 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
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
265
MFLib1/Source/C/Common/Draw2d.cpp
Normal file
265
MFLib1/Source/C/Common/Draw2d.cpp
Normal 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;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
329
MFLib1/Source/C/Common/DrawBox.cpp
Normal file
329
MFLib1/Source/C/Common/DrawBox.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
562
MFLib1/Source/C/Common/DrawLine.cpp
Normal file
562
MFLib1/Source/C/Common/DrawLine.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
75
MFLib1/Source/C/Common/DrawPnt.cpp
Normal file
75
MFLib1/Source/C/Common/DrawPnt.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
59
MFLib1/Source/C/Common/DrawPxl.cpp
Normal file
59
MFLib1/Source/C/Common/DrawPxl.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
24
MFLib1/Source/C/Common/DrawRect.cpp
Normal file
24
MFLib1/Source/C/Common/DrawRect.cpp
Normal 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;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
145
MFLib1/Source/C/Common/Maths.cpp
Normal file
145
MFLib1/Source/C/Common/Maths.cpp
Normal 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
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
481
MFLib1/Source/C/Common/QuickTxt.cpp
Normal file
481
MFLib1/Source/C/Common/QuickTxt.cpp
Normal 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;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
809
MFLib1/Source/C/Common/Sprites.cpp
Normal file
809
MFLib1/Source/C/Common/Sprites.cpp
Normal 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++;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
930
MFLib1/Source/C/Common/TextDef.cpp
Normal file
930
MFLib1/Source/C/Common/TextDef.cpp
Normal 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
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
5924
MFLib1/Source/C/Common/Trig.cpp
Normal file
5924
MFLib1/Source/C/Common/Trig.cpp
Normal file
File diff suppressed because it is too large
Load Diff
363
MFLib1/Source/C/Windows/D3D.cpp
Normal file
363
MFLib1/Source/C/Windows/D3D.cpp
Normal 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
|
||||
}
|
||||
*/
|
||||
//---------------------------------------------------------------
|
926
MFLib1/Source/C/Windows/Display.cpp
Normal file
926
MFLib1/Source/C/Windows/Display.cpp
Normal 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;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
176
MFLib1/Source/C/Windows/File.cpp
Normal file
176
MFLib1/Source/C/Windows/File.cpp
Normal 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;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
117
MFLib1/Source/C/Windows/Keyboard.cpp
Normal file
117
MFLib1/Source/C/Windows/Keyboard.cpp
Normal 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;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
449
MFLib1/Source/C/Windows/MFHost.cpp
Normal file
449
MFLib1/Source/C/Windows/MFHost.cpp
Normal 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();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
67
MFLib1/Source/C/Windows/Mem.cpp
Normal file
67
MFLib1/Source/C/Windows/Mem.cpp
Normal 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;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
17
MFLib1/Source/C/Windows/Mouse.cpp
Normal file
17
MFLib1/Source/C/Windows/Mouse.cpp
Normal 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 };
|
245
MFLib1/Source/C/Windows/Palette.cpp
Normal file
245
MFLib1/Source/C/Windows/Palette.cpp
Normal 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
312
MFStdLib/Headers/MFStdLib.h
Normal 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
|
||||
|
48
MFStdLib/Headers/StdFile.h
Normal file
48
MFStdLib/Headers/StdFile.h
Normal 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
152
MFStdLib/Headers/StdKeybd.h
Normal 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
|
44
MFStdLib/Headers/StdMaths.h
Normal file
44
MFStdLib/Headers/StdMaths.h
Normal 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
42
MFStdLib/Headers/StdMem.h
Normal 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
|
31
MFStdLib/Headers/StdMouse.h
Normal file
31
MFStdLib/Headers/StdMouse.h
Normal 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
|
346
MFStdLib/Source/StdLib/StdFile.cpp
Normal file
346
MFStdLib/Source/StdLib/StdFile.cpp
Normal 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 ) );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
||||
|
||||
|
6058
MFStdLib/Source/StdLib/StdMaths.cpp
Normal file
6058
MFStdLib/Source/StdLib/StdMaths.cpp
Normal file
File diff suppressed because it is too large
Load Diff
254
MFStdLib/Source/StdLib/StdMem.cpp
Normal file
254
MFStdLib/Source/StdLib/StdMem.cpp
Normal 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
414
MuckyBasic/Always.h
Normal 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
133
MuckyBasic/Key.h
Normal 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
450
MuckyBasic/Matrix.cpp
Normal 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
167
MuckyBasic/Matrix.h
Normal 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
343
MuckyBasic/Tga.cpp
Normal 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
80
MuckyBasic/Tga.h
Normal 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
2727
MuckyBasic/cg.cpp
Normal file
File diff suppressed because it is too large
Load Diff
32
MuckyBasic/cg.h
Normal file
32
MuckyBasic/cg.h
Normal 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
155
MuckyBasic/clip.cpp
Normal 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
22
MuckyBasic/clip.h
Normal 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
62
MuckyBasic/comp.cpp
Normal 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
18
MuckyBasic/comp.h
Normal 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
300
MuckyBasic/console.cpp
Normal 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
33
MuckyBasic/console.h
Normal 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
643
MuckyBasic/d3denum.cpp
Normal 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
180
MuckyBasic/d3denum.h
Normal 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
755
MuckyBasic/d3dframe.cpp
Normal 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
135
MuckyBasic/d3dframe.h
Normal 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
394
MuckyBasic/d3dutil.cpp
Normal 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
110
MuckyBasic/d3dutil.h
Normal 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
480
MuckyBasic/font.cpp
Normal 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
37
MuckyBasic/font.h
Normal 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
BIN
MuckyBasic/icon1.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
820
MuckyBasic/lex.cpp
Normal file
820
MuckyBasic/lex.cpp
Normal 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
161
MuckyBasic/lex.h
Normal 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
975
MuckyBasic/link.cpp
Normal 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
139
MuckyBasic/link.h
Normal 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
405
MuckyBasic/ll.cpp
Normal 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
220
MuckyBasic/ll.h
Normal 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
113
MuckyBasic/main.cpp
Normal 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
55
MuckyBasic/mem.cpp
Normal 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
40
MuckyBasic/mem.h
Normal 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
243
MuckyBasic/ml.h
Normal 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
291
MuckyBasic/muckyBASIC.dsp
Normal 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
37
MuckyBasic/muckyBASIC.dsw
Normal 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
116
MuckyBasic/muckyBASIC.rc
Normal 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
5945
MuckyBasic/os.cpp
Normal file
File diff suppressed because it is too large
Load Diff
664
MuckyBasic/os.h
Normal file
664
MuckyBasic/os.h
Normal 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
3994
MuckyBasic/parse.cpp
Normal file
File diff suppressed because it is too large
Load Diff
196
MuckyBasic/parse.h
Normal file
196
MuckyBasic/parse.h
Normal 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
85
MuckyBasic/resource.h
Normal 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
400
MuckyBasic/st.cpp
Normal 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
85
MuckyBasic/st.h
Normal 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
37
MuckyBasic/sysvar.cpp
Normal 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
33
MuckyBasic/sysvar.h
Normal 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
23
MuckyBasic/test.mbs
Normal 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
32
MuckyBasic/test2.mbs
Normal 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
384
MuckyBasic/userdlg.cpp
Normal 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
4435
MuckyBasic/vm.cpp
Normal file
File diff suppressed because it is too large
Load Diff
17
MuckyBasic/vm.h
Normal file
17
MuckyBasic/vm.h
Normal 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
896
MuckyBasic/wave.c
Normal 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
68
MuckyBasic/wave.h
Normal 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
Loading…
Reference in New Issue
Block a user