mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-19 00:15:30 +00:00
AGI: new font class created
moved font stuff into GfxFont class removed Mickey Mouse font data (is loaded from mickey.exe)
This commit is contained in:
parent
0f15ec2ce8
commit
0c2de08155
@ -40,6 +40,7 @@
|
||||
#include "audio/mixer.h"
|
||||
|
||||
#include "agi/agi.h"
|
||||
#include "agi/font.h"
|
||||
#include "agi/graphics.h"
|
||||
#include "agi/inv.h"
|
||||
#include "agi/sprite.h"
|
||||
@ -263,9 +264,6 @@ AgiBase::AgiBase(OSystem *syst, const AGIGameDescription *gameDesc) : Engine(sys
|
||||
_rnd = new Common::RandomSource("agi");
|
||||
_sound = 0;
|
||||
|
||||
_fontData = nullptr;
|
||||
_fontDataAllocated = nullptr;
|
||||
|
||||
initFeatures();
|
||||
initVersion();
|
||||
}
|
||||
@ -274,8 +272,6 @@ AgiBase::~AgiBase() {
|
||||
delete _rnd;
|
||||
|
||||
delete _sound;
|
||||
|
||||
free(_fontDataAllocated);
|
||||
}
|
||||
|
||||
void AgiBase::initRenderMode() {
|
||||
@ -334,351 +330,8 @@ void AgiBase::initRenderMode() {
|
||||
}
|
||||
}
|
||||
|
||||
void AgiBase::initFont() {
|
||||
// We are currently using the custom font for all fanmade games
|
||||
if (getFeatures() & (GF_FANMADE | GF_AGDS)) {
|
||||
// fanmade game, use custom font for now
|
||||
_fontData = fontData_FanGames; // our (own?) custom font, that supports umlauts etc.
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_renderMode) {
|
||||
case Common::kRenderAmiga:
|
||||
loadFontAmigaPseudoTopaz();
|
||||
//_fontData = fontData_Amiga; // use Amiga Topaz font
|
||||
break;
|
||||
case Common::kRenderApple2GS:
|
||||
// Special font, stored in file AGIFONT
|
||||
loadFontAppleIIgs();
|
||||
break;
|
||||
case Common::kRenderAtariST:
|
||||
// TODO: Atari ST uses another font
|
||||
// Seems to be the standard Atari ST 8x8 system font
|
||||
|
||||
case Common::kRenderCGA:
|
||||
case Common::kRenderEGA:
|
||||
case Common::kRenderVGA:
|
||||
switch (getGameID()) {
|
||||
case GID_MICKEY:
|
||||
// load mickey mouse font from interpreter file
|
||||
loadFontMickey();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_fontData) {
|
||||
// no font asigned?
|
||||
switch (getGameID()) {
|
||||
case GID_MICKEY:
|
||||
case GID_TROLL:
|
||||
case GID_WINNIE:
|
||||
// use IBM font for pre-AGI games as standard
|
||||
_fontData = fontData_IBM;
|
||||
break;
|
||||
default:
|
||||
// for everything else use Sierra PC font
|
||||
_fontData = fontData_Sierra;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We load the Mickey Mouse font from MICKEY.EXE
|
||||
void AgiBase::loadFontMickey() {
|
||||
Common::File interpreterFile;
|
||||
int32 interpreterFileSize = 0;
|
||||
byte *fontData = nullptr;
|
||||
|
||||
if (!interpreterFile.open("mickey.exe")) {
|
||||
// Continue, if file not found
|
||||
warning("Could not open file 'mickey.exe' for Mickey Mouse font");
|
||||
return;
|
||||
}
|
||||
|
||||
interpreterFileSize = interpreterFile.size();
|
||||
if (interpreterFileSize != 55136) {
|
||||
// unexpected file size
|
||||
interpreterFile.close();
|
||||
warning("File 'mickey.exe': unexpected file size");
|
||||
return;
|
||||
}
|
||||
interpreterFile.seek(32476); // offset of font data
|
||||
|
||||
// allocate space for font bitmap data
|
||||
fontData = (uint8 *)calloc(256, 8);
|
||||
_fontData = fontData;
|
||||
_fontDataAllocated = fontData;
|
||||
|
||||
// read font data, is already in the format that we need (plain bitmap 8x8)
|
||||
interpreterFile.read(fontData, 256 * 8);
|
||||
interpreterFile.close();
|
||||
}
|
||||
|
||||
// we create a bitmap out of the topaz data used in parallaction (which is normally found in staticres.cpp)
|
||||
// it's a recreation of the Amiga Topaz font but not really accurate
|
||||
void AgiBase::loadFontAmigaPseudoTopaz() {
|
||||
const byte *topazStart = fontData_AmigaPseudoTopaz + 32;
|
||||
const byte *topazHeader = topazStart + 78;
|
||||
const byte *topazData = nullptr;
|
||||
const byte *topazLocations = nullptr;
|
||||
byte *fontData = nullptr;
|
||||
uint16 topazHeight = 0;
|
||||
uint16 topazWidth = 0;
|
||||
uint16 topazModulo = 0;
|
||||
uint32 topazDataOffset = 0;
|
||||
uint32 topazLocationOffset = 0;
|
||||
byte topazLowChar = 0;
|
||||
byte topazHighChar = 0;
|
||||
uint16 topazTotalChars = 0;
|
||||
uint16 topazBitLength = 0;
|
||||
uint16 topazBitOffset = 0;
|
||||
uint16 topazByteOffset = 0;
|
||||
|
||||
// allocate space for font bitmap data
|
||||
fontData = (uint8 *)calloc(256, 8);
|
||||
_fontData = fontData;
|
||||
_fontDataAllocated = fontData;
|
||||
|
||||
topazHeight = READ_BE_UINT16(topazHeader + 0);
|
||||
topazWidth = READ_BE_UINT16(topazHeader + 4);
|
||||
|
||||
// we expect 8x8
|
||||
assert(topazHeight == 8);
|
||||
assert(topazWidth == 8);
|
||||
|
||||
topazLowChar = topazHeader[12];
|
||||
topazHighChar = topazHeader[13];
|
||||
topazTotalChars = topazHighChar - topazLowChar + 1;
|
||||
topazDataOffset = READ_BE_UINT32(topazHeader + 14);
|
||||
topazModulo = READ_BE_UINT16(topazHeader + 18);
|
||||
topazLocationOffset = READ_BE_UINT32(topazHeader + 20);
|
||||
|
||||
// Security checks
|
||||
assert(topazLowChar == ' ');
|
||||
assert(topazHighChar == 0xFF);
|
||||
|
||||
// copy first 32 characters over
|
||||
memcpy(fontData, fontData_Sierra, FONT_DISPLAY_WIDTH * 32);
|
||||
fontData += FONT_DISPLAY_WIDTH * 32;
|
||||
|
||||
// now actually convert from topaz data
|
||||
topazData = topazStart + topazDataOffset;
|
||||
topazLocations = topazStart + topazLocationOffset;
|
||||
|
||||
for (uint16 curChar = 0; curChar < topazTotalChars; curChar++) {
|
||||
topazBitOffset = READ_BE_UINT16(topazLocations + (curChar * 4) + 0);
|
||||
topazBitLength = READ_BE_UINT16(topazLocations + (curChar * 4) + 2);
|
||||
|
||||
if (topazBitLength == 8) {
|
||||
assert((topazBitOffset & 7) == 0);
|
||||
|
||||
topazByteOffset = topazBitOffset >> 3;
|
||||
for (uint16 curHeight = 0; curHeight < topazHeight; curHeight++) {
|
||||
*fontData = topazData[topazByteOffset];
|
||||
fontData++;
|
||||
topazByteOffset += topazModulo;
|
||||
}
|
||||
} else {
|
||||
memset(fontData, 0, 8);
|
||||
fontData += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AgiBase::loadFontAppleIIgs() {
|
||||
Common::File fontFile;
|
||||
uint16 headerIIgs_OffsetMacHeader = 0;
|
||||
uint16 headerIIgs_Version = 0;
|
||||
uint16 macRecord_FirstChar = 0;
|
||||
uint16 macRecord_LastChar = 0;
|
||||
int16 macRecord_MaxKern = 0;
|
||||
uint16 macRecord_RectHeight = 0;
|
||||
uint16 macRecord_StrikeWidth = 0;
|
||||
uint16 strikeDataLen = 0;
|
||||
byte *strikeDataPtr = nullptr;
|
||||
uint16 actualCharacterCount = 0;
|
||||
uint16 totalCharacterCount = 0;
|
||||
uint16 *locationTablePtr = nullptr;
|
||||
uint16 *offsetWidthTablePtr = nullptr;
|
||||
|
||||
uint16 curCharNr = 0;
|
||||
uint16 curRow = 0;
|
||||
uint16 curLocation = 0;
|
||||
uint16 curLocationBytes = 0;
|
||||
uint16 curLocationBits = 0;
|
||||
uint16 curCharOffsetWidth = 0;
|
||||
uint16 curCharOffset = 0;
|
||||
uint16 curCharWidth = 0;
|
||||
uint16 curStrikeWidth = 0;
|
||||
|
||||
uint16 curPixelNr = 0;
|
||||
uint16 curBitMask = 0;
|
||||
int16 positionAdjust = 0;
|
||||
byte curByte = 0;
|
||||
byte fontByte = 0;
|
||||
|
||||
uint16 strikeRowOffset = 0;
|
||||
uint16 strikeCurOffset = 0;
|
||||
|
||||
byte *fontData = nullptr;
|
||||
|
||||
if (!fontFile.open("agifont")) {
|
||||
// Continue,
|
||||
// This also happens when the user selected Apple IIgs as render for the palette for non-AppleIIgs games
|
||||
warning("Could not open file 'agifont' for Apple IIgs font");
|
||||
return;
|
||||
}
|
||||
|
||||
// Apple IIgs header
|
||||
headerIIgs_OffsetMacHeader = fontFile.readUint16LE();
|
||||
fontFile.skip(2); // font family
|
||||
fontFile.skip(2); // font style
|
||||
fontFile.skip(2); // point size
|
||||
headerIIgs_Version = fontFile.readUint16LE();
|
||||
fontFile.skip(2); // bounds type
|
||||
// end of Apple IIgs header
|
||||
// Macintosh font record
|
||||
fontFile.skip(2); // font type
|
||||
macRecord_FirstChar = fontFile.readUint16LE();
|
||||
macRecord_LastChar = fontFile.readUint16LE();
|
||||
fontFile.skip(2); // max width
|
||||
macRecord_MaxKern = fontFile.readSint16LE();
|
||||
fontFile.skip(2); // negative descent
|
||||
fontFile.skip(2); // rect width
|
||||
macRecord_RectHeight = fontFile.readUint16LE();
|
||||
fontFile.skip(2); // low word ptr table
|
||||
fontFile.skip(2); // font ascent
|
||||
fontFile.skip(2); // font descent
|
||||
fontFile.skip(2); // leading
|
||||
macRecord_StrikeWidth = fontFile.readUint16LE();
|
||||
|
||||
// security-checks
|
||||
if (headerIIgs_OffsetMacHeader != 6)
|
||||
error("AppleIIgs-font: unexpected header");
|
||||
if (headerIIgs_Version != 0x0101)
|
||||
error("AppleIIgs-font: not a 1.1 font");
|
||||
if ((macRecord_FirstChar != 0) || (macRecord_LastChar != 255))
|
||||
error("AppleIIgs-font: unexpected characters");
|
||||
if (macRecord_RectHeight != 8)
|
||||
error("AppleIIgs-font: expected 8x8 font");
|
||||
|
||||
// Calculate table sizes
|
||||
strikeDataLen = macRecord_StrikeWidth * macRecord_RectHeight * 2;
|
||||
actualCharacterCount = (macRecord_LastChar - macRecord_FirstChar + 1);
|
||||
totalCharacterCount = actualCharacterCount + 2; // replacement-char + extra character
|
||||
|
||||
// Allocate memory for tables
|
||||
strikeDataPtr = (byte *)calloc(strikeDataLen, 1);
|
||||
locationTablePtr = (uint16 *)calloc(totalCharacterCount, 2); // 1 word per character
|
||||
offsetWidthTablePtr = (uint16 *)calloc(totalCharacterCount, 2); // ditto
|
||||
|
||||
// read tables
|
||||
fontFile.read(strikeDataPtr, strikeDataLen);
|
||||
for (curCharNr = 0; curCharNr < totalCharacterCount; curCharNr++) {
|
||||
locationTablePtr[curCharNr] = fontFile.readUint16LE();
|
||||
}
|
||||
for (curCharNr = 0; curCharNr < totalCharacterCount; curCharNr++) {
|
||||
offsetWidthTablePtr[curCharNr] = fontFile.readUint16LE();
|
||||
}
|
||||
fontFile.close();
|
||||
|
||||
// allocate space for font bitmap data
|
||||
fontData = (uint8 *)calloc(256, 8);
|
||||
_fontData = fontData;
|
||||
_fontDataAllocated = fontData;
|
||||
|
||||
// extract font bitmap data
|
||||
for (curCharNr = 0; curCharNr < actualCharacterCount; curCharNr++) {
|
||||
curCharOffsetWidth = offsetWidthTablePtr[curCharNr];
|
||||
curLocation = locationTablePtr[curCharNr];
|
||||
if (curCharOffsetWidth == 0xFFFF) {
|
||||
// character does not exist in font, use replacement character instead
|
||||
curCharOffsetWidth = offsetWidthTablePtr[actualCharacterCount];
|
||||
curLocation = locationTablePtr[actualCharacterCount];
|
||||
curStrikeWidth = locationTablePtr[actualCharacterCount + 1] - curLocation;
|
||||
} else {
|
||||
curStrikeWidth = locationTablePtr[curCharNr + 1] - curLocation;
|
||||
}
|
||||
|
||||
// Figure out bytes + bits location
|
||||
curLocationBytes = curLocation >> 3;
|
||||
curLocationBits = curLocation & 0x0007;
|
||||
curCharWidth = curCharOffsetWidth & 0x00FF; // isolate width
|
||||
curCharOffset = curCharOffsetWidth >> 8; // isolate offset
|
||||
|
||||
if (!curCharWidth) {
|
||||
fontData += 8; // skip over this character
|
||||
continue;
|
||||
}
|
||||
|
||||
if (curCharWidth != 8) {
|
||||
if (curCharNr != 0x3B)
|
||||
error("AppleIIgs-font: expected 8x8 font");
|
||||
}
|
||||
|
||||
// Get all rows of the current character
|
||||
strikeRowOffset = 0;
|
||||
for (curRow = 0; curRow < macRecord_RectHeight; curRow++) {
|
||||
strikeCurOffset = strikeRowOffset + curLocationBytes;
|
||||
|
||||
// Copy over bits
|
||||
fontByte = 0;
|
||||
curByte = strikeDataPtr[strikeCurOffset];
|
||||
curBitMask = 0x80 >> curLocationBits;
|
||||
|
||||
for (curPixelNr = 0; curPixelNr < curStrikeWidth; curPixelNr++) {
|
||||
fontByte = fontByte << 1;
|
||||
if (curByte & curBitMask) {
|
||||
fontByte |= 0x01;
|
||||
}
|
||||
curBitMask = curBitMask >> 1;
|
||||
if (!curBitMask) {
|
||||
curByte = strikeDataPtr[strikeCurOffset + 1];
|
||||
curBitMask = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
// adjust, so that it's aligned to the left (starting at 0x80 bit)
|
||||
fontByte = fontByte << (8 - curStrikeWidth);
|
||||
|
||||
// now adjust according to offset + MaxKern
|
||||
positionAdjust = macRecord_MaxKern + curCharOffset;
|
||||
|
||||
// adjust may be negative for space, or 8 for "empty" characters
|
||||
if (positionAdjust > 8)
|
||||
error("AppleIIgs-font: invalid character spacing");
|
||||
|
||||
if (positionAdjust < 0) {
|
||||
// negative adjust strangely happens for empty characters like space
|
||||
if (curStrikeWidth)
|
||||
error("AppleIIgs-font: invalid character spacing");
|
||||
}
|
||||
|
||||
if (positionAdjust > 0) {
|
||||
// move the amount of pixels to the right
|
||||
fontByte = fontByte >> positionAdjust;
|
||||
}
|
||||
|
||||
*fontData = fontByte;
|
||||
fontData++;
|
||||
|
||||
strikeRowOffset += macRecord_StrikeWidth * 2;
|
||||
}
|
||||
}
|
||||
|
||||
free(offsetWidthTablePtr);
|
||||
free(locationTablePtr);
|
||||
free(strikeDataPtr);
|
||||
|
||||
// overwrite character 0x1A with the standard Sierra arrow to the right character
|
||||
// required for the original save/restore dialogs
|
||||
memcpy(_fontDataAllocated + (0x1A * 8), fontData_ArrowRightCharacter, sizeof(fontData_ArrowRightCharacter));
|
||||
const byte *AgiBase::getFontData() {
|
||||
return _font->getFontData();
|
||||
}
|
||||
|
||||
AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBase(syst, gameDesc) {
|
||||
@ -711,9 +364,6 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
|
||||
_game.mouseHidden = true;
|
||||
}
|
||||
|
||||
_fontData = nullptr;
|
||||
_fontDataAllocated = nullptr;
|
||||
|
||||
_game._vm = this;
|
||||
|
||||
_game.gfxMode = true;
|
||||
@ -797,10 +447,10 @@ void AgiEngine::initialize() {
|
||||
}
|
||||
|
||||
initRenderMode();
|
||||
initFont();
|
||||
|
||||
_console = new Console(this);
|
||||
_words = new Words(this);
|
||||
_font = new GfxFont(this);
|
||||
_gfx = new GfxMgr(this);
|
||||
_sound = new SoundMgr(this, _mixer);
|
||||
_picture = new PictureMgr(this, _gfx);
|
||||
@ -809,6 +459,7 @@ void AgiEngine::initialize() {
|
||||
_systemUI = new SystemUI(this, _gfx, _text);
|
||||
_inventory = new InventoryMgr(this, _gfx, _text, _systemUI);
|
||||
|
||||
_font->init();
|
||||
_text->init(_systemUI);
|
||||
|
||||
_gfx->initMachine();
|
||||
@ -883,6 +534,7 @@ AgiEngine::~AgiEngine() {
|
||||
delete _picture;
|
||||
_gfx->deinitMachine();
|
||||
delete _gfx;
|
||||
delete _font;
|
||||
delete _words;
|
||||
delete _console;
|
||||
}
|
||||
|
@ -592,7 +592,7 @@ public:
|
||||
virtual int loadWords(const char *);
|
||||
};
|
||||
|
||||
|
||||
class GfxFont;
|
||||
class GfxMgr;
|
||||
class SpritesMgr;
|
||||
class InventoryMgr;
|
||||
@ -642,19 +642,12 @@ protected:
|
||||
virtual void initialize() = 0;
|
||||
|
||||
void initRenderMode();
|
||||
void initFont();
|
||||
|
||||
void loadFontMickey();
|
||||
void loadFontAmigaPseudoTopaz();
|
||||
void loadFontAppleIIgs();
|
||||
|
||||
const uint8 *_fontData; // pointer to the currently used font
|
||||
uint8 *_fontDataAllocated;
|
||||
|
||||
public:
|
||||
Words *_words;
|
||||
|
||||
GfxMgr *_gfx;
|
||||
GfxFont *_font;
|
||||
GfxMgr *_gfx;
|
||||
|
||||
Common::RenderMode _renderMode;
|
||||
volatile uint32 _clockCount;
|
||||
@ -715,7 +708,7 @@ public:
|
||||
bool canLoadGameStateCurrently();
|
||||
bool canSaveGameStateCurrently();
|
||||
|
||||
const uint8 *getFontData() { return _fontData; };
|
||||
const byte *getFontData();
|
||||
|
||||
void cycleInnerLoopActive(int16 loopType) {
|
||||
_game.cycleInnerLoopActive = true;
|
||||
|
1346
engines/agi/font.cpp
Normal file
1346
engines/agi/font.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1225
engines/agi/font.h
1225
engines/agi/font.h
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@ MODULE_OBJS := \
|
||||
console.o \
|
||||
cycle.o \
|
||||
detection.o \
|
||||
font.o \
|
||||
global.o \
|
||||
graphics.o \
|
||||
id.o \
|
||||
|
@ -56,11 +56,12 @@ PreAgiEngine::PreAgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) :
|
||||
|
||||
void PreAgiEngine::initialize() {
|
||||
initRenderMode();
|
||||
initFont();
|
||||
|
||||
_font = new GfxFont(this);
|
||||
_gfx = new GfxMgr(this);
|
||||
_picture = new PictureMgr(this, _gfx);
|
||||
|
||||
_font->init();
|
||||
_gfx->initMachine();
|
||||
|
||||
_game.gameFlags = 0;
|
||||
@ -93,6 +94,10 @@ void PreAgiEngine::initialize() {
|
||||
PreAgiEngine::~PreAgiEngine() {
|
||||
_mixer->stopHandle(_speakerHandle);
|
||||
delete _speakerStream;
|
||||
|
||||
delete _picture;
|
||||
delete _gfx;
|
||||
delete _font;
|
||||
}
|
||||
|
||||
int PreAgiEngine::rnd(int hi) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user