LAB: Initial code

This commit is contained in:
Eugene Sandulenko 2014-10-06 14:50:05 +02:00
parent 64f9c902dd
commit 8ca14d1d64
42 changed files with 19438 additions and 0 deletions

221
engines/lab/allocroom.cpp Normal file
View File

@ -0,0 +1,221 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/storage.h"
#include "lab/parsetypes.h"
#include "lab/stddefines.h"
namespace Lab {
/* Have to make sure that ROOMBUFFERSIZE is bigger than the biggest piece of memory
that we need */
#define ROOMBUFFERSIZE (2 * 20480L)
#define EMPTYROOM ((uint16) -1)
#define MAXMARKERS 10
extern RoomData *Rooms;
extern uint16 ManyRooms;
typedef struct {
uint16 RoomNum;
void *Start0, *End0, *Start1, *End1;
} RoomMarker;
static RoomMarker RoomMarkers[MAXMARKERS];
static void *RoomBuffer = NULL;
static uint16 CurMarker = 0;
static void *MemPlace = NULL, *NextMemPlace = NULL;
static int32 MemLeftInBuffer = 0L;
/*****************************************************************************/
/* Allocates the memory for the room buffers. */
/*****************************************************************************/
bool initRoomBuffer(void) {
uint16 counter;
CurMarker = 0;
if (allocate((void **)&RoomBuffer, ROOMBUFFERSIZE)) {
MemPlace = RoomBuffer;
MemLeftInBuffer = ROOMBUFFERSIZE;
for (counter = 0; counter < MAXMARKERS; counter++)
RoomMarkers[counter].RoomNum = EMPTYROOM;
return true;
} else
return false;
}
/*****************************************************************************/
/* Frees the memory for the room buffers. */
/*****************************************************************************/
void freeRoomBuffer(void) {
if (RoomBuffer)
deallocate(RoomBuffer, ROOMBUFFERSIZE);
}
/*****************************************************************************/
/* Frees a room's resources. */
/*****************************************************************************/
static void freeRoom(uint16 RMarker) {
uint16 RoomNum;
RoomNum = RoomMarkers[RMarker].RoomNum;
if (RoomNum != EMPTYROOM) {
Rooms[RoomNum].NorthView = NULL;
Rooms[RoomNum].SouthView = NULL;
Rooms[RoomNum].EastView = NULL;
Rooms[RoomNum].WestView = NULL;
Rooms[RoomNum].RuleList = NULL;
Rooms[RoomNum].RoomMsg = NULL;
}
RoomMarkers[RMarker].RoomNum = EMPTYROOM;
RoomMarkers[RMarker].Start0 = NULL;
RoomMarkers[RMarker].End0 = NULL;
RoomMarkers[RMarker].Start1 = NULL;
RoomMarkers[RMarker].End1 = NULL;
}
/*****************************************************************************/
/* Gets a chunk of memory from the buffer. */
/*****************************************************************************/
static void *getCurMem(uint16 Size) {
uint16 counter;
void *Ptr, *Start0, *Start1, *End0, *End1;
if (((int32) Size) > MemLeftInBuffer) {
MemPlace = RoomBuffer;
MemLeftInBuffer = ROOMBUFFERSIZE;
NextMemPlace = NULL;
}
Ptr = MemPlace;
MemPlace = (char *)MemPlace + Size;
MemLeftInBuffer -= Size;
if (MemPlace > NextMemPlace) {
NextMemPlace = NULL;
for (counter = 0; counter < MAXMARKERS; counter++) {
if (RoomMarkers[counter].RoomNum != EMPTYROOM) {
Start0 = RoomMarkers[counter].Start0;
Start1 = RoomMarkers[counter].Start1;
End0 = RoomMarkers[counter].End0;
End1 = RoomMarkers[counter].End1;
if (((Start0 >= Ptr) && (Start0 < MemPlace)) ||
((End0 >= Ptr) && (End0 < MemPlace)) ||
((Ptr >= Start0) && (Ptr <= End0)) ||
((Start1 >= Ptr) && (Start1 < MemPlace)) ||
((End1 >= Ptr) && (End1 < MemPlace)) ||
((Ptr >= Start1) && (Ptr <= End1))) {
freeRoom(counter);
} else {
if (Start0 >= MemPlace)
if ((NextMemPlace == NULL) || (Start0 < NextMemPlace))
NextMemPlace = Start0;
if (Start1 >= MemPlace)
if ((NextMemPlace == NULL) || (Start1 < NextMemPlace))
NextMemPlace = Start1;
}
}
}
if (NextMemPlace == NULL) {
NextMemPlace = RoomBuffer;
NextMemPlace = (char *)NextMemPlace + ROOMBUFFERSIZE;
}
}
return Ptr;
}
/*****************************************************************************/
/* Grabs a chunk of memory from the room buffer, and manages it for a */
/* particular room. */
/*****************************************************************************/
void allocRoom(void **Ptr, uint16 Size, uint16 RoomNum) {
uint16 RMarker;
bool doit = true;
if (1 & Size) /* Memory is required to be even aligned */
Size++;
RMarker = 0;
while ((RMarker < MAXMARKERS) && doit) {
if (RoomMarkers[RMarker].RoomNum == RoomNum)
doit = false;
else
RMarker++;
}
if (RMarker >= MAXMARKERS) {
RMarker = CurMarker;
CurMarker++;
if (CurMarker >= MAXMARKERS)
CurMarker = 0;
freeRoom(RMarker);
RoomMarkers[RMarker].RoomNum = RoomNum;
}
*Ptr = getCurMem(Size);
if (RoomMarkers[RMarker].Start0 == NULL) {
RoomMarkers[RMarker].Start0 = *Ptr;
RoomMarkers[RMarker].End0 = (void *)(((char *)(*Ptr)) + Size - 1);
} else if (*Ptr < RoomMarkers[RMarker].Start0) {
if (RoomMarkers[RMarker].Start1 == NULL)
RoomMarkers[RMarker].Start1 = *Ptr;
RoomMarkers[RMarker].End1 = (void *)(((char *)(*Ptr)) + Size - 1);
} else
RoomMarkers[RMarker].End0 = (void *)(((char *)(*Ptr)) + Size - 1);
}
} // End of namespace Lab

461
engines/lab/audioi.cpp Normal file
View File

@ -0,0 +1,461 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/labfun.h"
namespace Lab {
#define PLAYBUFSIZE 65536L
#if defined(DOSCODE)
const char VERSION[] = "1.01";
char *AudioI_DriverName = "a32sbdg.dll";
#endif
extern bool MusicOn;
#if defined(DOSCODE)
static HTIMER server;
static HDRIVER hdriver;
static char *drvr;
static char *dll;
static drvr_desc *desc;
#endif
//static sound_buff firstblock, tempblock;
static int bufnum;
#if defined(DOSCODE)
static unsigned seg1;
static unsigned seg2;
static union REGS inregs, outregs;
#endif
bool EffectPlaying = false, ContMusic = false, DoMusic = false;
static char *CurMusic, *startMusic;
static uint32 StartMusicLen;
#if defined(DOSCODE)
static uint16 *mem, *head, *tail, counter;
#pragma off (check_stack)
void cdecl timer_callback(void) {
head = (uint16 *)(0x41A);
tail = (uint16 *)(0x41C);
mem = (uint16 *)(0x400 + *head);
if (*tail > *head)
counter = (*tail - *head) >> 1;
else
counter = (*head - *tail) >> 1;
if (counter > 16)
counter = 16;
while (counter) {
if ((*mem == 0x2e03) || (*mem == 0x300) || (*mem == 0x0003)) {
*tail = *head;
return;
}
mem++;
counter--;
}
}
#endif
void freeAudio(void) {
if (!DoMusic)
return;
#if defined(DOSCODE)
AIL_release_timer_handle(server);
AIL_shutdown(NULL);
#else
//SDLWrapAudio();
#endif
}
bool initAudio(void) {
if (!DoMusic)
return true;
#if 0
#if defined(DOSCODE)
AudioI_DriverName = "a32sbdg.dll";
//
// Allocate two 16K buffers from real-mode (lower 1MB) memory
//
// *buf1, *buf2 -> protected-mode pointers to buffers (sel:0000)
// *seg1, *seg2 -> real-mode (physical) pointers to buffers (seg:0000)
//
// Note: DPMI calculations assume flat model near pointer offset 0 =
// segment 0, offset 0 (Rational DOS4GW). The reason -- our simple
// file loader function can't use the far pointer formed by the selector
// returned by the DPMI call.
// Note that these examples do not implement out-of-memory error
// checking
//
inregs.x.eax = 0x100;
inregs.x.ebx = (16384 / 16);
int386(0x31, &inregs, &outregs);
seg1 = outregs.x.eax << 16;
buf1 = (char *)(outregs.x.eax * 16);
if (buf1 == NULL)
return false;
inregs.x.eax = 0x100;
inregs.x.ebx = (16384 / 16);
int386(0x31, &inregs, &outregs);
seg2 = outregs.x.eax << 16;
buf2 = (char *)(outregs.x.eax * 16);
if (buf2 == NULL)
return false;
//
// Load driver file
//
dll = FILE_read(AudioI_DriverName, NULL);
if (dll == NULL) {
return false;
}
drvr = DLL_load(dll, DLLMEM_ALLOC | DLLSRC_MEM, NULL);
if (drvr == NULL) {
return false;
}
free(dll);
//
// Initialize API before calling any Library functions
//
AIL_startup();
hdriver = AIL_register_driver(drvr);
if (hdriver == -1) {
AIL_shutdown(NULL);
return false;
}
//
// Get driver type and factory default I/O parameters; exit if
// driver is not capable of interpreting PCM sound data
//
desc = AIL_describe_driver(hdriver);
if (desc->drvr_type != DSP_DRVR) {
AIL_shutdown(NULL);
return false;
}
if (!AIL_detect_device(hdriver, desc->default_IO, desc->default_IRQ, desc->default_DMA, desc->default_DRQ)) {
desc->default_IRQ = 5;
if (!AIL_detect_device(hdriver, desc->default_IO, desc->default_IRQ, desc->default_DMA, desc->default_DRQ)) {
AIL_shutdown(NULL);
return false;
}
}
AIL_init_driver(hdriver, desc->default_IO, desc->default_IRQ, desc->default_DMA, desc->default_DRQ);
//
// Register a timer function; set up for 10-millisecond (100 Hz.)
// callback intervals
//
server = AIL_register_timer(timer_callback);
if (server != -1) {
AIL_set_timer_period(server, 20000L);
AIL_start_timer(server);
}
#else
// we allocate extra mempory for 16-bit samples
buf1 = malloc(PLAYBUFSIZE);
if (buf1 == NULL)
return false;
buf2 = malloc(PLAYBUFSIZE);
if (buf2 == NULL)
return false;
if (!SDLInitAudio())
return false;
#endif
#endif
return true;
}
void initSampleRate(uint16 SampleSpeed) {
flushAudio();
if (SampleSpeed < 4000)
SampleSpeed = 4000;
#if defined(DOSCODE)
firstblock.sample_rate = 256 - (1000000L / SampleSpeed);
firstblock.pack_type = 0 | 0x80; // 8-bit mono sample
#else
//firstblock.sample_rate = SampleSpeed;
//firstblock.pack_type = AUDIO_S16; // SOUND_MONO | SOUND_16BIT; // 16-bit mono sample
#endif
}
bool musicBufferEmpty(uint16 i) {
#if defined(NEWCODE)
return (AIL_sound_buffer_status(hdriver, i) == DAC_DONE);
#else
//return (SDLSoundBufferStatus(i) == DAC_DONE);
return true;
#endif
}
void playMusicBlock(void *Ptr, uint32 Size, uint16 BufferNum, uint16 SampleSpeed) {
#if defined(DOSCODE)
uint32 TempPtr;
uint32 seg;
char *buf;
TempPtr = ((uint32) Ptr) / 16L;
seg = TempPtr << 16;
buf = (char *)(TempPtr * 16);
if (SampleSpeed < 4000)
SampleSpeed = 4000;
firstblock.sample_rate = 256 - (1000000L / SampleSpeed);
firstblock.pack_type = 0 | 0x80; // 8-bit mono sample
tempblock = firstblock;
tempblock.sel_data = buf;
tempblock.seg_data = seg;
tempblock.len = Size;
AIL_register_sound_buffer(hdriver, BufferNum, &tempblock);
AIL_format_sound_buffer(hdriver, &tempblock);
AIL_start_digital_playback(hdriver);
AIL_set_digital_playback_volume(hdriver, 127);
#else
#if 0
if (SampleSpeed < 4000)
SampleSpeed = 4000;
firstblock.sample_rate = SampleSpeed;
firstblock.pack_type = SOUND_MONO | SOUND_16BIT; // 16-bit mono sample
tempblock = firstblock;
tempblock.sel_data = Ptr;
tempblock.len = Size;
SDLPlayBuffer(BufferNum, &tempblock);
#endif
#endif
}
void updateSoundBuffers(void) {
if (!DoMusic)
return;
if (!EffectPlaying)
return;
#if defined(DOSCODE)
for (int i = 0; i < 2; i++) {
if ((AIL_sound_buffer_status(hdriver, i) == DAC_DONE) && firstblock.len) {
tempblock.len = min(16384L, firstblock.len);
firstblock.len -= tempblock.len;
if (!(bufnum ^= 1)) {
memcpy(buf1, CurMusic, (unsigned) tempblock.len);
tempblock.sel_data = buf1;
tempblock.seg_data = seg1;
} else {
memcpy(buf2, CurMusic, (unsigned) tempblock.len);
tempblock.sel_data = buf2;
tempblock.seg_data = seg2;
}
CurMusic += tempblock.len;
AIL_register_sound_buffer(hdriver, i, &tempblock);
AIL_format_sound_buffer(hdriver, &tempblock);
AIL_start_digital_playback(hdriver);
AIL_set_digital_playback_volume(hdriver, 127);
}
}
//
// Playback ends when no bytes are left in the source data and
// the status of both buffers equals DAC_DONE
//
if (!firstblock.len) {
if (ContMusic) {
CurMusic = startMusic;
firstblock.len = StartMusicLen;
} else if ((AIL_sound_buffer_status(hdriver, 0) == DAC_DONE) &&
(AIL_sound_buffer_status(hdriver, 1) == DAC_DONE)) {
flushAudio();
EffectPlaying = false;
}
}
#else
#if 0
for (int i = 0; i < 2; i++) {
if ((SDLSoundBufferStatus(i) == DAC_DONE) && firstblock.len) {
// use extra memory for 16-bit samples
tempblock.len = min(PLAYBUFSIZE, firstblock.len);
firstblock.len -= tempblock.len;
if (!(bufnum ^= 1)) {
memcpy(buf1, CurMusic, (unsigned) tempblock.len);
tempblock.sel_data = buf1;
} else {
memcpy(buf2, CurMusic, (unsigned) tempblock.len);
tempblock.sel_data = buf2;
}
CurMusic += tempblock.len;
SDLPlayBuffer(i, &tempblock);
}
}
//
// Playback ends when no bytes are left in the source data and
// the status of both buffers equals DAC_DONE
//
if (!firstblock.len) {
if (ContMusic) {
CurMusic = startMusic;
firstblock.len = StartMusicLen;
} else if ((SDLSoundBufferStatus(0) == DAC_DONE) &&
(SDLSoundBufferStatus(1) == DAC_DONE)) {
flushAudio();
EffectPlaying = false;
}
}
#endif
#endif
}
void flushAudio(void) {
if (!DoMusic)
return;
#if defined(DOSCODE)
AIL_stop_digital_playback(hdriver);
#else
//SDLStopPlayback();
#endif
EffectPlaying = false;
}
void playMusic(uint16 SampleSpeed, uint16 Volume, uint32 Length, bool flush, void *Data) {
if (!DoMusic)
return;
g_music->pauseBackMusic();
if (flush)
flushAudio();
if (SampleSpeed < 4000)
SampleSpeed = 4000;
#if defined(DOSCODE)
firstblock.sample_rate = 256 - (1000000L / SampleSpeed);
firstblock.pack_type = 0 | 0x80; // 8-bit mono sample
#else
//firstblock.sample_rate = SampleSpeed;
//firstblock.pack_type = SOUND_MONO | SOUND_16BIT; // 16-bit mono sample
#endif
//firstblock.len = Length;
bufnum = 0;
//tempblock = firstblock;
EffectPlaying = true;
CurMusic = (char *)Data;
startMusic = CurMusic;
StartMusicLen = Length;
updateSoundBuffers();
}
} // End of namespace Lab

View File

@ -0,0 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
add_engine lab "Labirynth of Time" no

104
engines/lab/detection.cpp Normal file
View File

@ -0,0 +1,104 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "engines/advancedDetector.h"
#include "common/system.h"
#include "base/plugins.h"
#include "lab/lab.h"
static const PlainGameDescriptor lab_setting[] = {
{ "lab", "Labyrith of Time Engine game" },
{ 0, 0 }
};
static const ADGameDescription labDescriptions[] = {
{
"lab",
"",
{
{ "doors", 0, "d77536010e7e5ae17ee066323ceb9585", 2537 },
{ "notes11", 0, "63e873f659f8f46f9809d16a2bf653c7", 3562 },
{ NULL, 0, NULL, 0 }
},
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
GUIO0()
},
{
"lab",
"",
AD_ENTRY1s("doors", "7bf458df6ec30cc8ef4665e4d7c77f59", 2537),
Common::EN_ANY,
Common::kPlatformAmiga,
ADGF_NO_FLAGS,
GUIO0()
},
AD_TABLE_END_MARKER
};
static const char *const directoryGlobs[] = {
"fonts",
"game",
0
};
class LabMetaEngine : public AdvancedMetaEngine {
public:
LabMetaEngine() : AdvancedMetaEngine(labDescriptions, sizeof(ADGameDescription), lab_setting) {
_singleid = "lab";
_maxScanDepth = 2;
_directoryGlobs = directoryGlobs;
}
virtual const char *getName() const {
return "Lab";
}
virtual const char *getOriginalCopyright() const {
return "Labytinth of Time (c) 2004 The Wyrmkeep Entertainment Co.";
}
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription * /* desc */) const {
// Instantiate Engine even if the game data is not found.
*engine = new Lab::LabEngine(syst);
return true;
}
};
#if PLUGIN_ENABLED_DYNAMIC(LAB)
REGISTER_PLUGIN_DYNAMIC(LAB, PLUGIN_TYPE_ENGINE, LabMetaEngine);
#else
REGISTER_PLUGIN_STATIC(LAB, PLUGIN_TYPE_ENGINE, LabMetaEngine);
#endif

102
engines/lab/diff.h Normal file
View File

@ -0,0 +1,102 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#ifndef LAB_DIFF_H
#define LAB_DIFF_H
#include "lab/stddefines.h"
namespace Lab {
struct DIFFHeader {
uint16 Version, x, y;
char depth, fps;
uint32 BufferSize;
uint16 Machine;
uint32 Flags;
};
struct BitMap {
uint16 BytesPerRow, Rows;
byte Flags, Depth;
byte *Planes[16];
};
#if !defined(DOSCODE)
#define BITMAPF_VIDEO (1<<7)
#endif
/* unDiff.c */
void initOffsets(uint16 bytesperrow);
bool unDIFFMemory(byte *Dest, /* Where to Un-DIFF */
byte *diff, /* The DIFFed code. */
uint16 HeaderSize, /* Size of header (1, 2 or 4 bytes)
(only supports 1 currently */
uint16 CopySize); /* Size of minimum copy or skip.
(1, 2 or 4 bytes) */
bool VUnDIFFMemory(byte *Dest, byte *diff, uint16 HeaderSize, uint16 CopySize, uint16 bytesperrow);
void runLengthDecode(byte *Dest, byte *Source);
void VRunLengthDecode(byte *Dest, byte *Source, uint16 bytesperrow);
/* readDiff.c */
void blackScreen();
void blackAllScreen();
void whiteScreen(void);
bool readDiff(bool playonce);
void diffNextFrame(void);
void playCntMusic(void);
void readSound(void);
void stopDiff(void);
void stopDiffEnd(void);
void stopSound(void);
void diffSetMusic(void);
} // End of namespace Lab
#endif /* LAB_DIFF_H */

1834
engines/lab/engine.cpp Normal file

File diff suppressed because it is too large Load Diff

902
engines/lab/graphics.cpp Normal file
View File

