Skip to content

Commit

Permalink
MORTEVIELLE: Implemented loading of the font data, and rewrote drawin…
Browse files Browse the repository at this point in the history
…g routines to use it.
  • Loading branch information
dreammaster authored and Strangerke committed Apr 6, 2012
1 parent 07cce9c commit 5d9b9f1
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 14 deletions.
6 changes: 4 additions & 2 deletions devtools/create_mortdat/create_mortdat.cpp
Expand Up @@ -107,7 +107,7 @@ void openOutputFile(const char *outFilename) {
outputFile.open(outFilename, kFileWriteMode);

// Write header
outputFile.write("mort", 4);
outputFile.write("MORT", 4);
outputFile.writeByte(VERSION_MAJOR);
outputFile.writeByte(VERSION_MINOR);
}
Expand All @@ -132,7 +132,9 @@ void process() {

// Write out a section header to the output file and the font data
char fontHeader[4] = { 'F', 'O', 'N', 'T' };
outputFile.write(fontHeader, 4);
outputFile.write(fontHeader, 4); // Section Id
outputFile.writeWord(121 * 6); // Section size

outputFile.write(fontBuffer, 121 * 6);
}

Expand Down
Binary file modified dists/engine-data/mort.dat
Binary file not shown.
136 changes: 135 additions & 1 deletion engines/mortevielle/mortevielle.cpp
Expand Up @@ -20,14 +20,22 @@
*
*/

#include "common/system.h"
#include "engines/util.h"
#include "engines/engine.h"
#include "graphics/palette.h"
#include "graphics/pixelformat.h"
#include "mortevielle/mortevielle.h"
#include "mortevielle/mort.h"
#include "mortevielle/var_mor.h"

