diff options
author | Paul Gilbert | 2012-01-05 07:56:45 +1100 |
---|---|---|
committer | Strangerke | 2012-04-06 08:19:27 +0200 |
commit | 1727798a8ea95574ecf6d43ec2fc071b6cb87d0b (patch) | |
tree | 38e969310f04a28aee9c92acd05ee0557083c6de | |
parent | 60f287c85d146c0bc8eca96fb9570036426c4ec1 (diff) | |
download | scummvm-rg350-1727798a8ea95574ecf6d43ec2fc071b6cb87d0b.tar.gz scummvm-rg350-1727798a8ea95574ecf6d43ec2fc071b6cb87d0b.tar.bz2 scummvm-rg350-1727798a8ea95574ecf6d43ec2fc071b6cb87d0b.zip |
MORTEVIELLE: Implemented loading of the font data, and rewrote drawing routines to use it.
-rw-r--r-- | devtools/create_mortdat/create_mortdat.cpp | 6 | ||||
-rw-r--r-- | dists/engine-data/mort.dat | bin | 736 -> 738 bytes | |||
-rw-r--r-- | engines/mortevielle/mortevielle.cpp | 136 | ||||
-rw-r--r-- | engines/mortevielle/mortevielle.h | 22 | ||||
-rw-r--r-- | engines/mortevielle/mouse.cpp | 3 | ||||
-rw-r--r-- | engines/mortevielle/ovd1.cpp | 2 | ||||
-rw-r--r-- | engines/mortevielle/sprint.cpp | 4 | ||||
-rw-r--r-- | engines/mortevielle/var_mor.cpp | 20 | ||||
-rw-r--r-- | engines/mortevielle/var_mor.h | 3 |
9 files changed, 182 insertions, 14 deletions
diff --git a/devtools/create_mortdat/create_mortdat.cpp b/devtools/create_mortdat/create_mortdat.cpp index 62b81806bc..aa7da0169a 100644 --- a/devtools/create_mortdat/create_mortdat.cpp +++ b/devtools/create_mortdat/create_mortdat.cpp @@ -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); } @@ -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); } diff --git a/dists/engine-data/mort.dat b/dists/engine-data/mort.dat Binary files differindex ce4e5bb1c8..ebfb8a8e0e 100644 --- a/dists/engine-data/mort.dat +++ b/dists/engine-data/mort.dat diff --git a/engines/mortevielle/mortevielle.cpp b/engines/mortevielle/mortevielle.cpp index 68b8dbeeb4..43534a6ae0 100644 --- a/engines/mortevielle/mortevielle.cpp +++ b/engines/mortevielle/mortevielle.cpp @@ -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() { @@ -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); diff --git a/engines/mortevielle/mortevielle.h b/engines/mortevielle/mortevielle.h index 14bee28a03..b9d8265385 100644 --- a/engines/mortevielle/mortevielle.h +++ b/engines/mortevielle/mortevielle.h @@ -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 { @@ -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; diff --git a/engines/mortevielle/mouse.cpp b/engines/mortevielle/mouse.cpp index 1aaea06d68..d78b458816 100644 --- a/engines/mortevielle/mouse.cpp +++ b/engines/mortevielle/mouse.cpp @@ -25,6 +25,7 @@ * Copyright (c) 1988-1989 Lankhor */ +#include "common/rect.h" #include "mortevielle/mouse.h" #include "mortevielle/var_mor.h" @@ -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) { diff --git a/engines/mortevielle/ovd1.cpp b/engines/mortevielle/ovd1.cpp index a1a47a2913..3aa942c7e2 100644 --- a/engines/mortevielle/ovd1.cpp +++ b/engines/mortevielle/ovd1.cpp @@ -275,8 +275,6 @@ void ani50() { gd = tan; break; }*/ - // Hardcode display mode to EGA - gd = ega; gotoxy(1, 24); clreol; diff --git a/engines/mortevielle/sprint.cpp b/engines/mortevielle/sprint.cpp index e6a172b821..67bd3ab119 100644 --- a/engines/mortevielle/sprint.cpp +++ b/engines/mortevielle/sprint.cpp @@ -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" @@ -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 diff --git a/engines/mortevielle/var_mor.cpp b/engines/mortevielle/var_mor.cpp index a8b10c1201..e07a7359ac 100644 --- a/engines/mortevielle/var_mor.cpp +++ b/engines/mortevielle/var_mor.cpp @@ -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" @@ -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); } /** diff --git a/engines/mortevielle/var_mor.h b/engines/mortevielle/var_mor.h index 63d3112760..f9c29e20f6 100644 --- a/engines/mortevielle/var_mor.h +++ b/engines/mortevielle/var_mor.h @@ -28,6 +28,7 @@ #ifndef MORTEVIELLE_VAR_H #define MORTEVIELLE_VAR_H +#include "common/rect.h" #include "common/str.h" namespace Mortevielle { @@ -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 ------------------------------*/ |