@ -0,0 +1,902 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/diff.h"
#include "lab/parsetypes.h"
#include "lab/labfun.h"
#include "lab/parsefun.h"
#include "lab/mouse.h"
#include "lab/vga.h"
#include "lab/text.h"
namespace Lab {
struct BitMap bit1, bit2, *DispBitMap = &bit1, *DrawBitMap = &bit1;
extern struct BitMap RawDiffBM;
extern char diffcmap[256 * 3], lastcmap[256 * 3];
extern bool IsBM, NoFlip, nopalchange, ContMusic;
extern int32 ReadSoFar;
extern bool ReadIsDone, ReadIsError;
extern bool DoBlack, EffectPlaying, stopsound;
extern bool IsHiRes;
extern struct TextFont *MsgFont;
extern const char *CurFileName;
/*---------------------------------------------------------------------------*/
/*------ From readPict.c. Reads in pictures and animations from disk. ------*/
/*---------------------------------------------------------------------------*/
extern uint32 VGAScreenWidth, VGAScreenHeight, VGAPages, VGABytesPerPage;
/*****************************************************************************/
/* Reads in a picture into the dest bitmap. */
/*****************************************************************************/
bool readPict(const char *filename, bool PlayOnce) {
byte **file = NULL;
#if defined(DOSCODE)
uint16 counter;
#endif
stopDiff();
ReadSoFar = 0L;
ReadIsDone = false;
ReadIsError = false;
file = g_music->newOpen(filename);
if (file == NULL) {
if ((filename[0] == 'p') || (filename[0] == 'P'))
blackScreen();
return false;
}
DispBitMap->BytesPerRow = VGAScreenWidth;
DispBitMap->Rows = VGAScreenHeight;
#if defined(DOSCODE)
DispBitMap->Flags = 0;
#else
DispBitMap->Flags = BITMAPF_VIDEO;
#endif
DispBitMap->Depth = VGAPages;
#if defined(DOSCODE)
for (counter = 0; counter < VGAPages; counter++)
DispBitMap->Planes[counter] = getVGABaseAddr();
#else
// playDiff deals with resetting planes for the "video" display.
#endif
readDiff(PlayOnce);
#if !defined(DOSCODE)
ungetVGABaseAddr();
#endif
return true;
}
/*****************************************************************************/
/* Reads in a music file. Ignores any graphics. */
/*****************************************************************************/
bool readMusic(const char *filename) {
byte **file = NULL;
file = g_music->newOpen(filename);
if (file == NULL) {
return false;
}
DoBlack = false;
readSound();
return true;
}
/*****************************************************************************/
/* Reads in a picture into buffer memory. */
/*****************************************************************************/
byte *readPictToMem(const char *filename, uint16 x, uint16 y) {
byte **file = NULL;
byte *Mem, *CurMem;
#if defined(DOSCODE)
uint16 counter;
#endif
stopDiff();
ReadSoFar = 0L;
ReadIsDone = false;
ReadIsError = false;
allocFile((void **)&Mem, (int32) x * (int32) y, "Bitmap");
CurMem = Mem;
file = g_music->newOpen(filename);
if (file == NULL)
return NULL;
DispBitMap->BytesPerRow = x;
DispBitMap->Rows = y;
DispBitMap->Flags = 0;
DispBitMap->Depth = VGAPages;
#if defined(DOSCODE)
for (counter = 0; counter < VGAPages; counter++) {
DispBitMap->Planes[counter] = CurMem;
CurMem += VGABytesPerPage;
}
#else
DispBitMap->Planes[0] = CurMem;
DispBitMap->Planes[1] = DispBitMap->Planes[0] + 0x10000;
DispBitMap->Planes[2] = DispBitMap->Planes[1] + 0x10000;
DispBitMap->Planes[3] = DispBitMap->Planes[2] + 0x10000;
DispBitMap->Planes[4] = DispBitMap->Planes[3] + 0x10000;
#endif
readDiff(true);
return Mem;
}
/*---------------------------------------------------------------------------*/
/*------------ Does all the text rendering to the message boxes. ------------*/
/*---------------------------------------------------------------------------*/
bool DoNotDrawMessage = false;
extern bool LongWinInFront, Alternate;
/*----- The flowText routines -----*/
/******************************************************************************/
/* Extracts the first word from a string. */
/******************************************************************************/
static void getWord(char *WordBuffer, const char *MainBuffer, uint16 *WordWidth) {
uint16 width = 0;
while ((MainBuffer[width] != ' ') && MainBuffer[width] &&
(MainBuffer[width] != '\n')) {
WordBuffer[width] = MainBuffer[width];
width++;
}
WordBuffer[width] = 0;
*WordWidth = width;
}
/******************************************************************************/
/* Gets a line of text for flowText; makes sure that its length is less than */
/* or equal to the maximum width. */
/******************************************************************************/
static void getLine(struct TextFont *tf, char *LineBuffer, const char **MainBuffer, uint16 LineWidth) {
uint16 CurWidth = 0, WordWidth;
char WordBuffer[100];
bool doit = true;
LineWidth += textLength(tf, " ", 1);
LineBuffer[0] = 0;
while ((*MainBuffer)[0] && doit) {
getWord(WordBuffer, *MainBuffer, &WordWidth);
strcat(WordBuffer, " ");
if ((CurWidth + textLength(tf, WordBuffer, WordWidth + 1)) <= LineWidth) {
strcat(LineBuffer, WordBuffer);
(*MainBuffer) += WordWidth;
if ((*MainBuffer)[0] == '\n')
doit = false;
if ((*MainBuffer)[0])
(*MainBuffer)++;
CurWidth = textLength(tf, LineBuffer, strlen(LineBuffer));
} else
doit = false;
}
/* NYI: Would add code here to break up words in case they were longer than a line */
}
/******************************************************************************/
/* Dumps a chunk of text to an arbitrary box; flows it within that box and */
/* optionally centers it. Returns the number of characters that were */
/* processed. */
/* */
/* Note: Every individual word MUST be int16 enough to fit on a line, and */
/* each line less than 255 characters. */
/******************************************************************************/
uint32 flowText(void *font, /* the TextAttr pointer */
uint16 spacing, /* How much vertical spacing between the lines */
uint16 pencolor, /* pen number to use for text */
uint16 backpen, /* the background color */
bool fillback, /* Whether to fill the background */
bool centerh, /* Whether to center the text horizontally */
bool centerv, /* Whether to center the text vertically */
bool output, /* Whether to output any text */
uint16 x1, /* Cords */
uint16 y1, uint16 x2, uint16 y2, const char *str) { /* The text itself */
struct TextFont *msgfont = (TextFont *)font;
char linebuffer[256];
const char *temp;
uint16 numlines, actlines, fontheight, width;
uint16 x, y;
if (fillback) {
setAPen(backpen);
rectFill(x1, y1, x2, y2);
}
if (str == NULL)
return 0L;
setAPen(pencolor);
fontheight = textHeight(msgfont) + spacing;
numlines = (y2 - y1 + 1) / fontheight;
width = x2 - x1 + 1;
y = y1;
if (centerv && output) {
temp = str;
actlines = 0;
while (temp[0]) {
getLine(msgfont, linebuffer, &temp, width);
actlines++;
}
if (actlines <= numlines)
y += ((y2 - y1 + 1) - (actlines * fontheight)) / 2;
}
temp = str;
while (numlines && str[0]) {
getLine(msgfont, linebuffer, &str, width);
x = x1;
if (centerh)
x += (width - textLength(msgfont, linebuffer, strlen(linebuffer))) / 2;
if (output)
text(msgfont, x, y, pencolor, linebuffer, strlen(linebuffer));
numlines--;
y += fontheight;
}
return (str - temp);
}
extern uint32 VGABASEADDRESS, VGABytesPerPage;
/******************************************************************************/
/* Calls flowText, but flows it to memory. Same restrictions as flowText. */
/******************************************************************************/
uint32 flowTextToMem(struct Image *DestIm, void *font, /* the TextAttr pointer */
uint16 spacing, /* How much vertical spacing between the lines */
uint16 pencolor, /* pen number to use for text */
uint16 backpen, /* the background color */
bool fillback, /* Whether to fill the background */
bool centerh, /* Whether to center the text horizontally */
bool centerv, /* Whether to center the text vertically */
bool output, /* Whether to output any text */
uint16 x1, /* Cords */
uint16 y1, uint16 x2, uint16 y2, const char *str) { /* The text itself */
uint32 res, vgabyte = VGABytesPerPage;
//VGABASEADDRESS = (uint32)(DestIm->ImageData);
VGABytesPerPage = (uint32) DestIm->Width * (int32) DestIm->Height;
res = flowText(font, spacing, pencolor, backpen, fillback, centerh, centerv, output, x1, y1, x2, y2, str);
VGABytesPerPage = vgabyte;
return res;
}
/*----- The control panel stuff -----*/
void createBox(uint16 y2) {
setAPen(7); /* Message box area */
rectFill(VGAScaleX(4), VGAScaleY(154), VGAScaleX(315), VGAScaleY(y2 - 2));
setAPen(0); /* Box around message area */
drawHLine(VGAScaleX(2), VGAScaleY(152), VGAScaleX(317));
drawVLine(VGAScaleX(317), VGAScaleY(152), VGAScaleY(y2));
drawHLine(VGAScaleX(2), VGAScaleY(y2), VGAScaleX(317));
drawVLine(VGAScaleX(2), VGAScaleY(152), VGAScaleY(y2));
}
int32 longcharsdrawn = 0L;
bool LastMessageLong = false;
void longDrawMessage(const char *str) {
char NewText[512];
if (str == NULL)
return;
attachGadgetList(NULL);
mouseHide();
strcpy(NewText, str);
if (!LongWinInFront) {
LongWinInFront = true;
setAPen(3); /* Clear Area */
rectFill(0, VGAScaleY(149) + SVGACord(2), VGAScaleX(319), VGAScaleY(199));
}
createBox(198);
longcharsdrawn = flowText(MsgFont, 0, 1, 7, false, true, true, true, VGAScaleX(6), VGAScaleY(155), VGAScaleX(313), VGAScaleY(195), str);
mouseShow();
}
/******************************************************************************/
/* Draws a message to the message box. */
/******************************************************************************/
void drawMessage(const char *str) {
if (DoNotDrawMessage) {
DoNotDrawMessage = false;
return;
}
if (str) {
if ((textLength(MsgFont, str, strlen(str)) > VGAScaleX(306))) {
longDrawMessage(str);
LastMessageLong = true;
} else {
if (LongWinInFront) {
LongWinInFront = false;
drawPanel();
}
mouseHide();
createBox(168);
text(MsgFont, VGAScaleX(7), VGAScaleY(155) + SVGACord(2), 1, str, strlen(str));
mouseShow();
LastMessageLong = false;
}
}
}
/*---------------------------------------------------------------------------*/
/*--------------------------- All the wipe stuff. ---------------------------*/
/*---------------------------------------------------------------------------*/
#define TRANSWIPE 1
#define SCROLLWIPE 2
#define SCROLLBLACK 3
#define SCROLLBOUNCE 4
#define TRANSPORTER 5
#define READFIRSTFRAME 6
#define READNEXTFRAME 7
/*****************************************************************************/
/* Copies memory from one location to another 64 bytes at a time. */
/*****************************************************************************/
void copyLong64(uint32 *Dest, uint32 *Source, uint32 Many64) {
while (Many64) {
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
Dest++;
Source++;
Many64--;
}
}
/*****************************************************************************/
/* Scrolls the display to black. */
/*****************************************************************************/
static void doScrollBlack(void) {
byte *mem, *tempmem;
struct Image Im;
uint16 width, height, by, nheight, CurPage;
uint32 size, copysize;
uint32 *BaseAddr;
mouseHide();
width = VGAScaleX(320);
height = VGAScaleY(149) + SVGACord(2);
/*
while (EffectPlaying)
{
g_music->updateMusic();
waitTOF();
}
*/
allocFile((void **) &mem, (int32) width * (int32) height, "Temp Mem");
/*
mem = stealBufMem((int32) width * (int32) height);
*/
Im.Width = width;
Im.Height = height;
Im.ImageData = mem;
g_music->fillUpMusic(true);
readScreenImage(&Im, 0, 0);
g_music->fillUpMusic(true);
BaseAddr = (uint32 *) getVGABaseAddr();
by = VGAScaleX(4);
nheight = height;
while (nheight) {
g_music->newCheckMusic();
if (!IsHiRes)
waitTOF();
#if !defined(DOSCODE)
BaseAddr = (uint32 *) getVGABaseAddr();
#endif
if (by > nheight)
by = nheight;
mem += by * width;
nheight -= by;
size = (int32) nheight * (int32) width;
CurPage = 0;
tempmem = mem;
while (size) {
if (size > VGABytesPerPage)
copysize = VGABytesPerPage;
else
copysize = size;
size -= copysize;
setPage(CurPage);
copyLong64(BaseAddr, (uint32 *) tempmem, copysize >> 6);
tempmem += copysize;
CurPage++;
}
setAPen(0);
rectFill(0, nheight, width - 1, nheight + by - 1);
g_system->updateScreen();
if (!IsHiRes) {
if (nheight <= (height / 8))
by = 1;
else if (nheight <= (height / 4))
by = 2;
else if (nheight <= (height / 2))
by = 3;
}
}
freeAllStolenMem();
mouseShow();
#if !defined(DOSCODE)
ungetVGABaseAddr();
#endif
}
extern struct BitMap RawDiffBM;
extern DIFFHeader headerdata;
static void copyPage(uint16 width, uint16 height, uint16 nheight, uint16 startline, byte *mem) {
uint32 size, OffSet, copysize;
uint16 CurPage;
uint32 *BaseAddr;
BaseAddr = (uint32 *) getVGABaseAddr();
size = (int32)(height - nheight) * (int32) width;
mem += startline * width;
CurPage = ((int32) nheight * (int32) width) / VGABytesPerPage;
OffSet = ((int32) nheight * (int32) width) - (CurPage * VGABytesPerPage);
while (size) {
if (size > (VGABytesPerPage - OffSet))
copysize = VGABytesPerPage - OffSet;
else
copysize = size;
size -= copysize;
setPage(CurPage);
copyLong64(BaseAddr + (OffSet >> 2), (uint32 *) mem, copysize >> 6);
mem += copysize;
CurPage++;
OffSet = 0;
}
#if !defined(DOSCODE)
ungetVGABaseAddr();
#endif
}
/*****************************************************************************/
/* Scrolls the display to a new picture from a black screen. */
/*****************************************************************************/
static void doScrollWipe(char *filename) {
byte *mem;
uint16 width, height, by, nheight, startline = 0, onrow = 0;
mouseHide();
width = VGAScaleX(320);
height = VGAScaleY(149) + SVGACord(2);
while (EffectPlaying) {
g_music->newCheckMusic();
waitTOF();
}
IsBM = true;
readPict(filename, true);
VGASetPal(diffcmap, 256);
IsBM = false;
mem = RawDiffBM.Planes[0];
g_music->fillUpMusic(true);
by = VGAScaleX(3);
nheight = height;
while (onrow < headerdata.y) {
g_music->newCheckMusic();
if ((by > nheight) && nheight)
by = nheight;
if ((startline + by) > (headerdata.y - height - 1))
break;
if (nheight)
nheight -= by;
copyPage(width, height, nheight, startline, mem);
g_system->updateScreen();
if (!nheight)
startline += by;
onrow += by;
if (nheight <= (height / 4))
by = VGAScaleX(5);
else if (nheight <= (height / 3))
by = VGAScaleX(4);
else if (nheight <= (height / 2))
by = VGAScaleX(3);
}
mouseShow();
}
/*****************************************************************************/
/* Does the scroll bounce. Assumes bitmap already in memory. */
/*****************************************************************************/
static void doScrollBounce(void) {
byte *mem;
uint16 width, height, startline, counter,
#if defined(DOSCODE)
newby[5] = {5, 4, 3, 2, 1}, newby1[8] = {3, 3, 2, 2, 2, 1, 1, 1};
#else
newby[5] = {10, 8, 6, 4, 2}, newby1[8] = {6, 6, 4, 4, 4, 2, 2, 2};
#endif
mouseHide();
width = VGAScaleX(320);
height = VGAScaleY(149) + SVGACord(2);
mem = RawDiffBM.Planes[0];
g_music->fillUpMusic(true);
startline = headerdata.y - height - 1;
for (counter = 0; counter < 5; counter++) {
g_music->newCheckMusic();
startline -= newby[counter];
copyPage(width, height, 0, startline, mem);
g_system->updateScreen();
waitTOF();
}
for (counter = 8; counter > 0; counter--) {
g_music->newCheckMusic();
startline += newby1[counter - 1];
copyPage(width, height, 0, startline, mem);
g_system->updateScreen();
waitTOF();
}
mouseShow();
}
/*****************************************************************************/
/* Does the transporter wipe. */
/*****************************************************************************/
static void doTransWipe(CloseDataPtr *CPtr, char *filename) {
uint16 LastY, CurY, counter, linesdone = 0, lineslast;
struct Image ImSource, ImDest;
if (IsHiRes) {
lineslast = 3;
LastY = 358;
} else {
lineslast = 1;
LastY = 148;
}
for (counter = 0; counter < 2; counter++) {
CurY = counter * 2;
while (CurY < LastY) {
if (linesdone >= lineslast) {
g_music->updateMusic();
waitTOF();
linesdone = 0;
}
ghoastRect(0, 0, CurY, VGAScreenWidth - 1, CurY + 1);
CurY += 4;
linesdone++;
}
}
setAPen(0);
for (counter = 0; counter < 2; counter++) {
CurY = counter * 2;
while (CurY <= LastY) {
if (linesdone >= lineslast) {
g_music->updateMusic();
waitTOF();
linesdone = 0;
}
rectFill(0, CurY, VGAScreenWidth - 1, CurY + 1);
CurY += 4;
linesdone++;
}
}
if (filename == NULL)
CurFileName = getPictName(CPtr);
else if (filename[0] > ' ')
CurFileName = filename;
else
CurFileName = getPictName(CPtr);
byte *BitMapMem = readPictToMem(CurFileName, VGAScreenWidth, LastY + 5);
VGASetPal(diffcmap, 256);
if (BitMapMem) {
ImSource.Width = VGAScreenWidth;
ImSource.Height = LastY;
ImSource.ImageData = BitMapMem;
ImDest.Width = VGAScreenWidth;
ImDest.Height = VGAScreenHeight;
ImDest.ImageData = getVGABaseAddr();
for (counter = 0; counter < 2; counter++) {
CurY = counter * 2;
while (CurY < LastY) {
if (linesdone >= lineslast) {
g_music->updateMusic();
waitTOF();
linesdone = 0;
}
#if !defined(DOSCODE)
ImDest.ImageData = getVGABaseAddr();
#endif
bltBitMap(&ImSource, 0, CurY, &ImDest, 0, CurY, VGAScreenWidth, 2);
ghoastRect(0, 0, CurY, VGAScreenWidth - 1, CurY + 1);
CurY += 4;
linesdone++;
}
}
for (counter = 0; counter < 2; counter++) {
CurY = counter * 2;
while (CurY <= LastY) {
if (linesdone >= lineslast) {
g_music->updateMusic();
waitTOF();
linesdone = 0;
}
#if !defined(DOSCODE)
ImDest.ImageData = getVGABaseAddr();
#endif
if (CurY == LastY)
bltBitMap(&ImSource, 0, CurY, &ImDest, 0, CurY, VGAScreenWidth, 1);
else
bltBitMap(&ImSource, 0, CurY, &ImDest, 0, CurY, VGAScreenWidth, 2);
CurY += 4;
linesdone++;
}
}
}
#if !defined(DOSCODE)
ungetVGABaseAddr();
#endif
}
/*****************************************************************************/
/* Does a certain number of pre-programmed wipes. */
/*****************************************************************************/
void doWipe(uint16 WipeType, CloseDataPtr *CPtr, char *filename) {
if ((WipeType == TRANSWIPE) || (WipeType == TRANSPORTER))
doTransWipe(CPtr, filename);
else if (WipeType == SCROLLWIPE)
doScrollWipe(filename);
else if (WipeType == SCROLLBLACK)
doScrollBlack();
else if (WipeType == SCROLLBOUNCE)
doScrollBounce();
else if (WipeType == READFIRSTFRAME)
readPict(filename, false);
else if (WipeType == READNEXTFRAME)
diffNextFrame();
}
} // End of namespace Lab

234
engines/lab/interface.cpp Normal file
View File

@ -0,0 +1,234 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/interface.h"
#include "lab/storage.h"
#include "lab/timing.h"
#include "lab/mouse.h"
#include "lab/vga.h"
#include "common/util.h"
namespace Lab {
extern bool IsHiRes;
Common::KeyState _keyPressed;
struct Gadget *createButton(uint16 x, uint16 y, uint16 id, uint16 key, Image *im, Image *imalt) {
Gadget *gptr;
if (allocate((void **)&gptr, sizeof(struct Gadget))) {
gptr->x = x;
gptr->y = y;
gptr->GadgetID = id;
#if !defined(DOSCODE)
gptr->KeyEquiv = key;
#endif
gptr->Im = im;
gptr->ImAlt = imalt;
gptr->NextGadget = NULL;
return gptr;
} else
return NULL;
}
void freeButtonList(Gadget *gptrlist) {
struct Gadget *gptr, *next = gptrlist;
while (next) {
gptr = next;
next = next->NextGadget;
deallocate(gptr, sizeof(struct Gadget));
}
}
/*****************************************************************************/
/* Draws a gadget list to the screen. */
/*****************************************************************************/
void drawGadgetList(struct Gadget *gadlist) {
while (gadlist) {
drawImage(gadlist->Im, gadlist->x, gadlist->y);
if (GADGETOFF & gadlist->GadgetFlags)
ghoastGadget(gadlist, 1);
gadlist = gadlist->NextGadget;
}
}
/*****************************************************************************/
/* Ghoasts a gadget, and makes it unavailable for using. */
/*****************************************************************************/
void ghoastGadget(struct Gadget *curgad, uint16 pencolor) {
ghoastRect(pencolor, curgad->x, curgad->y, curgad->x + curgad->Im->Width - 1, curgad->y + curgad->Im->Height - 1);
curgad->GadgetFlags |= GADGETOFF;
}
/*****************************************************************************/
/* Unghoasts a gadget, and makes it available again. */
/*****************************************************************************/
void unGhoastGadget(struct Gadget *curgad) {
drawImage(curgad->Im, curgad->x, curgad->y);
curgad->GadgetFlags &= !(GADGETOFF);
}
/*****************************************************************************/
/* Make a key press have the right case for a gadget KeyEquiv value. */
/*****************************************************************************/
#if !defined(DOSCODE)
uint16 makeGadgetKeyEquiv(uint16 key) {
if (Common::isAlnum(key))
key = tolower(key);
return key;
}
#endif
/*****************************************************************************/
/* Checks whether or not the cords fall within one of the gadgets in a list */
/* of gadgets. */
/*****************************************************************************/
static struct Gadget *checkNumGadgetHit(struct Gadget *gadlist, uint16 key) {
#if !defined(DOSCODE)
uint16 gkey = key - '0';
#else
key = key - '0';
#endif
while (gadlist != NULL) {
#if !defined(DOSCODE)
if ((gkey - 1 == gadlist->GadgetID || (gkey == 0 && gadlist->GadgetID == 9) ||
(gadlist->KeyEquiv != 0 && makeGadgetKeyEquiv(key) == gadlist->KeyEquiv))
&& !(GADGETOFF & gadlist->GadgetFlags))
#else
if ((((key - 1) == gadlist->GadgetID) || ((key == 0) && (gadlist->GadgetID == 9))) &&
!(GADGETOFF & gadlist->GadgetFlags))
#endif
{
mouseHide();
drawImage(gadlist->ImAlt, gadlist->x, gadlist->y);
mouseShow();
g_system->delayMillis(80);
mouseHide();
drawImage(gadlist->Im, gadlist->x, gadlist->y);
mouseShow();
return gadlist;
} else {
gadlist = gadlist->NextGadget;
}
}
return NULL;
}
/*****************************************************************************/
/* Checks whether or not a key has been pressed. */
/*****************************************************************************/
static bool keyPress(uint16 *KeyCode) {
if (_keyPressed.keycode) {
*KeyCode = _keyPressed.keycode;
return true;
}
return false;
}
struct IntuiMessage IMessage;
extern struct Gadget *ScreenGadgetList;
struct IntuiMessage *getMsg(void) {
struct Gadget *curgad;
int Qualifiers;
updateMouse();
#if !defined(DOSCODE)
Qualifiers = _keyPressed.flags;
#endif
if ((curgad = mouseGadget()) != NULL) {
updateMouse();
IMessage.Class = GADGETUP;
IMessage.Code = curgad->GadgetID;
IMessage.GadgetID = curgad->GadgetID;
IMessage.Qualifier = Qualifiers;
return &IMessage;
}
else if (mouseButton(&IMessage.MouseX, &IMessage.MouseY, true)) { /* Left Button */
IMessage.Qualifier = IEQUALIFIER_LEFTBUTTON | Qualifiers;
IMessage.Class = MOUSEBUTTONS;
return &IMessage;
}
else if (mouseButton(&IMessage.MouseX, &IMessage.MouseY, false)) { /* Right Button */
IMessage.Qualifier = IEQUALIFIER_RBUTTON | Qualifiers;
IMessage.Class = MOUSEBUTTONS;
return &IMessage;
}
else if (keyPress(&IMessage.Code)) { /* Keyboard key */
curgad = checkNumGadgetHit(ScreenGadgetList, IMessage.Code);
if (curgad) {
IMessage.Class = GADGETUP;
IMessage.Code = curgad->GadgetID;
IMessage.GadgetID = curgad->GadgetID;
} else
IMessage.Class = RAWKEY;
IMessage.Qualifier = Qualifiers;
return &IMessage;
} else
return NULL;
}
void replyMsg(void *Msg) {
return;
}
} // End of namespace Lab

143
engines/lab/interface.h Normal file
View File

@ -0,0 +1,143 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/vga.h"
#include "common/keyboard.h"
#ifndef LAB_INTEFACE_H
#define LAB_INTEFACE_H
namespace Lab {
struct IntuiMessage {
uint32 Class;
uint16 Code, Qualifier, MouseX, MouseY, GadgetID;
uint32 Seconds, Micros;
};
struct Gadget {
uint16 x, y, GadgetID;
#if !defined(DOSCODE)
uint16 KeyEquiv; // if not zero, a key that activates gadget
#endif
uint32 GadgetFlags;
struct Image *Im, *ImAlt;
struct Gadget *NextGadget;
};
extern Common::KeyState _keyPressed;
/* Defines for the GadgetFlags portion */
#define GADGETOFF 0x01
/* Defines for the Class variable in IntuiMessage */
#define SIZEVERIFY 0x00000001
#define NEWSIZE 0x00000002
#define REFRESHWINDOW 0x00000004
#define MOUSEBUTTONS 0x00000008
#define MOUSEMOVE 0x00000010
#define GADGETDOWN 0x00000020
#define GADGETUP 0x00000040
#define REQSET 0x00000080
#define MENUPICK 0x00000100
#define CLOSEWINDOW 0x00000200
#define RAWKEY 0x00000400
#define REQVERIFY 0x00000800
#define REQCLEAR 0x00001000
#define MENUVERIFY 0x00002000
#define NEWPREFS 0x00004000
#define DISKINSERTED 0x00008000
#define DISKREMOVED 0x00010000
#define WBENCHMESSAGE 0x00020000 /* System use only */
#define ACTIVEWINDOW 0x00040000
#define INACTIVEWINDOW 0x00080000
#define DELTAMOVE 0x00100000
#define VANULLLAKEY 0x00200000
/* Defines for the Qualifier variable in IntuiMessage */
#define IEQUALIFIER_LSHIFT 0x0001
#define IEQUALIFIER_RSHIFT 0x0002
#define IEQUALIFIER_CAPSLOCK 0x0004
#define IEQUALIFIER_CONTROL 0x0008
#define IEQUALIFIER_LALT 0x0010
#define IEQUALIFIER_RALT 0x0020
#define IEQUALIFIER_LCOMMAND 0x0040
#define IEQUALIFIER_RCOMMAND 0x0080
#define IEQUALIFIER_NUMERICPAD 0x0100
#define IEQUALIFIER_REPEAT 0x0200
#define IEQUALIFIER_INTERRUPT 0x0400
#define IEQUALIFIER_MULTIBROADCAST 0x0800
#define IEQUALIFIER_MIDBUTTON 0x1000
#define IEQUALIFIER_RBUTTON 0x2000
#define IEQUALIFIER_LEFTBUTTON 0x4000
#if !defined(DOSCODE)
// these values come from the SDL virtual key table
#define VKEY_UPARROW 273
#define VKEY_DNARROW 274
#define VKEY_RTARROW 275
#define VKEY_LTARROW 276
#endif
/*---------------------------------------------------------------------------*/
/*--------------------------- Function Prototypes ---------------------------*/
/*---------------------------------------------------------------------------*/
struct Gadget *createButton(uint16 x, uint16 y, uint16 id,
#if !defined(DOSCODE)
uint16 key,
#endif
struct Image *im, struct Image *imalt);
void freeButtonList(void *gptrlist);
void drawGadgetList(struct Gadget *gadlist);
void ghoastGadget(struct Gadget *curgad, uint16 pencolor);
void unGhoastGadget(struct Gadget *curgad);
struct IntuiMessage *getMsg(void);
void replyMsg(void *Msg);
} // End of namespace Lab
#endif /* LAB_INTEFACE_H */

470
engines/lab/intro.cpp Normal file
View File