namespace Mortevielle {

MortevielleEngine *g_vm;

MortevielleEngine::MortevielleEngine(OSystem *system, const ADGameDescription *gameDesc):
Engine(system), _gameDescription(gameDesc) {
g_vm = this;
}

MortevielleEngine::~MortevielleEngine() {
Expand All @@ -37,10 +45,136 @@ bool MortevielleEngine::hasFeature(EngineFeature f) const {
return false;
}

Common::Error MortevielleEngine::run() {
Common::ErrorCode MortevielleEngine::initialise() {
// Initialise graphics mode
initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT, true);

// Set up an intermediate screen surface
_screenSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());

// Set the screen mode
gd = ega;
res = 2;

// Load the mort.dat resource
return loadMortDat();
}

/**
* Loads the contents of the Mort.dat data file
*/
Common::ErrorCode MortevielleEngine::loadMortDat() {
Common::File f;

// Open the mort.dat file
if (!f.open(MORT_DAT)) {
GUIErrorMessage("Could not locate Mort.dat file");
return Common::kReadingFailed;
}

// Validate the data file header
char fileId[4];
f.read(fileId, 4);
if (strncmp(fileId, "MORT", 4) != 0) {
GUIErrorMessage("The located mort.dat data file is invalid");
return Common::kReadingFailed;
}

// Check the version
if (f.readByte() < MORT_DAT_REQUIRED_VERSION) {
GUIErrorMessage("The located mort.dat data file is too a version");
return Common::kReadingFailed;
}
f.readByte(); // Minor version

// Loop to load resources from the data file
while (f.pos() < f.size()) {
// Get the Id and size of the next resource
char dataType[4];
int dataSize;
f.read(dataType, 4);
dataSize = f.readUint16LE();

if (!strncmp(dataType, "FONT", 4)) {
// Font resource
assert(dataSize == (FONT_NUM_CHARS * FONT_HEIGHT));
f.read(_fontData, FONT_NUM_CHARS * FONT_HEIGHT);
} else {
// Unknown section
f.skip(dataSize);
}
}

f.close();
return Common::kNoError;
}

/*-------------------------------------------------------------------------*/

/**
* Update the physical screen
*/
void MortevielleEngine::updateScreen() {
g_system->copyRectToScreen((const byte *)_screenSurface.getBasePtr(0, 0),
SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
g_system->updateScreen();
}
/**
* Draws a character at the specified co-ordinates
* @remarks Because the ScummVM surface is using a double height 640x200 surface to
* simulate the original 640x200 surface, all Y values have to be doubled
*/
void MortevielleEngine::writeCharacter(const Common::Point &pt, unsigned char ch,
int palIndex, Graphics::Surface *surface) {
if (surface == NULL)
surface = &_screenSurface;

// Get the start of the character to use
assert((ch >= ' ') && (ch <= (unsigned char)(32 + FONT_NUM_CHARS)));
const byte *charData = &_fontData[((int)ch - 32) * FONT_HEIGHT];

// Loop through decoding each character's data
for (int yp = 0; yp < FONT_HEIGHT; ++yp) {
byte *lineP = (byte *)surface->getBasePtr(pt.x, (pt.y + yp) * 2);
byte byteVal = *charData++;

for (int xp = 0; xp < 8; ++xp, ++lineP, byteVal <<= 1) {
if (byteVal & 0x80) {
*lineP = palIndex;
*(lineP + SCREEN_WIDTH) = palIndex;
}
}
}
}

/**
* Sets a single pixel at the specified co-ordinates
* @remarks Because the ScummVM surface is using a double height 640x200 surface to
* simulate the original 640x200 surface, all Y values have to be doubled
*/
void MortevielleEngine::setPixel(const Common::Point &pt, int palIndex,
Graphics::Surface *surface) {
if (surface == NULL)
surface = &_screenSurface;

byte *destP = (byte *)surface->getBasePtr(pt.x, pt.y * 2);
*destP = palIndex;
*(destP + SCREEN_WIDTH) = palIndex;
}


/*-------------------------------------------------------------------------*/

Common::Error MortevielleEngine::run() {
// Initialise the game
Common::ErrorCode err = initialise();
if (err != Common::kNoError)
return err;

// TODO: Remove once palette loading is correctly done
uint32 white = 0xffffffff;
g_system->getPaletteManager()->setPalette((const byte *)&white, 15, 1);

// Dispatch to the game's main routine
const char *argv[] = { "" };
mortevielle_main(1, argv);
Expand Down
22 changes: 21 additions & 1 deletion engines/mortevielle/mortevielle.h
Expand Up @@ -23,9 +23,12 @@
#ifndef MORTEVIELLE_H
#define MORTEVIELLE_H

#include "common/file.h"
#include "common/rect.h"
#include "engines/advancedDetector.h"
#include "engines/engine.h"
#include "common/error.h"
#include "graphics/surface.h"

namespace Mortevielle {

Expand All @@ -35,17 +38,34 @@ enum {

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 400
#define MORT_DAT_REQUIRED_VERSION 1
#define MORT_DAT "mort.dat"

#define FONT_WIDTH 8
#define FONT_HEIGHT 6
#define FONT_NUM_CHARS 121

class MortevielleEngine : public Engine {
private:
const ADGameDescription *_gameDescription;

Common::ErrorCode initialise();
Common::ErrorCode loadMortDat();
void loadFont(Common::File &f);
public:
Graphics::Surface _screenSurface;
byte _fontData[FONT_NUM_CHARS * FONT_HEIGHT];
public:
MortevielleEngine(OSystem *system, const ADGameDescription *gameDesc);
~MortevielleEngine();
virtual bool hasFeature(EngineFeature f) const;
virtual Common::Error run();

uint32 getGameFlags() const;

void updateScreen();
void writeCharacter(const Common::Point &pt,
unsigned char ch, int palIndex, Graphics::Surface *surface = NULL);
void setPixel(const Common::Point &pt, int palIndex, Graphics::Surface *surface = NULL);
};

extern MortevielleEngine *g_vm;
Expand Down
3 changes: 2 additions & 1 deletion engines/mortevielle/mouse.cpp
Expand Up @@ -25,6 +25,7 @@
* Copyright (c) 1988-1989 Lankhor
*/

#include "common/rect.h"
#include "mortevielle/mouse.h"
#include "mortevielle/var_mor.h"

Expand Down Expand Up @@ -256,7 +257,7 @@ void show_mouse() {
}
break;
} /* case Gd */
affput(2, gd, x_s, y_s, 0, 0);
affput(Common::Point(x_s, y_s), 0, 0);
}

void pos_mouse(int x, int y) {
Expand Down
2 changes: 0 additions & 2 deletions engines/mortevielle/ovd1.cpp
Expand Up @@ -275,8 +275,6 @@ void ani50() {
gd = tan;
break;
}*/
// Hardcode display mode to EGA
gd = ega;

gotoxy(1, 24);
clreol;
Expand Down
4 changes: 4 additions & 0 deletions engines/mortevielle/sprint.cpp
Expand Up @@ -27,6 +27,7 @@

#include "common/str.h"
#include "common/textconsole.h"
#include "mortevielle/mortevielle.h"
#include "mortevielle/mouse.h"
#include "mortevielle/sprint.h"
#include "mortevielle/var_mor.h"
Expand Down Expand Up @@ -85,6 +86,9 @@ void writeg(Common::String l, int c)
xo = xo + i;
}
show_mouse();

// TODO: Move screen updates to main loop once constructed
g_vm->updateScreen();
}

} // End of namespace Mortevielle
20 changes: 14 additions & 6 deletions engines/mortevielle/var_mor.cpp
Expand Up @@ -28,6 +28,7 @@
#include "common/debug.h"
#include "common/str.h"
#include "common/textconsole.h"
#include "mortevielle/mortevielle.h"
#include "mortevielle/sprint.h"
#include "mortevielle/var_mor.h"

Expand Down Expand Up @@ -306,18 +307,25 @@ void hirs() {
*/
}

/* procedure affput(Chx,Gd,x,y,coul,char:int); external 'c:\mc\divaf.com'; */
void affput(int Chx, int Gd, int x, int y, int coul, int char_) {
warning("TODO: Implement affput");
/**
* Draws either a single pixel or a character to the screen
*/
void affput(const Common::Point &pt, int palIndex, int ch) {
if (ch == 0)
g_vm->setPixel(pt, palIndex);
else
g_vm->writeCharacter(pt, ch, palIndex);
}

void affcar(int gd, int x, int y, int coul, int chr) {
if (res == 1) affput(1, gd, ((uint)x >> 1), y, coul, chr);
else affput(1, gd, x, y, coul, chr);
if (res == 1)
affput(Common::Point(((uint)x >> 1), y), coul, chr);
else
affput(Common::Point(x, y), coul, chr);
}

void putpix(int gd, int x, int y, int coul) {
affput(0, gd, x, y, coul, 0);
affput(Common::Point(x, y), coul, 0);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion engines/mortevielle/var_mor.h
Expand Up @@ -28,6 +28,7 @@
#ifndef MORTEVIELLE_VAR_H
#define MORTEVIELLE_VAR_H

#include "common/rect.h"
#include "common/str.h"

namespace Mortevielle {
Expand Down Expand Up @@ -396,7 +397,7 @@ void affcar(int gd, int x, int y, int coul, int chr);
void putpix(int gd, int x, int y, int coul);
Common::String copy(const Common::String &s, int idx, size_t size);
void Val(const Common::String &s, int &V, int Code);
void affput(int Chx, int Gd, int x, int y, int coul, int char_);
void affput(const Common::Point &pt, int palIndex, int ch);

/*---------------------------------------------------------------------------*/
/*------------------------------ STUBS ------------------------------*/
Expand Down

0 comments on commit 5d9b9f1

Please sign in to comment.