LAB: Rewrite picture handling and get rid of the memory manager

This commit is contained in:
Filippos Karapetis 2015-12-04 21:18:41 +02:00 committed by Willem Jan Palenstijn
parent d376fd8dd0
commit a182a6af1a
13 changed files with 79 additions and 378 deletions

View File

@ -586,7 +586,7 @@ void Anim::diffNextFrame() {
/*****************************************************************************/
/* A separate task launched by readDiff. Plays the DIFF. */
/*****************************************************************************/
void Anim::playDiff() {
void Anim::playDiff(byte *buffer) {
_waitSec = 0L;
_waitMicros = 0L;
_delayMicros = 0L;
@ -605,7 +605,7 @@ void Anim::playDiff() {
_vm->_graphics->blackScreen();
}
_start = *startoffile; /* Make a copy of the pointer to the start of the file */
_start = buffer; /* 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) {
@ -709,9 +709,9 @@ void Anim::stopSound() {
/*****************************************************************************/
/* Reads in a DIFF file. */
/*****************************************************************************/
bool Anim::readDiff(bool playOnce) {
bool Anim::readDiff(byte *buffer, bool playOnce) {
_playOnce = playOnce;
playDiff();
playDiff(buffer);
return true;
}

View File

@ -114,14 +114,13 @@ public:
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);
bool readDiff(bool playOnce);
bool readDiff(byte *buffer, bool playOnce);
void playDiff(byte *buffer);
void diffNextFrame();
void readSound(bool waitTillFinished, Common::File *file);
void stopDiff();
void stopDiffEnd();
void stopSound();
void playDiff();
};
} // End of namespace Lab

View File

@ -1057,22 +1057,14 @@ void LabEngine::go() {
_isHiRes = ((getFeatures() & GF_LOWRES) == 0);
bool mem = false;
if (initBuffer(BUFFERSIZE, true)) {
mem = true;
} else {
warning("initBuffer() failed");
return;
}
if (!_graphics->setUpScreens()) {
_isHiRes = false;
mem = mem && _graphics->setUpScreens();
_graphics->setUpScreens();
}
_event->initMouse();
mem = mem && initRoomBuffer();
initRoomBuffer();
if (!doIntro)
_music->initMusic();
@ -1081,18 +1073,15 @@ void LabEngine::go() {
_event->mouseHide();
if (doIntro && mem) {
if (doIntro) {
Intro *intro = new Intro(this);
intro->introSequence();
delete intro;
} else
_anim->_doBlack = true;
if (mem) {
_event->mouseShow();
mainGameLoop();
} else
debug("\n\nNot enough memory to start game.\n\n");
_event->mouseShow();
mainGameLoop();
if (QuitLab) { /* Won the game */
_graphics->blackAllScreen();
@ -1117,7 +1106,7 @@ void LabEngine::go() {
closeFont(_msgFont);
freeRoomBuffer();
freeBuffer();
_graphics->freePict();
freeScreens();

View File

@ -48,6 +48,11 @@ DisplayMan::DisplayMan(LabEngine *vm) : _vm(vm) {
_screenBytesPerPage = 65536;
_curapen = 0;
_curBitmap = NULL;
}
DisplayMan::~DisplayMan() {
freePict();
}
/*****************************************************************************/
@ -103,26 +108,32 @@ uint16 DisplayMan::SVGACord(uint16 cord) {
/*------ From readPict.c. Reads in pictures and animations from disk. ------*/
/*---------------------------------------------------------------------------*/
void DisplayMan::loadPict(const char *filename) {
Common::File *bitmapFile = _vm->_resource->openDataFile(filename);
freePict();
_curBitmap = new byte[bitmapFile->size()];
bitmapFile->read(_curBitmap, bitmapFile->size());
delete bitmapFile;
}
/*****************************************************************************/
/* Reads in a picture into the dest bitmap. */
/*****************************************************************************/
bool DisplayMan::readPict(const char *filename, bool playOnce) {
_vm->_anim->stopDiff();
byte **file = _vm->_music->newOpen(filename);
loadPict(filename);
if (file == NULL) {
if ((filename[0] == 'p') || (filename[0] == 'P'))
blackScreen();
_vm->_music->updateMusic();
return false;
}
if (!_vm->_music->_doNotFilestopSoundEffect)
_vm->_music->stopSoundEffect();
DispBitMap->_bytesPerRow = _vm->_screenWidth;
DispBitMap->_rows = _vm->_screenHeight;
DispBitMap->_flags = BITMAPF_VIDEO;
_vm->_anim->readDiff(playOnce);
_vm->_anim->readDiff(_curBitmap, playOnce);
return true;
}
@ -131,30 +142,32 @@ bool DisplayMan::readPict(const char *filename, bool playOnce) {
/* Reads in a picture into buffer memory. */
/*****************************************************************************/
byte *DisplayMan::readPictToMem(const char *filename, uint16 x, uint16 y) {
byte *mem;
_vm->_anim->stopDiff();
allocFile((void **)&mem, (int32)x * (int32)y, "Bitmap");
byte *curMem = mem;
loadPict(filename);
byte **file = _vm->_music->newOpen(filename);
_vm->_music->updateMusic();
if (file == NULL)
return NULL;
if (!_vm->_music->_doNotFilestopSoundEffect)
_vm->_music->stopSoundEffect();
DispBitMap->_bytesPerRow = x;
DispBitMap->_rows = y;
DispBitMap->_flags = BITMAPF_NONE;
DispBitMap->_planes[0] = curMem;
DispBitMap->_planes[0] = _curBitmap;
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;
_vm->_anim->readDiff(true);
_vm->_anim->readDiff(_curBitmap, true);
return mem;
return _curBitmap;
}
void DisplayMan::freePict() {
delete _curBitmap;
_curBitmap = NULL;
}
/*****************************************************************************/
@ -413,16 +426,15 @@ void DisplayMan::drawMessage(const char *str) {
/* Scrolls the display to black. */
/*****************************************************************************/
void DisplayMan::doScrollBlack() {
byte *mem, *tempmem;
byte *tempmem;
Image im;
uint32 size, copysize;
uint32 *baseAddr;
_vm->_event->mouseHide();
uint16 width = VGAScaleX(320);
uint16 height = VGAScaleY(149) + SVGACord(2);
byte *mem = new byte[width * height];
allocFile((void **)&mem, (int32)width * (int32)height, "Temp Mem");
_vm->_event->mouseHide();
im._width = width;
im._height = height;
@ -479,7 +491,8 @@ void DisplayMan::doScrollBlack() {
}
}
freeAllStolenMem();
delete[] mem;
freePict();
_vm->_event->mouseShow();
}

View File

@ -40,20 +40,20 @@ private:
LabEngine *_vm;
byte _curapen;
byte *_curBitmap;
public:
bool _longWinInFront;
bool _lastMessageLong;
uint32 _screenBytesPerPage;
DisplayMan(LabEngine *lab);
virtual ~DisplayMan();
uint16 scaleX(uint16 x);
uint16 scaleY(uint16 y);
int16 VGAScaleX(int16 x);
int16 VGAScaleY(int16 y);
uint16 SVGACord(uint16 cord);
void loadPict(const char *filename);
bool readPict(const char *filename, bool playOnce);
void freePict();
byte *readPictToMem(const char *filename, uint16 x, uint16 y);
void doScrollBlack();
void copyPage(uint16 width, uint16 height, uint16 nheight, uint16 startline, byte *mem);
@ -101,6 +101,10 @@ public:
void drawVLine(uint16 x1, uint16 y, uint16 x2);
void screenUpdate();
bool createScreen(bool HiRes);
bool _longWinInFront;
bool _lastMessageLong;
uint32 _screenBytesPerPage;
};
} // End of namespace Lab

View File

@ -85,39 +85,37 @@ void Intro::doPictText(const char *filename, TextFont *msgFont, bool isScreen) {
uint32 lastSecs = 0L, lastMicros = 0L, secs = 0L, micros = 0L;
IntuiMessage *msg;
byte *curPlace, **tFile;
bool drawNextText = true, end = false, begin = true;
int32 cls, code, Drawn;
int16 qualifier;
Common::File *textFile = g_lab->_resource->openDataFile(path);
byte *textBuffer = new byte[textFile->size()];
textFile->read(textBuffer, textFile->size());
delete textFile;
byte *curText = textBuffer;
while (1) {
if (drawNextText) {
if (begin) {
if (begin)
begin = false;
tFile = _vm->_music->newOpen(path);
if (!tFile)
return;
curPlace = *tFile;
} else if (isScreen)
else if (isScreen)
fade(false, 0);
if (isScreen) {
_vm->_graphics->setAPen(7);
_vm->_graphics->rectFill(_vm->_graphics->VGAScaleX(10), _vm->_graphics->VGAScaleY(10), _vm->_graphics->VGAScaleX(310), _vm->_graphics->VGAScaleY(190));
Drawn = _vm->_graphics->flowText(msgFont, (!_vm->_isHiRes) * -1, 5, 7, false, false, true, true, _vm->_graphics->VGAScaleX(14), _vm->_graphics->VGAScaleY(11), _vm->_graphics->VGAScaleX(306), _vm->_graphics->VGAScaleY(189), (char *)curPlace);
Drawn = _vm->_graphics->flowText(msgFont, (!_vm->_isHiRes) * -1, 5, 7, false, false, true, true, _vm->_graphics->VGAScaleX(14), _vm->_graphics->VGAScaleY(11), _vm->_graphics->VGAScaleX(306), _vm->_graphics->VGAScaleY(189), (char *)curText);
fade(true, 0);
} else {
Drawn = _vm->_graphics->longDrawMessage((char *)curPlace);
Drawn = _vm->_graphics->longDrawMessage((char *)curText);
}
curPlace += Drawn;
curText += Drawn;
end = (*curPlace == 0);
end = (*curText == 0);
drawNextText = false;
introEatMessages();
@ -126,6 +124,7 @@ void Intro::doPictText(const char *filename, TextFont *msgFont, bool isScreen) {
if (isScreen)
fade(false, 0);
delete[] textBuffer;
return;
}
@ -145,6 +144,7 @@ void Intro::doPictText(const char *filename, TextFont *msgFont, bool isScreen) {
if (isScreen)
fade(false, 0);
delete[] textBuffer;
return;
} else {
drawNextText = true;
@ -164,6 +164,7 @@ void Intro::doPictText(const char *filename, TextFont *msgFont, bool isScreen) {
if (isScreen)
fade(false, 0);
delete[] textBuffer;
return;
}
@ -173,6 +174,7 @@ void Intro::doPictText(const char *filename, TextFont *msgFont, bool isScreen) {
if (isScreen)
fade(false, 0);
delete[] textBuffer;
return;
} else
drawNextText = true;
@ -184,6 +186,7 @@ void Intro::doPictText(const char *filename, TextFont *msgFont, bool isScreen) {
if (isScreen)
fade(false, 0);
delete[] textBuffer;
return;
}
}
@ -192,11 +195,12 @@ void Intro::doPictText(const char *filename, TextFont *msgFont, bool isScreen) {
if (isScreen)
fade(false, 0);
delete[] textBuffer;
return;
} else
drawNextText = true;
}
}
} // while(1)
}
/*****************************************************************************/
@ -323,8 +327,6 @@ void Intro::introSequence() {
nReadPict("DA", true);
musicDelay();
_vm->_music->newOpen("p:Intro/Intro.1"); /* load the picture into the buffer */
_vm->_music->updateMusic();
_vm->_graphics->blackAllScreen();
_vm->_music->updateMusic();
@ -345,8 +347,6 @@ void Intro::introSequence() {
doPictText("i.2A", msgFont, true);
doPictText("i.2B", msgFont, true);
freeAllStolenMem();
_vm->_graphics->blackAllScreen();
_vm->_music->updateMusic();

View File

@ -397,7 +397,6 @@ void LabEngine::doTile(bool showsolution) {
void LabEngine::showTile(const char *filename, bool showsolution) {
uint16 start = showsolution ? 0 : 1;
resetBuffer();
_anim->_doBlack = true;
_anim->_noPalChange = true;
_graphics->readPict(filename, true);
@ -411,8 +410,6 @@ void LabEngine::showTile(const char *filename, bool showsolution) {
delete tileFile;
allocFile((void **)&_tempScrollData, Tiles[1]->_width * Tiles[1]->_height * 2L, "tempdata");
doTile(showsolution);
setPalette(_anim->_diffPalette, 256);
}
@ -521,7 +518,6 @@ void LabEngine::doCombination() {
/* Reads in a backdrop picture. */
/*****************************************************************************/
void LabEngine::showCombination(const char *filename) {
resetBuffer();
_anim->_doBlack = true;
_anim->_noPalChange = true;
_graphics->readPict(filename, true);
@ -536,8 +532,6 @@ void LabEngine::showCombination(const char *filename) {
delete numFile;
allocFile((void **)&_tempScrollData, Images[0]->_width * Images[0]->_height * 2L, "tempdata");
doCombination();
setPalette(_anim->_diffPalette, 256);

View File

@ -35,139 +35,6 @@
namespace Lab {
static byte *buffer = NULL, *realbufferstart = NULL, *startoffilestorage = NULL;
byte **startoffile = &startoffilestorage;
static uint32 buffersize, realbuffersize;
/*-------------------- Routines that buffer a whole file --------------------*/
#define MAXMARKERS 15
struct FileMarker {
char name[32];
void *Start, *End;
};
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;
}
/*****************************************************************************/
/* Checks if a file is already buffered. */
/*****************************************************************************/
byte **isBuffered(const char *fileName) {
if (fileName == NULL)
return NULL;
for (int i = 0; i < MAXMARKERS; i++) {
if (strcmp(FileMarkers[i].name, fileName) == 0) {
*startoffile = (byte *)FileMarkers[i].Start;
return startoffile;
}
}
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;
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 = 0;
if ((((char *)_memPlace) + Size - 1) >=
(((char *)buffer) + buffersize))
_memPlace = buffer;
*Ptr = _memPlace;
_memPlace = (char *)_memPlace + Size;
for (int i = 0; i < MAXMARKERS; i++) {
if (FileMarkers[i].name[0]) {
if (((FileMarkers[i].Start >= Ptr) && (FileMarkers[i].Start < _memPlace))
|| ((FileMarkers[i].End >= Ptr) && (FileMarkers[i].End < _memPlace))
|| ((Ptr >= FileMarkers[i].Start) && (Ptr <= FileMarkers[i].End)))
freeFile(i);
}
}
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, uint32 &size) {
byte *buf;
Common::File file;
file.open(translateFileName(name));
if (!file.isOpen()) {
warning("Cannot open file %s", translateFileName(name));
return NULL;
}
size = file.size();
buf = (byte *)malloc(size);
if (!buf)
error("Unable to allocate %d bytes file file %s", size, name);
*startoffile = buf;
file.read(buf, size);
return startoffile;
}
/*****************************************************************************/
/* Reads a block of memory. */
/*****************************************************************************/
@ -176,110 +43,6 @@ void readBlock(void *Buffer, uint32 Size, byte **File) {
(*File) += Size;
}
/*****************************************************************************/
/* Resets the internal buffers to empty. */
/*****************************************************************************/
void resetBuffer() {
uint16 RMarker;
_curMarker = 0;
RMarker = 0;
_memPlace = buffer;
while (RMarker < MAXMARKERS) {
freeFile(RMarker);
RMarker++;
}
}
/*****************************************************************************/
/* Initializes the buffer. */
/*****************************************************************************/
bool initBuffer(uint32 BufSize, bool IsGraphicsMem) {
buffer = (byte *)calloc(BufSize, 1);
buffersize = BufSize;
realbuffersize = buffersize;
realbufferstart = buffer;
resetBuffer();
return (buffer != NULL);
}
/*****************************************************************************/
/* Frees the buffer. */
/*****************************************************************************/
void freeBuffer() {
freeAllStolenMem();
if (buffer)
free(buffer);
}
/*------------------------------------------------------------------------*/
/* 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() {
for (int i = 0; i < MAXMARKERS; i++)
freeFile(i);
}
/*****************************************************************************/
/* Steal some memory from the buffer */
/*****************************************************************************/
void *stealBufMem(int32 Size) {
void *Mem;
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()) {
warning("openPartial skipped %s", translateFileName(name));
delete f;
return 0;
}
return f;
}
/*****************************************************************************/
/* Frees all the memory stolen from the buffer. */
/*****************************************************************************/
void freeAllStolenMem() {
flushBuffers();
buffer = realbufferstart;
buffersize = realbuffersize;
_memPlace = buffer;
}
static char NewFileName[255];
/*****************************************************************************/

View File

@ -92,27 +92,7 @@ void gadgetsOnOff(void *gptr, void *win, int32 num, bool on);
void eatMessages();
bool quitPlaying();
/*---------------------------*/
/*------ From LabFile.c -----*/
/*---------------------------*/
/* Buffer a whole file */
byte **isBuffered(const char *fileName);
byte **openFile(const char *name, uint32 &size);
void readBlock(void *Buffer, uint32 Size, byte **File);
void resetBuffer();
bool initBuffer(uint32 BufSize, bool IsGraphicsMem);
void freeBuffer();
/* Functions that borrow memory from the buffer */
bool allocFile(void **Ptr, uint32 Size, const char *fileName);
void *stealBufMem(int32 Size);
void freeAllStolenMem();
/* Read chunks of a file */
Common::File *openPartial(const char *name);
void closePartial(int32 File);
/*---------------------------*/
/*----- From LabSets.c ------*/

View File

@ -175,7 +175,7 @@ bool Music::initMusic() {
else
filename = "Music:BackGrou";
_file = openPartial(filename);
_file = g_lab->_resource->openDataFile(filename);
if (_file) {
startMusic(true);
@ -277,7 +277,7 @@ void Music::changeMusic(const char *newmusic) {
_tLeftInFile = _leftinfile;
}
_file = openPartial(newmusic);
_file = g_lab->_resource->openDataFile(newmusic);
if (_file) {
_musicOn = true; /* turn it off */
@ -320,32 +320,4 @@ void Music::resetMusic() {
_tFile = 0;
}
/*****************************************************************************/
/* 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) {
byte **file;
if (!name || !strcmp(name, "") || !strcmp(name, " "))
return NULL;
if ((file = isBuffered(name)))
return file;
updateMusic();
if (!_doNotFilestopSoundEffect)
stopSoundEffect();
uint32 unused;
file = openFile(name, unused);
updateMusic();
return file;
}
} // End of namespace Lab

View File

@ -52,7 +52,6 @@ class Music {
public:
Music(LabEngine *vm);
byte **newOpen(const char *name);
bool initMusic();
void freeMusic();
void updateMusic();

View File

@ -300,8 +300,6 @@ bool takeItem(uint16 x, uint16 y, CloseDataPtr *cptr) {
/* Processes the action list. */
/*****************************************************************************/
void LabEngine::doActions(Action *aptr, CloseDataPtr *lcptr) {
bool firstLoaded = true;
while (aptr) {
_music->updateMusic();
@ -334,13 +332,8 @@ void LabEngine::doActions(Action *aptr, CloseDataPtr *lcptr) {
break;
case LOADDIFF:
if (firstLoaded) {
resetBuffer();
firstLoaded = false;
}
if (aptr->Data)
_music->newOpen((char *)aptr->Data); /* Puts a file into memory */
_graphics->loadPict((char *)aptr->Data); /* Puts a file into memory */
break;
@ -524,7 +517,7 @@ void LabEngine::doActions(Action *aptr, CloseDataPtr *lcptr) {
break;
case RESETBUFFER:
resetBuffer();
g_lab->_graphics->freePict();
break;
case SPECIALCMD:

View File

@ -152,7 +152,6 @@ void doWestPaper() {
closeFont(paperFont);
g_lab->setPalette(g_lab->_anim->_diffPalette, 256);
freeAllStolenMem();
}
/*****************************************************************************/
@ -377,7 +376,6 @@ void LabEngine::processJournal() {
/* Does the journal processing. */
/*****************************************************************************/
void LabEngine::doJournal() {
resetBuffer();
_graphics->blackAllScreen();
lastpage = false;
@ -410,8 +408,6 @@ void LabEngine::doJournal() {
_graphics->setAPen(0);
_graphics->rectFill(0, 0, _screenWidth - 1, _screenHeight - 1);
_graphics->blackScreen();
freeAllStolenMem();
}
bool LabEngine::saveRestoreGame() {
@ -638,7 +634,6 @@ void LabEngine::doMonitor(char *background, char *textfile, bool isinteractive,
_graphics->readPict("P:Mon/NWD3", true);
_graphics->blackAllScreen();
resetBuffer();
monitorPage = 0;
lastpage = false;
FadePalette = hipal;
@ -656,11 +651,11 @@ void LabEngine::doMonitor(char *background, char *textfile, bool isinteractive,
_event->mouseHide();
delete[] ntext;
closeFont(monitorFont);
freeAllStolenMem();
_graphics->setAPen(0);
_graphics->rectFill(0, 0, _screenWidth - 1, _screenHeight - 1);
_graphics->blackAllScreen();
_graphics->freePict();
}
} // End of namespace Lab