@ -0,0 +1,470 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/labfun.h"
#include "lab/timing.h"
#include "lab/diff.h"
#include "lab/text.h"
#include "lab/interface.h"
namespace Lab {
static struct TextFont filler, *msgfont = &filler;
extern bool nopalchange, noscreenchange, hidemouse, DoBlack, NoFlip, IsHiRes;
extern char diffcmap[256 * 3];
extern uint32 VGAScreenWidth, VGAScreenHeight;
extern uint16 *FadePalette;
static uint16 Palette[16] = {
0x0000, 0x0855, 0x0FF9, 0x0EE7, 0x0ED5, 0x0DB4, 0x0CA2, 0x0C91, 0x0B80, 0x0B80, 0x0B91, 0x0CA2, 0x0CB3, 0x0DC4, 0x0DD6, 0x0EE7
};
static bool QuitIntro = false, IntroDoBlack;
extern int32 longcharsdrawn;
/******************************************************************************/
/* Goes thru, and responds to all the intuition messages currently in the */
/* the message port. */
/******************************************************************************/
void introEatMessages(void) {
struct IntuiMessage *Msg;
while (1) {
Msg = getMsg();
if (Msg == NULL)
return;
else {
if (((Msg->Class == MOUSEBUTTONS) && (IEQUALIFIER_RBUTTON & Msg->Qualifier)) ||
((Msg->Class == RAWKEY) && (Msg->Code == 27)))
QuitIntro = true;
replyMsg(Msg);
}
}
}
/*****************************************************************************/
/* Reads in a picture. */
/*****************************************************************************/
static void doPictText(const char *Filename, bool isscreen) {
uint32 lastsecs = 0L, lastmicros = 0L, secs = 0L, micros = 0L;
struct IntuiMessage *Msg;
char filename[50] = "Lab:rooms/Intro/";
byte *curplace, **tfile;
bool DrawNextText = true, End = false, Begin = true;
int32 Class, Code, Drawn;
int16 Qualifier;
uint timedelay;
strcat(filename, Filename);
if (isscreen) {
g_music->fillUpMusic(true);
timedelay = 35;
} else {
g_music->newCheckMusic();
timedelay = 7;
}
if (QuitIntro)
return;
while (1) {
if (DrawNextText) {
if (Begin) {
Begin = false;
tfile = g_music->newOpen(filename);
if (!tfile)
return;
curplace = *tfile;
} else if (isscreen)
fade(false, 0);
if (isscreen) {
setAPen(7L);
rectFill(VGAScaleX(10), VGAScaleY(10), VGAScaleX(310), VGAScaleY(190));
Drawn = flowText(msgfont, (!IsHiRes) * -1, 5, 7, false, false, true, true, VGAScaleX(14), VGAScaleY(11), VGAScaleX(306), VGAScaleY(189), (char *)curplace);
fade(true, 0);
} else {
longDrawMessage((char *)curplace);
Drawn = longcharsdrawn;
}
curplace += Drawn;
End = (*curplace == 0);
DrawNextText = false;
introEatMessages();
if (QuitIntro) {
if (isscreen)
fade(false, 0);
return;
}
getTime(&lastsecs, &lastmicros);
}
Msg = getMsg();
if (Msg == NULL) {
g_music->newCheckMusic();
diffNextFrame();
getTime(&secs, &micros);
anyTimeDiff(lastsecs, lastmicros, secs, micros, &secs, &micros);
if (secs > timedelay) {
if (End) {
if (isscreen)
fade(false, 0);
return;
} else {
DrawNextText = true;
}
}
waitTOF();
} else {
Class = Msg->Class;
Qualifier = Msg->Qualifier;
Code = Msg->Code;
replyMsg(Msg);
if (((Class == MOUSEBUTTONS) && (IEQUALIFIER_RBUTTON & Qualifier)) ||
((Class == RAWKEY) && (Code == 27))) {
QuitIntro = true;
if (isscreen)
fade(false, 0);
return;
}
else if (Class == MOUSEBUTTONS) {
if (IEQUALIFIER_LEFTBUTTON & Qualifier) {
if (End) {
if (isscreen)
fade(false, 0);
return;
} else
DrawNextText = true;
}
introEatMessages();
if (QuitIntro) {
if (isscreen)
fade(false, 0);
return;
}
}
if (End) {
if (isscreen)
fade(false, 0);
return;
} else
DrawNextText = true;
}
}
}
/*****************************************************************************/
/* Does a one second delay, but checks the music while doing it. */
/*****************************************************************************/
void musicDelay(void) {
int16 counter;
g_music->newCheckMusic();
if (QuitIntro)
return;
for (counter = 0; counter < 20; counter++) {
g_music->newCheckMusic();
waitTOF();
waitTOF();
waitTOF();
}
}
static void NReadPict(const char *Filename, bool PlayOnce) {
char filename[20] = "P:Intro/";
g_music->newCheckMusic();
if (QuitIntro)
return;
strcat(filename, Filename);
DoBlack = IntroDoBlack;
stopDiffEnd();
readPict(filename, PlayOnce);
}
//#define ALL_LOGOS
/*****************************************************************************/
/* Does the introduction sequence for Labyrinth. */
/*****************************************************************************/
void introSequence(void) {
uint16 counter, counter1;
DoBlack = true;
#if defined(DOSCODE)
readPict("p:Intro/EA0", true);
readPict("p:Intro/EA1", true);
readPict("p:Intro/EA2", true);
readPict("p:Intro/EA3", true);
#elif defined(ALL_LOGOS) || defined(NDEBUG)
readPict("p:Intro/WYRMKEEP", true);
microDelay(4, 0, NULL);
#endif
blackAllScreen();
g_music->initMusic();
nopalchange = true;
noscreenchange = true;
readPict("p:Intro/TNDcycle2.pic", true);
nopalchange = false;
noscreenchange = false;
FadePalette = Palette;
#if defined(ALL_LOGOS) || defined(NDEBUG)
for (counter = 0; counter < 16; counter++) {
Palette[counter] = ((diffcmap[counter * 3] >> 2) << 8) +
((diffcmap[counter * 3 + 1] >> 2) << 4) +
(diffcmap[counter * 3 + 2] >> 2);
}
newCheckMusic();
fade(true, 0);
for (int times = 0; times < 150; times++) {
newCheckMusic();
uint16 temp = Palette[2];
for (counter = 2; counter < 15; counter++)
Palette[counter] = Palette[counter + 1];
Palette[15] = temp;
setAmigaPal(Palette, 16);
waitTOF();
}
fade(false, 0);
blackAllScreen();
#endif
g_music->newCheckMusic();
readPict("p:Intro/Title.A", true);
readPict("p:Intro/AB", true);
musicDelay();
readPict("p:Intro/BA", true);
readPict("p:Intro/AC", true);
musicDelay();
#if !defined(DOSCODE)
musicDelay(); // more credits on this page now
#endif
readPict("p:Intro/CA", true);
readPict("p:Intro/AD", true);
musicDelay();
#if !defined(DOSCODE)
musicDelay(); // more credits on this page now
#endif
readPict("p:Intro/DA", true);
musicDelay();
g_music->newOpen("p:Intro/Intro.1"); /* load the picture into the buffer */
g_music->newCheckMusic();
blackAllScreen();
g_music->fillUpMusic(true);
getFont("P:Map.font", msgfont);
nopalchange = true;
noscreenchange = true;
readPict("p:Intro/Intro.1", true);
noscreenchange = false;
nopalchange = false;
for (counter = 0; counter < 16; counter++) {
Palette[counter] = ((diffcmap[counter * 3] >> 2) << 8) +
((diffcmap[counter * 3 + 1] >> 2) << 4) +
(diffcmap[counter * 3 + 2] >> 2);
}
doPictText("i.1", true);
doPictText("i.2A", true);
doPictText("i.2B", true);
freeAllStolenMem();
blackAllScreen();
g_music->fillUpMusic(true);
IntroDoBlack = true;
NReadPict("Station1", true);
doPictText("i.3", false);
NReadPict("Station2", true);
doPictText("i.4", false);
NReadPict("Stiles4", true);
doPictText("i.5", false);
NReadPict("Stiles3", true);
doPictText("i.6", false);
NReadPict("Platform2", true);
doPictText("i.7", false);
NReadPict("Subway.1", true);
doPictText("i.8", false);
NReadPict("Subway.2", true);
doPictText("i.9", false);
doPictText("i.10", false);
doPictText("i.11", false);
if (!QuitIntro)
for (counter = 0; counter < 50; counter++) {
for (counter1 = (8 * 3); counter1 < (255 * 3); counter1++)
diffcmap[counter1] = 255 - diffcmap[counter1];
g_music->newCheckMusic();
waitTOF();
VGASetPal(diffcmap, 256);
waitTOF();
waitTOF();
}
doPictText("i.12", false);
doPictText("i.13", false);
IntroDoBlack = false;
NReadPict("Daed0", true);
doPictText("i.14", false);
NReadPict("Daed1", true);
doPictText("i.15", false);
NReadPict("Daed2", true);
doPictText("i.16", false);
doPictText("i.17", false);
doPictText("i.18", false);
NReadPict("Daed3", true);
doPictText("i.19", false);
doPictText("i.20", false);
NReadPict("Daed4", true);
doPictText("i.21", false);
NReadPict("Daed5", true);
doPictText("i.22", false);
doPictText("i.23", false);
doPictText("i.24", false);
NReadPict("Daed6", true);
doPictText("i.25", false);
doPictText("i.26", false);
NReadPict("Daed7", false);
doPictText("i.27", false);
doPictText("i.28", false);
stopDiffEnd();
NReadPict("Daed8", true);
doPictText("i.29", false);
doPictText("i.30", false);
NReadPict("Daed9", true);
doPictText("i.31", false);
doPictText("i.32", false);
doPictText("i.33", false);
NReadPict("Daed9a", true);
NReadPict("Daed10", true);
doPictText("i.34", false);
doPictText("i.35", false);
doPictText("i.36", false);
NReadPict("SubX", true);
if (QuitIntro) {
setAPen(0);
rectFill(0, 0, VGAScreenWidth - 1, VGAScreenHeight - 1);
DoBlack = true;
}
hidemouse = false;
}
} // End of namespace Lab

68
engines/lab/lab.cpp Normal file
View File

@ -0,0 +1,68 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "common/debug-channels.h"
#include "common/scummsys.h"
#include "common/error.h"
#include "common/fs.h"
#include "common/rect.h"
#include "engines/util.h"
#include "lab/lab.h"
#include "lab/labfun.h"
namespace Lab {
bool LabEngine::hasFeature(EngineFeature f) const {
return (f == kSupportsRTL) ? true : false;
}
LabEngine::LabEngine(OSystem *syst)
: Engine(syst) {
}
LabEngine::~LabEngine() {
// Remove all of our debug levels here
DebugMan.clearAllDebugChannels();
}
Common::Error LabEngine::run() {
// Initialize graphics using following:
initGraphics(320, 200, false);
g_music = new Music();
inner_main();
return Common::kNoError;
}
} // End of namespace Lab

52
engines/lab/lab.h Normal file
View File

@ -0,0 +1,52 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#ifndef LAB_H
#define LAB_H
#include "common/array.h"
#include "engines/engine.h"
namespace Lab {
class LabEngine : public Engine {
public:
LabEngine(OSystem *syst);
~LabEngine();
virtual Common::Error run();
bool hasFeature(EngineFeature f) const;
};
} // End of namespace Lab
#endif // LAB_H

549
engines/lab/labfile.cpp Normal file
View File

@ -0,0 +1,549 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/labfun.h"
#include "lab/mouse.h"
#include "lab/storage.h"
#include "common/file.h"
namespace Lab {
#define MAXREADSIZE 30720L
#define DMABUGSIZE 0 /* The number of bytes the DMA driver might screw */
/* NOTE: set to 0 for non-CDTV machines. */
static byte *buffer = NULL, *realbufferstart = NULL, *startoffilestorage = NULL;
byte **startoffile = &startoffilestorage;
static uint32 buffersize, realbuffersize;
uint32 ReadSoFar;
bool ReadIsError, ReadIsDone;
#if defined(WIN32)
#define stat _stat
#endif
/*****************************************************************************/
/* Returns the size of a file. */
/*****************************************************************************/
uint32 sizeOfFile(const char *name) {
Common::File file;
file.open(translateFileName(name));
if (!file.isOpen()) {
warning("Cannot open file %s", translateFileName(name));
return 0;
}
uint32 size = file.size();
file.close();
return size;
}
/*-------------------- Routines that buffer a whole file --------------------*/
/*----- divides up and manages the buffer -----*/
#define MAXMARKERS 15
typedef struct {
char name[32];
void *Start, *End;
} FileMarker;
static FileMarker FileMarkers[MAXMARKERS];
static uint16 CurMarker = 0;
static void *MemPlace = NULL;
/*****************************************************************************/
/* Frees a File's resources. */
/*****************************************************************************/
static void freeFile(uint16 RMarker) {
FileMarkers[RMarker].name[0] = 0;
FileMarkers[RMarker].Start = NULL;
FileMarkers[RMarker].End = NULL;
}
/*****************************************************************************/
/* Gets a chunk of memory from the buffer. */
/*****************************************************************************/
static void *getCurMem(uint32 size) {
void *ptr = 0;
warning ("STUB: getCurMem(%d)", size);
#if 0
if ((((char *) MemPlace) + size - 1) >=
(((char *) buffer) + buffersize))
MemPlace = buffer;
ptr = MemPlace;
((char *)MemPlace) += size;
for (int counter = 0; counter < MAXMARKERS; counter++) {
if (FileMarkers[counter].name[0]) {
if (((FileMarkers[counter].Start >= ptr) &&
(FileMarkers[counter].Start < MemPlace)) ||
((FileMarkers[counter].End >= ptr) &&
(FileMarkers[counter].End < MemPlace)) ||
((ptr >= FileMarkers[counter].Start) &&
(ptr <= FileMarkers[counter].End)))
freeFile(counter);
}
}
#endif
return ptr;
}
/*****************************************************************************/
/* Checks if a file is already buffered. */
/*****************************************************************************/
byte **isBuffered(const char *fileName) {
uint16 RMarker;
if (fileName == NULL)
return NULL;
RMarker = 0;
while (RMarker < MAXMARKERS) {
if (strcmp(FileMarkers[RMarker].name, fileName) == 0) {
*startoffile = (byte *) FileMarkers[RMarker].Start;
return startoffile;
} else
RMarker++;
}
return NULL;
}
/*****************************************************************************/
/* Grabs a chunk of memory from the room buffer, and manages it for a */
/* particular room. If it returns true, then the file is already in memory. */
/*****************************************************************************/
bool allocFile(void **Ptr, uint32 Size, const char *fileName) {
uint16 RMarker;
byte **temp;
Size += DMABUGSIZE;
if (1 & Size) /* Memory is required to be even aligned */
Size++;
temp = isBuffered(fileName);
if (temp) {
*Ptr = *temp;
return true;
}
RMarker = CurMarker;
CurMarker++;
if (CurMarker >= MAXMARKERS)
CurMarker = 0;
freeFile(RMarker);
strcpy(FileMarkers[RMarker].name, fileName);
*Ptr = getCurMem(Size);
FileMarkers[RMarker].Start = *Ptr;
FileMarkers[RMarker].End = (void *)(((char *)(*Ptr)) + Size - 1);
return false;
}
/*----- Main routines -----*/
/*****************************************************************************/
/* Reads a file into memory. */
/*****************************************************************************/
byte **openFile(const char *name) {
warning("STUB: openFile");
return NULL;
#if 0
char *tempbuffer, *Buffer;
int32 Size, Left;
int FPtr, ReadSize, myread;
ReadSoFar = 0L;
ReadIsError = false;
ReadIsDone = false;
if ((buffer == NULL) || (name == NULL)) {
ReadIsError = true;
ReadIsDone = true;
return NULL;
}
Size = sizeOfFile(name);
if (!Size || (Size > ((int32) buffersize))) {
ReadIsError = true;
ReadIsDone = true;
return NULL;
}
if (allocFile((void **) &Buffer, Size, name)) { /* Get place in Buffer */
*startoffile = Buffer; /* If the file is buffered */
ReadSoFar = Size;
ReadIsError = false;
ReadIsDone = true;
return startoffile;
}
#if defined(WIN32)
#if defined(DEMODATA)
{
FILE *fh = fopen("c:\\depot\\labyrinth\\demodata.log", "a+w");
fprintf(fh, "%s\n", name);
fclose(fh);
}
#endif
FPtr = open(translateFileName(name), O_RDONLY | O_BINARY);
#else
FPtr = open(translateFileName(name), O_RDONLY);
#endif
if (FPtr != -1) {
Left = Size;
tempbuffer = Buffer;
*startoffile = Buffer;
while (Left) {
fileCheckMusic(Left);
if (Left > MAXREADSIZE)
ReadSize = MAXREADSIZE;
else
ReadSize = (int) Left;
if (!(myread = read(FPtr, tempbuffer, ReadSize + DMABUGSIZE))) {
ReadIsError = false;
ReadIsDone = true;
close(FPtr);
return NULL;
}
/* Not necessary for IBM version
if ((ReadSize == MAXREADSIZE) && DMABUGSIZE)
Seek(FPtr, -DMABUGSIZE, (int32) OFFSET_CURRENT);
*/
ReadSoFar += ReadSize;
tempbuffer += ReadSize;
Left -= ReadSize;
}
ReadIsDone = true;
close(FPtr);
return startoffile;
} else {
ReadIsError = false;
ReadIsDone = true;
return NULL;
}
#endif
}
/*****************************************************************************/
/* Reads a block of memory. */
/*****************************************************************************/
void readBlock(void *Buffer, uint32 Size, byte **File) {
memcpy(Buffer, *File, (size_t) Size);
(*File) += Size;
}
/*****************************************************************************/
/* Reads on character. */
/*****************************************************************************/
char readChar(char **File) {
char c = **File;
(*File)++;
return c;
}
/*****************************************************************************/
/* Skips a chunk of memory. */
/*****************************************************************************/
void skip(byte **File, uint32 skip) {
(*File) += skip;
}
/*****************************************************************************/
/* Resets the internal buffers to empty. */
/*****************************************************************************/
void resetBuffer(void) {
uint16 RMarker;
CurMarker = 0;
RMarker = 0;
MemPlace = buffer;
while (RMarker < MAXMARKERS) {
freeFile(RMarker);
RMarker++;
}
}
/*****************************************************************************/
/* Initializes the buffer. */
/*****************************************************************************/
bool initBuffer(uint32 BufSize, bool IsGraphicsMem) {
if (!allocate((void **) &buffer, BufSize))
buffer = NULL;
buffersize = BufSize;
realbuffersize = buffersize;
realbufferstart = buffer;
resetBuffer();
return (buffer != NULL);
}
/*****************************************************************************/
/* Frees the buffer. */
/*****************************************************************************/
void freeBuffer(void) {
freeAllStolenMem();
if (buffer)
deallocate(buffer, buffersize);
}
/*------------------------------------------------------------------------*/
/* The following routines allow stealing of memory from the buffer (which */
/* later may or may not be given back). */
/*------------------------------------------------------------------------*/
/*****************************************************************************/
/* Clears all the buffers. */
/*****************************************************************************/
static void flushBuffers(void) {
uint16 RMarker;
RMarker = 0;
while (RMarker < MAXMARKERS) {
freeFile(RMarker);
RMarker++;
}
}
/*****************************************************************************/
/* Steal some memory from the buffer */
/*****************************************************************************/
void *stealBufMem(int32 Size) {
void *Mem;
Size += DMABUGSIZE;
flushBuffers();
Mem = buffer;
buffer += Size;
buffersize -= Size;
MemPlace = buffer;
return Mem;
}
Common::File *openPartial(const char *name) {
Common::File *f;
f = new Common::File();
f->open(translateFileName(name));
if (!f->isOpen()) {
delete f;
return 0;
}
return f;
}
/*****************************************************************************/
/* Frees all the memory stolen from the buffer. */
/*****************************************************************************/
void freeAllStolenMem(void) {
flushBuffers();
buffer = realbufferstart;
buffersize = realbuffersize;
MemPlace = buffer;
}
/*--------------- Routines that read partial chunks of a file ---------------*/
/*****************************************************************************/
/* Reads Size amount of bytes into buffer. */
/*****************************************************************************/
uint32 readPartial(int32 File, void *buf, uint32 Size) {
uint32 haveread = 0;
warning("STUB: readPartial");
#if 0
uint32 nsize;
while (Size) {
if (Size > MAXREADSIZE)
nsize = MAXREADSIZE;
else
nsize = Size;
haveread += (uint32)(read((int) File, buf, (int) nsize));
Size -= nsize;
((char *) buf) += nsize;
updateMouse();
}
#endif
return haveread;
}
/*****************************************************************************/
/* Reads Size amount of bytes into buffer. Use this one if the data must */
/* absolutely be correct (compressed data for example). Otherwise, because */
/* of the DMA bug, last two bytes may be screwed. */
/*****************************************************************************/
uint32 newReadPartial(int32 File, void *buf, uint32 Size) {
return readPartial((int) File, buf, Size);
}
/*****************************************************************************/
/* Reads Size amount of bytes into buffer. Use this one if the data must */
/* absolutely be correct (compressed data for example). Otherwise, because */
/* of the DMA bug, last two bytes may be screwed. This one will work if the */
/* data is not padded the extra two bytes. */
/*****************************************************************************/
uint32 bufferedReadPartial(int32 File, void *buf, uint32 Size) {
return readPartial(File, buf, Size);
}
/*****************************************************************************/
/* Sets the current position in the file relative to the beginning of the */
/* file. */
/*****************************************************************************/
void setPos(int32 File, uint32 Place) {
warning("STUB: setPos");
//lseek((int) File, (int32) Place, SEEK_SET);
}
/*****************************************************************************/
/* Skips a certain number of bytes either forward or backwards. */
/*****************************************************************************/
void skipPartial(int32 File, int32 Skip) {
warning("STUB: skipPartial");
//lseek((int) File, Skip, SEEK_CUR);
}
} // End of namespace Lab

393
engines/lab/labfun.h Normal file
View File

@ -0,0 +1,393 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#ifndef LAB_LABFUN_H
#define LAB_LABFUN_H
#include "lab/stddefines.h"
#include "lab/parsetypes.h"
#include "common/file.h"
namespace Lab {
/* Direction defines */
#define NORTH 0
#define SOUTH 1
#define EAST 2
#define WEST 3
/* Generic co-ordinate define. */
typedef struct {
uint16 x1, y1;
} Cords;
struct Image;
struct TextFont;
/*----------------------------*/
/*------ From Audioi.c -------*/
/*----------------------------*/
bool initAudio(void);
void freeAudio(void);
void initSampleRate(uint16 SampleSpeed);
bool musicBufferEmpty(uint16 i);
void playMusicBlock(void *Ptr, uint32 Size, uint16 BufferNum, uint16 SampleSpeed);
void updateSoundBuffers(void);
void flushAudio(void);
void playMusic(uint16 SampleSpeed, uint16 Volume, uint32 Length, bool flush, void *Data);
/*----------------------------*/
/*----- From graphics.c ------*/
/*----------------------------*/
/* Reads in pictures */
bool readPict(const char *filename, bool PlayOnce);
bool readMusic(const char *filename);
byte *readPictToMem(const char *filename, uint16 x, uint16 y);
/* Window text stuff */
uint32 flowText(void *font, /* the TextAttr pointer */
uint16 spacing, /* How much vertical spacing between the lines */
uint16 pencolor, /* pen number to use for text */
uint16 backpen, /* the background color */
bool fillback, /* Whether to fill the background */
bool centerh, /* Whether to center the text horizontally */
bool centerv, /* Whether to center the text vertically */
bool output, /* Whether to output any text */
uint16 x1, /* Cords */
uint16 y1, uint16 x2, uint16 y2, const char *text); /* The text itself */
uint32 flowTextToMem(struct Image *DestIm, void *font, /* the TextAttr pointer */
uint16 spacing, /* How much vertical spacing between the lines */
uint16 pencolor, /* pen number to use for text */
uint16 backpen, /* the background color */
bool fillback, /* Whether to fill the background */
bool centerh, /* Whether to center the text horizontally */
bool centerv, /* Whether to center the text vertically */
bool output, /* Whether to output any text */
uint16 x1, /* Cords */
uint16 y1, uint16 x2, uint16 y2, const char *text); /* The text itself */
void drawMessage(const char *text);
void longDrawMessage(const char *text);
bool readFont(char *filename, void *font, void *data);
/* The Wipes */
void doWipe(uint16 WipeType, CloseDataPtr *CPtr, char *filename);
/* Double Buffer stuff */
void newFlipViews(void *scrPtr, uint16 *newpal, uint16 numcolors);
void flipViews(void *scrPtr);
/*----------------------------*/
/*----- From Interface.c -----*/
/*----------------------------*/
struct Gadget *addGadButton(uint16 x, uint16 y, void *UpImage, void *DownImage, uint16 id);
void gadgetsOnOff(void *gptr, void *win, int32 num, bool on);
/*----------------------*/
/*---- From Intro.c ----*/
/*----------------------*/
void introSequence(void);
/*----------------------*/
/*----- From Lab.c -----*/
/*----------------------*/
void eatMessages(void);
bool setUpScreens(void);
void drawPanel(void);
bool quitPlaying(void);
/*---------------------------*/
/*------ From LabFile.c -----*/
/*---------------------------*/
uint32 sizeOfFile(const char *name);
/* Buffer a whole file */
byte **isBuffered(const char *fileName);
byte **openFile(const char *name);
void readBlock(void *Buffer, uint32 Size, byte **File);
char readChar(char **File);
void skip(byte **File, uint32 skip);
void resetBuffer(void);
bool initBuffer(uint32 BufSize, bool IsGraphicsMem);
void freeBuffer(void);
/* Functions that borrow memory from the buffer */
bool allocFile(void **Ptr, uint32 Size, const char *fileName);
void *stealBufMem(int32 Size);
void freeAllStolenMem(void);
/* Read chunks of a file */
Common::File *openPartial(const char *name);
void closePartial(int32 File);
uint32 readPartial(int32 File, void *buffer, uint32 Size);
uint32 newReadPartial(int32 File, void *buffer, uint32 Size);
uint32 bufferedReadPartial(int32 File, void *buffer, uint32 Size);
void setPos(int32 File, uint32 Place);
void skipPartial(int32 File, int32 Skip);
/*---------------------------*/
/*------ From LabText.c -----*/
/*---------------------------*/
bool initLabText(void);
void freeLabText(void);
void decrypt(byte *text);
/*---------------------------*/
/*----- From LabMusic.c -----*/
/*---------------------------*/
#define MANYBUFFERS 5L
#define MAXBUFFERS 5L
#define MINBUFFERS 2L
class Music {
public:
Music();
byte **newOpen(const char *name);
bool initMusic(void);
void freeMusic(void);
void fillUpMusic(bool doit);
void updateMusic(void);
void checkMusic(void);
void newCheckMusic(void);
void closeMusic(void);
void setMusic(bool on);
void restartBackMusic(void);
void pauseBackMusic(void);
void changeMusic(const char *newmusic);
void resetMusic(void);
void fileCheckMusic(uint32 filelength);
bool _winmusic, _doNotFileFlushAudio;
bool _turnMusicOn;
bool _musicOn;
private:
void fillbuffer(uint16 unit);
uint16 getManyBuffersLeft(void);
void startMusic(bool startatbegin);
Common::File *_file;
Common::File *_tFile;
bool _musicPaused;
bool _tMusicOn;
uint32 _tFileLength;
uint32 _tLeftInFile;
uint16 _manyBuffers;
void *_musicBuffer[MAXBUFFERS];
uint16 _musicFilledTo, _musicPlaying, _musicOnBuffer;
uint32 _filelength, _leftinfile;
};
extern Music *g_music;
/*---------------------------*/
/*----- From LabSets.c ------*/
/*---------------------------*/
typedef struct {
uint16 lastElement, array[1];
} LargeSetRecord;
typedef LargeSetRecord *LargeSet;
bool createSet(LargeSet *set, uint16 last);
void deleteSet(LargeSet set);
bool In(LargeSet set, uint16 element);
void inclElement(LargeSet set, uint16 element);
void exclElement(LargeSet set, uint16 element);
/*---------------------------*/
/*----- From Machine.c ------*/
/*---------------------------*/
uint16 scaleX(uint16 x);
uint16 scaleY(uint16 y);
uint16 VGAScaleX(uint16 x);
uint16 VGAScaleY(uint16 y);
int16 VGAScaleXs(int16 x);
int16 VGAScaleYs(int16 y);
uint16 SVGACord(uint16 cord);
uint16 VGAUnScaleX(uint16 x);
uint16 VGAUnScaleY(uint16 y);
char *translateFileName(const char *filename);
/*---------------------------*/
/*-------- From Map.c -------*/
/*---------------------------*/
void fade(bool fadein, uint16 res);
void setAmigaPal(uint16 *pal, uint16 numcolors);
char *getText(const char *filename);
bool getFont(const char *filename, TextFont *textfont);
void readImage(byte **buffer, Image **im);
void doMap(LargeSet RoomsFound, uint16 CurRoom);
void doJournal(LargeSet Conditions);
void doNotes(void);
void doWestPaper(void);
void doMonitor(char *background, char *textfile, bool isinteractive, uint16 x1, uint16 y1, uint16 x2, uint16 y2);
uint16 doDisks(void);
bool saveRestoreGame(void);
/*--------------------------*/
/*----- From saveGame.c ----*/
/*--------------------------*/
bool saveFloppy(char *path, uint16 RoomNum, uint16 Direction, uint16 NumQuarters, LargeSet Conditions, LargeSet Rooms, uint16 filenum, uint16 type);
bool readFloppy(char *path, uint16 *RoomNum, uint16 *Direction, uint16 *NumQuarters, LargeSet Conditions, LargeSet Rooms, uint16 filenum, uint16 type);
/*--------------------------*/
/*----- From Special.c -----*/
/*--------------------------*/
void showCombination(const char *filename);
void mouseCombination(LargeSet Conditions, uint16 x, uint16 y);
void showTile(const char *filename, bool showsolution);
void mouseTile(LargeSet Conditions, uint16 x, uint16 y);
void inner_main();
} // End of namespace Lab
#endif /* LAB_LABFUN_H */

543
engines/lab/labmusic.cpp Normal file
View File

@ -0,0 +1,543 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/storage.h"
#include "lab/labfun.h"
#include "lab/timing.h"
#include "lab/mouse.h"
namespace Lab {
#define MUSICBUFSIZE (2 * 65536L)
#define SAMPLESPEED 15000L
extern bool EffectPlaying;
Music *g_music;
Music::Music() {
_file = 0;
_tFile = 0;
_musicPaused = false;
_tMusicOn = false;
_tFileLength = 0;
_tLeftInFile = 0;
_manyBuffers = MANYBUFFERS;
_musicFilledTo = 0;
_musicPlaying = 0;
_musicOnBuffer = 0;
_filelength = 0;
_leftinfile = 0;
_musicOn = false;
_turnMusicOn = false;
_winmusic = false;
_doNotFileFlushAudio = false;
}
/*****************************************************************************/
/* Figures out which buffer is currently playing based on messages sent to */
/* it from the Audio device. */
/*****************************************************************************/
void Music::updateMusic(void) {
uint16 i;
#if !defined(DOSCODE)
//SDL_ProcessInput(0);
#endif
updateMouse();
if (EffectPlaying)
updateSoundBuffers();
else if (_musicOn) {
for (i = 0; i < 2; i++) {
if (musicBufferEmpty(i)) {
playMusicBlock(_musicBuffer[_musicPlaying], MUSICBUFSIZE, i, SAMPLESPEED);
if (_musicPlaying)
_musicOnBuffer = _musicPlaying - 1;
else
_musicOnBuffer = _manyBuffers - 1;
_musicPlaying++;
if (_musicPlaying >= _manyBuffers)
_musicPlaying = 0;
}
}
}
}
void Music::fillbuffer(uint16 unit) {
uint32 Size = MUSICBUFSIZE;
void *ptr = _musicBuffer[unit];
#if defined(DOSCODE)
char *endptr;
#endif
if (Size < _leftinfile) {
_file->read(ptr, Size);
_leftinfile -= Size;
} else {
_file->read(ptr, _leftinfile);
#if defined(DOSCODE)
endptr = ptr;
endptr += _leftinfile - 2;
memset((void *)(((uint32) ptr) + _leftinfile), *endptr, Size - _leftinfile);
#else
memset((char *)ptr + _leftinfile, 0, Size - _leftinfile);
#endif
_file->seek(0);
_leftinfile = _filelength;
}
}
/*****************************************************************************/
/* Figures out how many *complete* buffers of music left to play. */
/*****************************************************************************/
uint16 Music::getManyBuffersLeft(void) {
uint16 mp = _musicOnBuffer;
if (mp == _musicFilledTo) /* Already filled */
return _manyBuffers;
else if (mp > _musicFilledTo)
return _manyBuffers - (mp - _musicFilledTo);
else
return _musicFilledTo - mp;
}
/*****************************************************************************/
/* Fills up the buffers that have already been played if necessary; if doit */
/* is set to TRUE then it will fill up all empty buffers. Otherwise, it */
/* Check if there are MINBUFFERS or less buffers that are playing. */
/*****************************************************************************/
void Music::fillUpMusic(bool doit) {
int16 ManyLeft, ManyFill;
updateMusic();
if (!_musicOn)
return;
ManyLeft = getManyBuffersLeft();
if (ManyLeft < MINBUFFERS)
doit = true;
else if (ManyLeft == _manyBuffers) /* All the buffers are already full */
doit = false;
if (doit && (ManyLeft < _manyBuffers) && ManyLeft) {
ManyFill = _manyBuffers - ManyLeft - 1;
while (ManyFill > 0) {
_musicFilledTo++;
if (_musicFilledTo >= _manyBuffers)
_musicFilledTo = 0;
fillbuffer(_musicFilledTo);
updateMusic();
ManyFill--;
}
updateMusic();
ManyLeft = getManyBuffersLeft();
if (ManyLeft < _manyBuffers) {
ManyFill = _manyBuffers - ManyLeft - 1;
while (ManyFill > 0) {
_musicFilledTo++;
if (_musicFilledTo >= _manyBuffers)
_musicFilledTo = 0;
fillbuffer(_musicFilledTo);
updateMusic();
ManyFill--;
}
}
}
updateMusic();
/* NYI: A check for dirty cds; for instance, if lots of buffers already
played */
}
/*****************************************************************************/
/* Starts up the music initially. */
/*****************************************************************************/
void Music::startMusic(bool startatbegin) {
uint16 counter;
if (!_musicOn)
return;
flushAudio();
if (startatbegin) {
_file->seek(0);
_leftinfile = _filelength;
}
initSampleRate(SAMPLESPEED);
_musicPlaying = 0;
_musicOnBuffer = 0;
_musicFilledTo = _manyBuffers - 1;
_musicOn = false;
for (counter = 0; counter < _manyBuffers; counter++)
fillbuffer(counter);
_musicOn = true;
updateMusic();
}
/*****************************************************************************/
/* Initializes the music buffers. */
/*****************************************************************************/
bool Music::initMusic(void) {
uint16 counter;
bool mem;
if (!_turnMusicOn)
return true;
_musicOn = true;
_musicPaused = false;
const char *filename;
if (_winmusic)
filename = "Music:WinGame";
else
filename = "Music:BackGrou";
mem = true;
if (_musicBuffer[0] == NULL) {
for (counter = 0; counter < _manyBuffers; counter++)
mem = mem && allocatedos((void **) & (_musicBuffer[counter]), MUSICBUFSIZE);
}
if (mem) {
_filelength = sizeOfFile(filename);
_file = openPartial(filename);
if (_file) {
startMusic(true);
return true;
}
}
_musicOn = false;
return false;
}
/*****************************************************************************/
/* Frees up the music buffers and closes the file. */
/*****************************************************************************/
void Music::freeMusic(void) {
_musicOn = false;
if (_file->isOpen())
_file->close();
_file = 0;
}
/*****************************************************************************/
/* Pauses the background music. */
/*****************************************************************************/
void Music::pauseBackMusic(void) {
if (!_musicPaused && _musicOn) {
updateMusic();
_musicOn = false;
flushAudio();
if (_musicPlaying)
_musicPlaying--;
else
_musicPlaying = _manyBuffers - 1;
_musicPaused = true;
}
}
/*****************************************************************************/
/* Restarts the paused background music. */
/*****************************************************************************/
void Music::restartBackMusic(void) {
if (_musicPaused) {
flushAudio();
_musicOn = true;
updateMusic();
_musicPaused = false;
}
}
/*****************************************************************************/
/* Checks to see if need to fill buffers fill of music. */
/*****************************************************************************/
void Music::checkMusic(void) {
updateMusic();
if (!_musicOn)
return;
fillUpMusic(false);
}
/*****************************************************************************/
/* Checks to see if need to fill buffers fill of music. */
/*****************************************************************************/
void Music::newCheckMusic(void) {
checkMusic();
}
/*****************************************************************************/
/* Turns the music on and off. */
/*****************************************************************************/
void Music::setMusic(bool on) {
flushAudio();
if (on && !_musicOn) {
_musicOn = true;
startMusic(true);
} else if (!on && _musicOn) {
_musicOn = false;
updateMusic();
} else
_musicOn = on;
}
/*****************************************************************************/
/* Changes the background music to something else. */
/*****************************************************************************/
void Music::changeMusic(const char *newmusic) {
if (!_tFile) {
_tFile = _file;
_tMusicOn = _musicOn;
_tFileLength = _filelength;
#if defined(DOSCODE)
_tLeftInFile = _leftinfile;
#else
_tLeftInFile = _leftinfile + 65536L;
if (_tLeftInFile > _tFileLength)
_tLeftInFile = _leftinfile;
#endif
}
_file = openPartial(newmusic);
if (_file) {
_musicOn = true; /* turn it off */
setMusic(false);
_filelength = sizeOfFile(newmusic);
_musicOn = false; /* turn it back on */
setMusic(true);
} else {
_file = _tFile;
_tFile = 0;
}
}
/*****************************************************************************/
/* Changes the background music to the original piece playing. */
/*****************************************************************************/
void Music::resetMusic(void) {
if (!_tFile)
return;
if (_file->isOpen())
_file->close();
_file = _tFile;
_filelength = _tFileLength;
_leftinfile = _tLeftInFile;
_file->seek(_filelength - _leftinfile);
_musicOn = true;
setMusic(false);
updateMusic();
if (!_tMusicOn) {
_tFile = 0;
return;
}
_musicOn = _tMusicOn;
startMusic(false);
_tFile = 0;
}
#define FUDGEFACTOR 5L
#define READSPEED (2 * 130000L)
/*****************************************************************************/
/* Checks whether or note enough memory in music buffer before loading any */
/* files. Fills it if not. Does not take into account the current buffer */
/* playing; a built in fudge factor. We've also got another FUDGEFACTOR */
/* defined above in case things go wrong. */
/* */
/* Here, the seconds are multipled by 10. */
/*****************************************************************************/
byte **Music::newOpen(const char *name) {
uint32 filelength, LeftSecs, Time;
byte **file;
if (name == NULL) {
return NULL;
}
if ((strcmp(name, "") == 0) || (strcmp(name, " ") == 0)) {
return NULL;
}
if ((file = isBuffered(name))) {
return file;
}
if (_musicOn) {
updateMusic();
#if defined(DOSCODE)
LeftSecs = (getManyBuffersLeft() * MUSICBUFSIZE * 10) / SAMPLESPEED;
#else
LeftSecs = (getManyBuffersLeft() * MUSICBUFSIZE * 10) / (2 * SAMPLESPEED);
#endif
filelength = sizeOfFile(name) * 10;
Time = 10 + /* Seek time for the music and the file */
(filelength / READSPEED) + /* Read time for the file */
FUDGEFACTOR;
if (Time >= LeftSecs)
fillUpMusic(true);
}
if (!_doNotFileFlushAudio && EffectPlaying)
flushAudio();
file = openFile(name);
checkMusic();
return file;
}
/*****************************************************************************/
/* Checks whether or note enough memory in music buffer to continue loading */
/* in a file. Fills the music buffer if not. Does not take into account */
/* the current buffer playing; a built in fudge factor. We've also got */
/* another FUDGEFACTOR defined above in case things go wrong. */
/* */
/* Here, the seconds are multipled by 10. */
/*****************************************************************************/
void Music::fileCheckMusic(uint32 filelength) {
uint32 LeftSecs, Time;
if (_musicOn) {
updateMusic();
#if defined(DOSCODE)
LeftSecs = (getManyBuffersLeft() * MUSICBUFSIZE * 10) / SAMPLESPEED;
#else
LeftSecs = (getManyBuffersLeft() * MUSICBUFSIZE * 10) / (2 * SAMPLESPEED);
#endif
filelength *= 10;
Time = 5 + /* Seek time for the music */
(filelength / READSPEED) + /* Read time for the file */
FUDGEFACTOR;
if (Time >= LeftSecs)
fillUpMusic(true);
}
}
} // End of namespace Lab

94
engines/lab/labsets.cpp Normal file
View File

@ -0,0 +1,94 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/labfun.h"
#include "lab/storage.h"
namespace Lab {
const uint32 LargeSetSIZE = sizeof(LargeSetRecord) - 2;
/*****************************************************************************/
/* Creates a large set. */
/*****************************************************************************/
bool createSet(LargeSet *set, uint16 last) {
last = (((last + 15) >> 4) << 4);
if (allocate((void **) set, (last >> 3) + LargeSetSIZE)) {
(*set)->lastElement = last;
return true;
} else /* Not Enough Memory! */
return false;
}
/*****************************************************************************/
/* Deletes a large set. */
/*****************************************************************************/
void deleteSet(LargeSet set) {
if (set != NULL)
deallocate(set, (set->lastElement >> 3) + LargeSetSIZE);
}
/*****************************************************************************/
/* Tests if an element is in the set. */
/*****************************************************************************/
bool In(LargeSet set, uint16 element) {
return ((1 << ((element - 1) % 16)) & (set->array[(element - 1) >> 4])) > 0;
}
/*****************************************************************************/
/* Sets an element in the Large set. */
/*****************************************************************************/
void inclElement(LargeSet set, uint16 element) {
INCL((set->array[(element - 1) >> 4]), (1 << ((element - 1) % 16)));
}
/*****************************************************************************/
/* Removes an element in the Large set. */
/*****************************************************************************/
void exclElement(LargeSet set, uint16 element) {
EXCL((set->array[(element - 1) >> 4]), (1 << ((element - 1) % 16)));
}
} // End of namespace Lab

168
engines/lab/labtext.cpp Normal file
View File

@ -0,0 +1,168 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/storage.h"
#include "lab/labfun.h"
namespace Lab {
static uint32 SizeOfMemChunk;
static char *BeginOfMemChunk, *CurPlace;
char *LOWERFLOORS, *MIDDLEFLOORS, *UPPERFLOORS, *MEDMAZEFLOORS, *HEDGEMAZEFLOORS, *SURMAZEFLOORS, *CARNIVALFLOOR, *SURMAZEMSG, *FACINGNORTH, *FACINGEAST, *FACINGSOUTH, *FACINGWEST, *LAMPONMSG, *TURNLEFT, *TURNRIGHT, *GOFORWARDDIR, *NOPATH, *TAKEITEM, *SAVETEXT, *LOADTEXT, *BOOKMARKTEXT, *PERSONALTEXT, *DISKTEXT, *SAVEBOOK, *RESTOREBOOK, *SAVEFLASH, *RESTOREFLASH, *SAVEDISK, *RESTOREDISK, *NODISKINDRIVE, *WRITEPROTECTED, *SELECTDISK, *FORMATFLOPPY, *FORMATTING, *NOTHING, *USEONWHAT, *TAKEWHAT, *MOVEWHAT, *OPENWHAT, *CLOSEWHAT, *LOOKWHAT, *USEMAP, *USEJOURNAL, *TURNLAMPON, *TURNLAMPOFF, *USEWHISKEY, *USEPITH, *USEHELMET;
#define LABTEXTFILE "Lab:Rooms/LabText"
/*****************************************************************************/
/* Gets the next string from the list, and changes the end of string marker */
/* from an end of line to a null character. */
/*****************************************************************************/
static void setString(char **string) {
*string = CurPlace;
while (*CurPlace != '\n')
CurPlace++;
*CurPlace = 0;
CurPlace++;
}
/*****************************************************************************/
/* Initializes everything for the Labyrinth text stuff */
/*****************************************************************************/
bool initLabText(void) {
if ((SizeOfMemChunk = sizeOfFile(LABTEXTFILE)))
if (allocate((void **) &BeginOfMemChunk, SizeOfMemChunk)) {
Common::File *file = openPartial(LABTEXTFILE);
if (file) {
file->read(BeginOfMemChunk, SizeOfMemChunk);
file->close();
CurPlace = BeginOfMemChunk;
setString(&LOWERFLOORS);
setString(&MIDDLEFLOORS);
setString(&UPPERFLOORS);
setString(&MEDMAZEFLOORS);
setString(&HEDGEMAZEFLOORS);
setString(&SURMAZEFLOORS);
setString(&CARNIVALFLOOR);
setString(&SURMAZEMSG);
setString(&FACINGNORTH);
setString(&FACINGEAST);
setString(&FACINGSOUTH);
setString(&FACINGWEST);
setString(&LAMPONMSG);
setString(&TURNLEFT);
setString(&TURNRIGHT);
setString(&GOFORWARDDIR);
setString(&NOPATH);
setString(&TAKEITEM);
setString(&SAVETEXT);
setString(&LOADTEXT);
setString(&BOOKMARKTEXT);
setString(&PERSONALTEXT);
setString(&DISKTEXT);
setString(&SAVEBOOK);
setString(&RESTOREBOOK);
setString(&SAVEFLASH);
setString(&RESTOREFLASH);
setString(&SAVEDISK);
setString(&RESTOREDISK);
setString(&NODISKINDRIVE);
setString(&WRITEPROTECTED);
setString(&SELECTDISK);
setString(&FORMATFLOPPY);
setString(&FORMATTING);
setString(&NOTHING);
setString(&USEONWHAT);
setString(&TAKEWHAT);
setString(&MOVEWHAT);
setString(&OPENWHAT);
setString(&CLOSEWHAT);
setString(&LOOKWHAT);
setString(&USEMAP);
setString(&USEJOURNAL);
setString(&TURNLAMPON);
setString(&TURNLAMPOFF);
setString(&USEWHISKEY);
setString(&USEPITH);
setString(&USEHELMET);
return true;
}
}
return false;
}
/*****************************************************************************/
/* Frees the memory from the Labyrinth text stuff. */
/*****************************************************************************/
void freeLabText(void) {
if (SizeOfMemChunk && BeginOfMemChunk)
deallocate(BeginOfMemChunk, SizeOfMemChunk);
}
/*****************************************************************************/
/* Decrypts a chunk of text. */
/*****************************************************************************/
void decrypt(byte *text) {
if (text == NULL)
return;
while (*text != '\0') {
(*text) -= (byte) 95;
text++;
}
}
} // End of namespace Lab

372
engines/lab/machine.cpp Normal file
View File

@ -0,0 +1,372 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
namespace Lab {
bool IsHiRes = false;
/*****************************************************************************/
/* Scales the x co-ordinates to that of the new display. In the room parser */
/* file, co-ordinates are set up on a 360x336 display. */
/*****************************************************************************/
uint16 scaleX(uint16 x) {
if (IsHiRes)
return (uint16)((x * 16) / 9);
else
return (uint16)((x * 8) / 9);
}
/*****************************************************************************/
/* Scales the y co-ordinates to that of the new display. In the room parser */
/* file, co-ordinates are set up on a 368x336 display. */
/*****************************************************************************/
uint16 scaleY(uint16 y) {
if (IsHiRes)
return (y + (y / 14));
else
return ((y * 10) / 24);
}
/*****************************************************************************/
/* Scales the VGA cords to SVGA if necessary; otherwise, returns VGA cords. */
/*****************************************************************************/
uint16 VGAScaleX(uint16 x) {
if (IsHiRes)
return (x * 2);
else
return x;
}
/*****************************************************************************/
/* Scales the VGA cords to SVGA if necessary; otherwise, returns VGA cords. */
/*****************************************************************************/
uint16 VGAScaleY(uint16 y) {
if (IsHiRes)
return ((y * 12) / 5);
else
return y;
}
/*****************************************************************************/
/* Scales the VGA cords to SVGA if necessary; otherwise, returns VGA cords. */
/*****************************************************************************/
int16 VGAScaleXs(int16 x) {
if (IsHiRes)
return (x * 2);
else
return x;
}
/*****************************************************************************/
/* Scales the VGA cords to SVGA if necessary; otherwise, returns VGA cords. */
/*****************************************************************************/
int16 VGAScaleYs(int16 y) {
if (IsHiRes)
return ((y * 12) / 5);
else
return y;
}
uint16 SVGACord(uint16 cord) {
if (IsHiRes)
return cord;
else
return 0;
}
/*****************************************************************************/
/* Converts SVGA cords to VGA if necessary, otherwise returns VGA cords. */
/*****************************************************************************/
uint16 VGAUnScaleX(uint16 x) {
if (IsHiRes)
return (x / 2);
else
return x;
}
/*****************************************************************************/
/* Converts SVGA cords to VGA if necessary, otherwise returns VGA cords. */
/*****************************************************************************/
uint16 VGAUnScaleY(uint16 y) {
if (IsHiRes)
return ((y * 5) / 12);
else
return y;
}
#if defined(WIN32)
/*****************************************************************************/
/* Replaces all occurences of a character in a string with a new one. */
/*****************************************************************************/
static void strrplc(char *text, char orig, char replace) {
uint16 counter;
counter = 0;
while (text[counter]) {
if (text[counter] == orig)
text[counter] = replace;
counter++;
}
}
#endif
/*****************************************************************************/
/* Checks to see if all the characters in the second string are at the start */
/* of the first. */
/*****************************************************************************/
static bool strstart(const char **Source, const char *Start) {
uint16 len1, len2, counter;
len1 = strlen(*Source);
len2 = strlen(Start);
if (len1 < len2)
return false;
for (counter = 0; counter < len2; counter++)
if ((*Source)[counter] != Start[counter])
return false;
(*Source) += len2;
return true;
}
static char NewFileName[255];
/*****************************************************************************/
/* Modifes the filename so that paths and stuff are correct. Should mostly */
/* deal with assigns and the '/' instead of '\' on IBM systems. */
/* */
/* NOTE: Make a *copy* of the string, and modify that. It would be a real */
/* *bad* idea to modify the original. Since Labyrinth only focuses its */
/* attention to one file at a time, it would be fine to have one variable */
/* not on the stack which is used to store the new filename. */
/*****************************************************************************/
static void mystrupr(char *s) {
char c;
while ((c = *s) != 0)
*s++ = toupper(c);
}
char *translateFileName(const char *filename) {
char tempfilename[255];
char *dot;
strcpy(tempfilename, filename);
mystrupr(tempfilename);
*NewFileName = 0;
filename = tempfilename;
if (strstart(&filename, "P:")) {
if (IsHiRes)
strcat(NewFileName, "GAME/SPICT/");
else
strcat(NewFileName, "GAME/PICT/");
} else if (strstart(&filename, "LAB:"))
strcat(NewFileName, "GAME/");
else if (strstart(&filename, "MUSIC:"))
strcat(NewFileName, "GAME/MUSIC/");
strcat(NewFileName, filename);
dot = strrchr(NewFileName, '.');
if (dot != NewFileName && dot != NULL && dot[4] != '/') { // Linux may start with '.'
dot[4] = 0; // Back to the days of 8.3, even if your OS was never DOSish!!
}
return NewFileName;
}
#if defined(USE_SWAP)
uint16 swapUShort(uint16 value) {
char *b = (char *)&value;
char t = b[0];
b[0] = b[1];
b[1] = t;
return value;
}
uint16 *swapUShortPtr(uint16 *ptr, int count) {
while (count-- > 0) {
char *b = (char *)ptr++;
char t = b[0];
b[0] = b[1];
b[1] = t;
}
return ptr;
}
int16 swapShort(int16 value) {
char *b = (char *)&value;
char t = b[0];
b[0] = b[1];
b[1] = t;
return value;
}
int16 *swapShortPtr(int16 *ptr, int count) {
while (count-- > 0) {
char *b = (char *)ptr++;
char t = b[0];
b[0] = b[1];
b[1] = t;
}
return ptr;
}
unsigned int swapUInt(unsigned int value) {
char *b = (char *)&value;
char t = b[0];
b[0] = b[3];
b[3] = t;
t = b[1];
b[1] = b[2];
b[2] = t;
return value;
}
unsigned int *swapUIntPtr(unsigned int *ptr, int count) {
while (count-- > 0) {
char *b = (char *)ptr++;
char t = b[0];
b[0] = b[3];
b[3] = t;
t = b[1];
b[1] = b[2];
b[2] = t;
}
return ptr;
}
int swapInt(int value) {
char *b = (char *)&value;
char t = b[0];
b[0] = b[3];
b[3] = t;
t = b[1];
b[1] = b[2];
b[2] = t;
return value;
}
int *swapIntPtr(int *ptr, int count) {
while (count-- > 0) {
char *b = (char *)ptr++;
char t = b[0];
b[0] = b[3];
b[3] = t;
t = b[1];
b[1] = b[2];
b[2] = t;
}
return ptr;
}
uint32 swapULong(uint32 value) {
char *b = (char *)&value;
char t = b[0];
b[0] = b[3];
b[3] = t;
t = b[1];
b[1] = b[2];
b[2] = t;
return value;
}
uint32 *swapULongPtr(uint32 *ptr, int count) {
while (count-- > 0) {
char *b = (char *)ptr++;
char t = b[0];
b[0] = b[3];
b[3] = t;
t = b[1];
b[1] = b[2];
b[2] = t;
}
return ptr;
}
int32 swapLong(int32 value) {
char *b = (char *)&value;
char t = b[0];
b[0] = b[3];
b[3] = t;
t = b[1];
b[1] = b[2];
b[2] = t;
return value;
}
int32 *swapLongPtr(int32 *ptr, int count) {
while (count-- > 0) {
char *b = (char *)ptr++;
char t = b[0];
b[0] = b[3];
b[3] = t;
t = b[1];
b[1] = b[2];
b[2] = t;
}
return ptr;
}
#endif
} // End of namespace Lab

955
engines/lab/map.cpp Normal file
View File

@ -0,0 +1,955 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/storage.h"
#include "lab/labfun.h"
#include "lab/diff.h"
#include "lab/vga.h"
#include "lab/text.h"
#include "lab/mouse.h"
#include "lab/parsefun.h"
#include "lab/parsetypes.h"
#include "lab/interface.h"
#include "lab/text.h"
#include "lab/stddefines.h"
namespace Lab {
static struct TextFont *BigMsgFont;
static struct TextFont bmf;
extern uint16 Direction;
extern bool IsHiRes;
extern uint32 VGAScreenWidth, VGAScreenHeight;
#if !defined(DOSCODE)
extern CloseDataPtr CPtr;
extern uint16 RoomNum;
#endif
/*****************************************************************************/
/* Converts an Amiga palette (up to 16 colors) to a VGA palette, then sets */
/* the VGA palette. */
/*****************************************************************************/
void setAmigaPal(uint16 *pal, uint16 numcolors) {
char vgapal[16 * 3];
uint16 counter, vgacount;
if (numcolors > 16)
numcolors = 16;
vgacount = 0;
for (counter = 0; counter < numcolors; counter++) {
vgapal[vgacount] = (char)(((pal[counter] & 0xf00) >> 8) << 2);
vgacount++;
vgapal[vgacount] = (char)(((pal[counter] & 0x0f0) >> 4) << 2);
vgacount++;
vgapal[vgacount] = (char)(((pal[counter] & 0x00f)) << 2);
vgacount++;
}
writeColorRegsSmooth(vgapal, 0, 16);
}
/*****************************************************************************/
/* Gets a font from disk and puts it into temporary memory. */
/*****************************************************************************/
bool getFont(const char *filename, TextFont *textfont) {
byte *fontbuffer;
fontbuffer = (byte *)stealBufMem(sizeOfFile(filename) -
(sizeof(struct TextFont) + 4));
g_music->checkMusic();
if (fontbuffer == NULL)
return false;
return openFontMem(filename, textfont, fontbuffer);
}
/*****************************************************************************/
/* Gets a chunk of text and puts it into the graphics memory. */
/*****************************************************************************/
char *getText(const char *filename) {
bool dodecrypt;
byte **tfile;
g_music->checkMusic();
dodecrypt = (isBuffered(filename) == NULL);
tfile = g_music->newOpen(filename);
if (!tfile)
return NULL;
if (dodecrypt)
decrypt(*tfile);
return (char *)*tfile;
}
/*****************************************************************************/
/* Reads in an image from disk. */
/*****************************************************************************/
void readImage(byte **buffer, Image **im) {
uint32 size;
(*im) = (Image *)(*buffer);
(*im)->Width = READ_LE_UINT16(*buffer);
(*im)->Height = READ_LE_UINT16(*buffer + 2);
*buffer += 8; /* sizeof(struct Image); */
size = (*im)->Width * (*im)->Height;
if (1L & size)
size++;
(*im)->ImageData = (byte *)(*buffer);
(*buffer) += size;
}
/*---------------------------------------------------------------------------*/
/*------------------------------ The Map stuff ------------------------------*/
/*---------------------------------------------------------------------------*/
extern RoomData *Rooms;
extern char *ViewPath;
static Image *Map, *Room, *UpArrowRoom, *DownArrowRoom, *Bridge,
*HRoom, *VRoom, *Maze, *HugeMaze, *Path, *MapNorth,
*MapEast, *MapSouth, *MapWest, *XMark, *Back, *BackAlt,
*Down, *DownAlt, *Up, *UpAlt;
static uint16 MaxRooms;
static MapData *Maps;
extern char *LOWERFLOORS, *MIDDLEFLOORS, *UPPERFLOORS, *MEDMAZEFLOORS, *HEDGEMAZEFLOORS, *SURMAZEFLOORS, *CARNIVALFLOOR, *SURMAZEMSG;
extern TextFont *MsgFont;
uint16 *FadePalette;
static uint16 MapGadX[3] = {101, 55, 8}, MapGadY[3] = {105, 105, 105};
#if !defined(DOSCODE)
static Gadget downgadget = { 101, 105, 2, VKEY_DNARROW, 0L, NULL, NULL, NULL },
upgadget = { 55, 105, 1, VKEY_UPARROW, 0L, NULL, NULL, &downgadget },
backgadget = { 8, 105, 0, 0, 0L, NULL, NULL, &upgadget },
#else
static Gadget downgadget = { 101, 105, 2, 0L, NULL, NULL, NULL },
upgadget = { 55, 105, 1, 0L, NULL, NULL, &downgadget },
backgadget = { 8, 105, 0, 0L, NULL, NULL, &upgadget },
#endif
*MapGadgetList = &backgadget;
static uint16 AmigaMapPalette[] = {
0x0BA8, 0x0C11, 0x0A74, 0x0076,
0x0A96, 0x0DCB, 0x0CCA, 0x0222,
0x0444, 0x0555, 0x0777, 0x0999,
0x0AAA, 0x0ED0, 0x0EEE, 0x0694
};
#define LOWERFLOOR 1
#define MIDDLEFLOOR 2
#define UPPERFLOOR 3
#define MEDMAZEFLOOR 4
#define HEDGEMAZEFLOOR 5
#define SURMAZEFLOOR 6
#define CARNIVAL 7
static uint16 mapScaleX(uint16 x) {
if (IsHiRes)
return (x - 45);
else
return ((x - 45) >> 1);
}
static uint16 mapScaleY(uint16 y) {
if (IsHiRes)
return y;
else
return ((y - 35) >> 1) - (y >> 6);
}
/*****************************************************************************/
/* Loads in the map data. */
/*****************************************************************************/
static bool loadMapData(void) {
byte **buffer, Temp[5];
int32 Size;
struct Gadget *gptr;
uint16 counter;
BigMsgFont = &bmf;
if (!getFont("P:Map.fon", BigMsgFont))
BigMsgFont = MsgFont;
Size = sizeOfFile("P:MapImage");
resetBuffer(); /* Make images load into start of buffer */
buffer = g_music->newOpen("P:MapImage");
if (!buffer)
return false;
stealBufMem(Size); /* Now freeze that buffer from further use */
readImage(buffer, &Map);
readImage(buffer, &Room);
readImage(buffer, &UpArrowRoom);
readImage(buffer, &DownArrowRoom);
readImage(buffer, &HRoom);
readImage(buffer, &VRoom);
readImage(buffer, &Maze);
readImage(buffer, &HugeMaze);
readImage(buffer, &MapNorth);
readImage(buffer, &MapEast);
readImage(buffer, &MapSouth);
readImage(buffer, &MapWest);
readImage(buffer, &Path);
readImage(buffer, &Bridge);
readImage(buffer, &Back);
readImage(buffer, &BackAlt);
readImage(buffer, &Up);
readImage(buffer, &UpAlt);
readImage(buffer, &Down);
readImage(buffer, &DownAlt);
backgadget.Im = Back;
backgadget.ImAlt = BackAlt;
upgadget.Im = Up;
upgadget.ImAlt = UpAlt;
downgadget.Im = Down;
downgadget.ImAlt = DownAlt;
counter = 0;
gptr = MapGadgetList;
while (gptr) {
gptr->x = VGAScaleX(MapGadX[counter]);
gptr->y = VGAScaleY(MapGadY[counter]);
gptr = gptr->NextGadget;
counter++;
}
buffer = g_music->newOpen("Lab:Maps");
stealBufMem(sizeOfFile("Lab:Maps")); /* Freeze the memory for the maps */
readBlock(Temp, 4L, buffer);
Temp[4] = 0;
if (strcmp((char *)Temp, "MAP0") == 0) {
readBlock(&MaxRooms, 2L, buffer);
#if !defined(DOSCODE)
swapUShortPtr(&MaxRooms, 1);
#endif
Maps = (MapData *)(*buffer);
#if !defined(DOSCODE)
for (counter = 1; counter <= MaxRooms; counter++) {
swapUShortPtr(&Maps[counter].x, 4);
swapULongPtr(&Maps[counter].MapFlags, 1);
}
#endif
} else
return false;
return true;
}
static uint16 fadeNumIn(uint16 num, uint16 res, uint16 counter) {
return (num - ((((int32)(15 - counter)) * ((int32)(num - res))) / 15));
}
static uint16 fadeNumOut(uint16 num, uint16 res, uint16 counter) {
return (num - ((((int32) counter) * ((int32)(num - res))) / 15));
}
/*****************************************************************************/
/* Does the fading of the Palette on the screen. */
/*****************************************************************************/
void fade(bool fadein, uint16 res) {
uint16 pennum, counter, newpal[16];
for (counter = 0; counter < 16; counter++) {
for (pennum = 0; pennum < 16; pennum++) {
if (fadein)
newpal[pennum] = (0x00F & fadeNumIn(0x00F & FadePalette[pennum], 0x00F & res, counter)) +
(0x0F0 & fadeNumIn(0x0F0 & FadePalette[pennum], 0x0F0 & res, counter)) +
(0xF00 & fadeNumIn(0xF00 & FadePalette[pennum], 0xF00 & res, counter));
else
newpal[pennum] = (0x00F & fadeNumOut(0x00F & FadePalette[pennum], 0x00F & res, counter)) +
(0x0F0 & fadeNumOut(0x0F0 & FadePalette[pennum], 0x0F0 & res, counter)) +
(0xF00 & fadeNumOut(0xF00 & FadePalette[pennum], 0xF00 & res, counter));
}
setAmigaPal(newpal, 16);
waitTOF();
g_music->updateMusic();
}
}
/*****************************************************************************/
/* Figures out what a room's coordinates should be. */
/*****************************************************************************/
static void roomCords(uint16 CurRoom, uint16 *x1, uint16 *y1, uint16 *x2, uint16 *y2) {
*x1 = mapScaleX(Maps[CurRoom].x);
*y1 = mapScaleY(Maps[CurRoom].y);
*x2 = *x1;
*y2 = *y1;
switch (Maps[CurRoom].SpecialID) {
case NORMAL:
case UPARROWROOM:
case DOWNARROWROOM:
(*x2) += Room->Width;
(*y2) += Room->Height;
break;
case BRIDGEROOM:
(*x2) += Bridge->Width;
(*y2) += Bridge->Height;
break;
case VCORRIDOR:
(*x2) += VRoom->Width;
(*y2) += VRoom->Height;
break;
case HCORRIDOR:
(*x2) += HRoom->Width;
(*y2) += HRoom->Height;
break;
}
}
/*****************************************************************************/
/* Draws a room to the bitmap. */
/*****************************************************************************/
static void drawRoom(uint16 CurRoom, bool drawx) {
uint16 x, y, xx, xy, offset;
uint32 flags;
x = mapScaleX(Maps[CurRoom].x);
y = mapScaleY(Maps[CurRoom].y);
flags = Maps[CurRoom].MapFlags;
switch (Maps[CurRoom].SpecialID) {
case NORMAL:
case UPARROWROOM:
case DOWNARROWROOM:
if (Maps[CurRoom].SpecialID == NORMAL)
drawImage(Room, x, y);
else if (Maps[CurRoom].SpecialID == DOWNARROWROOM)
drawImage(DownArrowRoom, x, y);
else
drawImage(UpArrowRoom, x, y);
offset = (Room->Width - Path->Width) / 2;
if ((NORTHDOOR & flags) && (y >= Path->Height))
drawImage(Path, x + offset, y - Path->Height);
if (SOUTHDOOR & flags)
drawImage(Path, x + offset, y + Room->Height);
offset = (Room->Height - Path->Height) / 2;
if (EASTDOOR & flags)
drawImage(Path, x + Room->Width, y + offset);
if (WESTDOOR & flags)
drawImage(Path, x - Path->Width, y + offset);
xx = x + (Room->Width - XMark->Width) / 2;
xy = y + (Room->Height - XMark->Height) / 2;
break;
case BRIDGEROOM:
drawImage(Bridge, x, y);
xx = x + (Bridge->Width - XMark->Width) / 2;
xy = y + (Bridge->Height - XMark->Height) / 2;
break;
case VCORRIDOR:
drawImage(VRoom, x, y);
offset = (VRoom->Width - Path->Width) / 2;
if (NORTHDOOR & flags)
drawImage(Path, x + offset, y - Path->Height);
if (SOUTHDOOR & flags)
drawImage(Path, x + offset, y + VRoom->Height);
offset = (Room->Height - Path->Height) / 2;
if (EASTDOOR & flags)
drawImage(Path, x + VRoom->Width, y + offset);
if (WESTDOOR & flags)
drawImage(Path, x - Path->Width, y + offset);
if (EASTBDOOR & flags)
drawImage(Path, x + VRoom->Width, y - offset - Path->Height + VRoom->Height);
if (WESTBDOOR & flags)
drawImage(Path, x - Path->Width, y - offset - Path->Height + VRoom->Height);
offset = (VRoom->Height - Path->Height) / 2;
if (EASTMDOOR & flags)
drawImage(Path, x + VRoom->Width, y - offset - Path->Height + VRoom->Height);
if (WESTMDOOR & flags)
drawImage(Path, x - Path->Width, y - offset - Path->Height + VRoom->Height);
xx = x + (VRoom->Width - XMark->Width) / 2;
xy = y + (VRoom->Height - XMark->Height) / 2;
break;
case HCORRIDOR:
drawImage(HRoom, x, y);
offset = (Room->Width - Path->Width) / 2;
if (NORTHDOOR & flags)
drawImage(Path, x + offset, y - Path->Height);
if (SOUTHDOOR & flags)
drawImage(Path, x + offset, y + Room->Height);
if (NORTHRDOOR & flags)
drawImage(Path, x - offset - Path->Width + HRoom->Width, y - Path->Height);
if (SOUTHRDOOR & flags)
drawImage(Path, x - offset - Path->Width + HRoom->Width, y + Room->Height);
offset = (HRoom->Width - Path->Width) / 2;
if (NORTHMDOOR & flags)
drawImage(Path, x - offset - Path->Width + HRoom->Width, y - Path->Height);
if (SOUTHMDOOR & flags)
drawImage(Path, x - offset - Path->Width + HRoom->Width, y + Room->Height);
offset = (Room->Height - Path->Height) / 2;
if (EASTDOOR & flags)
drawImage(Path, x + HRoom->Width, y + offset);
if (WESTDOOR & flags)
drawImage(Path, x - Path->Width, y + offset);
xx = x + (HRoom->Width - XMark->Width) / 2;
xy = y + (HRoom->Height - XMark->Height) / 2;
break;
default:
return;
}
if (drawx)
drawImage(XMark, xx, xy);
}
/*****************************************************************************/
/* Checks if a floor has been visitted. */
/*****************************************************************************/
static bool onFloor(LargeSet RoomsFound, uint16 Floor) {
uint16 drawroom;
for (drawroom = 1; drawroom <= MaxRooms; drawroom++) {
if ((Maps[drawroom].PageNumber == Floor)
&& In(RoomsFound, drawroom)
&& Maps[drawroom].x) {
return true;
}
}
return false;
}
/*****************************************************************************/
/* Figures out which floor, if any, should be gone to if the up arrow is hit */
/*****************************************************************************/
static void getUpFloor(LargeSet RoomsFound, uint16 *Floor, bool *isfloor) {
do {
*isfloor = true;
if (*Floor < UPPERFLOOR)
(*Floor)++;
else {
*Floor = CARNIVAL + 1;
*isfloor = false;
return;
}
} while ((!onFloor(RoomsFound, *Floor)) && (*Floor <= CARNIVAL));
}
/*****************************************************************************/
/* Figures out which floor, if any, should be gone to if the down arrow is */
/* hit. */
/*****************************************************************************/
static void getDownFloor(LargeSet RoomsFound, uint16 *Floor, bool *isfloor) {
do {
*isfloor = true;
if ((*Floor == LOWERFLOOR) || (*Floor == 0)) {
*Floor = 0;
*isfloor = false;
return;
} else if (*Floor > UPPERFLOOR) {
/* LAB: Labyrinth specific code */
if (*Floor == HEDGEMAZEFLOOR)
*Floor = UPPERFLOOR;
else if ((*Floor == CARNIVAL) || (*Floor == MEDMAZEFLOOR))
*Floor = MIDDLEFLOOR;
else if (*Floor == SURMAZEFLOOR)
*Floor = LOWERFLOOR;
else {
*Floor = 0;
*isfloor = false;
return;
}
} else
(*Floor)--;
} while ((!onFloor(RoomsFound, *Floor)) && *Floor);
}
/*****************************************************************************/
/* Draws the map */
/*****************************************************************************/
static void drawMap(LargeSet RoomsFound, uint16 CurRoom, uint16 CurMsg, uint16 Floor, bool fadeout, bool fadein) {
uint16 drawroom;
char *sptr;
uint16 tempfloor;
bool noghoast;
mouseHide();
if (fadeout)
fade(false, 0);
setAPen(0);
rectFill(0, 0, VGAScreenWidth - 1, VGAScreenHeight - 1);
drawImage(Map, 0, 0);
drawGadgetList(MapGadgetList);
for (drawroom = 1; drawroom <= MaxRooms; drawroom++) {
if ((Maps[drawroom].PageNumber == Floor)
&& In(RoomsFound, drawroom)
&& Maps[drawroom].x) {
drawRoom(drawroom, (bool)(drawroom == CurRoom));
g_music->checkMusic();
}
}
if ((Maps[CurRoom].PageNumber == Floor) /* Makes sure the X is drawn in corridors */
&& In(RoomsFound, CurRoom) /* NOTE: this here on purpose just in case there's some wierd condition, like the surreal maze where there are no rooms */
&& Maps[CurRoom].x)
drawRoom(CurRoom, true);
tempfloor = Floor;
getUpFloor(RoomsFound, &tempfloor, &noghoast);
if (noghoast)
unGhoastGadget(&upgadget);
else
ghoastGadget(&upgadget, 12);
tempfloor = Floor;
getDownFloor(RoomsFound, &tempfloor, &noghoast);
if (noghoast)
unGhoastGadget(&downgadget);
else
ghoastGadget(&downgadget, 12);
/* LAB: Labyrinth specific code */
if (Floor == LOWERFLOOR) {
if (onFloor(RoomsFound, SURMAZEFLOOR))
drawImage(Maze, mapScaleX(538), mapScaleY(277));
}
else if (Floor == MIDDLEFLOOR) {
if (onFloor(RoomsFound, CARNIVAL))
drawImage(Maze, mapScaleX(358), mapScaleY(72));
if (onFloor(RoomsFound, MEDMAZEFLOOR))
drawImage(Maze, mapScaleX(557), mapScaleY(325));
}
else if (Floor == UPPERFLOOR) {
if (onFloor(RoomsFound, HEDGEMAZEFLOOR))
drawImage(HugeMaze, mapScaleX(524), mapScaleY(97));
}
else if (Floor == SURMAZEFLOOR) {
flowText(MsgFont, 0, 7, 0, true, true, true, true, mapScaleX(360), 0, mapScaleX(660), mapScaleY(450), SURMAZEMSG);
}
/* LAB: Labyrinth specific code */
sptr = NULL;
switch (Floor) {
case LOWERFLOOR:
sptr = LOWERFLOORS;
break;
case MIDDLEFLOOR:
sptr = MIDDLEFLOORS;
break;
case UPPERFLOOR:
sptr = UPPERFLOORS;
break;
case MEDMAZEFLOOR:
sptr = MEDMAZEFLOORS;
break;
case HEDGEMAZEFLOOR:
sptr = HEDGEMAZEFLOORS;
break;
case SURMAZEFLOOR:
sptr = SURMAZEFLOORS;
break;
case CARNIVAL:
sptr = CARNIVALFLOOR;
break;
default:
sptr = NULL;
break;
}
if (sptr)
flowText(MsgFont, 0, 5, 3, true, true, true, true, VGAScaleX(14), VGAScaleY(75), VGAScaleX(134), VGAScaleY(97), sptr);
if ((sptr = Rooms[CurMsg].RoomMsg))
flowText(MsgFont, 0, 5, 3, true, true, true, true, VGAScaleX(14), VGAScaleY(148), VGAScaleX(134), VGAScaleY(186), sptr);
if (fadein)
fade(true, 0);
mouseShow();
}
/*****************************************************************************/
/* Processes the map. */
/*****************************************************************************/
void processMap(uint16 CurRoom, LargeSet RoomsFound) {
uint32 Class, place = 1;
uint16 Code, Qualifier, MouseX, MouseY, GadgetID, CurFloor, OldFloor, OldMsg, CurMsg, drawroom, x1, y1, x2, y2;
char *sptr, newcolor[3];
bool drawmap;
struct IntuiMessage *Msg;
CurMsg = CurRoom;
CurFloor = Maps[CurRoom].PageNumber;
while (1) {
g_music->checkMusic(); /* Make sure we check the music at least after every message */
Msg = getMsg();
if (Msg == NULL) {
g_music->newCheckMusic();
if (place <= 14) {
newcolor[0] = 14 << 2;
newcolor[1] = place << 2;
newcolor[2] = newcolor[1];
} else {
newcolor[0] = 14 << 2;
newcolor[1] = (28 - place) << 2;
newcolor[2] = newcolor[1];
}
waitTOF();
writeColorReg(newcolor, 1);
updateMouse();
waitTOF();
updateMouse();
waitTOF();
updateMouse();
waitTOF();
updateMouse();
place++;
if (place >= 28)
place = 1;
} else {
Class = Msg->Class;
Code = Msg->Code;
GadgetID = Msg->GadgetID;
Qualifier = Msg->Qualifier;
MouseX = Msg->MouseX;
MouseY = Msg->MouseY;
if (((Class == MOUSEBUTTONS) && (IEQUALIFIER_RBUTTON & Qualifier)) ||
((Class == RAWKEY) && (Code == 27)))
return;
if (Class == GADGETUP) {
if (GadgetID == 0) { /* Quit menu button */
return;
} else if (GadgetID == 1) { /* Up arrow */
OldFloor = CurFloor;
getUpFloor(RoomsFound, &CurFloor, &drawmap);
if (drawmap) {
fade(false, 0);
drawMap(RoomsFound, CurRoom, CurMsg, CurFloor, false, false);
fade(true, 0);
} else
CurFloor = OldFloor;
} else if (GadgetID == 2) { /* Down arrow */
OldFloor = CurFloor;
getDownFloor(RoomsFound, &CurFloor, &drawmap);
if (drawmap) {
fade(false, 0);
drawMap(RoomsFound, CurRoom, CurMsg, CurFloor, false, false);
fade(true, 0);
} else
CurFloor = OldFloor;
}
}
else if ((Class == MOUSEBUTTONS) && (IEQUALIFIER_LEFTBUTTON & Qualifier)) {
if ((CurFloor == LOWERFLOOR) && (MouseX >= mapScaleX(538)) && (MouseY >= mapScaleY(277))
&& (MouseX <= mapScaleX(633)) && (MouseY <= mapScaleY(352))
&& onFloor(RoomsFound, SURMAZEFLOOR)) {
CurFloor = SURMAZEFLOOR;
fade(false, 0);
drawMap(RoomsFound, CurRoom, CurMsg, CurFloor, false, false);
fade(true, 0);
}
else if ((CurFloor == MIDDLEFLOOR) && (MouseX >= mapScaleX(358)) && (MouseY >= mapScaleY(71))
&& (MouseX <= mapScaleX(452)) && (MouseY <= mapScaleY(147))
&& onFloor(RoomsFound, CARNIVAL)) {
CurFloor = CARNIVAL;
fade(false, 0);
drawMap(RoomsFound, CurRoom, CurMsg, CurFloor, false, false);
fade(true, 0);
}
else if ((CurFloor == MIDDLEFLOOR) && (MouseX >= mapScaleX(557)) && (MouseY >= mapScaleY(325))
&& (MouseX <= mapScaleX(653)) && (MouseY <= mapScaleY(401))
&& onFloor(RoomsFound, MEDMAZEFLOOR)) {
CurFloor = MEDMAZEFLOOR;
fade(false, 0);
drawMap(RoomsFound, CurRoom, CurMsg, CurFloor, false, false);
fade(true, 0);
}
else if ((CurFloor == UPPERFLOOR) && (MouseX >= mapScaleX(524)) && (MouseY >= mapScaleY(97))
&& (MouseX <= mapScaleX(645)) && (MouseY <= mapScaleY(207))
&& onFloor(RoomsFound, HEDGEMAZEFLOOR)) {
CurFloor = HEDGEMAZEFLOOR;
fade(false, 0);
drawMap(RoomsFound, CurRoom, CurMsg, CurFloor, false, false);
fade(true, 0);
}
else if (MouseX > mapScaleX(314)) {
OldMsg = CurMsg;
for (drawroom = 1; drawroom <= MaxRooms; drawroom++) {
roomCords(drawroom, &x1, &y1, &x2, &y2);
if ((Maps[drawroom].PageNumber == CurFloor)
&& In(RoomsFound, drawroom)
&& (MouseX >= x1) && (MouseX <= x2)
&& (MouseY >= y1) && (MouseY <= y2)) {
CurMsg = drawroom;
}
}
if (OldMsg != CurMsg) {
if (Rooms[CurMsg].RoomMsg == NULL)
readViews(CurMsg, ViewPath);
if ((sptr = Rooms[CurMsg].RoomMsg)) {
mouseHide();
setAPen(3);
rectFill(VGAScaleX(13), VGAScaleY(148), VGAScaleX(135), VGAScaleY(186));
flowText(MsgFont, 0, 5, 3, true, true, true, true, VGAScaleX(14), VGAScaleY(148), VGAScaleX(134), VGAScaleY(186), sptr);
if (Maps[OldMsg].PageNumber == CurFloor)
drawRoom(OldMsg, (bool)(OldMsg == CurRoom));
roomCords(CurMsg, &x1, &y1, &x2, &y2);
x1 = (x1 + x2) / 2;
y1 = (y1 + y2) / 2;
if ((CurMsg != CurRoom) && (Maps[CurMsg].PageNumber == CurFloor)) {
setAPen(1);
rectFill(x1 - 1, y1, x1, y1);
}
mouseShow();
}
}
}
}
#if !defined(DOSCODE)
g_system->updateScreen();
#endif
}
}
}
/*****************************************************************************/
/* Cleans up behind itself. */
/*****************************************************************************/
void mapCleanUp(void) {
freeAllStolenMem();
}
/*****************************************************************************/
/* Does the map processing. */
/*****************************************************************************/
void doMap(LargeSet RoomsFound, uint16 CurRoom) {
FadePalette = AmigaMapPalette;
g_music->checkMusic();
loadMapData();
blackAllScreen();
if (Direction == NORTH)
XMark = MapNorth;
else if (Direction == SOUTH)
XMark = MapSouth;
else if (Direction == EAST)
XMark = MapEast;
else if (Direction == WEST)
XMark = MapWest;
drawMap(RoomsFound, CurRoom, CurRoom, Maps[CurRoom].PageNumber, false, true);
mouseShow();
attachGadgetList(MapGadgetList);
#if !defined(DOSCODE)
g_system->updateScreen();
#endif
processMap(CurRoom, RoomsFound);
attachGadgetList(NULL);
fade(false, 0);
blackAllScreen();
mouseHide();
setAPen(0);
rectFill(0, 0, VGAScreenWidth - 1, VGAScreenHeight - 1);
mapCleanUp();
blackAllScreen();
mouseShow();
#if !defined(DOSCODE)
g_system->updateScreen();
#endif
}
} // End of namespace Lab

View File

@ -0,0 +1,127 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/labfun.h"
#include "lab/modernsavegame.h"
namespace Lab {
byte g_SaveGameImage[SAVED_IMAGE_SIZE]; // 640 x 358
char g_SaveGamePath[512];
char g_PathSeperator[4];
extern LargeSet Conditions,
RoomsFound;
#define SAVEVERSION "LBS3"
int getSaveGameList(struct SaveGameInfo *info, int maxNum) {
warning("STUB: getSaveGameList");
return 0;
#if 0
char path[512];
struct stat statb;
int total = 0;
int i;
for (i = 0; i < maxNum; i++) {
checkMusic();
sprintf(path, "%s%s%d", g_SaveGamePath, g_PathSeperator, i);
statb.st_size = 0;
stat(path, &statb);
if (statb.st_size > 0) {
struct tm *create_date;
FILE *fh;
create_date = localtime(&statb.st_ctime);
strcpy(info->SaveGameDate, asctime(create_date));
fh = fopen(path, "rb");
if (fh != NULL) {
char temp[5];
unsigned short t;
int toSeek;
info->Index = i;
fread(temp, 1, 4, fh);
temp[4] = 0;
fread(&t, 1, 2, fh);
info->RoomNumber = swapUShort(t);
fread(&t, 1, 2, fh);
info->Direction = swapUShort(t);
toSeek = 2 + Conditions->lastElement / 8 + RoomsFound->lastElement / 8 + 6 + 2 * 16;
fseek(fh, toSeek, SEEK_CUR);
info->SaveGameImage = NULL;
if (strcmp(temp, SAVEVERSION) == 0) {
info->SaveGameImage = malloc(SAVED_IMAGE_SIZE);
if (info->SaveGameImage != NULL)
fread(info->SaveGameImage, 1, SAVED_IMAGE_SIZE, fh);
} else {
info->SaveGameImage = malloc(SAVED_IMAGE_SIZE);
if (info->SaveGameImage != NULL)
memset(info->SaveGameImage, 0, SAVED_IMAGE_SIZE);
}
fclose(fh);
info++;
total++;
}
}
}
return total;
#endif
}
void freeSaveGameList(struct SaveGameInfo *info, int count) {
int i;
for (i = 0; i < count; i++) {
free(info->SaveGameImage);
++info;
}
}
} // End of namespace Lab

View File

@ -0,0 +1,55 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#ifndef LAB_MODERNGAMESAVE_H
#define LAB_MODERNGAMESAVE_H
namespace Lab {
#define MAX_SAVED_GAMES 15
#define SAVED_IMAGE_SIZE (128 * 72)
extern byte g_SaveGameImage[SAVED_IMAGE_SIZE]; // 640 x 358
struct SaveGameInfo {
unsigned short Index;
unsigned short RoomNumber;
unsigned short Direction;
byte *SaveGameImage;
char SaveGameDate[128];
};
int getSaveGameList(struct SaveGameInfo *info, int maxNum);
void freeSaveGameList(struct SaveGameInfo *info, int count);
} // End of namespace Lab
#endif /* LAB_MODERNGAMESAVE_H */

40
engines/lab/module.mk Normal file
View File

@ -0,0 +1,40 @@
MODULE := engines/lab
MODULE_OBJS := \
allocroom.o \
audioi.o \
detection.o \
engine.o \
graphics.o \
interface.o \
intro.o \
lab.o \
labfile.o \
labmusic.o \
labsets.o \
labtext.o \
machine.o \
map.o \
modernsavegame.o \
mouse.o \
processroom.o \
readdiff.o \
readparse.o \
savegame.o \
savegamepalmap.o \
special.o \
storage.o \
text.o \
timing.o \
undiff.o \
vga.o
# This module can be built as a plugin
ifeq ($(ENABLE_LAB), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk

569
engines/lab/mouse.cpp Normal file
View File

@ -0,0 +1,569 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/mouse.h"
#include "lab/vga.h"
#include "lab/stddefines.h"
#include "lab/timing.h"
#include "lab/interface.h"
namespace Lab {
extern bool IsHiRes;
extern uint32 VGAScreenWidth, VGAScreenHeight;
void mouseHideXY(void);
#if defined(DOSCODE)
/*****************************************************************************/
/* Standard mouse calling template. */
/*****************************************************************************/
static void mouse(int16 *m1, int16 *m2, int16 *m3, int16 *m4) {
union REGS reg;
reg.w.ax = *m1;
reg.w.bx = *m2;
reg.w.cx = *m3;
reg.w.dx = *m4;
int386(0x33, &reg, &reg);
*m1 = reg.w.ax;
*m2 = reg.w.bx;
*m3 = reg.w.cx;
*m4 = reg.w.dx;
}
#endif
static bool LeftClick = false;
static uint16 leftx = 0, lefty = 0;
static bool RightClick = false;
static uint16 rightx = 0, righty = 0;
static bool MouseHidden = true, QuitMouseHandler = false;
static int32 NumHidden = 1;
static uint16 CurMouseX, CurMouseY;
static uint16 MouseImageWidth = 10, MouseImageHeight = 15;
static struct Gadget *LastGadgetHit = NULL;
struct Gadget *ScreenGadgetList = NULL;
static byte MouseData[] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1, 7, 1, 0, 0, 0, 0, 0, 0, 0,
1, 7, 7, 1, 0, 0, 0, 0, 0, 0,
1, 7, 7, 7, 1, 0, 0, 0, 0, 0,
1, 7, 7, 7, 7, 1, 0, 0, 0, 0,
1, 7, 7, 7, 7, 7, 1, 0, 0, 0,
1, 7, 7, 7, 7, 7, 7, 1, 0, 0,
1, 7, 7, 7, 7, 7, 7, 7, 1, 0,
1, 7, 7, 7, 7, 7, 1, 1, 1, 1,
1, 7, 7, 1, 7, 7, 1, 0, 0, 0,
1, 7, 1, 0, 1, 7, 7, 1, 0, 0,
1, 1, 0, 0, 1, 7, 7, 1, 0, 0,
0, 0, 0, 0, 0, 1, 7, 7, 1, 0,
0, 0, 0, 0, 0, 1, 7, 7, 1, 0,
0, 0, 0, 0, 0, 0, 1, 1, 0, 0};
static struct Image MouseImage, BackImage;
static byte BackImageBuffer[256];
static uint16 backx, backy;
static bool drawmouse = false, gadhit = false;
static struct Gadget *hitgad = NULL;
void mouseShowXY(uint16 CurMouseX, uint16 CurMouseY);
/*****************************************************************************/
/* Checks whether or not the cords fall within one of the gadgets in a list */
/* of gadgets. */
/*****************************************************************************/
static Gadget *checkGadgetHit(struct Gadget *gadlist, uint16 x, uint16 y) {
uint16 counter;
while (gadlist != NULL) {
if ((x >= gadlist->x) && (y >= gadlist->y) &&
(x <= (gadlist->x + gadlist->Im->Width)) &&
(y <= (gadlist->y + gadlist->Im->Height)) &&
!(GADGETOFF & gadlist->GadgetFlags)) {
if (IsHiRes) {
gadhit = true;
hitgad = gadlist;
} else {
QuitMouseHandler = true;
VGAStorePage();
mouseHideXY();
drawImage(gadlist->ImAlt, gadlist->x, gadlist->y);
mouseShowXY(x, y);
for (counter = 0; counter < 3; counter++)
waitTOF();
mouseHideXY();
drawImage(gadlist->Im, gadlist->x, gadlist->y);
mouseShowXY(x, y);
VGARestorePage();
QuitMouseHandler = false;
}
return gadlist;
} else {
gadlist = gadlist->NextGadget;
}
}
return NULL;
}
void attachGadgetList(struct Gadget *GadList) {
if (ScreenGadgetList != GadList)
LastGadgetHit = NULL;
ScreenGadgetList = GadList;
}
static void drawMouse(void) {
if (BackImage.ImageData) {
#if !defined(DOSCODE)
if (backx <= 640 - BackImage.Width && backy <= 480 - BackImage.Height)
#endif
drawMaskImage(&MouseImage, backx, backy);
} else {
#if !defined(DOSCODE)
if (CurMouseX <= 640 - MouseImage.Width && CurMouseY <= 480 - MouseImage.Height)
#endif
drawMaskImage(&MouseImage, CurMouseX, CurMouseY);
}
}
static void getBackMouse(void) {
BackImage.Width = MouseImage.Width;
BackImage.Height = MouseImage.Height;
BackImage.ImageData = BackImageBuffer;
backx = CurMouseX;
backy = CurMouseY;
#if !defined(DOSCODE)
if (/* backx >= 0 && backy >= 0 && */ backx <= 640 - BackImage.Width && backy <= 480 - BackImage.Height)
#endif
readScreenImage(&BackImage, backx, backy);
}
static void restoreBackMouse(void) {
if (BackImage.ImageData) {
#if !defined(DOSCODE)
if (/* backx >= 0 && backy >= 0 && */ backx <= 640 - BackImage.Width && backy <= 480 - BackImage.Height)
#endif
drawImage(&BackImage, backx, backy);
BackImage.ImageData = NULL;
}
}
static struct Gadget *TempGad;
#if defined(DOSCODE)
#pragma off (check_stack)
void _loadds far mouse_handler(int32 max, int32 mcx, int32 mdx) {
#pragma aux mouse_handler parm [EAX] [ECX] [EDX]
#else
void mouse_handler(int32 max, int32 mcx, int32 mdx) {
#endif
if (!IsHiRes)
mcx /= 2;
if (max & 0x01) { /* mouse Move */
if ((CurMouseX != mcx) || (CurMouseY != mdx)) {
CurMouseX = mcx;
CurMouseY = mdx;
if (IsHiRes && !QuitMouseHandler) {
drawmouse = true;
} else if (!MouseHidden && !QuitMouseHandler) {
VGAStorePage();
restoreBackMouse();
getBackMouse();
drawMouse();
VGARestorePage();
}
}
}
if ((max & 0x02) && (NumHidden < 2)) { /* Left mouse button click */
if (ScreenGadgetList)
TempGad = checkGadgetHit(ScreenGadgetList, mcx, mdx);
else
TempGad = NULL;
if (TempGad) {
LastGadgetHit = TempGad;
} else {
LeftClick = true;
leftx = mcx;
lefty = mdx;
}
}
if ((max & 0x08) && (NumHidden < 2)) { /* Right mouse button click */
RightClick = true;
rightx = mcx;
righty = mdx;
}
}
void updateMouse(void) {
uint16 counter;
#if !defined(DOSCODE)
bool doUpdateDisplay = false;
#endif
if (drawmouse && !MouseHidden) {
QuitMouseHandler = true;
drawmouse = false;
restoreBackMouse();
getBackMouse();
drawMouse();
QuitMouseHandler = false;
#if !defined(DOSCODE)
doUpdateDisplay = true;
#endif
}
if (gadhit) {
gadhit = false;
QuitMouseHandler = true;
mouseHide();
drawImage(hitgad->ImAlt, hitgad->x, hitgad->y);
mouseShow();
for (counter = 0; counter < 3; counter++)
waitTOF();
mouseHide();
drawImage(hitgad->Im, hitgad->x, hitgad->y);
mouseShow();
#if !defined(DOSCODE)
doUpdateDisplay = true;
#endif
QuitMouseHandler = false;
}
#if !defined(DOSCODE)
if (doUpdateDisplay)
g_system->updateScreen();
#endif
}
/*****************************************************************************/
/* Initializes the mouse. */
/*****************************************************************************/
bool initMouse(void) {
#if defined(DOSCODE)
void (interrupt far * int_handler)();
int32 vector;
byte firstbyte;
struct SREGS sregs;
union REGS inregs, outregs;
int (far * function_ptr)();
int16 m1, m2, m3, m4;
segread(&sregs);
/* Determine mouse-driver interrupt address */
int_handler = _dos_getvect(0x33); /* Get interrupt vector */
firstbyte = *(byte far *) int_handler; /* Get first instruction of interrupt */
vector = (int32) int_handler;
if ((vector == 0L) || (firstbyte == 0xcf)) { /* Vector should not be zero */
/* First instruction should not be iret */
return false;
}
m1 = 0;
mouse(&m1, &m2, &m3, &m4);
if (m1 != -1)
return false;
m1 = 0x0f;
m3 = 3;
m4 = 10;
mouse(&m1, &m2, &m3, &m4);
m1 = 0x07;
m3 = 0;
m4 = VGAScreenWidth - MouseImageWidth;
if (!IsHiRes) m4 *= 2;
mouse(&m1, &m2, &m3, &m4);
m1 = 0x08;
m3 = 0;
m4 = VGAScreenHeight - MouseImageHeight;
mouse(&m1, &m2, &m3, &m4);
#endif
BackImage.ImageData = NULL;
MouseImage.ImageData = MouseData;
MouseImage.Width = MouseImageWidth;
MouseImage.Height = MouseImageHeight;
mouseMove(0, 0);
#if defined(DOSCODE)
if (IsHiRes) {
m1 = 0x0f;
m3 = 0x03;
m4 = 0x04;
mouse(&m1, &m2, &m3, &m4);
}
inregs.w.ax = 0xc;
inregs.w.cx = 0x01 + 0x02 + 0x08; /* mouse move, left and right mouse clicks */
function_ptr = mouse_handler;
inregs.x.edx = FP_OFF(function_ptr);
sregs.es = FP_SEG(function_ptr);
int386x(0x33, &inregs, &outregs, &sregs);
/* mouse reset and status */
return mouseReset();
#endif
return true;
}
/*****************************************************************************/
/* Resets the mouse. */
/*****************************************************************************/
bool mouseReset(void) {
#if defined(DOSCODE)
int16 m1 = 0, dum;
mouse(&m1, &dum, &dum, &dum);
return (m1 == -1);
#else
return true;
#endif
}
/*****************************************************************************/
/* Shows the mouse. */
/*****************************************************************************/
void mouseShow(void) {
QuitMouseHandler = true;
VGAStorePage();
mouseShowXY(CurMouseX, CurMouseY);
VGARestorePage();
QuitMouseHandler = false;
}
/*****************************************************************************/
/* Shows the mouse. */
/*****************************************************************************/
void mouseShowXY(uint16 MouseX, uint16 MouseY) {
QuitMouseHandler = true;
if (NumHidden)
NumHidden--;
if ((NumHidden == 0) && MouseHidden) {
CurMouseX = MouseX;
CurMouseY = MouseY;
getBackMouse();
drawMouse();
#if !defined(DOSCODE)
g_system->updateScreen();
#endif
MouseHidden = false;
}
QuitMouseHandler = false;
}
/*****************************************************************************/
/* Hides the mouse. */
/*****************************************************************************/
void mouseHide(void) {
QuitMouseHandler = true;
NumHidden++;
if (NumHidden && !MouseHidden) {
MouseHidden = true;
VGAStorePage();
restoreBackMouse();
VGARestorePage();
}
QuitMouseHandler = false;
}
/*****************************************************************************/
/* Hides the mouse. */
/*****************************************************************************/
void mouseHideXY(void) {
QuitMouseHandler = true;
NumHidden++;
if (NumHidden && !MouseHidden) {
MouseHidden = true;
restoreBackMouse();
}
QuitMouseHandler = false;
}
/*****************************************************************************/
/* Gets the current mouse co-ordinates. NOTE: On IBM version, will scale */
/* from virtual to screen co-ordinates automatically. */
/*****************************************************************************/
void mouseXY(uint16 *x, uint16 *y) {
int xx = 0, yy = 0;
//SDL_GetMousePos(&xx, &yy);
warning("STUB: mouseXY");
*x = (uint16)xx;
*y = (uint16)yy;
if (!IsHiRes)
(*x) /= 2;
}
/*****************************************************************************/
/* Moves the mouse to new co-ordinates. */
/*****************************************************************************/
void mouseMove(uint16 x, uint16 y) {
#if defined(DOSCODE)
int16 m1 = 4, dum;
#endif
if (!IsHiRes)
x *= 2;
g_system->warpMouse(x, y);
if (!MouseHidden) {
QuitMouseHandler = true;
mouseXY(&CurMouseX, &CurMouseY);
VGAStorePage();
restoreBackMouse();
getBackMouse();
drawMouse();
VGARestorePage();
#if !defined(DOSCODE)
g_system->updateScreen();
#endif
QuitMouseHandler = false;
}
}
/*****************************************************************************/
/* Checks whether or not the mouse buttons have been pressed, and the last */
/* co-ordinates of the button press. leftbutton tells whether to check the */
/* left or right button. */
/*****************************************************************************/
bool mouseButton(uint16 *x, uint16 *y, bool leftbutton) {
if (leftbutton) {
if (LeftClick) {
*x = leftx;
*y = lefty;
LeftClick = false;
return true;
}
} else {
if (RightClick) {
*x = rightx;
*y = righty;
RightClick = false;
return true;
}
}
return false;
}
Gadget *mouseGadget(void) {
Gadget *Temp = LastGadgetHit;
LastGadgetHit = NULL;
return Temp;
}
} // End of namespace Lab

62
engines/lab/mouse.h Normal file
View File

@ -0,0 +1,62 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#ifndef LAB_MOUSE_H
#define LAB_MOUSE_H
namespace Lab {
struct Gadget;
bool initMouse(void);
bool mouseReset(void);
void updateMouse(void);
void mouseShow(void);
void mouseHide(void);
void mouseXY(uint16 *x, uint16 *y);
void mouseMove(uint16 x, uint16 y);
bool mouseButton(uint16 *x, uint16 *y, bool leftbutton);
Gadget *mouseGadget(void);
void attachGadgetList(struct Gadget *GadList);
} // End of namespace Lab
#endif /* LAB_MOUSE_H */

101
engines/lab/parsefun.h Normal file
View File

@ -0,0 +1,101 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#ifndef LAB_PARSEFUN_H
#define LAB_PARSEFUN_H
#include "lab/stddefines.h"
#include "lab/labfun.h"
#include "lab/parsetypes.h"
namespace Lab {
/* From Parser.c */
bool parse(const char *InputFile);
/* From allocRoom.c */
bool initRoomBuffer(void);
void freeRoomBuffer(void);
void allocRoom(void **Ptr, uint16 Size, uint16 RoomNum);
/* From ReadParse.c */
bool readRoomData(const char *fileName);
bool readInventory(const char *fileName);
char *numtostr(char *text, uint16 Num);
bool readViews(uint16 RoomNum, const char *Path);
bool readInitialConditions(LargeSet Conditions, const char *fileName);
/* From ProcessRoom.c */
ViewDataPtr getViewData(uint16 RoomNum, uint16 Direction);
char *getPictName(CloseDataPtr *LCPtr);
void drawDirection(CloseDataPtr LCPtr);
bool processArrow(uint16 *Direction, uint16 Arrow);
void setCurCloseAbs(uint16 x, uint16 y, CloseDataPtr *cptr);
void setCurClose(uint16 x, uint16 y, CloseDataPtr *cptr);
bool takeItem(uint16 x, uint16 y, CloseDataPtr *cptr);
bool doActionRule(int16 x, int16 y, int16 Action, int16 RoomNum, CloseDataPtr *LCPtr);
bool doOperateRule(int16 x, int16 y, int16 ItemNum, CloseDataPtr *LCPtr);
bool doGoForward(CloseDataPtr *LCPtr);
bool doTurn(uint16 from, uint16 to, CloseDataPtr *LCPtr);
bool doMainView(CloseDataPtr *LCPtr);
/*
bool doConditions(int16 x,
int16 y,
CloseDataPtr *LCPtr);
*/
} // End of namespace Lab
#endif /* LAB_PARSEFUN_H */

237
engines/lab/parsetypes.h Normal file
View File

@ -0,0 +1,237 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#ifndef LAB_PARSETYPES_H
#define LAB_PARSETYPES_H
namespace Lab {
#define MAXFILELEN 31
/*------------------------------- Action types ------------------------------*/
#define PLAYSOUND 1
#define PLAYSOUNDCONT 2
#define SHOWDIFF 3
#define SHOWDIFFCONT 4
#define LOADDIFF 5
#define LOADBM 6
#define SHOWBM 7
#define WIPECMD 8
#define NOUPDATE 9
#define FORCEUPDATE 10
#define SHOWCURPICT 11
#define SETELEMENT 12
#define UNSETELEMENT 13
#define SHOWMESSAGE 14
#define SHOWMESSAGES 15
#define SETPOSITION 16
#define SETCLOSEUP 17
#define MAINVIEW 18
#define SUBINV 19
#define ADDINV 20
#define SHOWDIR 21
#define WAITSECS 22
#define STOPMUSIC 23
#define STARTMUSIC 24
#define CHANGEMUSIC 25
#define RESETMUSIC 26
#define FILLMUSIC 27
#define WAITSOUND 28
#define CLEARSOUND 29
#define WINMUSIC 30
#define WINGAME 31
#define LOSTGAME 32
#define RESETBUFFER 33
#define SPECIALCMD 34
#define CSHOWMESSAGE 35
#define PLAYSOUNDB 36
/* Rule Types */
#define ACTION 1
#define OPERATE 2
#define GOFORWARD 3
#define CONDITIONS 4
#define TURN 5
#define GOMAINVIEW 6
#define TURNFROMTO 7
/*----------------------------- Rule Type Action ----------------------------*/
#define TAKE 1
#define MOVE 2
#define OPENDOOR 3
#define CLOSEDOOR 4
#define TAKEDEF 5
#if defined(WIN32)
#pragma pack(push, 1)
#endif
typedef struct closeData {
uint16 x1, y1, x2, y2;
int16 CloseUpType; /* if > 0, an object. If < 0,
an item */
uint16 depth; /* Level of the closeup. */
char *GraphicName, *Message;
struct closeData *NextCloseUp, *SubCloseUps;
} CloseData;
typedef CloseData *CloseDataPtr;
typedef struct viewData {
int16 *Condition;
char *GraphicName;
struct viewData *NextCondition;
CloseDataPtr closeUps;
} viewData;
typedef viewData *ViewDataPtr;
struct Action {
int16 ActionType, Param1, Param2, Param3;
byte *Data; /* Message, or a pointer to array
of messages. */
Action *NextAction;
};
typedef Action *ActionPtr;
typedef struct rule {
int16 RuleType, Param1, Param2, *Condition;
ActionPtr ActionList;
struct rule *NextRule;
} Rule;
typedef Rule *RulePtr;
typedef struct {
uint16 NorthDoor, SouthDoor, EastDoor, WestDoor;
byte WipeType;
ViewDataPtr NorthView, SouthView, EastView, WestView;
RulePtr RuleList;
char *RoomMsg;
} RoomData;
typedef struct inventoryData {
/* New inventory stuff */
/*
int16 *Condition;
char *GraphicName,
* InvName;
struct inventoryData *NextInventory;
CloseDataPtr closeUps;
RulePtr RuleList;
*/
/* Old inventory stuff */
uint16 Many;
char *name, *BInvName;
} InventoryData;
/* Map Flags */
/* Where the doors are; in a corridor, assumed to be left doors */
#define NORTHDOOR 1L
#define EASTDOOR 2L
#define SOUTHDOOR 4L
#define WESTDOOR 8L
/* Where the doors are in corridors; M means middle, R means right, B means bottom */
#define NORTHMDOOR 16L
#define NORTHRDOOR 32L
#define SOUTHMDOOR 64L
#define SOUTHRDOOR 128L
#define EASTMDOOR 16L
#define EASTBDOOR 32L
#define WESTMDOOR 64L
#define WESTBDOOR 128L
/* Special Map ID's */
#define NORMAL 0
#define UPARROWROOM 1
#define DOWNARROWROOM 2
#define BRIDGEROOM 3
#define VCORRIDOR 4
#define HCORRIDOR 5
#define MEDMAZE 6
#define HEDGEMAZE 7
#define SURMAZE 8
#define MULTIMAZEF1 9
#define MULTIMAZEF2 10
#define MULTIMAZEF3 11
typedef struct {
uint16 x, y, PageNumber, SpecialID;
uint32 MapFlags;
} MapData;
#if defined(WIN32)
#pragma pack(pop)
#endif
#if !defined(DOSCODE)
typedef struct {
uint16 RoomNum;
uint16 Direction;
} CrumbData;
#define MAX_CRUMBS 128
#endif
} // End of namespace Lab
#endif /* LAB_PARSETYPES_H */

1056
engines/lab/processroom.cpp Normal file

File diff suppressed because it is too large Load Diff

673
engines/lab/readdiff.cpp Normal file
View File

@ -0,0 +1,673 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/timing.h"
#include "lab/diff.h"
#include "lab/labfun.h"
#include "lab/vga.h"
#include "lab/mouse.h"
namespace Lab {
extern struct BitMap *DispBitMap, *DrawBitMap;
extern uint32 VGABytesPerPage;
/*
extern int32 ReadSoFar;
extern bool ReadIsDone,
ReadIsError;
*/
extern byte **startoffile;
static bool PlayOnce = false, changedscreen;
bool NoFlip = false, /* Don't flip the new picture to front */
DoBlack = false, /* Black the screen before new picture */
nopalchange = false, /* Don't change the palette. */
noscreenchange = false, /* Don't change the screen type. */
IsBM = false, /* Just fill in the RawDIFFBM structure */
hidemouse = false, /* Don't set the mouse colors */
stopsound = false,
soundplaying = false,
screenbuffer = false,
waiteffect = false, /* Wait for each sound effect to finish
before coninuing. */
mwaiteffect = false;
uint16 DataBytesPerRow;
extern bool EffectPlaying;
#define CONTINUOUS 0xFFFF
DIFFHeader headerdata;
/*------ Stuff for the animation task. -----*/
static byte *start;
static uint32 diffwidth, diffheight;
static bool continuous,
IsPlaying = false,
StopPlaying = false,
StopPlayingEnd = false,
IsAnim = false,
IsPal = false;
char diffcmap[256 * 3], lastcmap[256 * 3];
struct BitMap RawDiffBM;
/*****************************************************************************/
/* Does the undiffing between the bitmaps. */
/*****************************************************************************/
void unDiff(byte *NewBuf, byte *OldBuf, byte *DiffData, uint16 bytesperrow, bool IsV) {
byte buftype;
DiffData++;
buftype = *DiffData;
DiffData++;
if (IsV)
VUnDIFFMemory(NewBuf, DiffData, 1, buftype + 1, bytesperrow);
else
unDIFFMemory(NewBuf, DiffData, 1, buftype + 1);
}
static char blackbuffer[256 * 3];
/*****************************************************************************/
/* Changes the front screen to black. */
/*****************************************************************************/
void blackScreen() {
memset(blackbuffer, 0, 248 * 3);
writeColorRegs(blackbuffer, 8, 248);
g_system->delayMillis(32);
}
/*****************************************************************************/
/* Changes the front screen to white. */
/*****************************************************************************/
void whiteScreen(void) {
memset(blackbuffer, 255, 248 * 3);
writeColorRegs(blackbuffer, 8, 248);
}
/*****************************************************************************/
/* Changes the entire screen to black. */
/*****************************************************************************/
void blackAllScreen() {
memset(blackbuffer, 0, 256 * 3);
writeColorRegs(blackbuffer, 0, 256);
g_system->delayMillis(32);
}
/* For Play Diff */
static uint32 header, size, processed = 0L, WaitSec = 0L, WaitMicros = 0L, DelayMicros = 0L;
static uint16 CurBit = 0, framenumber = 0, samplespeed, numchunks = 1;
static byte *Buffer, temp[5];
static bool FirstThru = true, donepal = false;
static byte *storagefordifffile, * *difffile = &storagefordifffile;
void diffNextFrame(void) {
if (header == 65535) /* Already done. */
return;
#if !defined(DOSCODE)
if (DispBitMap->Flags & BITMAPF_VIDEO) {
DispBitMap->Planes[0] = getVGABaseAddr();
DispBitMap->Planes[1] = DispBitMap->Planes[0] + 0x10000;
DispBitMap->Planes[2] = DispBitMap->Planes[1] + 0x10000;
DispBitMap->Planes[3] = DispBitMap->Planes[2] + 0x10000;
DispBitMap->Planes[4] = DispBitMap->Planes[3] + 0x10000;
}
#endif
mouseHide();
while (1) {
/* NYI: Don't need.
if (ReadIsError)
{
IsPlaying = false;
mouseShow();
return;
}
*/
if (CurBit >= numchunks) {
mouseShow();
#ifdef undef /* NYI: Don't need. */
while (!ReadIsDone && !ReadIsError) /* Wait for the file to load */
waitTOF();
#endif
if (!NoFlip && !IsBM) {
if (headerdata.fps) {
waitForTime(WaitSec, WaitMicros);
addCurTime(0L, DelayMicros, &WaitSec, &WaitMicros);
}
if (IsPal && !nopalchange) {
VGASetPal(diffcmap, 256);
IsPal = false;
}
donepal = true;
FirstThru = false;
}
if (IsPal && !nopalchange && !IsBM && !donepal) {
VGASetPal(diffcmap, 256);
IsPal = false;
}
donepal = false;
framenumber++;
if ((framenumber == 1) && (continuous || (!PlayOnce)))
Buffer = *difffile;
IsAnim = (framenumber >= 3) && (!PlayOnce);
CurBit = 0;
#if !defined(DOSCODE)
if (DispBitMap->Flags & BITMAPF_VIDEO)
g_system->updateScreen();
#endif
return; /* done with the next frame. */
}
g_music->updateMusic();
readBlock(&header, 4L, difffile);
#if !defined(DOSCODE)
swapULongPtr(&header, 1);
#endif
readBlock(&size, 4L, difffile);
#if !defined(DOSCODE)
swapULongPtr(&size, 1);
#endif
processed += 8L;
processed += size;
switch (header) {
case 8L:
memcpy(lastcmap, diffcmap, 256 * 3);
readBlock(diffcmap, size, difffile);
IsPal = true;
break;
case 10L:
RawDiffBM.Planes[CurBit] = *difffile;
if (IsBM)
skip(difffile, size);
else {
#if defined(DOSCODE)
setPage(CurBit);
#endif
readBlock(DrawBitMap->Planes[CurBit], size, difffile);
}
CurBit++;
break;
case 11L:
#if defined(DOSCODE)
setPage(CurBit);
#endif
skip(difffile, 4L);
runLengthDecode(DrawBitMap->Planes[CurBit], *difffile);
CurBit++;
skip(difffile, size - 4);
break;
case 12L:
#if defined(DOSCODE)
setPage(CurBit);
#endif
skip(difffile, 4L);
VRunLengthDecode(DrawBitMap->Planes[CurBit], *difffile, DrawBitMap->BytesPerRow);
CurBit++;
skip(difffile, size - 4);
break;
case 20L:
#if defined(DOSCODE)
setPage(CurBit);
#endif
unDiff(DrawBitMap->Planes[CurBit], DispBitMap->Planes[CurBit], *difffile, DrawBitMap->BytesPerRow, false);
CurBit++;
skip(difffile, size);
break;
case 21L:
#if defined(DOSCODE)
setPage(CurBit);
#endif
unDiff(DrawBitMap->Planes[CurBit], DispBitMap->Planes[CurBit], *difffile, DrawBitMap->BytesPerRow, true);
CurBit++;
skip(difffile, size);
break;
case 25L:
CurBit++;
break;
case 26L:
/* NYI: This don't work no more
memcpy((void *) DrawBitMap->Planes[CurBit],
(void *) DispBitMap->Planes[CurBit], (uint16) (diffheight*diffwidth));
*/
CurBit++;
break;
case 30L:
case 31L: {
if (waiteffect) {
while (EffectPlaying) {
g_music->updateMusic();
waitTOF();
}
}
size -= 8L;
skip(difffile, 4L);
readBlock(&samplespeed, 2L, difffile);
#if !defined(DOSCODE)
swapUShortPtr(&samplespeed, 1);
#endif
skip(difffile, 2L);
byte *music = *difffile;
uint32 musicsize = size;
skip(difffile, size);
playMusic(samplespeed, 64, musicsize, true, music);
break;
}
case 65535L:
if ((framenumber == 1) || PlayOnce || StopPlayingEnd) {
#if !defined(DOSCODE)
int didTOF = 0;
#endif
if (waiteffect) {
while (EffectPlaying) {
g_music->updateMusic();
waitTOF();
#if !defined(DOSCODE)
if (DispBitMap->Flags & BITMAPF_VIDEO)
didTOF = 1;
#endif
}
}
IsPlaying = false;
mouseShow();
#if !defined(DOSCODE)
if (DispBitMap->Flags & BITMAPF_VIDEO)
ungetVGABaseAddr();
if (!didTOF)
g_system->updateScreen();
#endif
return;
}
framenumber = 4; /* Random frame number so it never gets back to 2 */
*difffile = Buffer;
break;
default:
skip(difffile, size);
break;
}
}
#if !defined(DOSCODE)
if (DispBitMap->Flags & BITMAPF_VIDEO)
ungetVGABaseAddr();
#endif
}
/*****************************************************************************/
/* A separate task launched by readDiff. Plays the DIFF. */
/*****************************************************************************/
void playDiff(void) {
processed = 0L;
WaitSec = 0L;
WaitMicros = 0L;
DelayMicros = 0L;
header = 0;
CurBit = 0;
framenumber = 0;
numchunks = 1;
FirstThru = true;
donepal = false;
difffile = &storagefordifffile;
IsPlaying = true;
StopPlaying = false;
StopPlayingEnd = false;
changedscreen = false;
if (DoBlack) {
DoBlack = false;
blackScreen();
}
start = *startoffile; /* Make a copy of the pointer to the start of the file */
*difffile = start; /* Now can modify the file without modifying the original */
if (start == NULL) {
IsPlaying = false;
return;
}
continuous = false;
readBlock(temp, 4L, difffile);
temp[4] = '\0';
readBlock(&header, 4L, difffile);
#if !defined(DOSCODE)
swapULongPtr(&header, 1);
#endif
processed += 8L;
if (!((strcmp((char *)temp, "DIFF") == 0) && (header == 1219009121L))) {
IsPlaying = false;
return;
}
readBlock(&header, 4L, difffile);
#if !defined(DOSCODE)
swapULongPtr(&header, 1);
#endif
readBlock(&size, 4L, difffile);
#if !defined(DOSCODE)
swapULongPtr(&size, 1);
#endif
if (header == 0) {
#if defined(IS_MACOSX)
// sizeof(headerdata) != 18, but the padding might be at the end
readBlock(&headerdata.Version, 2, difffile);
readBlock(&headerdata.x, 2, difffile);
readBlock(&headerdata.y, 2, difffile);
readBlock(&headerdata.depth, 1, difffile);
readBlock(&headerdata.fps, 1, difffile);
readBlock(&headerdata.BufferSize, 4, difffile);
readBlock(&headerdata.Machine, 2, difffile);
readBlock(&headerdata.Flags, 4, difffile);
#else
readBlock(&headerdata, 18, difffile);
#endif
skip(difffile, size - 18);
#if !defined(DOSCODE)
swapUShortPtr(&headerdata.Version, 3);
swapULongPtr(&headerdata.BufferSize, 1);
swapUShortPtr(&headerdata.Machine, 1);
swapULongPtr(&headerdata.Flags, 1);
#endif
continuous = CONTINUOUS & headerdata.Flags;
diffwidth = headerdata.x;
diffheight = headerdata.y;
DataBytesPerRow = diffwidth;
#if defined(DOSCODE)
numchunks = (((int32) diffwidth) * diffheight) / VGABytesPerPage;
if ((numchunks * VGABytesPerPage) < (((int32) diffwidth) * diffheight))
numchunks++;
#else
numchunks = (((int32) diffwidth) * diffheight) / 0x10000;
if ((uint32)(numchunks * 0x10000) < (uint32)(((int32) diffwidth) * diffheight))
numchunks++;
#endif
} else {
return;
}
processed += 8L + size;
for (header = 0; header < 8; header++)
RawDiffBM.Planes[header] = NULL;
if (headerdata.fps)
DelayMicros = ONESECOND / headerdata.fps;
if (PlayOnce) {
while (header != 65535)
diffNextFrame();
} else
diffNextFrame();
}
/*****************************************************************************/
/* Stops an animation from running. */
/*****************************************************************************/
void stopDiff(void) {
if (IsPlaying) {
StopPlaying = true;
/* NYI:
while (IsPlaying)
waitTOF();
*/
if (IsAnim)
blackScreen();
}
}
/*****************************************************************************/
/* Stops an animation from running. */
/*****************************************************************************/
void stopDiffEnd(void) {
if (IsPlaying) {
StopPlayingEnd = true;
while (IsPlaying) {
g_music->newCheckMusic();
diffNextFrame();
}
}
}
/*****************************************************************************/
/* Stops the continuous sound from playing. */
/*****************************************************************************/
void stopSound(void) {
stopsound = true;
}
/*****************************************************************************/
/* Checks the music while a diff is playing. */
/*****************************************************************************/
void diffSetMusic(void) {
return;
while (IsPlaying) {
waitTOF();
g_music->newCheckMusic();
}
}
/*****************************************************************************/
/* Reads in a DIFF file. */
/*****************************************************************************/
bool readDiff(bool playonce) {
PlayOnce = playonce;
playDiff();
return true;
}
static byte *mstart;
void readSound(void) {
uint32 header_ = 0, size_;
uint16 samplespeed_;
// uint16 numchunks = 1;
char temp_[5];
// bool FirstThru = true;
byte *storagefordifffile_, **difffile_ = &storagefordifffile_;
mstart = *startoffile; /* Make a copy of the pointer to the start of the file */
*difffile_ = mstart; /* Now can modify the file without modifying the original */
if (mstart == NULL)
return;
readBlock(temp_, 4L, difffile_);
temp_[4] = '\0';
readBlock(&header_, 4L, difffile_);
#if !defined(DOSCODE)
swapULongPtr(&header_, 1);
#endif
processed += 8L;
if (!((strcmp(temp_, "DIFF") == 0) && (header_ == 1219009121L)))
return;
readBlock(&header_, 4L, difffile_);
#if !defined(DOSCODE)
swapULongPtr(&header_, 1);
#endif
readBlock(&size_, 4L, difffile_);
#if !defined(DOSCODE)
swapULongPtr(&size_, 1);
#endif
if (header_ == 0)
skip(difffile_, size_);
else
return;
while (header_ != 65535) {
g_music->updateMusic();
readBlock(&header_, 4L, difffile_);
#if !defined(DOSCODE)
swapULongPtr(&header_, 1);
#endif
readBlock(&size_, 4L, difffile_);
#if !defined(DOSCODE)
swapULongPtr(&size_, 1);
#endif
if ((header_ == 30) || (header_ == 31)) {
if (mwaiteffect) {
while (EffectPlaying) {
g_music->updateMusic();
waitTOF();
}
}
size_ -= 8L;
skip(difffile_, 4L);
readBlock(&samplespeed_, 2L, difffile_);
#if !defined(DOSCODE)
swapUShortPtr(&samplespeed_, 1);
#endif
skip(difffile_, 2L);
byte *music = *difffile_;
uint32 musicsize = size_;
skip(difffile_, size_);
playMusic(samplespeed_, 64, musicsize, true, music);
} else if (header_ == 65535L) {
if (mwaiteffect) {
while (EffectPlaying) {
g_music->updateMusic();
waitTOF();
}
}
} else
skip(difffile_, size_);
}
}
} // End of namespace Lab

514
engines/lab/readparse.cpp Normal file
View File

@ -0,0 +1,514 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/labfun.h"
#include "lab/parsetypes.h"
#include "lab/parsefun.h"
#include "lab/storage.h"
#include "lab/stddefines.h"
namespace Lab {
#define MAXSTRINGLENGTH 250
static bool UseMemory = false;
/* Global parser data */
extern RoomData *Rooms;
extern InventoryData *Inventory;
extern uint16 NumInv, ManyRooms, HighestCondition, Direction;
extern LargeSet Conditions, RoomsFound;
static uint16 allocroom;
static bool rallocate(void **Ptr, uint32 Size) {
if (UseMemory)
return allocate(Ptr, Size);
else {
allocRoom(Ptr, (uint16) Size, allocroom);
return true;
}
}
/*****************************************************************************/
/* Reads in the RoomData. */
/*****************************************************************************/
bool readRoomData(const char *fileName) {
byte **file;
uint16 Counter;
char Temp[5];
if ((file = g_music->newOpen(fileName)) != NULL) {
readBlock(Temp, 4L, file);
Temp[4] = '\0';
if (strcmp(Temp, "DOR1") != 0)
return false;
readBlock(&ManyRooms, 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&ManyRooms, 1);
#endif
readBlock(&HighestCondition, 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&HighestCondition, 1);
#endif
if (allocate((void **) &Rooms, (ManyRooms + 1) * sizeof(RoomData))) {
for (Counter = 1; Counter <= ManyRooms; Counter++) {
readBlock(&(Rooms[Counter].NorthDoor), 2L, file);
readBlock(&(Rooms[Counter].SouthDoor), 2L, file);
readBlock(&(Rooms[Counter].EastDoor), 2L, file);
readBlock(&(Rooms[Counter].WestDoor), 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&(Rooms[Counter].NorthDoor), 1);
swapUShortPtr(&(Rooms[Counter].SouthDoor), 1);
swapUShortPtr(&(Rooms[Counter].EastDoor), 1);
swapUShortPtr(&(Rooms[Counter].WestDoor), 1);
#endif
readBlock(&(Rooms[Counter].WipeType), 1L, file);
}
} else
return false;
} else
return false;
return true;
}
/*****************************************************************************/
/* Reads in a NULL terminated string, and allocates memory for it. */
/*****************************************************************************/
static bool readString(char **string, byte **file) {
char len;
uint32 counter = 0L;
readBlock(&len, 1L, file);
if (len) {
counter = len;
if (rallocate((void **) string, counter)) {
readBlock(*string, counter, file);
(*string)[counter - 1] = 0; /* Sanity modification */
decrypt((byte *)*string);
return true;
}
} else {
*string = NULL;
return true;
}
return false;
}
/*****************************************************************************/
/* Reads in the Inventory data. */
/*****************************************************************************/
bool readInventory(const char *fileName) {
byte **file;
uint16 Counter;
char Temp[5];
if ((file = g_music->newOpen(fileName)) != NULL) {
readBlock(Temp, 4L, file);
Temp[4] = '\0';
if (strcmp(Temp, "INV1") != 0)
return false;
readBlock(&NumInv, 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&NumInv, 1);
#endif
UseMemory = true;
if (rallocate((void **) &Inventory, (NumInv + 1) * sizeof(InventoryData))) {
for (Counter = 1; Counter <= NumInv; Counter++) {
readBlock(&(Inventory[Counter].Many), 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&(Inventory[Counter].Many), 1);
#endif
if (!readString(&(Inventory[Counter].name), file)) {
UseMemory = false;
return false;
}
if (!readString(&(Inventory[Counter].BInvName), file)) {
UseMemory = false;
return false;
}
}
} else {
UseMemory = false;
return false;
}
} else
return false;
UseMemory = false;
return true;
}
/*****************************************************************************/
/* Converts a number to a string. */
/*****************************************************************************/
char *numtostr(char *text, uint16 Num) {
uint16 Counter = 0;
if (Num == 0) {
text[0] = '0';
text[1] = 0;
return text;
}
strcpy(text, "00000");
if (Num >= 10000) {
text[0] = (Num / 10000) + '0';
Num -= (Num / 10000) * 10000;
}
if (Num >= 1000) {
text[1] = (Num / 1000) + '0';
Num -= (Num / 1000) * 1000;
}
if (Num >= 100) {
text[2] = (Num / 100) + '0';
Num -= (Num / 100) * 100;
}
if (Num >= 10) {
text[3] = (Num / 10) + '0';
Num -= (Num / 10) * 10;
}
text[4] = Num + '0';
text[5] = 0;
while (text[Counter] == '0')
Counter++;
return (&text[Counter]);
}
/*****************************************************************************/
/* Reads in a list of conditions. */
/*****************************************************************************/
static int16 *readConditions(byte **file) {
int16 Counter = 0, last, list[25], *ptr;
do {
readBlock(&last, 2L, file);
#if !defined(DOSCODE)
swapUShortPtr((uint16 *)&last, 1);
#endif
if (Counter < 25) {
list[Counter] = last;
Counter++;
} else
list[Counter] = 0;
} while (last);
if (!rallocate((void **) & (ptr), Counter * 2L))
return NULL;
memcpy(ptr, list, (size_t)(Counter * 2L));
return ptr;
}
/*****************************************************************************/
/* Reads in some CloseUp data. */
/*****************************************************************************/
static bool readCloseUps(CloseDataPtr *CPtr, uint16 depth, byte **file) {
char c;
while (1) {
*CPtr = NULL;
readBlock(&c, 1L, file);
if (c != '\0') {
if (rallocate((void **) CPtr, sizeof(CloseData))) {
(*CPtr)->SubCloseUps = NULL;
(*CPtr)->NextCloseUp = NULL;
(*CPtr)->depth = depth;
readBlock(*CPtr, 10L, file);
#if !defined(DOSCODE)
swapUShortPtr((uint16 *)*CPtr, 5);
#endif
if (!readString(&((*CPtr)->GraphicName), file))
return false;
if (!readString(&((*CPtr)->Message), file))
return false;
if (!readCloseUps(&((*CPtr)->SubCloseUps), depth + 1, file))
return false;
CPtr = &((*CPtr)->NextCloseUp);
} else
return false;
} else
return true;
}
}
/*****************************************************************************/
/* Reads in a View. */
/*****************************************************************************/
static bool readView(ViewDataPtr *VPtr, byte **file) {
char c;
while (1) {
*VPtr = NULL;
readBlock(&c, 1L, file);
if (c == 1) {
if (rallocate((void **) VPtr, sizeof(viewData))) {
(*VPtr)->closeUps = NULL;
(*VPtr)->NextCondition = NULL;
(*VPtr)->Condition = readConditions(file);
if (!(*VPtr)->Condition)
return false;
if (!readString(&((*VPtr)->GraphicName), file))
return false;
readCloseUps(&((*VPtr)->closeUps), 0, file);
VPtr = &((*VPtr)->NextCondition);
} else
return false;
} else
return true;
}
}
/*****************************************************************************/
/* Reads in an Action. */
/*****************************************************************************/
static bool readAction(ActionPtr *APtr, byte **file) {
char c;
byte **ptrarray;
uint16 counter;
while (1) {
*APtr = NULL;
readBlock(&c, 1L, file);
if (c == 1) {
if (rallocate((void **) APtr, sizeof(Action))) {
readBlock(*APtr, 8L, file);
#if !defined(DOSCODE)
swapShortPtr((int16 *)*APtr, 4);
#endif
if ((*APtr)->ActionType == SHOWMESSAGES) {
if (!rallocate((void **) &ptrarray, 4L * (*APtr)->Param1))
return false;
for (counter = 0; counter < (*APtr)->Param1; counter++)
readString((char **) & (ptrarray[counter]), file);
(*APtr)->Data = (byte *)ptrarray;
} else
readString((char **) & ((*APtr)->Data), file);
APtr = &((*APtr)->NextAction);
} else
return false;
} else
return true;
}
}
/*****************************************************************************/
/* Reads in a rule. */
/*****************************************************************************/
static bool readRule(RulePtr *RPtr, byte **file) {
char c;
while (1) {
*RPtr = NULL;
readBlock(&c, 1L, file);
if (c == 1) {
if (rallocate((void **) RPtr, sizeof(Rule))) {
readBlock(*RPtr, 6L, file);
#if !defined(DOSCODE)
swapShortPtr((int16 *)*RPtr, 3);
#endif
(*RPtr)->Condition = readConditions(file);
if (!(*RPtr)->Condition)
return false;
readAction(&((*RPtr)->ActionList), file);
} else
return false;
RPtr = &((*RPtr)->NextRule);
} else
return true;
}
}
/*****************************************************************************/
/* Reads in the views of a room. */
/*****************************************************************************/
bool readViews(uint16 RoomNum, const char *Path) {
char Temp[10], *RoomString, fileName[250];
byte **file;
allocroom = RoomNum;
RoomString = numtostr(Temp, RoomNum);
strcpy(fileName, Path);
strcat(fileName, RoomString);
if ((file = g_music->newOpen(fileName)) != NULL) {
readBlock(Temp, 4L, file);
Temp[4] = '\0';
if (strcmp(Temp, "ROM4") != 0)
return false;
readString(&(Rooms[RoomNum].RoomMsg), file);
readView(&Rooms[RoomNum].NorthView, file);
g_music->checkMusic();
readView(&Rooms[RoomNum].SouthView, file);
g_music->checkMusic();
readView(&Rooms[RoomNum].EastView, file);
g_music->checkMusic();
readView(&Rooms[RoomNum].WestView, file);
g_music->checkMusic();
readRule(&Rooms[RoomNum].RuleList, file);
return true;
} else
return false;
return false;
}
/*****************************************************************************/
/* Reads the initial conditions and sets the LargeSet accordingly. */
/*****************************************************************************/
bool readInitialConditions(LargeSet conditions, const char *fileName) {
byte **file;
uint16 many, set;
char temp[5];
if ((file = g_music->newOpen(fileName)) != NULL) {
readBlock(temp, 4L, file);
temp[4] = '\0';
if (strcmp(temp, "CON0") != 0)
return false;
readBlock(&many, 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&many, 1);
#endif
for (int counter = 0; counter < many; counter++) {
readBlock(&set, 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&set, 1);
#endif
inclElement(conditions, set);
}
} else
return false;
return true;
}
} // End of namespace Lab

323
engines/lab/savegame.cpp Normal file
View File

@ -0,0 +1,323 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/labfun.h"
#include "lab/modernsavegame.h"
namespace Lab {
/* The version string */
#if defined(DOSCODE)
#define SAVEVERSION "LBS2"
#else
#define SAVEVERSION "LBS3"
#define SAVEVERSION_COMPAT "LBS2"
#endif
#define BOOKMARK 0
#define CARDMARK 1
#define FLOPPY 2
typedef void *LABFH;
#define INVALID_LABFH NULL
uint16 FileType, FileNum;
/*----- The Amiga specific area of saveGame.c -----*/
/*****************************************************************************/
/* Opens a file to write to from disk. */
/*****************************************************************************/
static LABFH saveGameOpen(char *filename, bool iswrite) {
warning("STUB: saveGameOpen");
return 0;
#if 0
if (iswrite) {
unlink(filename);
return fopen(filename, "wb");
} else
return fopen(filename, "rb");
#endif
}
/*****************************************************************************/
/* Closes a file. */
/*****************************************************************************/
static void saveGameClose(LABFH file, bool iswrite) {
warning("STUB: saveGameClose");
return;
#if 0
if (file != INVALID_LABFH)
fclose(file);
#endif
}
/*****************************************************************************/
/* Writes a block of memory to whatever it is that we're writing to. */
/*****************************************************************************/
static void saveGameWriteBlock(LABFH file, void *data, uint32 size) {
warning("STUB: saveGameWriteBlock");
return;
//fwrite(data, 1, size, file);
}
/*****************************************************************************/
/* Writes a block of memory to whatever it is that we're writing to. */
/*****************************************************************************/
static void saveGameReadBlock(LABFH file, void *data, uint32 size) {
warning("STUB: saveGameReadBlock");
return;
//fread(data, 1, size, file);
}
/*----- The machine independent section of saveGame.c -----*/
/* Lab: Labyrinth specific */
extern uint16 combination[6];
extern uint16 CurTile[4] [4];
#if !defined(DOSCODE)
extern CrumbData BreadCrumbs[MAX_CRUMBS];
extern uint16 NumCrumbs;
extern bool DroppingCrumbs;
extern bool FollowingCrumbs;
#endif
/*****************************************************************************/
/* Writes the game out to disk. */
/* Assumes that the file has already been openned and is there. */
/*****************************************************************************/
static bool saveGame(uint16 RoomNum, uint16 Direction, uint16 Quarters, LargeSet set1, LargeSet set2, LABFH file) {
#if !defined(DOSCODE)
uint16 temp;
CrumbData crumbs[sizeof(BreadCrumbs) / sizeof(CrumbData)];
#endif
uint16 last, counter, counter1;
char c;
saveGameWriteBlock(file, (void *)SAVEVERSION, 4L);
#if defined(DOSCODE)
saveGameWriteBlock(file, &RoomNum, 2L);
saveGameWriteBlock(file, &Direction, 2L);
saveGameWriteBlock(file, &Quarters, 2L);
#else
temp = swapUShort(RoomNum);
saveGameWriteBlock(file, &temp, 2L);
temp = swapUShort(Direction);
saveGameWriteBlock(file, &temp, 2L);
temp = swapUShort(Quarters);
saveGameWriteBlock(file, &temp, 2L);
#endif
last = set1->lastElement / 8;
saveGameWriteBlock(file, &(set1->array[0]), (uint32) last);
last = set2->lastElement / 8;
saveGameWriteBlock(file, &(set2->array[0]), (uint32) last);
/* LAB: the combination lock and tile stuff */
for (counter = 0; counter < 6; counter++) {
c = (char)combination[counter];
saveGameWriteBlock(file, &c, 1L);
}
for (counter = 0; counter < 4; counter++)
for (counter1 = 0; counter1 < 4; counter1++)
#if defined(DOSCODE)
saveGameWriteBlock(file, &(CurTile[counter] [counter1]), 2L);
#else
{
temp = swapUShort(CurTile[counter] [counter1]);
saveGameWriteBlock(file, &temp, 2L);
}
#endif
#if !defined(DOSCODE)
saveGameWriteBlock(file, g_SaveGameImage, SAVED_IMAGE_SIZE);
memcpy(crumbs, BreadCrumbs, sizeof BreadCrumbs);
swapUShortPtr(&crumbs[0].RoomNum, sizeof(BreadCrumbs) / sizeof(uint16));
saveGameWriteBlock(file, crumbs, sizeof BreadCrumbs);
#endif
saveGameClose(file, true);
return true;
}
/*****************************************************************************/
/* Reads the game from disk. */
/* Assumes that the file has already been openned and is there. */
/*****************************************************************************/
static bool loadGame(uint16 *RoomNum, uint16 *Direction, uint16 *Quarters, LargeSet set1, LargeSet set2, LABFH file) {
#if !defined(DOSCODE)
uint16 t;
CrumbData crumbs[sizeof(BreadCrumbs) / sizeof(CrumbData)];
#endif
char temp[5], c;
uint16 last, counter, counter1;
saveGameReadBlock(file, temp, 4L);
temp[4] = 0;
/*
if (strcmp(temp, SAVEVERSION) != 0)
{
saveGameClose(file, false);
return false;
}
*/
#if defined(DOSCODE)
saveGameReadBlock(file, RoomNum, 2L);
saveGameReadBlock(file, Direction, 2L);
saveGameReadBlock(file, Quarters, 2L);
#else
saveGameReadBlock(file, &t, 2L);
*RoomNum = swapUShort(t);
saveGameReadBlock(file, &t, 2L);
*Direction = swapUShort(t);
saveGameReadBlock(file, &t, 2L);
*Quarters = swapUShort(t);
#endif
last = set1->lastElement / 8;
saveGameReadBlock(file, &(set1->array[0]), (uint32) last);
last = set2->lastElement / 8;
saveGameReadBlock(file, &(set2->array[0]), (uint32) last);
/* LAB: the combination lock and tile stuff */
for (counter = 0; counter < 6; counter++) {
saveGameReadBlock(file, &c, 1L);
combination[counter] = c;
}
for (counter = 0; counter < 4; counter++)
for (counter1 = 0; counter1 < 4; counter1++)
#if defined(DOSCODE)
saveGameReadBlock(file, &(CurTile[counter] [counter1]), 2L);
#else
{
saveGameReadBlock(file, &t, 2L);
CurTile[counter] [counter1] = swapUShort(t);
}
#endif
if (strcmp(temp, SAVEVERSION) == 0) {
saveGameReadBlock(file, g_SaveGameImage, SAVED_IMAGE_SIZE);
memset(crumbs, 0, sizeof BreadCrumbs);
saveGameReadBlock(file, crumbs, sizeof BreadCrumbs);
swapUShortPtr(&crumbs[0].RoomNum, sizeof(BreadCrumbs) / sizeof(uint16));
memcpy(BreadCrumbs, crumbs, sizeof BreadCrumbs);
DroppingCrumbs = (BreadCrumbs[0].RoomNum != 0);
FollowingCrumbs = false;
for (counter = 0; counter < MAX_CRUMBS; counter++)
if (BreadCrumbs[counter].RoomNum == 0) break;
NumCrumbs = counter;
}
saveGameClose(file, false);
return true;
}
/*****************************************************************************/
/* Saves the game to the floppy disk. */
/*****************************************************************************/
bool saveFloppy(char *path, uint16 RoomNum, uint16 Direction, uint16 NumQuarters, LargeSet Conditions, LargeSet Rooms, uint16 filenum, uint16 type) {
LABFH FPtr;
g_music->checkMusic();
FileType = type;
FileNum = filenum;
if ((FPtr = saveGameOpen(path, true)) != INVALID_LABFH)
saveGame(RoomNum, Direction, NumQuarters, Conditions, Rooms, FPtr);
else
return false;
return true;
}
/*****************************************************************************/
/* Reads the game from the floppy disk. */
/*****************************************************************************/
bool readFloppy(char *path, uint16 *RoomNum, uint16 *Direction, uint16 *NumQuarters, LargeSet Conditions, LargeSet Rooms, uint16 filenum, uint16 type) {
LABFH FPtr;
g_music->checkMusic();
FileType = type;
FileNum = filenum;
if ((FPtr = saveGameOpen(path, false)) != INVALID_LABFH) {
if (!loadGame(RoomNum, Direction, NumQuarters, Conditions, Rooms, FPtr))
return false;
} else
return false;
return true;
}
} // End of namespace Lab

File diff suppressed because it is too large Load Diff

2219
engines/lab/special.cpp Normal file

File diff suppressed because it is too large Load Diff

105
engines/lab/stddefines.h Normal file
View File

@ -0,0 +1,105 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "common/system.h"
#include "common/debug.h"
#include "common/textconsole.h"
#ifndef LAB_STDDEFINES_H
#define LAB_STDDEFINES_H
namespace Lab {
#define IS_MACOSX 1
#define USE_SWAP 1
#define INCL(BITSET,BIT) ((BITSET) |= (BIT))
#define EXCL(BITSET,BIT) ((BITSET) &= (~(BIT)))
#define SETBIT(BITSET,BITNUM) INCL(BITSET, (1 << (BITNUM)))
#define UNSETBIT(BITSET,BITNUM) EXCL(BITSET, (1 << (BITNUM)))
#define INBIT(BITSET,BITNUM) ( ((1 << (BITNUM)) & (BITSET)) > 0 )
#if !defined(WIN32)
#ifndef min
#define min(a,b) ((a)<(b) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) ((a)>(b) ? (a) : (b))
#endif
#endif
#if defined(IS_MACOSX)
#define getTime Lab_GetTime
#define delay Lab_Delay
#endif
#if !defined(DOSCODE)
#if defined(USE_NOSWAP)
#define swapUShort(value) (value)
#define swapUShortPtr(ptr,count) (ptr)
#define swapShort(value) (value)
#define swapShortPtr(ptr,count) (ptr)
#define swapUInt(value) (value)
#define swapUIntPtr(ptr,count) (ptr)
#define swapInt(value) (value)
#define swapIntPtr(ptr,count) (ptr)
#define swapULong(value) (value)
#define swapULongPtr(ptr,count) (ptr)
#define swapLong(value) (value)
#define swapLongPtr(ptr,count) (ptr)
#elif defined(USE_SWAP)
uint16 swapUShort(uint16 value);
uint16 *swapUShortPtr(uint16 *ptr, int count);
int16 swapShort(int16 value);
int16 *swapShortPtr(int16 *ptr, int count);
unsigned int swapUInt(unsigned int value);
unsigned int *swapUIntPtr(unsigned int *ptr, int count);
int swapInt(int value);
int *swapIntPtr(int *ptr, int count);
uint32 swapULong(uint32 value);
uint32 *swapULongPtr(uint32 *ptr, int count);
int32 swapLong(int32 value);
int32 *swapLongPtr(int32 *ptr, int count);
#else
#error Please tell me about swapping bytes!
#endif
#endif
} // End of namespace Lab
#endif /* LAB_STDDEFINES_H */

89
engines/lab/storage.cpp Normal file
View File

@ -0,0 +1,89 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
namespace Lab {
/*****************************************************************************/
/* Allocates a chunk of memory. */
/*****************************************************************************/
bool allocate(void **Ptr, uint32 Size) {
(*Ptr) = malloc(Size);
if (*Ptr)
memset(*Ptr, 0, (size_t) Size);
return (*Ptr != NULL);
}
/*****************************************************************************/
/* Allocates a piece of chip memory. */
/*****************************************************************************/
bool allocatechip(void **Ptr, uint32 Size) {
return allocate(Ptr, Size);
}
/*****************************************************************************/
/* Allocates a chunk of dos memory. */
/*****************************************************************************/
bool allocatedos(void **Ptr, uint32 Size) {
#if defined(DOSCODE)
static union REGS regs;
regs.x.eax = 0x100;
regs.x.ebx = (Size >> 4);
int386(0x31, &regs, &regs);
if (regs.x.cflag) {
*Ptr = NULL;
return false;
}
*Ptr = (char *)((regs.x.eax & 0xFFFF) << 4);
return (*Ptr != NULL);
#else
*Ptr = malloc(Size);
return (*Ptr != NULL);
#endif
}
/*****************************************************************************/
/* Deallocates a piece of memory. */
/*****************************************************************************/
void deallocate(void *Ptr, uint32 Size) {
if (Ptr)
free(Ptr);
}
} // End of namespace Lab

48
engines/lab/storage.h Normal file
View File

@ -0,0 +1,48 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#ifndef LAB_STORAGE_H
#define LAB_STORAGE_H
namespace Lab {
bool allocate(void **Ptr, uint32 Size);
bool allocatechip(void **Ptr, uint32 Size);
bool allocatedos(void **Ptr, uint32 Size);
void deallocate(void *Ptr, uint32 Size);
} // End of namespace Lab
#endif /* LAB_STORAGE_H */

293
engines/lab/text.cpp Normal file
View File

@ -0,0 +1,293 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/labfun.h"
#include "lab/storage.h"
#include "lab/text.h"
#include "lab/vga.h"
namespace Lab {
/*****************************************************************************/
/* Opens up a font from disk, but uses buffer memory to store it in. */
/*****************************************************************************/
bool openFontMem(const char *TextFontPath, struct TextFont *tf, byte *fontbuffer) {
byte **file = NULL;
char header[5];
int32 filesize, headersize = 4L + 2L + 256 * 3 + 4L;
filesize = sizeOfFile(TextFontPath);
file = g_music->newOpen(TextFontPath);
if ((file != NULL) && (filesize > headersize)) {
header[4] = 0;
readBlock(&header, 4L, file);
if (strcmp(header, "VGAF") == 0) {
tf->DataLength = filesize - headersize;
readBlock(&(tf->Height), 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&(tf->Height), 1);
#endif
readBlock(tf->Widths, 256L, file);
readBlock(tf->Offsets, 256L * 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(tf->Offsets, 256);
#endif
skip(file, 4L);
tf->data = fontbuffer;
readBlock(tf->data, tf->DataLength, file);
return true;
}
}
return false;
}
/*****************************************************************************/
/* Opens up a font from disk. */
/*****************************************************************************/
bool openFont(const char *TextFontPath, struct TextFont **tf) {
byte **file = NULL;
char header[5];
int32 filesize, headersize = 4L + 2L + 256 * 3 + 4L;
if (allocate((void **)tf, sizeof(struct TextFont))) {
filesize = sizeOfFile(TextFontPath);
file = g_music->newOpen(TextFontPath);
if ((file != NULL) && (filesize > headersize)) {
header[4] = 0;
readBlock(&header, 4L, file);
if (strcmp(header, "VGAF") == 0) {
(*tf)->DataLength = filesize - headersize;
readBlock(&((*tf)->Height), 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&((*tf)->Height), 1);
#endif
readBlock((*tf)->Widths, 256L, file);
readBlock((*tf)->Offsets, 256L * 2L, file);
#if !defined(DOSCODE)
swapUShortPtr((*tf)->Offsets, 256);
#endif
skip(file, 4L);
if (allocate((void **) & ((*tf)->data), (*tf)->DataLength)) {
readBlock((*tf)->data, (*tf)->DataLength, file);
return true;
}
}
}
deallocate(*tf, sizeof(struct TextFont));
}
*tf = NULL;
return false;
}
/*****************************************************************************/
/* Closes a font and frees all memory associated with it. */
/*****************************************************************************/
void closeFont(struct TextFont *tf) {
if (tf) {
if (tf->data && tf->DataLength)
deallocate(tf->data, tf->DataLength);
deallocate(tf, sizeof(struct TextFont));
}
}
/*****************************************************************************/
/* Returns the length of a text in the specified font. */
/*****************************************************************************/
uint16 textLength(struct TextFont *tf, const char *text, uint16 numchars) {
uint16 counter, length = 0;
if (tf)
for (counter = 0; counter < numchars; counter++) {
length += tf->Widths[(uint)*text];
text++;
}
return length;
}
/*****************************************************************************/
/* Returns the height of a specified font. */
/*****************************************************************************/
uint16 textHeight(struct TextFont *tf) {
if (tf)
return tf->Height;
else
return 0;
}
extern uint32 VGAScreenWidth, VGABytesPerPage;
/*****************************************************************************/
/* Draws the text to the screen. */
/*****************************************************************************/
void text(struct TextFont *tf, uint16 x, uint16 y, uint16 color, const char *text, uint16 numchars) {
byte *VGATop, *VGACur, *VGATemp, *VGATempLine, *cdata;
uint32 RealOffset, SegmentOffset;
int32 templeft, LeftInSegment;
uint16 counter, counterb, bwidth, mask, curpage, rows, cols, data;
VGATop = getVGABaseAddr();
for (counter = 0; counter < numchars; counter++) {
RealOffset = (VGAScreenWidth * y) + x;
curpage = RealOffset / VGABytesPerPage;
SegmentOffset = RealOffset - (curpage * VGABytesPerPage);
LeftInSegment = VGABytesPerPage - SegmentOffset;
VGACur = VGATop + SegmentOffset;
setPage(curpage);
if (tf->Widths[(uint)*text]) {
cdata = tf->data + tf->Offsets[(uint)*text];
bwidth = *cdata;
cdata++;
VGATemp = VGACur;
VGATempLine = VGACur;
for (rows = 0; rows < tf->Height; rows++) {
VGATemp = VGATempLine;
templeft = LeftInSegment;
for (cols = 0; cols < bwidth; cols++) {
data = *cdata;
cdata++;
if (data && (templeft >= 8)) {
if (0x80 & data)
*VGATemp = color;
VGATemp++;
if (0x40 & data)
*VGATemp = color;
VGATemp++;
if (0x20 & data)
*VGATemp = color;
VGATemp++;
if (0x10 & data)
*VGATemp = color;
VGATemp++;
if (0x08 & data)
*VGATemp = color;
VGATemp++;
if (0x04 & data)
*VGATemp = color;
VGATemp++;
if (0x02 & data)
*VGATemp = color;
VGATemp++;
if (0x01 & data)
*VGATemp = color;
VGATemp++;
templeft -= 8;
} else if (data) {
mask = 0x80;
templeft = LeftInSegment;
for (counterb = 0; counterb < 8; counterb++) {
if (templeft <= 0) {
curpage++;
setPage(curpage);
VGATemp = (byte *)(VGATop - templeft);
/* Set up VGATempLine for next line */
VGATempLine -= VGABytesPerPage;
/* Set up LeftInSegment for next line */
LeftInSegment += VGABytesPerPage + templeft;
templeft += VGABytesPerPage;
}
if (mask & data)
*VGATemp = color;
VGATemp++;
mask = mask >> 1;
templeft--;
}
} else {
templeft -= 8;
VGATemp += 8;
}
}
VGATempLine += VGAScreenWidth;
LeftInSegment -= VGAScreenWidth;
if (LeftInSegment <= 0) {
curpage++;
setPage(curpage);
VGATempLine -= VGABytesPerPage;
LeftInSegment += VGABytesPerPage;
}
}
}
x += tf->Widths[(int)*text];
text++;
}
#if !defined(DOSCODE)
ungetVGABaseAddr();
#endif
}
} // End of namespace Lab

69
engines/lab/text.h Normal file
View File

@ -0,0 +1,69 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#ifndef LAB_TEXT_H
#define LAB_TEXT_H
#include "lab/stddefines.h"
namespace Lab {
#if defined(WIN32)
#pragma pack(push, 1)
#endif
struct TextFont {
uint32 DataLength;
uint16 Height;
byte Widths[256];
uint16 Offsets[256];
byte *data;
};
#if defined(WIN32)
#pragma pack(pop)
#endif
bool openFontMem(const char *TextFontPath, struct TextFont *tf, byte *fontbuffer);
bool openFont(const char *TextFontPath, struct TextFont **tf);
void closeFont(struct TextFont *tf);
uint16 textLength(struct TextFont *tf, const char *text, uint16 numchars);
uint16 textHeight(struct TextFont *tf);
void text(struct TextFont *tf, uint16 x, uint16 y, uint16 color, const char *text, uint16 numchars);
} // End of namespace Lab
#endif /* LAB_TEXT_H */

147
engines/lab/timing.cpp Normal file
View File

@ -0,0 +1,147 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#include "lab/timing.h"
#include "lab/vga.h"
namespace Lab {
/*****************************************************************************/
/* Waits for for Secs seconds and Micros microseconds to pass. */
/*****************************************************************************/
void microDelay(uint32 secs, uint32 micros) {
uint32 waitSecs, waitMicros;
addCurTime(secs, micros, &waitSecs, &waitMicros);
while (1) {
getTime(&secs, &micros);
if ((secs > waitSecs) || ((secs == waitSecs) && (micros >= waitMicros)))
return;
g_system->delayMillis(10);
}
}
/*****************************************************************************/
/* Gets the current system time. */
/*****************************************************************************/
void getTime(uint32 *secs, uint32 *micros) {
uint32 t = g_system->getMillis();
*secs = t / 1000;
*micros = t % 1000;
}
/*****************************************************************************/
/* Adds seconds and microseconds to current time to get a new time. */
/*****************************************************************************/
void addCurTime(uint32 sec, uint32 micros, uint32 *timeSec, uint32 *timeMicros) {
getTime(timeSec, timeMicros);
(*timeSec) += sec;
(*timeMicros) += micros;
if (*timeMicros >= ONESECOND) {
(*timeSec)++;
(*timeMicros) -= ONESECOND;
}
}
/*****************************************************************************/
/* Finds the difference between time1 and time2. If time1 is later than */
/* time2, returns 0. */
/*****************************************************************************/
void anyTimeDiff(uint32 sec1, uint32 micros1, uint32 sec2, uint32 micros2, uint32 *diffSecs, uint32 *diffMicros) {
*diffSecs = 0;
*diffMicros = 0;
if (sec1 > sec2)
return;
else if ((sec1 == sec2) && (micros1 >= micros2))
return;
if (micros1 > micros2) {
*diffSecs = sec2 - sec1 - 1;
*diffMicros = (ONESECOND - micros1) + micros2;
} else {
*diffSecs = sec2 - sec1;
*diffMicros = micros2 - micros1;
}
}
/*****************************************************************************/
/* Finds the difference between the current time, and a future time. Returns */
/* 0 if the future time is actually before the current time. */
/*****************************************************************************/
void timeDiff(uint32 sec, uint32 micros, uint32 *diffSec, uint32 *diffMicros) {
uint32 curSec, curMicros;
*diffSec = 0;
*diffMicros = 0;
getTime(&curSec, &curMicros);
if (curSec > sec) /* Already passed the time */
return;
else if ((curSec == sec) && (curMicros >= micros)) /* Already passed the time */
return;
if (curMicros > micros) {
*diffSec = sec - curSec - 1;
*diffMicros = (ONESECOND - curMicros) + micros;
} else {
*diffSec = sec - curSec;
*diffMicros = micros - curMicros;
}
}
/*****************************************************************************/
/* Waits for a specified time to occur. */
/*****************************************************************************/
void waitForTime(uint32 sec, uint32 micros) {
uint32 curSec, curMicros;
getTime(&curSec, &curMicros);
if (curSec > sec)
return;
else if ((curSec == sec) && (curMicros >= micros))
return;
if (curMicros > micros)
microDelay(sec - curSec - 1, (ONESECOND - curMicros) + micros - 1);
else
microDelay(sec - curSec, micros - curMicros - 1);
}
} // End of namespace Lab

47
engines/lab/timing.h Normal file
View File

@ -0,0 +1,47 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#ifndef LAB_TIMING_H
#define LAB_TIMING_H
namespace Lab {
#define ONESECOND 1000
void microDelay(uint32 secs, uint32 micros);
void getTime(uint32 *secs, uint32 *micros);
void addCurTime(uint32 sec, uint32 micros, uint32 *timeSec, uint32 *timeMicros);
void anyTimeDiff(uint32 sec1, uint32 micros1, uint32 sec2, uint32 micros2, uint32 *diffSecs, uint32 *diffMicros);
void timeDiff(uint32 sec, uint32 micros, uint32 *diffSec, uint32 *diffMicros);
void waitForTime(uint32 sec, uint32 micros);
} // End of namespace Lab
#endif /* LAB_TIMING_H */

498
engines/lab/undiff.cpp Normal file
View File

@ -0,0 +1,498 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
namespace Lab {
extern uint16 DataBytesPerRow;
/*****************************************************************************/
/* Copies memory. */
/*****************************************************************************/
#define turbocopymem(Dest, Source, Len) (memcpy(Dest, Source, Len))
static void copytwo(byte *Dest, byte *Source) {
#if defined(USE_SWAP)
Dest[1] = Source[0];
Dest[0] = Source[1];
#else
*Dest = *Source;
Dest++;
Source++;
*Dest = *Source;
#endif
}
/*------------------------ unDiff Horizontal Memory -------------------------*/
/*****************************************************************************/
/* Undiffs a piece of memory when header size is a byte, and copy/skip size */
/* is also a byte. */
/*****************************************************************************/
static void unDIFFByteByte(byte *Dest, byte *diff) {
uint16 skip, copy;
while (1) {
skip = *diff;
diff++;
copy = *diff;
diff++;
if (skip == 255) {
if (copy == 0) {
copytwo((byte *) &skip, diff);
diff += 2;
copytwo((byte *) &copy, diff);
diff += 2;
} else if (copy == 255)
return;
}
Dest += skip;
turbocopymem(Dest, diff, copy);
Dest += copy;
diff += copy;
}
}
/*****************************************************************************/
/* Undiffs a piece of memory when header size is a byte, and copy/skip size */
/* is a word. */
/*****************************************************************************/
static void unDIFFByteWord(uint16 *Dest, uint16 *diff) {
uint16 skip, copy;
while (1) {
skip = ((byte *)diff)[0];
copy = ((byte *)diff)[1];
diff++;
if (skip == 255) {
if (copy == 0) {
skip = swapUShort(*diff);
diff++;
copy = swapUShort(*diff);
diff++;
} else if (copy == 255)
return;
}
Dest += skip;
while (copy > 3) {
*Dest = *diff; //swapUShort(*diff);
Dest++;
diff++;
*Dest = *diff; //swapUShort(*diff);
Dest++;
diff++;
*Dest = *diff; //swapUShort(*diff);
Dest++;
diff++;
*Dest = *diff; //swapUShort(*diff);
Dest++;
diff++;
copy -= 4;
}
while (copy) {
*Dest = *diff; //swapUShort(*diff);
Dest++;
diff++;
copy--;
}
}
}
#ifdef undef
/*****************************************************************************/
/* Undiffs a piece of memory when header size is a byte, and copy/skip size */
/* is a long word. */
/*****************************************************************************/
static void unDIFFByteLong(byte *Dest, byte *diff) {
uint16 skip, copy;
while (1) {
skip = *diff << 2;
diff++;
copy = *diff << 2;
diff++;
if (skip == (255 << 2)) {
if (copy == 0) {
skip = swapUShort(*((uint16 *) diff)) << 2;
diff += 2;
copy = swapUShort(*((uint16 *) diff) << 2;
diff += 2;
} else if (copy == (255 << 2))
return;
}
Dest += skip;
turbocopymem(Dest, diff, copy);
Dest += copy;
diff += copy;
}
}
#endif
/*****************************************************************************/
/* UnDiffs a coded DIFF string onto an already initialized piece of memory. */
/*****************************************************************************/
bool unDIFFMemory(byte *Dest, byte *diff, uint16 HeaderSize, uint16 CopySize) {
if (HeaderSize == 1) {
if (CopySize == 1)
unDIFFByteByte(Dest, diff);
else if (CopySize == 2)
unDIFFByteWord((uint16 *)Dest, (uint16 *)diff);
#ifdef undef
else if (CopySize == 4)
unDIFFByteLong((uint32 *)Dest, (uint32 *)diff);
#endif
else
return false;
}
/*
else if (HeaderSize == 2)
{
if (CopySize == 1)
unDIFFWordByte(Dest, diff);
else if (CopySize == 2)
unDIFFWordWord(Dest, diff);
else if (CopySize == 4)
unDIFFWordLong(Dest, diff);
else
return false;
}
*/
else
return (false);
return true;
}
/*------------------------- unDiff Vertical Memory --------------------------*/
/*****************************************************************************/
/* Undiffs a piece of memory when header size is a byte, and copy/skip size */
/* is a byte. */
/*****************************************************************************/
static void VUnDIFFByteByte(byte *Dest, byte *diff, uint16 bytesperrow) {
byte *CurPtr;
uint16 skip, copy;
uint16 counter = 0;
while (counter < DataBytesPerRow) {
CurPtr = Dest + counter;
for (;;) {
skip = *diff;
diff++;
copy = *diff;
diff++;
if (skip == 255) {
counter += copy;
break;
}
else {
CurPtr += (skip * bytesperrow);
while (copy) {
copy--;
*CurPtr = *diff;
CurPtr += bytesperrow;
diff++;
}
}
}
}
}
/*****************************************************************************/
/* Undiffs a piece of memory when header size is a byte, and copy/skip size */
/* is a word. */
/*****************************************************************************/
static void VUnDIFFByteWord(uint16 *Dest, uint16 *diff, uint16 bytesperrow) {
uint16 *CurPtr;
uint16 skip, copy;
uint16 counter = 0, wordsperrow;
wordsperrow = bytesperrow / 2;
while (counter < (DataBytesPerRow >> 1)) {
CurPtr = Dest + counter;
for (;;) {
skip = ((byte *)diff)[0];
copy = ((byte *)diff)[1];
diff++;
if (skip == 255) {
counter += copy;
break;
}
else {
CurPtr += (skip * wordsperrow);
while (copy) {
*CurPtr = *diff; //swapUShort(*diff);
CurPtr += wordsperrow;
diff++;
copy--;
}
}
}
}
}
/*****************************************************************************/
/* Undiffs a piece of memory when header size is a byte, and copy/skip size */
/* is a long. */
/*****************************************************************************/
static void VUnDIFFByteLong(uint32 *Dest, uint32 *diff, uint16 bytesperrow) {
uint32 *CurPtr;
uint16 skip, copy;
uint16 counter = 0, longsperrow;
byte *diff1 = (byte *)diff;
longsperrow = bytesperrow / 4;
while (counter < (DataBytesPerRow >> 2)) {
CurPtr = Dest + counter;
for (;;) {
skip = *diff1;
diff1++;
copy = *diff1;
diff1++;
if (skip == 255) {
counter += copy;
break;
}
else {
CurPtr += (skip * longsperrow);
while (copy) {
*CurPtr = *(uint32 *)diff1; //swapULong(*diff);
CurPtr += longsperrow;
diff1 += 4;
copy--;
}
}
}
}
}
/*****************************************************************************/
/* UnDiffs a coded DIFF string onto an already initialized piece of memory. */
/*****************************************************************************/
bool VUnDIFFMemory(byte *Dest, byte *diff, uint16 HeaderSize, uint16 CopySize, uint16 bytesperrow) {
if (HeaderSize == 1) {
if (CopySize == 1)
VUnDIFFByteByte(Dest, diff, bytesperrow);
else if (CopySize == 2)
VUnDIFFByteWord((uint16 *)Dest, (uint16 *)diff, bytesperrow);
else if (CopySize == 4)
VUnDIFFByteLong((uint32 *)Dest, (uint32 *)diff, bytesperrow);
else
return false;
}
/*
else if (HeaderSize == 2)
{
if (CopySize == 1)
VUnDIFFWordByte(Dest, diff, bytesperrow);
else if (CopySize == 2)
VUnDIFFWordWord(Dest, diff, bytesperrow);
else if (CopySize == 4)
VUnDIFFWordLong(Dest, diff, bytesperrow);
else
return false;
}
*/
else
return (false);
return true;
}
/*---------------------------- Runlength Decodes ----------------------------*/
/*****************************************************************************/
/* Runlength decodes a chunk of memory. */
/*****************************************************************************/
void runLengthDecode(byte *Dest, byte *Source) {
int8 num;
int16 count;
while (1) {
num = (int8)*Source;
Source++;
if (num == 127) {
return;
} else if (num > '\0') {
turbocopymem(Dest, Source, num);
Source += num;
Dest += num;
} else {
count = (int16)(-num);
num = *Source;
Source++;
while (count) {
*Dest = num;
Dest++;
count--;
}
}
}
}
/*****************************************************************************/
/* Does a vertical run length decode. */
/*****************************************************************************/
void VRunLengthDecode(byte *Dest, byte *Source, uint16 bytesperrow) {
int8 num;
int16 count;
uint16 Counter;
byte *Top;
Top = Dest;
for (Counter = 0; Counter < DataBytesPerRow; Counter++) {
Dest = Top;
Dest += Counter;
num = (int8)*Source;
Source++;
while (num != 127) {
if (num > '\0') {
while (num) {
*Dest = *Source;
Source++;
Dest += bytesperrow;
num--;
}
} else {
count = (int16)(-num);
num = (int8)*Source;
Source++;
while (count) {
*Dest = num;
Dest += bytesperrow;
count--;
}
}
num = *Source;
Source++;
}
}
}
} // End of namespace Lab

1082
engines/lab/vga.cpp Normal file

File diff suppressed because it is too large Load Diff

100
engines/lab/vga.h Normal file
View File

@ -0,0 +1,100 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/stddefines.h"
#ifndef LAB_VGA_H
#define LAB_VGA_H
namespace Lab {
struct Image {
uint16 Width;
uint16 Height;
byte *ImageData;
};
void setMode(char mode);
void getMode(uint16 *Mode);
void setPage(uint16 PageNum);
void VGAStorePage(void);
void VGARestorePage(void);
bool createScreen(bool HiRes);
void waitTOF(void);
void quickWaitTOF(void);
byte *getVGABaseAddr(void);
#if !defined(DOSCODE)
void ungetVGABaseAddr();
#endif
void writeColorReg(char *buf, uint16 regnum);
void writeColorRegs(char *buf, uint16 first, uint16 numreg);
void writeColorRegsSmooth(char *buf, uint16 first, uint16 numreg);
void VGASetPal(void *cmap, uint16 numcolors);
/*---------- Drawing Routines ----------*/
void drawImage(struct Image *Im, uint16 x, uint16 y);
void drawMaskImage(struct Image *Im, uint16 x, uint16 y);
void readScreenImage(struct Image *Im, uint16 x, uint16 y);
void bltBitMap(struct Image *ImSource, uint16 xs, uint16 ys, struct Image *ImDest, uint16 xd, uint16 yd, uint16 width, uint16 height);
void scrollDisplayX(int16 dx, uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void scrollDisplayY(int16 dy, uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void setAPen(uint16 pennum);
void drawHLine(uint16 x, uint16 y1, uint16 y2);
void drawVLine(uint16 x1, uint16 y, uint16 x2);
void rectFill(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void ghoastRect(uint16 pencolor, uint16 x1, uint16 y1, uint16 x2, uint16 y2);
} // End of namespace Lab
#endif /* LAB_VGA_H */