mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 13:50:13 +00:00
AGI: Add support for upscaling and Hercules hires font
- User option to force Hercules hires font for any rendering mode - Also change mouse cursor hotspots from 1,1 to 0,0 - Fix inaccuracy in mouse controlled game menu - Change render_Block(), drawBox(), drawDisplayRect() to use upper Y instead of lower Y. Original AGI uses lower Y, but upper Y makes upscaling way easier.
This commit is contained in:
parent
9059189e35
commit
e1c36a52b5
@ -466,7 +466,7 @@ void AgiEngine::initialize() {
|
||||
_console = new Console(this);
|
||||
_words = new Words(this);
|
||||
_font = new GfxFont(this);
|
||||
_gfx = new GfxMgr(this);
|
||||
_gfx = new GfxMgr(this, _font);
|
||||
_sound = new SoundMgr(this, _mixer);
|
||||
_picture = new PictureMgr(this, _gfx);
|
||||
_sprites = new SpritesMgr(this, _gfx);
|
||||
@ -474,9 +474,9 @@ void AgiEngine::initialize() {
|
||||
_systemUI = new SystemUI(this, _gfx, _text);
|
||||
_inventory = new InventoryMgr(this, _gfx, _text, _systemUI);
|
||||
|
||||
_font->init();
|
||||
_gfx->initVideo();
|
||||
|
||||
_font->init();
|
||||
_text->init(_systemUI);
|
||||
|
||||
_game.gameFlags = 0;
|
||||
@ -512,19 +512,6 @@ void AgiEngine::redrawScreen() {
|
||||
_text->promptRedraw();
|
||||
}
|
||||
|
||||
// Adjust a given coordinate to the local game screen
|
||||
// Used on mouse cursor coordinates before passing them to scripts
|
||||
void AgiEngine::adjustPosToGameScreen(int16 &x, int16 &y) {
|
||||
x = x / 2; // 320 -> 160
|
||||
y = y - _gfx->getRenderStartOffsetY(); // remove status bar line
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
}
|
||||
if (y >= SCRIPT_HEIGHT) {
|
||||
y = SCRIPT_HEIGHT + 1; // 1 beyond
|
||||
}
|
||||
}
|
||||
|
||||
AgiEngine::~AgiEngine() {
|
||||
agiDeinit();
|
||||
delete _loader;
|
||||
|
@ -739,8 +739,6 @@ public:
|
||||
Common::Error loadGameState(int slot);
|
||||
Common::Error saveGameState(int slot, const Common::String &description);
|
||||
|
||||
void adjustPosToGameScreen(int16 &x, int16 &y);
|
||||
|
||||
private:
|
||||
int _keyQueue[KEY_QUEUE_SIZE];
|
||||
int _keyQueueStart;
|
||||
|
@ -171,6 +171,16 @@ static const ADExtraGuiOptionsMap optionsList[] = {
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
GAMEOPTION_USE_HERCULES_FONT,
|
||||
{
|
||||
_s("Use Hercules hires font"),
|
||||
_s("Uses Hercules hires font, when font file is available."),
|
||||
"herculesfont",
|
||||
false
|
||||
}
|
||||
},
|
||||
|
||||
AD_EXTRA_GUI_OPTIONS_TERMINATOR
|
||||
};
|
||||
|
||||
|
@ -24,12 +24,13 @@ namespace Agi {
|
||||
|
||||
#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1
|
||||
#define GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE GUIO_GAMEOPTIONS2
|
||||
#define GAMEOPTION_DISABLE_MOUSE GUIO_GAMEOPTIONS3
|
||||
#define GAMEOPTION_DISABLE_MOUSE GUIO_GAMEOPTIONS3
|
||||
#define GAMEOPTION_USE_HERCULES_FONT GUIO_GAMEOPTIONS4
|
||||
// TODO: properly implement GAMEOPTIONs
|
||||
|
||||
#define GAMEOPTIONS_DEFAULT GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_DISABLE_MOUSE)
|
||||
#define GAMEOPTIONS_AMIGA GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE)
|
||||
#define GAMEOPTIONS_FANMADE_MOUSE GUIO1(GAMEOPTION_ORIGINAL_SAVELOAD)
|
||||
#define GAMEOPTIONS_DEFAULT GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_DISABLE_MOUSE,GAMEOPTION_USE_HERCULES_FONT)
|
||||
#define GAMEOPTIONS_AMIGA GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE,GAMEOPTION_USE_HERCULES_FONT)
|
||||
#define GAMEOPTIONS_FANMADE_MOUSE GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_USE_HERCULES_FONT)
|
||||
|
||||
#define GAME_LVFPN(id,extra,fname,md5,size,lang,ver,features,gid,platform,interp,guioptions) { \
|
||||
{ \
|
||||
|
@ -20,6 +20,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "agi/agi.h"
|
||||
#include "agi/font.h"
|
||||
#include "agi/text.h"
|
||||
@ -31,6 +32,7 @@ GfxFont::GfxFont(AgiBase *vm) {
|
||||
|
||||
_fontData = nullptr;
|
||||
_fontDataAllocated = nullptr;
|
||||
_fontIsHires = false;
|
||||
}
|
||||
|
||||
GfxFont::~GfxFont() {
|
||||
@ -619,52 +621,59 @@ static const uint8 fontData_ExtendedRussian[] = {
|
||||
};
|
||||
|
||||
void GfxFont::init() {
|
||||
switch (_vm->_renderMode) {
|
||||
case Common::kRenderAmiga:
|
||||
// Try user-file first, if that fails use our internal inaccurate topaz font
|
||||
loadFontScummVMFile("agi-font-amiga.bin");
|
||||
if (!_fontData) {
|
||||
loadFontAmigaPseudoTopaz();
|
||||
}
|
||||
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
|
||||
loadFontScummVMFile("agi-font-atarist.bin");
|
||||
if (!_fontData) {
|
||||
loadFontAtariST("agi-font-atarist-system.fnt");
|
||||
if (!_fontData) {
|
||||
// TODO: in case we find a recreation of the font, add it in here
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Common::kRenderCGA:
|
||||
case Common::kRenderEGA:
|
||||
case Common::kRenderVGA:
|
||||
switch (_vm->getGameID()) {
|
||||
case GID_MICKEY:
|
||||
// load mickey mouse font from interpreter file
|
||||
loadFontMickey();
|
||||
break;
|
||||
default:
|
||||
loadFontScummVMFile("agi-font-dos.bin");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
if (ConfMan.getBool("herculesfont")) {
|
||||
// User wants, that we use Hercules hires font, try to load it
|
||||
loadFontHercules();
|
||||
}
|
||||
|
||||
if (!_fontData) {
|
||||
// no font assigned?
|
||||
// use regular PC-BIOS font (taken from Dos-Box with a few modifications)
|
||||
_fontData = fontData_PCBIOS;
|
||||
debug("AGI: Using PC-BIOS font");
|
||||
switch (_vm->_renderMode) {
|
||||
case Common::kRenderAmiga:
|
||||
// Try user-file first, if that fails use our internal inaccurate topaz font
|
||||
loadFontScummVMFile("agi-font-amiga.bin");
|
||||
if (!_fontData) {
|
||||
loadFontAmigaPseudoTopaz();
|
||||
}
|
||||
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
|
||||
loadFontScummVMFile("agi-font-atarist.bin");
|
||||
if (!_fontData) {
|
||||
loadFontAtariST("agi-font-atarist-system.fnt");
|
||||
if (!_fontData) {
|
||||
// TODO: in case we find a recreation of the font, add it in here
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Common::kRenderCGA:
|
||||
case Common::kRenderEGA:
|
||||
case Common::kRenderVGA:
|
||||
switch (_vm->getGameID()) {
|
||||
case GID_MICKEY:
|
||||
// load mickey mouse font from interpreter file
|
||||
loadFontMickey();
|
||||
break;
|
||||
default:
|
||||
loadFontScummVMFile("agi-font-dos.bin");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_fontData) {
|
||||
// no font assigned?
|
||||
// use regular PC-BIOS font (taken from Dos-Box with a few modifications)
|
||||
_fontData = fontData_PCBIOS;
|
||||
debug("AGI: Using PC-BIOS font");
|
||||
}
|
||||
}
|
||||
|
||||
if (_vm->getLanguage() == Common::RU_RUS) {
|
||||
@ -678,6 +687,10 @@ const byte *GfxFont::getFontData() {
|
||||
return _fontData;
|
||||
}
|
||||
|
||||
bool GfxFont::isFontHires() {
|
||||
return _fontIsHires;
|
||||
}
|
||||
|
||||
void GfxFont::overwriteSaveRestoreDialogCharacter() {
|
||||
// overwrite character 0x1A with the standard Sierra arrow to the right character
|
||||
// required for the original save/restore dialogs
|
||||
@ -1165,4 +1178,96 @@ void GfxFont::loadFontAtariST(Common::String fontFilename) {
|
||||
debug("AGI: Using Atari ST 8x8 system font");
|
||||
}
|
||||
|
||||
// Loads a Sierra Hercules font file
|
||||
void GfxFont::loadFontHercules() {
|
||||
Common::File fontFile;
|
||||
int32 fontFileSize = 0;
|
||||
byte *fontData = nullptr;
|
||||
byte *rawData = nullptr;
|
||||
|
||||
uint16 rawDataPos = 0;
|
||||
uint16 curCharNr = 0;
|
||||
uint16 curCharLine = 0;
|
||||
|
||||
if (fontFile.open("hgc_font")) {
|
||||
// hgc_font file found, this is interleaved font data 16x12, should be 3072 bytes
|
||||
// 24 bytes per character, 128 characters
|
||||
fontFileSize = fontFile.size();
|
||||
if (fontFileSize == (128 * 24)) {
|
||||
// size seems to be fine
|
||||
fontData = (uint8 *)calloc(256, 32);
|
||||
_fontDataAllocated = fontData;
|
||||
|
||||
rawData = (byte *)calloc(128, 24);
|
||||
fontFile.read(rawData, 128 * 24);
|
||||
|
||||
// convert interleaved 16x12 -> non-interleaved 16x16
|
||||
for (curCharNr = 0; curCharNr < 128; curCharNr++) {
|
||||
fontData += 4; // skip the first 2 lines
|
||||
for (curCharLine = 0; curCharLine < 6; curCharLine++) {
|
||||
fontData[0] = rawData[rawDataPos + 2 + 0];
|
||||
fontData[1] = rawData[rawDataPos + 2 + 1];
|
||||
fontData[2] = rawData[rawDataPos + 0 + 0];
|
||||
fontData[3] = rawData[rawDataPos + 0 + 1];
|
||||
rawDataPos += 4;
|
||||
fontData += 4;
|
||||
}
|
||||
fontData += 4; // skip the last 2 lines
|
||||
}
|
||||
|
||||
} else {
|
||||
warning("Fontfile 'hgc_font': unexpected file size");
|
||||
}
|
||||
fontFile.close();
|
||||
|
||||
}
|
||||
|
||||
if (!_fontDataAllocated) {
|
||||
if (fontFile.open("hgc_graf.ovl")) {
|
||||
// hgc_graf.ovl file found, this is font data + code. non-interleaved font data, should be 3075 bytes
|
||||
// 16 bytes per character, 128 characters, 2048 bytes of font data, starting offset 21
|
||||
fontFileSize = fontFile.size();
|
||||
if (fontFileSize == 3075) {
|
||||
// size seems to be fine
|
||||
fontData = (uint8 *)calloc(256, 32);
|
||||
_fontDataAllocated = fontData;
|
||||
|
||||
fontFile.seek(21);
|
||||
rawData = (byte *)calloc(128, 16);
|
||||
fontFile.read(rawData, 128 * 16);
|
||||
|
||||
// repeat every line 2 times to get 16x16 pixels
|
||||
for (curCharNr = 0; curCharNr < 128; curCharNr++) {
|
||||
for (curCharLine = 0; curCharLine < 8; curCharLine++) {
|
||||
fontData[0] = rawData[rawDataPos + 0];
|
||||
fontData[1] = rawData[rawDataPos + 1];
|
||||
fontData[2] = rawData[rawDataPos + 0];
|
||||
fontData[3] = rawData[rawDataPos + 1];
|
||||
rawDataPos += 2;
|
||||
fontData += 4;
|
||||
}
|
||||
}
|
||||
|
||||
free(rawData);
|
||||
|
||||
} else {
|
||||
warning("Fontfile 'hgc_graf.ovl': unexpected file size");
|
||||
}
|
||||
fontFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (_fontDataAllocated) {
|
||||
// font loaded
|
||||
_fontData = _fontDataAllocated;
|
||||
_fontIsHires = true;
|
||||
|
||||
debug("AGI: Using Hercules hires font");
|
||||
|
||||
} else {
|
||||
// Continue, if no file was not found
|
||||
warning("Could not open/use file 'hgc_font' or 'hgc_graf.ovl' for Hercules hires font");
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Agi
|
||||
|
@ -36,6 +36,7 @@ private:
|
||||
public:
|
||||
void init();
|
||||
const byte *getFontData();
|
||||
bool isFontHires();
|
||||
|
||||
private:
|
||||
void overwriteSaveRestoreDialogCharacter();
|
||||
@ -46,9 +47,11 @@ private:
|
||||
void loadFontAmigaPseudoTopaz();
|
||||
void loadFontAppleIIgs();
|
||||
void loadFontAtariST(Common::String fontFilename);
|
||||
void loadFontHercules();
|
||||
|
||||
const uint8 *_fontData; // pointer to the currently used font
|
||||
uint8 *_fontDataAllocated;
|
||||
bool _fontIsHires;
|
||||
};
|
||||
|
||||
} // End of namespace Agi
|
||||
|
@ -39,7 +39,7 @@ namespace Agi {
|
||||
|
||||
#include "agi/font.h"
|
||||
|
||||
GfxMgr::GfxMgr(AgiBase *vm) : _vm(vm) {
|
||||
GfxMgr::GfxMgr(AgiBase *vm, GfxFont *font) : _vm(vm), _font(font) {
|
||||
_agipalFileNum = 0;
|
||||
|
||||
memset(&_paletteGfxMode, 0, sizeof(_paletteGfxMode));
|
||||
@ -50,7 +50,17 @@ GfxMgr::GfxMgr(AgiBase *vm) : _vm(vm) {
|
||||
|
||||
initPriorityTable();
|
||||
|
||||
_renderStartOffsetY = 0;
|
||||
_renderStartVisualOffsetY = 0;
|
||||
_renderStartDisplayOffsetY = 0;
|
||||
|
||||
_upscaledHires = DISPLAY_UPSCALED_DISABLED;
|
||||
_displayScreenWidth = DISPLAY_DEFAULT_WIDTH;
|
||||
_displayScreenHeight = DISPLAY_DEFAULT_HEIGHT;
|
||||
_displayFontWidth = 8;
|
||||
_displayFontHeight = 8;
|
||||
|
||||
_displayWidthMulAdjust = 0; // visualPos * (2+0) = displayPos
|
||||
_displayHeightMulAdjust = 0; // visualPos * (1+0) = displayPos
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,31 +135,45 @@ int GfxMgr::initVideo() {
|
||||
break;
|
||||
}
|
||||
|
||||
//bool forcedUpscale = true;
|
||||
|
||||
if (_font->isFontHires()) {
|
||||
// Upscaling enable
|
||||
_upscaledHires = DISPLAY_UPSCALED_640x400;
|
||||
_displayScreenWidth = 640;
|
||||
_displayScreenHeight = 400;
|
||||
_displayFontWidth = 16;
|
||||
_displayFontHeight = 16;
|
||||
|
||||
_displayWidthMulAdjust = 2;
|
||||
_displayHeightMulAdjust = 1;
|
||||
}
|
||||
|
||||
// set up mouse cursors
|
||||
switch (_vm->_renderMode) {
|
||||
case Common::kRenderEGA:
|
||||
case Common::kRenderCGA:
|
||||
case Common::kRenderVGA:
|
||||
initMouseCursor(&_mouseCursor, MOUSECURSOR_SCI, 11, 16, 1, 1);
|
||||
initMouseCursor(&_mouseCursor, MOUSECURSOR_SCI, 11, 16, 0, 0);
|
||||
initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_SCI_BUSY, 15, 16, 7, 8);
|
||||
break;
|
||||
case Common::kRenderAmiga:
|
||||
initMouseCursor(&_mouseCursor, MOUSECURSOR_AMIGA, 8, 11, 1, 1);
|
||||
initMouseCursor(&_mouseCursor, MOUSECURSOR_AMIGA, 8, 11, 0, 0);
|
||||
initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_AMIGA_BUSY, 13, 16, 7, 8);
|
||||
break;
|
||||
case Common::kRenderApple2GS:
|
||||
// had no special busy mouse cursor
|
||||
initMouseCursor(&_mouseCursor, MOUSECURSOR_APPLE_II_GS, 9, 11, 1, 1);
|
||||
initMouseCursor(&_mouseCursor, MOUSECURSOR_APPLE_II_GS, 9, 11, 0, 0);
|
||||
initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_SCI_BUSY, 15, 16, 7, 8);
|
||||
break;
|
||||
case Common::kRenderAtariST:
|
||||
initMouseCursor(&_mouseCursor, MOUSECURSOR_ATARI_ST, 11, 16, 1, 1);
|
||||
initMouseCursor(&_mouseCursor, MOUSECURSOR_ATARI_ST, 11, 16, 0, 0);
|
||||
initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_SCI_BUSY, 15, 16, 7, 8);
|
||||
break;
|
||||
case Common::kRenderMacintosh:
|
||||
// It looks like Atari ST + Macintosh used the same standard mouse cursor
|
||||
// TODO: Verify by checking actual hardware
|
||||
initMouseCursor(&_mouseCursor, MOUSECURSOR_ATARI_ST, 11, 16, 1, 1);
|
||||
initMouseCursor(&_mouseCursor, MOUSECURSOR_ATARI_ST, 11, 16, 0, 0);
|
||||
initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_MACINTOSH_BUSY, 10, 14, 7, 8);
|
||||
break;
|
||||
default:
|
||||
@ -158,15 +182,15 @@ int GfxMgr::initVideo() {
|
||||
}
|
||||
|
||||
_pixels = SCRIPT_WIDTH * SCRIPT_HEIGHT;
|
||||
_visualScreen = (byte *)calloc(_pixels, 1);
|
||||
_gameScreen = (byte *)calloc(_pixels, 1);
|
||||
_priorityScreen = (byte *)calloc(_pixels, 1);
|
||||
_activeScreen = _visualScreen;
|
||||
_activeScreen = _gameScreen;
|
||||
//_activeScreen = _priorityScreen;
|
||||
|
||||
_displayPixels = DISPLAY_WIDTH * DISPLAY_HEIGHT;
|
||||
_displayPixels = _displayScreenWidth * _displayScreenHeight;
|
||||
_displayScreen = (byte *)calloc(_displayPixels, 1);
|
||||
|
||||
initGraphics(DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_WIDTH > 320);
|
||||
initGraphics(_displayScreenWidth, _displayScreenHeight, _displayScreenWidth > 320);
|
||||
|
||||
setPalette(true); // set gfx-mode palette
|
||||
|
||||
@ -183,27 +207,151 @@ int GfxMgr::initVideo() {
|
||||
* @see init_video()
|
||||
*/
|
||||
int GfxMgr::deinitVideo() {
|
||||
// Free mouse cursors in case they were allocated
|
||||
if (_mouseCursor.bitmapDataAllocated)
|
||||
free(_mouseCursor.bitmapDataAllocated);
|
||||
if (_mouseCursorBusy.bitmapDataAllocated)
|
||||
free(_mouseCursorBusy.bitmapDataAllocated);
|
||||
|
||||
free(_displayScreen);
|
||||
free(_visualScreen);
|
||||
free(_gameScreen);
|
||||
free(_priorityScreen);
|
||||
|
||||
return errOK;
|
||||
}
|
||||
|
||||
void GfxMgr::setRenderStartOffset(uint16 offsetY) {
|
||||
if (offsetY >= (DISPLAY_HEIGHT - SCRIPT_HEIGHT))
|
||||
if (offsetY >= (VISUAL_HEIGHT - SCRIPT_HEIGHT))
|
||||
error("invalid render start offset");
|
||||
|
||||
_renderStartOffsetY = offsetY;
|
||||
_renderStartVisualOffsetY = offsetY;
|
||||
_renderStartDisplayOffsetY = offsetY * (1 + _displayHeightMulAdjust);
|
||||
}
|
||||
uint16 GfxMgr::getRenderStartOffsetY() {
|
||||
return _renderStartOffsetY;
|
||||
uint16 GfxMgr::getRenderStartDisplayOffsetY() {
|
||||
return _renderStartDisplayOffsetY;
|
||||
}
|
||||
|
||||
// Translates a game screen coordinate to a display screen coordinate
|
||||
// Game screen to 320x200 -> x * 2, y + renderStart
|
||||
// Game screen to 640x400 -> x * 4, (y * 2) + renderStart
|
||||
void GfxMgr::translateGamePosToDisplayScreen(int16 &x, int16 &y) {
|
||||
x = x * (2 + _displayWidthMulAdjust);
|
||||
y = y * (1 + _displayHeightMulAdjust) + _renderStartDisplayOffsetY;
|
||||
}
|
||||
|
||||
// Translates a visual coordinate to a display screen coordinate
|
||||
// Visual to 320x200 -> x * 2, y
|
||||
// Visual to 640x400 -> x * 4, y * 2
|
||||
void GfxMgr::translateVisualPosToDisplayScreen(int16 &x, int16 &y) {
|
||||
x = x * (2 + _displayWidthMulAdjust);
|
||||
y = y * (1 + _displayHeightMulAdjust);
|
||||
}
|
||||
|
||||
// Translates a display screen coordinate to a game screen coordinate
|
||||
// Display screen to 320x200 -> x / 2, y - renderStart
|
||||
// Display screen to 640x400 -> x / 4, (y / 2) - renderStart
|
||||
void GfxMgr::translateDisplayPosToGameScreen(int16 &x, int16 &y) {
|
||||
y -= _renderStartDisplayOffsetY; // remove status bar line
|
||||
x = x / (2 + _displayWidthMulAdjust);
|
||||
y = y / (1 + _displayHeightMulAdjust);
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
if (y >= SCRIPT_HEIGHT)
|
||||
y = SCRIPT_HEIGHT + 1; // 1 beyond
|
||||
}
|
||||
|
||||
// Translates dimension from visual screen to display screen
|
||||
void GfxMgr::translateVisualDimensionToDisplayScreen(int16 &width, int16 &height) {
|
||||
width = width * (2 + _displayWidthMulAdjust);
|
||||
height = height * (1 + _displayHeightMulAdjust);
|
||||
}
|
||||
|
||||
// Translates dimension from display screen to visual screen
|
||||
void GfxMgr::translateDisplayDimensionToVisualScreen(int16 &width, int16 &height) {
|
||||
width = width / (2 + _displayWidthMulAdjust);
|
||||
height = height / (1 + _displayHeightMulAdjust);
|
||||
}
|
||||
|
||||
// Translates a rect from game screen to display screen
|
||||
void GfxMgr::translateGameRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) {
|
||||
translateGamePosToDisplayScreen(x, y);
|
||||
translateVisualDimensionToDisplayScreen(width, height);
|
||||
}
|
||||
|
||||
// Translates a rect from visual screen to display screen
|
||||
void GfxMgr::translateVisualRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) {
|
||||
translateVisualPosToDisplayScreen(x, y);
|
||||
translateVisualDimensionToDisplayScreen(width, height);
|
||||
}
|
||||
|
||||
uint32 GfxMgr::getDisplayOffsetToGameScreenPos(int16 x, int16 y) {
|
||||
translateGamePosToDisplayScreen(x, y);
|
||||
return (y * _displayScreenWidth) + x;
|
||||
}
|
||||
|
||||
uint32 GfxMgr::getDisplayOffsetToVisualScreenPos(int16 x, int16 y) {
|
||||
translateVisualPosToDisplayScreen(x, y);
|
||||
return (y * _displayScreenWidth) + x;
|
||||
}
|
||||
|
||||
// Attention: uses display screen coordinates!
|
||||
void GfxMgr::copyDisplayRectToScreen(int16 x, int16 y, int16 width, int16 height) {
|
||||
g_system->copyRectToScreen(_displayScreen + y * _displayScreenWidth + x, _displayScreenWidth, x, y, width, height);
|
||||
}
|
||||
void GfxMgr::copyDisplayRectToScreen(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight) {
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
adjX *= 2; adjY *= 2;
|
||||
adjWidth *= 2; adjHeight *= 2;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
x += adjX; y += adjY;
|
||||
width += adjWidth; height += adjHeight;
|
||||
g_system->copyRectToScreen(_displayScreen + y * _displayScreenWidth + x, _displayScreenWidth, x, y, width, height);
|
||||
}
|
||||
void GfxMgr::copyDisplayRectToScreenUsingGamePos(int16 x, int16 y, int16 width, int16 height) {
|
||||
translateGameRectToDisplayScreen(x, y, width, height);
|
||||
g_system->copyRectToScreen(_displayScreen + (y * _displayScreenWidth) + x, _displayScreenWidth, x, y, width, height);
|
||||
}
|
||||
void GfxMgr::copyDisplayRectToScreenUsingVisualPos(int16 x, int16 y, int16 width, int16 height) {
|
||||
translateVisualRectToDisplayScreen(x, y, width, height);
|
||||
g_system->copyRectToScreen(_displayScreen + (y * _displayScreenWidth) + x, _displayScreenWidth, x, y, width, height);
|
||||
}
|
||||
void GfxMgr::copyDisplayToScreen() {
|
||||
g_system->copyRectToScreen(_displayScreen, _displayScreenWidth, 0, 0, _displayScreenWidth, _displayScreenHeight);
|
||||
}
|
||||
|
||||
void GfxMgr::translateFontPosToDisplayScreen(int16 &x, int16 &y) {
|
||||
x *= _displayFontWidth;
|
||||
y *= _displayFontHeight;
|
||||
}
|
||||
void GfxMgr::translateDisplayPosToFontScreen(int16 &x, int16 &y) {
|
||||
x /= _displayFontWidth;
|
||||
y /= _displayFontHeight;
|
||||
}
|
||||
void GfxMgr::translateFontDimensionToDisplayScreen(int16 &width, int16 &height) {
|
||||
width *= _displayFontWidth;
|
||||
height *= _displayFontHeight;
|
||||
}
|
||||
void GfxMgr::translateFontRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) {
|
||||
translateFontPosToDisplayScreen(x, y);
|
||||
translateFontDimensionToDisplayScreen(width, height);
|
||||
}
|
||||
Common::Rect GfxMgr::getFontRectForDisplayScreen(int16 column, int16 row, int16 width, int16 height) {
|
||||
Common::Rect displayRect(width * _displayFontWidth, height * _displayFontHeight);
|
||||
displayRect.moveTo(column * _displayFontWidth, row * _displayFontHeight);
|
||||
return displayRect;
|
||||
}
|
||||
|
||||
void GfxMgr::debugShowMap(int mapNr) {
|
||||
switch (mapNr) {
|
||||
case 0:
|
||||
_activeScreen = _visualScreen;
|
||||
_activeScreen = _gameScreen;
|
||||
break;
|
||||
case 1:
|
||||
_activeScreen = _priorityScreen;
|
||||
@ -212,11 +360,11 @@ void GfxMgr::debugShowMap(int mapNr) {
|
||||
break;
|
||||
}
|
||||
|
||||
render_Block(0, 167, SCRIPT_WIDTH, SCRIPT_HEIGHT);
|
||||
render_Block(0, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT);
|
||||
}
|
||||
|
||||
void GfxMgr::clear(byte color, byte priority) {
|
||||
memset(_visualScreen, color, _pixels);
|
||||
memset(_gameScreen, color, _pixels);
|
||||
memset(_priorityScreen, priority, _pixels);
|
||||
}
|
||||
|
||||
@ -224,7 +372,7 @@ void GfxMgr::clearDisplay(byte color, bool copyToScreen) {
|
||||
memset(_displayScreen, color, _displayPixels);
|
||||
|
||||
if (copyToScreen) {
|
||||
g_system->copyRectToScreen(_displayScreen, DISPLAY_WIDTH, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
|
||||
copyDisplayToScreen();
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,7 +380,7 @@ void GfxMgr::putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority
|
||||
int offset = y * SCRIPT_WIDTH + x;
|
||||
|
||||
if (drawMask & GFX_SCREEN_MASK_VISUAL) {
|
||||
_visualScreen[offset] = color;
|
||||
_gameScreen[offset] = color;
|
||||
}
|
||||
if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
|
||||
_priorityScreen[offset] = priority;
|
||||
@ -240,15 +388,72 @@ void GfxMgr::putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority
|
||||
}
|
||||
|
||||
void GfxMgr::putPixelOnDisplay(int16 x, int16 y, byte color) {
|
||||
int offset = y * DISPLAY_WIDTH + x;
|
||||
uint32 offset = 0;
|
||||
|
||||
_displayScreen[offset] = color;
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
offset = y * _displayScreenWidth + x;
|
||||
|
||||
_displayScreen[offset] = color;
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
offset = (y * _displayScreenWidth) + x;
|
||||
|
||||
_displayScreen[offset + 0] = color;
|
||||
_displayScreen[offset + 1] = color;
|
||||
_displayScreen[offset + _displayScreenWidth + 0] = color;
|
||||
_displayScreen[offset + _displayScreenWidth + 1] = color;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GfxMgr::putPixelOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, byte color) {
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
adjX *= 2; adjY *= 2;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
x += adjX;
|
||||
y += adjY;
|
||||
putPixelOnDisplay(x, y, color);
|
||||
}
|
||||
|
||||
void GfxMgr::putFontPixelOnDisplay(int16 baseX, int16 baseY, int16 addX, int16 addY, byte color, bool isHires) {
|
||||
uint32 offset = 0;
|
||||
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
offset = ((baseY + addY) * _displayScreenWidth) + (baseX + addX);
|
||||
_displayScreen[offset] = color;
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
if (isHires) {
|
||||
offset = ((baseY + addY) * _displayScreenWidth) + (baseX + addX);
|
||||
_displayScreen[offset] = color;
|
||||
} else {
|
||||
offset = ((baseY + addY * 2) * _displayScreenWidth) + (baseX + addX * 2);
|
||||
_displayScreen[offset + 0] = color;
|
||||
_displayScreen[offset + 1] = color;
|
||||
_displayScreen[offset + _displayScreenWidth + 0] = color;
|
||||
_displayScreen[offset + _displayScreenWidth + 1] = color;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
byte GfxMgr::getColor(int16 x, int16 y) {
|
||||
int offset = y * SCRIPT_WIDTH + x;
|
||||
|
||||
return _visualScreen[offset];
|
||||
return _gameScreen[offset];
|
||||
}
|
||||
|
||||
byte GfxMgr::getPriority(int16 x, int16 y) {
|
||||
@ -288,7 +493,8 @@ byte GfxMgr::getCGAMixtureColor(byte color) {
|
||||
return CGA_MixtureColorTable[color & 0x0F];
|
||||
}
|
||||
|
||||
// Attention: y-coordinate points to the LOWER left!
|
||||
// Attention: in our implementation, y-coordinate is upper left.
|
||||
// Sierra passed the lower left instead. We changed it to make upscaling easier.
|
||||
void GfxMgr::render_Block(int16 x, int16 y, int16 width, int16 height, bool copyToScreen) {
|
||||
if (!render_Clip(x, y, width, height))
|
||||
return;
|
||||
@ -304,17 +510,26 @@ void GfxMgr::render_Block(int16 x, int16 y, int16 width, int16 height, bool copy
|
||||
}
|
||||
|
||||
if (copyToScreen) {
|
||||
int16 upperY = y - height + 1 + _renderStartOffsetY;
|
||||
g_system->copyRectToScreen(_displayScreen + upperY * DISPLAY_WIDTH + x * 2, DISPLAY_WIDTH, x * 2, upperY, width * 2, height);
|
||||
copyDisplayRectToScreenUsingGamePos(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
bool GfxMgr::render_Clip(int16 &x, int16 &y, int16 &width, int16 &height, int16 clipAgainstWidth, int16 clipAgainstHeight) {
|
||||
if ((x >= clipAgainstWidth) || ((x + width - 1) < 0) ||
|
||||
(y < 0) || ((y - (height - 1)) >= clipAgainstHeight)) {
|
||||
(y < 0) || ((y + (height - 1)) >= clipAgainstHeight)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
height += y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if ((y + height - 1) >= clipAgainstHeight) {
|
||||
height = clipAgainstHeight - y;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ((y - height + 1) < 0)
|
||||
height = y + 1;
|
||||
|
||||
@ -322,6 +537,7 @@ bool GfxMgr::render_Clip(int16 &x, int16 &y, int16 &width, int16 &height, int16
|
||||
height -= y - (clipAgainstHeight - 1);
|
||||
y = clipAgainstHeight - 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (x < 0) {
|
||||
width += x;
|
||||
@ -335,44 +551,104 @@ bool GfxMgr::render_Clip(int16 &x, int16 &y, int16 &width, int16 &height, int16
|
||||
}
|
||||
|
||||
void GfxMgr::render_BlockEGA(int16 x, int16 y, int16 width, int16 height, bool copyToScreen) {
|
||||
int offsetVisual = SCRIPT_WIDTH * y + x;
|
||||
int offsetDisplay = (DISPLAY_WIDTH * (y + _renderStartOffsetY)) + x * 2;
|
||||
uint32 offsetVisual = SCRIPT_WIDTH * y + x;
|
||||
uint32 offsetDisplay = getDisplayOffsetToGameScreenPos(x, y);
|
||||
int16 remainingWidth = width;
|
||||
int16 remainingHeight = height;
|
||||
byte curColor = 0;
|
||||
int16 displayWidth = width * (2 + _displayWidthMulAdjust);
|
||||
|
||||
while (remainingHeight) {
|
||||
remainingWidth = width;
|
||||
while (remainingWidth) {
|
||||
curColor = _activeScreen[offsetVisual++];
|
||||
_displayScreen[offsetDisplay++] = curColor;
|
||||
_displayScreen[offsetDisplay++] = curColor;
|
||||
remainingWidth--;
|
||||
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
while (remainingWidth) {
|
||||
curColor = _activeScreen[offsetVisual++];
|
||||
_displayScreen[offsetDisplay++] = curColor;
|
||||
_displayScreen[offsetDisplay++] = curColor;
|
||||
remainingWidth--;
|
||||
}
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
while (remainingWidth) {
|
||||
curColor = _activeScreen[offsetVisual++];
|
||||
memset(&_displayScreen[offsetDisplay], curColor, 4);
|
||||
memset(&_displayScreen[offsetDisplay + _displayScreenWidth], curColor, 4);
|
||||
offsetDisplay += 4;
|
||||
remainingWidth--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
offsetVisual += SCRIPT_WIDTH - width;
|
||||
offsetDisplay += _displayScreenWidth - displayWidth;
|
||||
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
offsetDisplay += _displayScreenWidth;;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
offsetVisual -= SCRIPT_WIDTH + width;
|
||||
offsetDisplay -= DISPLAY_WIDTH + width * 2;
|
||||
|
||||
remainingHeight--;
|
||||
}
|
||||
}
|
||||
|
||||
void GfxMgr::render_BlockCGA(int16 x, int16 y, int16 width, int16 height, bool copyToScreen) {
|
||||
int offsetVisual = SCRIPT_WIDTH * y + x;
|
||||
int offsetDisplay = (DISPLAY_WIDTH * (y + _renderStartOffsetY)) + x * 2;
|
||||
uint32 offsetVisual = SCRIPT_WIDTH * y + x;
|
||||
uint32 offsetDisplay = getDisplayOffsetToGameScreenPos(x, y);
|
||||
int16 remainingWidth = width;
|
||||
int16 remainingHeight = height;
|
||||
byte curColor = 0;
|
||||
int16 displayWidth = width * (2 + _displayWidthMulAdjust);
|
||||
|
||||
while (remainingHeight) {
|
||||
remainingWidth = width;
|
||||
while (remainingWidth) {
|
||||
curColor = _activeScreen[offsetVisual++];
|
||||
_displayScreen[offsetDisplay++] = curColor & 0x03; // we process CGA mixture
|
||||
_displayScreen[offsetDisplay++] = curColor >> 2;
|
||||
remainingWidth--;
|
||||
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
while (remainingWidth) {
|
||||
curColor = _activeScreen[offsetVisual++];
|
||||
_displayScreen[offsetDisplay++] = curColor & 0x03; // we process CGA mixture
|
||||
_displayScreen[offsetDisplay++] = curColor >> 2;
|
||||
remainingWidth--;
|
||||
}
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
while (remainingWidth) {
|
||||
curColor = _activeScreen[offsetVisual++];
|
||||
_displayScreen[offsetDisplay + 0] = curColor & 0x03; // we process CGA mixture
|
||||
_displayScreen[offsetDisplay + 1] = curColor >> 2;
|
||||
_displayScreen[offsetDisplay + 2] = curColor & 0x03;
|
||||
_displayScreen[offsetDisplay + 3] = curColor >> 2;
|
||||
_displayScreen[offsetDisplay + _displayScreenWidth + 0] = curColor & 0x03;
|
||||
_displayScreen[offsetDisplay + _displayScreenWidth + 1] = curColor >> 2;
|
||||
_displayScreen[offsetDisplay + _displayScreenWidth + 2] = curColor & 0x03;
|
||||
_displayScreen[offsetDisplay + _displayScreenWidth + 3] = curColor >> 2;
|
||||
offsetDisplay += 4;
|
||||
remainingWidth--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
offsetVisual += SCRIPT_WIDTH - width;
|
||||
offsetDisplay += _displayScreenWidth - displayWidth;
|
||||
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
offsetDisplay += _displayScreenWidth;;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
offsetVisual -= SCRIPT_WIDTH + width;
|
||||
offsetDisplay -= DISPLAY_WIDTH + width * 2;
|
||||
|
||||
remainingHeight--;
|
||||
}
|
||||
@ -380,7 +656,7 @@ void GfxMgr::render_BlockCGA(int16 x, int16 y, int16 width, int16 height, bool c
|
||||
|
||||
void GfxMgr::transition_Amiga() {
|
||||
uint16 screenPos = 1;
|
||||
uint16 screenStepPos = 1;
|
||||
uint32 screenStepPos = 1;
|
||||
int16 posY = 0, posX = 0;
|
||||
int16 stepCount = 0;
|
||||
|
||||
@ -402,15 +678,29 @@ void GfxMgr::transition_Amiga() {
|
||||
posY = screenStepPos / SCRIPT_WIDTH;
|
||||
posX = screenStepPos - (posY * SCRIPT_WIDTH);
|
||||
|
||||
posY += _renderStartOffsetY; // adjust to only update the main area, not the status bar
|
||||
posX *= 2; // adjust for display screen
|
||||
// Adjust to only update the game screen, not the status bar
|
||||
translateGamePosToDisplayScreen(posX, posY);
|
||||
|
||||
screenStepPos = (screenStepPos * 2) + (_renderStartOffsetY * DISPLAY_WIDTH); // adjust here too for display screen
|
||||
for (int16 multiPixel = 0; multiPixel < 4; multiPixel++) {
|
||||
g_system->copyRectToScreen(_displayScreen + screenStepPos, DISPLAY_WIDTH, posX, posY, 2, 1);
|
||||
screenStepPos += (0x1A40 * 2); // 6720d
|
||||
posY += 42;
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
for (int16 multiPixel = 0; multiPixel < 4; multiPixel++) {
|
||||
screenStepPos = (posY * _displayScreenWidth) + posX;
|
||||
g_system->copyRectToScreen(_displayScreen + screenStepPos, _displayScreenWidth, posX, posY, 2, 1);
|
||||
posY += 42;
|
||||
}
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
for (int16 multiPixel = 0; multiPixel < 4; multiPixel++) {
|
||||
screenStepPos = (posY * _displayScreenWidth) + posX;
|
||||
g_system->copyRectToScreen(_displayScreen + screenStepPos, _displayScreenWidth, posX, posY, 4, 2);
|
||||
posY += 42 * 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
stepCount++;
|
||||
if (stepCount == 220) {
|
||||
// 30 times for the whole transition, so should take around 0.5 seconds
|
||||
@ -433,7 +723,7 @@ void GfxMgr::transition_Amiga() {
|
||||
// Atari ST definitely had a hi-res transition using the full resolution unlike the Amiga transition.
|
||||
void GfxMgr::transition_AtariSt() {
|
||||
uint16 screenPos = 1;
|
||||
uint16 screenStepPos = 1;
|
||||
uint32 screenStepPos = 1;
|
||||
int16 posY = 0, posX = 0;
|
||||
int16 stepCount = 0;
|
||||
|
||||
@ -452,17 +742,31 @@ void GfxMgr::transition_AtariSt() {
|
||||
|
||||
if ((screenPos < 13440) && (screenPos & 1)) {
|
||||
screenStepPos = screenPos >> 1;
|
||||
posY = screenStepPos / DISPLAY_WIDTH;
|
||||
posX = screenStepPos - (posY * DISPLAY_WIDTH);
|
||||
posY = screenStepPos / DISPLAY_DEFAULT_WIDTH;
|
||||
posX = screenStepPos - (posY * DISPLAY_DEFAULT_WIDTH);
|
||||
|
||||
posY += _renderStartOffsetY; // adjust to only update the main area, not the status bar
|
||||
|
||||
screenStepPos = screenStepPos + (_renderStartOffsetY * DISPLAY_WIDTH); // adjust here too for display screen
|
||||
for (int16 multiPixel = 0; multiPixel < 8; multiPixel++) {
|
||||
g_system->copyRectToScreen(_displayScreen + screenStepPos, DISPLAY_WIDTH, posX, posY, 1, 1);
|
||||
screenStepPos += 0x1a40; // 6720d
|
||||
posY += 21;
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
posY += _renderStartDisplayOffsetY; // adjust to only update the main area, not the status bar
|
||||
for (int16 multiPixel = 0; multiPixel < 8; multiPixel++) {
|
||||
screenStepPos = (posY * _displayScreenWidth) + posX;
|
||||
g_system->copyRectToScreen(_displayScreen + screenStepPos, _displayScreenWidth, posX, posY, 1, 1);
|
||||
posY += 21;
|
||||
}
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
posX *= 2; posY *= 2;
|
||||
posY += _renderStartDisplayOffsetY; // adjust to only update the main area, not the status bar
|
||||
for (int16 multiPixel = 0; multiPixel < 8; multiPixel++) {
|
||||
screenStepPos = (posY * _displayScreenWidth) + posX;
|
||||
g_system->copyRectToScreen(_displayScreen + screenStepPos, _displayScreenWidth, posX, posY, 2, 2);
|
||||
posY += 21 * 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
stepCount++;
|
||||
if (stepCount == 168) {
|
||||
// 40 times for the whole transition, so should take around 0.7 seconds
|
||||
@ -493,7 +797,7 @@ void GfxMgr::block_save(int16 x, int16 y, int16 width, int16 height, byte *buffe
|
||||
//warning("block_save: %d, %d -> %d, %d", x, y, width, height);
|
||||
|
||||
while (remainingHeight) {
|
||||
memcpy(curBufferPtr, _visualScreen + offset, width);
|
||||
memcpy(curBufferPtr, _gameScreen + offset, width);
|
||||
offset += SCRIPT_WIDTH;
|
||||
curBufferPtr += width;
|
||||
remainingHeight--;
|
||||
@ -519,7 +823,7 @@ void GfxMgr::block_restore(int16 x, int16 y, int16 width, int16 height, byte *bu
|
||||
//warning("block_restore: %d, %d -> %d, %d", x, y, width, height);
|
||||
|
||||
while (remainingHeight) {
|
||||
memcpy(_visualScreen + offset, curBufferPtr, width);
|
||||
memcpy(_gameScreen + offset, curBufferPtr, width);
|
||||
offset += SCRIPT_WIDTH;
|
||||
curBufferPtr += width;
|
||||
remainingHeight--;
|
||||
@ -535,15 +839,8 @@ void GfxMgr::block_restore(int16 x, int16 y, int16 width, int16 height, byte *bu
|
||||
}
|
||||
}
|
||||
|
||||
// Attention: uses visual screen coordinates!
|
||||
void GfxMgr::copyDisplayRectToScreen(int16 x, int16 y, int16 width, int16 height) {
|
||||
g_system->copyRectToScreen(_displayScreen + y * DISPLAY_WIDTH + x, DISPLAY_WIDTH, x, y, width, height);
|
||||
}
|
||||
void GfxMgr::copyDisplayToScreen() {
|
||||
g_system->copyRectToScreen(_displayScreen, DISPLAY_WIDTH, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
|
||||
}
|
||||
|
||||
// coordinates are for visual screen, but are supposed to point somewhere inside the playscreen
|
||||
// x, y is the upper left. Sierra passed them as lower left. We change that to make upscaling easier.
|
||||
// attention: Clipping is done here against 160x200 instead of 160x168
|
||||
// Original interpreter didn't do any clipping, we do it for security.
|
||||
// Clipping against the regular script width/height must not be done,
|
||||
@ -551,13 +848,13 @@ void GfxMgr::copyDisplayToScreen() {
|
||||
// Going beyond 160x168 will result in messageboxes not getting fully removed
|
||||
// In KQ4's case, the scripts clear the screen that's why it works.
|
||||
void GfxMgr::drawBox(int16 x, int16 y, int16 width, int16 height, byte backgroundColor, byte lineColor) {
|
||||
if (!render_Clip(x, y, width, height, SCRIPT_WIDTH, DISPLAY_HEIGHT - _renderStartOffsetY))
|
||||
if (!render_Clip(x, y, width, height, VISUAL_WIDTH, VISUAL_HEIGHT - _renderStartVisualOffsetY))
|
||||
return;
|
||||
|
||||
// coordinate translation: visual-screen -> display-screen
|
||||
x = x * 2;
|
||||
y = y + _renderStartOffsetY; // drawDisplayRect paints anywhere on the whole screen, our coordinate is within playscreen
|
||||
width = width * 2; // width was given as visual width, we need display width
|
||||
translateVisualRectToDisplayScreen(x, y, width, height);
|
||||
|
||||
y = y + _renderStartDisplayOffsetY; // drawDisplayRect paints anywhere on the whole screen, our coordinate is within playscreen
|
||||
|
||||
// draw box background
|
||||
drawDisplayRect(x, y, width, height, backgroundColor);
|
||||
@ -567,27 +864,27 @@ void GfxMgr::drawBox(int16 x, int16 y, int16 width, int16 height, byte backgroun
|
||||
case Common::kRenderApple2GS:
|
||||
case Common::kRenderAmiga:
|
||||
// Slightly different window frame, and actually using 1-pixel width, which is "hi-res"
|
||||
drawDisplayRect(x + 2, y - 2, width - 4, 1, lineColor);
|
||||
drawDisplayRect(x + width - 3, y - 2, 1, height - 4, lineColor);
|
||||
drawDisplayRect(x + 2, y - height + 3, width - 4, 1, lineColor);
|
||||
drawDisplayRect(x + 2, y - 2, 1, height - 4, lineColor);
|
||||
drawDisplayRect(x, +2, y, +2, width, -4, 0, 1, lineColor);
|
||||
drawDisplayRect(x + width, -3, y, +2, 0, 1, height, -4, lineColor);
|
||||
drawDisplayRect(x, +2, y + height, -3, width, -4, 0, 1, lineColor);
|
||||
drawDisplayRect(x, +2, y, +2, 0, 1, height, -4, lineColor);
|
||||
break;
|
||||
case Common::kRenderMacintosh:
|
||||
// 1 pixel between box and frame lines. Frame lines were black
|
||||
drawDisplayRect(x + 1, y - 1, width - 2, 1, 0);
|
||||
drawDisplayRect(x + width - 2, y - 1, 1, height - 2, 0);
|
||||
drawDisplayRect(x + 1, y - height + 2, width - 2, 1, 0);
|
||||
drawDisplayRect(x + 1, y - 1, 1, height - 2, 0);
|
||||
drawDisplayRect(x, +1, y, +1, width, -2, 0, 1, 0);
|
||||
drawDisplayRect(x + width, -2, y, +1, 0, 1, height, -2, 0);
|
||||
drawDisplayRect(x, +1, y + height, -2, width, -2, 0, 1, 0);
|
||||
drawDisplayRect(x, +1, y, +1, 0, 1, height, -2, 0);
|
||||
break;
|
||||
case Common::kRenderCGA:
|
||||
case Common::kRenderEGA:
|
||||
case Common::kRenderVGA:
|
||||
case Common::kRenderAtariST:
|
||||
default:
|
||||
drawDisplayRect(x + 2, y - 1, width - 4, 1, lineColor);
|
||||
drawDisplayRect(x + width - 4, y - 2, 2, height - 4, lineColor);
|
||||
drawDisplayRect(x + 2, y - height + 2, width - 4, 1, lineColor);
|
||||
drawDisplayRect(x + 2, y - 2, 2, height - 4, lineColor);
|
||||
drawDisplayRect(x, +2, y, +1, width, -4, 0, 1, lineColor);
|
||||
drawDisplayRect(x + width, -4, y, +2, 0, 2, height, -4, lineColor);
|
||||
drawDisplayRect(x, +2, y + height, -2, width, -4, 0, 1, lineColor);
|
||||
drawDisplayRect(x, +2, y, +2, 0, 2, height, -4, lineColor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -604,25 +901,41 @@ void GfxMgr::drawDisplayRect(int16 x, int16 y, int16 width, int16 height, byte c
|
||||
break;
|
||||
}
|
||||
if (copyToScreen) {
|
||||
int16 upperY = y - height + 1;
|
||||
g_system->copyRectToScreen(_displayScreen + upperY * DISPLAY_WIDTH + x, DISPLAY_WIDTH, x, upperY, width, height);
|
||||
copyDisplayRectToScreen(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void GfxMgr::drawDisplayRect(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight, byte color, bool copyToScreen) {
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
x += adjX; y += adjY;
|
||||
width += adjWidth; height += adjHeight;
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
x += adjX * 2; y += adjY * 2;
|
||||
width += adjWidth * 2; height += adjHeight * 2;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
drawDisplayRect(x, y, width, height, color, copyToScreen);
|
||||
}
|
||||
|
||||
void GfxMgr::drawDisplayRectEGA(int16 x, int16 y, int16 width, int16 height, byte color) {
|
||||
int offsetDisplay = (DISPLAY_WIDTH * y) + x;
|
||||
uint32 offsetDisplay = (y * _displayScreenWidth) + x;
|
||||
int16 remainingHeight = height;
|
||||
|
||||
while (remainingHeight) {
|
||||
memset(_displayScreen + offsetDisplay, color, width);
|
||||
|
||||
offsetDisplay -= DISPLAY_WIDTH;
|
||||
offsetDisplay += _displayScreenWidth;
|
||||
remainingHeight--;
|
||||
}
|
||||
}
|
||||
|
||||
void GfxMgr::drawDisplayRectCGA(int16 x, int16 y, int16 width, int16 height, byte color) {
|
||||
int offsetDisplay = (DISPLAY_WIDTH * y) + x;
|
||||
uint32 offsetDisplay = (y * _displayScreenWidth) + x;
|
||||
int16 remainingHeight = height;
|
||||
int16 remainingWidth = width;
|
||||
byte CGAMixtureColor = getCGAMixtureColor(color);
|
||||
@ -643,18 +956,20 @@ void GfxMgr::drawDisplayRectCGA(int16 x, int16 y, int16 width, int16 height, byt
|
||||
remainingWidth -= 2;
|
||||
}
|
||||
|
||||
offsetDisplay -= DISPLAY_WIDTH;
|
||||
offsetDisplay += _displayScreenWidth;
|
||||
remainingHeight--;
|
||||
}
|
||||
}
|
||||
|
||||
// row + column are text-coordinates
|
||||
void GfxMgr::drawCharacter(int16 row, int16 column, byte character, byte foreground, byte background, bool disabledLook) {
|
||||
int16 x = column * FONT_DISPLAY_WIDTH;
|
||||
int16 y = row * FONT_DISPLAY_HEIGHT;
|
||||
int16 x = column;
|
||||
int16 y = row;
|
||||
byte transformXOR = 0;
|
||||
byte transformOR = 0;
|
||||
|
||||
translateFontPosToDisplayScreen(x, y);
|
||||
|
||||
// Now figure out, if special handling needs to be done
|
||||
if (_vm->_game.gfxMode) {
|
||||
if (background & 0x08) {
|
||||
@ -675,22 +990,43 @@ void GfxMgr::drawStringOnDisplay(int16 x, int16 y, const char *text, byte foregr
|
||||
while (*text) {
|
||||
drawCharacterOnDisplay(x, y, *text, foregroundColor, backgroundColor);
|
||||
text++;
|
||||
x += FONT_DISPLAY_WIDTH;
|
||||
x += _displayFontWidth;
|
||||
}
|
||||
}
|
||||
|
||||
void GfxMgr::drawStringOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, const char *text, byte foregroundColor, byte backgroundColor) {
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
x += adjX;
|
||||
y += adjY;
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
x += adjX * 2;
|
||||
y += adjY * 2;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
drawStringOnDisplay(x, y, text, foregroundColor, backgroundColor);
|
||||
}
|
||||
|
||||
void GfxMgr::drawCharacterOnDisplay(int16 x, int16 y, const byte character, byte foreground, byte background, byte transformXOR, byte transformOR) {
|
||||
int16 curX, curY;
|
||||
const byte *fontData;
|
||||
bool fontIsHires = _font->isFontHires();
|
||||
int16 fontHeight = fontIsHires ? 16 : FONT_DISPLAY_HEIGHT;
|
||||
int16 fontWidth = fontIsHires ? 16 : FONT_DISPLAY_WIDTH;
|
||||
int16 fontBytesPerCharacter = fontIsHires ? 32 : FONT_BYTES_PER_CHARACTER;
|
||||
byte curByte = 0;
|
||||
uint16 curBit;
|
||||
|
||||
// get font data of specified character
|
||||
fontData = _vm->getFontData() + character * FONT_BYTES_PER_CHARACTER;
|
||||
fontData = _font->getFontData() + character * fontBytesPerCharacter;
|
||||
|
||||
curBit = 0;
|
||||
for (curY = 0; curY < FONT_DISPLAY_HEIGHT; curY++) {
|
||||
for (curX = 0; curX < FONT_DISPLAY_WIDTH; curX++) {
|
||||
for (curY = 0; curY < fontHeight; curY++) {
|
||||
for (curX = 0; curX < fontWidth; curX++) {
|
||||
if (!curBit) {
|
||||
curByte = *fontData;
|
||||
// do transformations in case they are needed (invert/disabled look)
|
||||
@ -700,9 +1036,9 @@ void GfxMgr::drawCharacterOnDisplay(int16 x, int16 y, const byte character, byte
|
||||
curBit = 0x80;
|
||||
}
|
||||
if (curByte & curBit) {
|
||||
putPixelOnDisplay(x + curX, y + curY, foreground);
|
||||
putFontPixelOnDisplay(x, y, curX, curY, foreground, fontIsHires);
|
||||
} else {
|
||||
putPixelOnDisplay(x + curX, y + curY, background);
|
||||
putFontPixelOnDisplay(x, y, curX, curY, background, fontIsHires);
|
||||
}
|
||||
curBit = curBit >> 1;
|
||||
}
|
||||
@ -710,18 +1046,20 @@ void GfxMgr::drawCharacterOnDisplay(int16 x, int16 y, const byte character, byte
|
||||
transformOR ^= 0xFF;
|
||||
}
|
||||
|
||||
copyDisplayRectToScreen(x, y, FONT_DISPLAY_WIDTH, FONT_DISPLAY_HEIGHT);
|
||||
copyDisplayRectToScreen(x, y, _displayFontWidth, _displayFontHeight);
|
||||
}
|
||||
|
||||
#define SHAKE_VERTICAL_PIXELS 4
|
||||
#define SHAKE_HORIZONTAL_PIXELS 8
|
||||
#define SHAKE_HORIZONTAL_PIXELS 4
|
||||
|
||||
// Sierra used some EGA port trickery to do it, we have to do it by copying pixels around
|
||||
void GfxMgr::shakeScreen(int16 repeatCount) {
|
||||
int shakeNr, shakeCount;
|
||||
uint8 *blackSpace;
|
||||
int16 shakeHorizontalPixels = SHAKE_HORIZONTAL_PIXELS * (2 + _displayWidthMulAdjust);
|
||||
int16 shakeVerticalPixels = SHAKE_VERTICAL_PIXELS * (1 + _displayHeightMulAdjust);
|
||||
|
||||
if ((blackSpace = (uint8 *)calloc(SHAKE_HORIZONTAL_PIXELS * DISPLAY_WIDTH, 1)) == NULL)
|
||||
if ((blackSpace = (uint8 *)calloc(shakeVerticalPixels * _displayScreenWidth, 1)) == NULL)
|
||||
return;
|
||||
|
||||
shakeCount = repeatCount * 8; // effectively 4 shakes per repeat
|
||||
@ -733,10 +1071,10 @@ void GfxMgr::shakeScreen(int16 repeatCount) {
|
||||
// move back
|
||||
copyDisplayToScreen();
|
||||
} else {
|
||||
g_system->copyRectToScreen(_displayScreen, DISPLAY_WIDTH, SHAKE_HORIZONTAL_PIXELS, SHAKE_VERTICAL_PIXELS, DISPLAY_WIDTH - SHAKE_HORIZONTAL_PIXELS, DISPLAY_HEIGHT - SHAKE_VERTICAL_PIXELS);
|
||||
g_system->copyRectToScreen(_displayScreen, _displayScreenWidth, shakeHorizontalPixels, shakeVerticalPixels, _displayScreenWidth - shakeHorizontalPixels, _displayScreenHeight - shakeVerticalPixels);
|
||||
// additionally fill the remaining space with black
|
||||
g_system->copyRectToScreen(blackSpace, DISPLAY_WIDTH, 0, 0, DISPLAY_WIDTH, SHAKE_VERTICAL_PIXELS);
|
||||
g_system->copyRectToScreen(blackSpace, SHAKE_HORIZONTAL_PIXELS, 0, 0, SHAKE_HORIZONTAL_PIXELS, DISPLAY_HEIGHT);
|
||||
g_system->copyRectToScreen(blackSpace, _displayScreenWidth, 0, 0, _displayScreenWidth, shakeVerticalPixels);
|
||||
g_system->copyRectToScreen(blackSpace, shakeHorizontalPixels, 0, 0, shakeHorizontalPixels, _displayScreenHeight);
|
||||
}
|
||||
g_system->updateScreen();
|
||||
g_system->delayMillis(66); // Sierra waited for 4 V'Syncs, which is around 66 milliseconds
|
||||
@ -956,7 +1294,38 @@ int GfxMgr::getAGIPalFileNum() {
|
||||
}
|
||||
|
||||
void GfxMgr::initMouseCursor(MouseCursorData *mouseCursor, const byte *bitmapData, uint16 width, uint16 height, int hotspotX, int hotspotY) {
|
||||
mouseCursor->bitmapData = bitmapData;
|
||||
switch (_upscaledHires) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
mouseCursor->bitmapData = bitmapData;
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400: {
|
||||
mouseCursor->bitmapDataAllocated = (byte *)malloc(width * height * 4);
|
||||
mouseCursor->bitmapData = mouseCursor->bitmapDataAllocated;
|
||||
|
||||
// Upscale mouse cursor
|
||||
byte *upscaledData = mouseCursor->bitmapDataAllocated;
|
||||
|
||||
for (uint16 y = 0; y < height; y++) {
|
||||
for (uint16 x = 0; x < width; x++) {
|
||||
byte curColor = *bitmapData++;
|
||||
upscaledData[x * 2 + 0] = curColor;
|
||||
upscaledData[x * 2 + 1] = curColor;
|
||||
upscaledData[x * 2 + (width * 2) + 0] = curColor;
|
||||
upscaledData[x * 2 + (width * 2) + 1] = curColor;
|
||||
}
|
||||
upscaledData += width * 2 * 2;
|
||||
}
|
||||
|
||||
width *= 2;
|
||||
height *= 2;
|
||||
hotspotX *= 2;
|
||||
hotspotY *= 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
mouseCursor->width = width;
|
||||
mouseCursor->height = height;
|
||||
mouseCursor->hotspotX = hotspotX;
|
||||
|
@ -29,8 +29,15 @@ namespace Agi {
|
||||
|
||||
#define SCRIPT_WIDTH 160
|
||||
#define SCRIPT_HEIGHT 168
|
||||
#define DISPLAY_WIDTH 320
|
||||
#define DISPLAY_HEIGHT 200
|
||||
#define VISUAL_WIDTH 160
|
||||
#define VISUAL_HEIGHT 200
|
||||
#define DISPLAY_DEFAULT_WIDTH 320
|
||||
#define DISPLAY_DEFAULT_HEIGHT 200
|
||||
|
||||
enum GfxScreenUpscaledMode {
|
||||
DISPLAY_UPSCALED_DISABLED = 0,
|
||||
DISPLAY_UPSCALED_640x400 = 1
|
||||
};
|
||||
|
||||
class AgiEngine;
|
||||
|
||||
@ -42,6 +49,7 @@ enum GfxScreenMasks {
|
||||
|
||||
struct MouseCursorData {
|
||||
const byte *bitmapData;
|
||||
byte *bitmapDataAllocated;
|
||||
uint16 width;
|
||||
uint16 height;
|
||||
int hotspotX;
|
||||
@ -51,6 +59,7 @@ struct MouseCursorData {
|
||||
class GfxMgr {
|
||||
private:
|
||||
AgiBase *_vm;
|
||||
GfxFont *_font;
|
||||
|
||||
uint8 _paletteGfxMode[256 * 3];
|
||||
uint8 _paletteTextMode[256 * 3];
|
||||
@ -59,7 +68,7 @@ private:
|
||||
int _agipalFileNum;
|
||||
|
||||
public:
|
||||
GfxMgr(AgiBase *vm);
|
||||
GfxMgr(AgiBase *vm, GfxFont *font);
|
||||
|
||||
int initVideo();
|
||||
int deinitVideo();
|
||||
@ -73,18 +82,58 @@ public:
|
||||
void setMouseCursor(bool busy = false);
|
||||
|
||||
void setRenderStartOffset(uint16 offsetY);
|
||||
uint16 getRenderStartOffsetY();
|
||||
uint16 getRenderStartDisplayOffsetY();
|
||||
|
||||
void translateGamePosToDisplayScreen(int16 &x, int16 &y);
|
||||
void translateVisualPosToDisplayScreen(int16 &x, int16 &y);
|
||||
void translateDisplayPosToGameScreen(int16 &x, int16 &y);
|
||||
|
||||
void translateVisualDimensionToDisplayScreen(int16 &width, int16 &height);
|
||||
void translateDisplayDimensionToVisualScreen(int16 &width, int16 &height);
|
||||
|
||||
void translateGameRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height);
|
||||
void translateVisualRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height);
|
||||
void translateDisplayRectToVisualScreen(int16 &x, int16 &y, int16 &width, int16 &height);
|
||||
|
||||
uint32 getDisplayOffsetToGameScreenPos(int16 x, int16 y);
|
||||
uint32 getDisplayOffsetToVisualScreenPos(int16 x, int16 y);
|
||||
|
||||
void copyDisplayRectToScreen(int16 x, int16 y, int16 width, int16 height);
|
||||
void copyDisplayRectToScreen(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight);
|
||||
void copyDisplayRectToScreenUsingGamePos(int16 x, int16 y, int16 width, int16 height);
|
||||
void copyDisplayRectToScreenUsingVisualPos(int16 x, int16 y, int16 width, int16 height);
|
||||
void copyDisplayToScreen();
|
||||
|
||||
void translateFontPosToDisplayScreen(int16 &x, int16 &y);
|
||||
void translateDisplayPosToFontScreen(int16 &x, int16 &y);
|
||||
void translateFontDimensionToDisplayScreen(int16 &width, int16 &height);
|
||||
void translateFontRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height);
|
||||
Common::Rect getFontRectForDisplayScreen(int16 column, int16 row, int16 width, int16 height);
|
||||
|
||||
private:
|
||||
uint _pixels;
|
||||
//uint16 _displayWidth;
|
||||
//uint16 _displayHeight;
|
||||
uint _displayPixels;
|
||||
|
||||
byte *_activeScreen;
|
||||
byte *_visualScreen; // 160x168
|
||||
byte *_priorityScreen; // 160x168
|
||||
byte *_displayScreen; // 320x200
|
||||
byte *_gameScreen; // 160x168 - screen, where the actual game content is drawn to (actual graphics, not including status line, prompt, etc.)
|
||||
byte *_priorityScreen; // 160x168 - screen contains priority information of the game screen
|
||||
// the term "visual screen" is effectively the display screen, but at 160x200 resolution. Used for coordinate translation
|
||||
byte *_displayScreen; // 320x200 or 640x400 - screen, that the game is rendered to and which is then copied to framebuffer
|
||||
|
||||
uint16 _displayScreenWidth;
|
||||
uint16 _displayScreenHeight;
|
||||
|
||||
uint16 _displayFontWidth;
|
||||
uint16 _displayFontHeight;
|
||||
|
||||
uint16 _displayWidthMulAdjust;
|
||||
uint16 _displayHeightMulAdjust;
|
||||
|
||||
/**
|
||||
* This variable defines, if upscaled hires is active and what upscaled mode
|
||||
* is used.
|
||||
*/
|
||||
GfxScreenUpscaledMode _upscaledHires;
|
||||
|
||||
bool _priorityTableSet;
|
||||
uint8 _priorityTable[SCRIPT_HEIGHT]; /**< priority table */
|
||||
@ -92,15 +141,32 @@ private:
|
||||
MouseCursorData _mouseCursor;
|
||||
MouseCursorData _mouseCursorBusy;
|
||||
|
||||
uint16 _renderStartOffsetY;
|
||||
uint16 _renderStartVisualOffsetY;
|
||||
uint16 _renderStartDisplayOffsetY;
|
||||
|
||||
public:
|
||||
uint16 getDisplayScreenWidth() {
|
||||
return _displayScreenWidth;
|
||||
}
|
||||
uint16 getDisplayFontWidth() {
|
||||
return _displayFontWidth;
|
||||
}
|
||||
uint16 getDisplayFontHeight() {
|
||||
return _displayFontHeight;
|
||||
}
|
||||
|
||||
GfxScreenUpscaledMode getUpscaledHires() {
|
||||
return _upscaledHires;
|
||||
}
|
||||
|
||||
void debugShowMap(int mapNr);
|
||||
|
||||
void clear(byte color, byte priority);
|
||||
void clearDisplay(byte color, bool copyToScreen = true);
|
||||
void putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority);
|
||||
void putPixelOnDisplay(int16 x, int16 y, byte color);
|
||||
void putPixelOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, byte color);
|
||||
void putFontPixelOnDisplay(int16 baseX, int16 baseY, int16 addX, int16 addY, byte color, bool isHires);
|
||||
|
||||
byte getColor(int16 x, int16 y);
|
||||
byte getPriority(int16 x, int16 y);
|
||||
@ -122,11 +188,9 @@ public:
|
||||
void block_save(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr);
|
||||
void block_restore(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr);
|
||||
|
||||
void copyDisplayRectToScreen(int16 x, int16 y, int16 width, int16 height);
|
||||
void copyDisplayToScreen();
|
||||
|
||||
void drawBox(int16 x, int16 y, int16 width, int16 height, byte backgroundColor, byte lineColor);
|
||||
void drawDisplayRect(int16 x, int16 y, int16 width, int16 height, byte color, bool copyToScreen = true);
|
||||
void drawDisplayRect(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight, byte color, bool copyToScreen = true);
|
||||
private:
|
||||
void drawDisplayRectEGA(int16 x, int16 y, int16 width, int16 height, byte color);
|
||||
void drawDisplayRectCGA(int16 x, int16 y, int16 width, int16 height, byte color);
|
||||
@ -134,6 +198,7 @@ private:
|
||||
public:
|
||||
void drawCharacter(int16 row, int16 column, byte character, byte foreground, byte background, bool disabledLook);
|
||||
void drawStringOnDisplay(int16 x, int16 y, const char *text, byte foreground, byte background);
|
||||
void drawStringOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, const char *text, byte foregroundColor, byte backgroundColor);
|
||||
void drawCharacterOnDisplay(int16 x, int16 y, byte character, byte foreground, byte background, byte transformXOR = 0, byte transformOR = 0);
|
||||
|
||||
void shakeScreen(int16 repeatCount);
|
||||
|
@ -313,7 +313,8 @@ bool AgiEngine::handleMouseClicks(uint16 &key) {
|
||||
|
||||
if (!cycleInnerLoopIsActive()) {
|
||||
// Only do this, when no inner loop is currently active
|
||||
Common::Rect displayLineRect(DISPLAY_WIDTH, FONT_DISPLAY_HEIGHT);
|
||||
Common::Rect displayLineRect = _gfx->getFontRectForDisplayScreen(0, 0, FONT_COLUMN_CHARACTERS, 1);
|
||||
// Common::Rect displayLineRect(_gfx->getDisplayScreenWidth(), _gfx->getDisplayFontHeight());
|
||||
|
||||
if (displayLineRect.contains(_mouse.pos)) {
|
||||
// Mouse is inside first line of the screen
|
||||
@ -328,7 +329,7 @@ bool AgiEngine::handleMouseClicks(uint16 &key) {
|
||||
// Prompt is currently enabled
|
||||
int16 promptRow = _text->promptRow_Get();
|
||||
|
||||
displayLineRect.moveTo(0, promptRow * FONT_DISPLAY_HEIGHT);
|
||||
displayLineRect.moveTo(0, promptRow * _gfx->getDisplayFontHeight());
|
||||
|
||||
if (displayLineRect.contains(_mouse.pos)) {
|
||||
// and user clicked within the line of the prompt
|
||||
@ -351,9 +352,7 @@ bool AgiEngine::handleMouseClicks(uint16 &key) {
|
||||
_text->stringPos_Get(stringRow, stringColumn);
|
||||
stringMaxLen = _text->stringGetMaxLen();
|
||||
|
||||
Common::Rect displayRect(stringMaxLen * FONT_DISPLAY_WIDTH, FONT_DISPLAY_HEIGHT);
|
||||
displayRect.moveTo(stringColumn * FONT_DISPLAY_WIDTH, stringRow * FONT_DISPLAY_HEIGHT);
|
||||
|
||||
Common::Rect displayRect = _gfx->getFontRectForDisplayScreen(stringColumn, stringRow, stringMaxLen, 1);
|
||||
if (displayRect.contains(_mouse.pos)) {
|
||||
// user clicked inside the input space
|
||||
showPredictiveDialog();
|
||||
@ -493,7 +492,7 @@ bool AgiEngine::handleController(uint16 key) {
|
||||
// in case you walked to the log by using the mouse, so don't!!!
|
||||
int16 egoDestinationX = _mouse.pos.x;
|
||||
int16 egoDestinationY = _mouse.pos.y;
|
||||
adjustPosToGameScreen(egoDestinationX, egoDestinationY);
|
||||
_gfx->translateDisplayPosToGameScreen(egoDestinationX, egoDestinationY);
|
||||
|
||||
screenObjEgo->motionType = kMotionEgo;
|
||||
if (egoDestinationX < (screenObjEgo->xSize / 2)) {
|
||||
|
@ -49,8 +49,8 @@ GfxMenu::GfxMenu(AgiEngine *vm, GfxMgr *gfx, PictureMgr *picture, TextMgr *text)
|
||||
_drawnMenuNr = -1;
|
||||
_drawnMenuHeight = 0;
|
||||
_drawnMenuWidth = 0;
|
||||
_drawnMenuRow = 0;
|
||||
_drawnMenuColumn = 0;
|
||||
_drawnMenuY = 0;
|
||||
_drawnMenuX = 0;
|
||||
}
|
||||
|
||||
GfxMenu::~GfxMenu() {
|
||||
@ -323,8 +323,9 @@ void GfxMenu::execute() {
|
||||
|
||||
// Unless we are in "via mouse" mode. In that case check current mouse position
|
||||
if (viaMouse) {
|
||||
int16 mouseRow = _vm->_mouse.pos.y / FONT_DISPLAY_HEIGHT;
|
||||
int16 mouseColumn = _vm->_mouse.pos.x / FONT_DISPLAY_WIDTH;
|
||||
int16 mouseRow = _vm->_mouse.pos.y;
|
||||
int16 mouseColumn = _vm->_mouse.pos.x;
|
||||
_gfx->translateDisplayPosToFontScreen(mouseColumn, mouseRow);
|
||||
|
||||
mouseFindMenuSelection(mouseRow, mouseColumn, _drawnMenuNr, _mouseModeItemNr);
|
||||
}
|
||||
@ -368,7 +369,7 @@ void GfxMenu::execute() {
|
||||
// WORKAROUND: Playarea starts right at the stop, so instead of clearing that part, render it from playarea
|
||||
// Required for at least Donald Duck
|
||||
// This was not done by original AGI, which means the upper pixel line were cleared in this case.
|
||||
_gfx->render_Block(0, (1 * FONT_VISUAL_HEIGHT) - 1, SCRIPT_WIDTH, FONT_VISUAL_HEIGHT);
|
||||
_gfx->render_Block(0, 0, SCRIPT_WIDTH, FONT_VISUAL_HEIGHT);
|
||||
} else {
|
||||
_text->clearLine(0, 0);
|
||||
}
|
||||
@ -427,10 +428,11 @@ void GfxMenu::drawMenu(int16 selectedMenuNr, int16 selectedMenuItemNr) {
|
||||
// calculate active menu dimensions
|
||||
_drawnMenuHeight = (menuEntry->itemCount + 2) * FONT_VISUAL_HEIGHT;
|
||||
_drawnMenuWidth = (menuEntry->maxItemTextLen * FONT_VISUAL_WIDTH) + 8;
|
||||
_drawnMenuRow = (menuEntry->itemCount + 3 - _text->getWindowRowMin()) * FONT_VISUAL_HEIGHT - 1;
|
||||
_drawnMenuColumn = (itemEntry->column - 1) * FONT_VISUAL_WIDTH;
|
||||
_drawnMenuY = (1 - _text->getWindowRowMin()) * FONT_VISUAL_HEIGHT;
|
||||
//(menuEntry->itemCount + 3 - _text->getWindowRowMin()) * FONT_VISUAL_HEIGHT - 1;
|
||||
_drawnMenuX = (itemEntry->column - 1) * FONT_VISUAL_WIDTH;
|
||||
|
||||
_gfx->drawBox(_drawnMenuColumn, _drawnMenuRow, _drawnMenuWidth, _drawnMenuHeight, 15, 0);
|
||||
_gfx->drawBox(_drawnMenuX, _drawnMenuY, _drawnMenuWidth, _drawnMenuHeight, 15, 0);
|
||||
|
||||
while (itemCount) {
|
||||
if (itemNr == selectedMenuItemNr) {
|
||||
@ -448,7 +450,7 @@ void GfxMenu::removeActiveMenu(int16 selectedMenuNr) {
|
||||
drawMenuName(selectedMenuNr, false);
|
||||
|
||||
// overwrite actual menu items by rendering play screen
|
||||
_gfx->render_Block(_drawnMenuColumn, _drawnMenuRow, _drawnMenuWidth, _drawnMenuHeight);
|
||||
_gfx->render_Block(_drawnMenuX, _drawnMenuY, _drawnMenuWidth, _drawnMenuHeight);
|
||||
}
|
||||
|
||||
void GfxMenu::keyPress(uint16 newKey) {
|
||||
@ -549,8 +551,10 @@ void GfxMenu::keyPress(uint16 newKey) {
|
||||
// In "via mouse" mode, we check if user let go of the left mouse button and then select the item that way
|
||||
void GfxMenu::mouseEvent(uint16 newKey) {
|
||||
// Find out, where current mouse cursor actually is
|
||||
int16 mouseRow = _vm->_mouse.pos.y / FONT_DISPLAY_HEIGHT;
|
||||
int16 mouseColumn = _vm->_mouse.pos.x / FONT_DISPLAY_WIDTH;
|
||||
int16 mouseRow = _vm->_mouse.pos.y;
|
||||
int16 mouseColumn = _vm->_mouse.pos.x;
|
||||
|
||||
_gfx->translateDisplayPosToFontScreen(mouseColumn, mouseRow);
|
||||
|
||||
int16 activeMenuNr, activeItemNr;
|
||||
mouseFindMenuSelection(mouseRow, mouseColumn, activeMenuNr, activeItemNr);
|
||||
@ -638,7 +642,7 @@ void GfxMenu::mouseFindMenuSelection(int16 mouseRow, int16 mouseColumn, int16 &a
|
||||
|
||||
if (mouseRow == menuEntry->row) {
|
||||
// line match
|
||||
if ((mouseColumn >= menuEntry->column) && (mouseColumn <= (menuEntry->column + menuEntry->textLen))) {
|
||||
if ((mouseColumn >= menuEntry->column) && (mouseColumn < (menuEntry->column + menuEntry->textLen))) {
|
||||
// full match
|
||||
activeMenuNr = menuNr;
|
||||
activeMenuItemNr = -1; // no item selected
|
||||
@ -660,7 +664,7 @@ void GfxMenu::mouseFindMenuSelection(int16 mouseRow, int16 mouseColumn, int16 &a
|
||||
|
||||
if (mouseRow == itemEntry->row) {
|
||||
// line match
|
||||
if ((mouseColumn >= itemEntry->column) && (mouseColumn <= (itemEntry->column + itemEntry->textLen))) {
|
||||
if ((mouseColumn >= itemEntry->column) && (mouseColumn < (itemEntry->column + itemEntry->textLen))) {
|
||||
// full match
|
||||
if (itemEntry->enabled) {
|
||||
// Only see it, when it's currently enabled
|
||||
|
@ -111,8 +111,8 @@ private:
|
||||
|
||||
uint16 _drawnMenuHeight;
|
||||
uint16 _drawnMenuWidth;
|
||||
int16 _drawnMenuRow;
|
||||
int16 _drawnMenuColumn;
|
||||
int16 _drawnMenuY;
|
||||
int16 _drawnMenuX;
|
||||
|
||||
// Following variables are used in "via mouse" mode
|
||||
int16 _mouseModeItemNr;
|
||||
|
@ -2227,7 +2227,7 @@ void cmdMousePosn(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
|
||||
int16 mouseX = vm->_mouse.pos.x;
|
||||
int16 mouseY = vm->_mouse.pos.y;
|
||||
|
||||
state->_vm->adjustPosToGameScreen(mouseX, mouseY);
|
||||
vm->_gfx->translateDisplayPosToGameScreen(mouseX, mouseY);
|
||||
|
||||
vm->setVar(destVarNr1, mouseX);
|
||||
vm->setVar(destVarNr2, mouseY);
|
||||
|
@ -1001,7 +1001,7 @@ void PictureMgr::clear() {
|
||||
void PictureMgr::showPic() {
|
||||
debugC(8, kDebugLevelMain, "Show picture!");
|
||||
|
||||
_gfx->render_Block(0, 167, SCRIPT_WIDTH, SCRIPT_HEIGHT);
|
||||
_gfx->render_Block(0, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1014,8 +1014,7 @@ void PictureMgr::showPic(int16 x, int16 y, int16 pic_width, int16 pic_height) {
|
||||
|
||||
debugC(8, kDebugLevelMain, "Show picture!");
|
||||
|
||||
// render block requires lower left coordinate!
|
||||
_gfx->render_Block(x, pic_height + y - 1, pic_width, pic_height);
|
||||
_gfx->render_Block(x, y, pic_width, pic_height);
|
||||
}
|
||||
|
||||
void PictureMgr::showPicWithTransition() {
|
||||
@ -1038,13 +1037,13 @@ void PictureMgr::showPicWithTransition() {
|
||||
case Common::kRenderAmiga:
|
||||
case Common::kRenderApple2GS:
|
||||
// Platform Amiga/Apple II GS -> render and do Amiga transition
|
||||
_gfx->render_Block(0, 167, SCRIPT_WIDTH, SCRIPT_HEIGHT, false);
|
||||
_gfx->render_Block(0, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT, false);
|
||||
_gfx->transition_Amiga();
|
||||
return;
|
||||
break;
|
||||
case Common::kRenderAtariST:
|
||||
// Platform Atari ST used a different transition, looks "high-res" (full 320x168)
|
||||
_gfx->render_Block(0, 167, SCRIPT_WIDTH, SCRIPT_HEIGHT, false);
|
||||
_gfx->render_Block(0, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT, false);
|
||||
_gfx->transition_AtariSt();
|
||||
return;
|
||||
default:
|
||||
@ -1054,7 +1053,7 @@ void PictureMgr::showPicWithTransition() {
|
||||
}
|
||||
}
|
||||
|
||||
_gfx->render_Block(0, 167, SCRIPT_WIDTH, SCRIPT_HEIGHT);
|
||||
_gfx->render_Block(0, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT);
|
||||
}
|
||||
|
||||
// preagi needed functions (for plotPattern)
|
||||
|
@ -58,7 +58,7 @@ void PreAgiEngine::initialize() {
|
||||
initRenderMode();
|
||||
|
||||
_font = new GfxFont(this);
|
||||
_gfx = new GfxMgr(this);
|
||||
_gfx = new GfxMgr(this, _font);
|
||||
_picture = new PictureMgr(this, _gfx);
|
||||
|
||||
_font->init();
|
||||
@ -112,7 +112,7 @@ void PreAgiEngine::clearScreen(int attr, bool overrideDefault) {
|
||||
}
|
||||
|
||||
void PreAgiEngine::clearGfxScreen(int attr) {
|
||||
_gfx->drawDisplayRect(0, 0, DISPLAY_WIDTH - 1, IDI_MAX_ROW_PIC * 8 - 1, (attr & 0xF0) / 0x10);
|
||||
_gfx->drawDisplayRect(0, 0, DISPLAY_DEFAULT_WIDTH - 1, IDI_MAX_ROW_PIC * 8 - 1, (attr & 0xF0) / 0x10);
|
||||
}
|
||||
|
||||
// String functions
|
||||
|
@ -354,7 +354,8 @@ void SpritesMgr::showSprite(ScreenObjEntry *screenObj) {
|
||||
}
|
||||
|
||||
// render this block
|
||||
_gfx->render_Block(x, y, width, height);
|
||||
int16 upperY = y - height + 1;
|
||||
_gfx->render_Block(x, upperY, width, height);
|
||||
}
|
||||
|
||||
void SpritesMgr::showSprites(SpriteList &spriteList) {
|
||||
|
@ -751,21 +751,23 @@ bool SystemUI::askForVerification(const char *verifyText, const char *button1Tex
|
||||
// Buttons enabled, calculate button coordinates
|
||||
int16 msgBoxX = 0, msgBoxY = 0, msgBoxLowerY = 0;
|
||||
int16 msgBoxWidth = 0, msgBoxHeight = 0;
|
||||
int16 fontHeight = _gfx->getDisplayFontHeight();
|
||||
int16 fontWidth = _gfx->getDisplayFontWidth();
|
||||
|
||||
_text->getMessageBoxInnerDisplayDimensions(msgBoxX, msgBoxY, msgBoxWidth, msgBoxHeight);
|
||||
// Adjust Y coordinate to lower edge
|
||||
// Calculate lower Y
|
||||
msgBoxLowerY = msgBoxY + (msgBoxHeight - 1);
|
||||
|
||||
buttonEntry.active = false;
|
||||
if (button1Text) {
|
||||
buttonEntry.text = button1Text;
|
||||
buttonEntry.textWidth = strlen(button1Text) * FONT_DISPLAY_WIDTH;
|
||||
buttonEntry.textWidth = strlen(button1Text) * _gfx->getDisplayFontWidth();
|
||||
buttonEntry.isDefault = true;
|
||||
_buttonArray.push_back(buttonEntry);
|
||||
}
|
||||
if (button2Text) {
|
||||
buttonEntry.text = button2Text;
|
||||
buttonEntry.textWidth = strlen(button2Text) * FONT_DISPLAY_WIDTH;
|
||||
buttonEntry.textWidth = strlen(button2Text) * _gfx->getDisplayFontWidth();
|
||||
buttonEntry.isDefault = false;
|
||||
_buttonArray.push_back(buttonEntry);
|
||||
}
|
||||
@ -773,37 +775,30 @@ bool SystemUI::askForVerification(const char *verifyText, const char *button1Tex
|
||||
// Render-Mode specific calculations
|
||||
switch (_vm->_renderMode) {
|
||||
case Common::kRenderApple2GS:
|
||||
_buttonArray[0].rect = Common::Rect(14 + _buttonArray[0].textWidth, FONT_DISPLAY_HEIGHT + 6);
|
||||
_buttonArray[0].rect.moveTo(msgBoxX + 2, msgBoxLowerY - (8 + FONT_DISPLAY_HEIGHT + 2));
|
||||
|
||||
_buttonArray[0].rect = createRect(msgBoxX, +2, msgBoxLowerY - fontHeight, -(8 + 2), _buttonArray[0].textWidth, +14, fontHeight, +6);
|
||||
|
||||
if (_buttonArray.size() > 1) {
|
||||
int16 adjustedX = msgBoxX + msgBoxWidth - 10;
|
||||
_buttonArray[1].rect = Common::Rect(14 + _buttonArray[1].textWidth, FONT_DISPLAY_HEIGHT + 6);
|
||||
adjustedX -= _buttonArray[1].rect.width();
|
||||
_buttonArray[1].rect.moveTo(adjustedX, msgBoxLowerY - (8 + FONT_DISPLAY_HEIGHT + 2));
|
||||
int16 adjustedX = msgBoxX + msgBoxWidth - _buttonArray[1].textWidth; // - 10;
|
||||
_buttonArray[1].rect = createRect(adjustedX, -(14 + 10), _buttonArray[0].rect.top, 0, _buttonArray[1].textWidth, +14, fontHeight, +6);
|
||||
}
|
||||
break;
|
||||
|
||||
case Common::kRenderAmiga:
|
||||
_buttonArray[0].rect = Common::Rect(4 + _buttonArray[0].textWidth + 4, 2 + FONT_DISPLAY_HEIGHT + 2);
|
||||
_buttonArray[0].rect.moveTo(msgBoxX, msgBoxLowerY - _buttonArray[0].rect.height());
|
||||
case Common::kRenderAmiga: {
|
||||
_buttonArray[0].rect = createRect(msgBoxX, 0, msgBoxLowerY - fontHeight, -(2 + 2), _buttonArray[0].textWidth, +(4 + 4), fontHeight, +(2 + 2));
|
||||
|
||||
if (_buttonArray.size() > 1) {
|
||||
int16 adjustedX = msgBoxX + msgBoxWidth;
|
||||
_buttonArray[1].rect = Common::Rect(4 + _buttonArray[1].textWidth + 4, 2 + FONT_DISPLAY_HEIGHT + 2);
|
||||
adjustedX -= _buttonArray[1].rect.width();
|
||||
_buttonArray[1].rect.moveTo(adjustedX, msgBoxLowerY - _buttonArray[1].rect.height());
|
||||
int16 adjustedX = msgBoxX + msgBoxWidth - _buttonArray[1].textWidth;
|
||||
_buttonArray[1].rect = createRect(adjustedX, -(4 + 4), _buttonArray[0].rect.top, 0, _buttonArray[1].textWidth, +(4 + 4), fontHeight, +(2 + 2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Common::kRenderAtariST:
|
||||
_buttonArray[0].rect = Common::Rect(_buttonArray[0].textWidth, FONT_DISPLAY_HEIGHT);
|
||||
_buttonArray[0].rect.moveTo(msgBoxX + (5 * FONT_DISPLAY_WIDTH), msgBoxLowerY - FONT_DISPLAY_HEIGHT);
|
||||
_buttonArray[0].rect = createRect(msgBoxX + (5 * fontWidth), 0, msgBoxLowerY - fontHeight, 0, _buttonArray[0].textWidth, 0, fontHeight, 0);
|
||||
|
||||
if (_buttonArray.size() > 1) {
|
||||
int16 adjustedX = msgBoxX + msgBoxWidth - (5 * FONT_DISPLAY_WIDTH);
|
||||
_buttonArray[1].rect = Common::Rect(_buttonArray[1].textWidth, FONT_DISPLAY_HEIGHT);
|
||||
adjustedX -= _buttonArray[1].rect.width();
|
||||
_buttonArray[1].rect.moveTo(adjustedX, msgBoxLowerY - _buttonArray[1].rect.height());
|
||||
int16 adjustedX = msgBoxX + msgBoxWidth - (5 * fontWidth + _buttonArray[1].textWidth);
|
||||
_buttonArray[1].rect = createRect(adjustedX, 0, _buttonArray[0].rect.top, 0, _buttonArray[1].textWidth, 0, fontHeight, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -951,6 +946,25 @@ void SystemUI::askForVerificationKeyPress(uint16 newKey) {
|
||||
}
|
||||
}
|
||||
|
||||
Common::Rect SystemUI::createRect(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight) {
|
||||
switch (_gfx->getUpscaledHires()) {
|
||||
case DISPLAY_UPSCALED_DISABLED:
|
||||
break;
|
||||
case DISPLAY_UPSCALED_640x400:
|
||||
adjX *= 2; adjY *= 2;
|
||||
adjWidth *= 2; adjHeight *= 2;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
x += adjX; y += adjY;
|
||||
width += adjWidth; height += adjHeight;
|
||||
Common::Rect newRect(width, height);
|
||||
newRect.moveTo(x, y);
|
||||
return newRect;
|
||||
}
|
||||
|
||||
#define SYSTEMUI_BUTTONEDGE_APPLEIIGS_WIDTH 8
|
||||
#define SYSTEMUI_BUTTONEDGE_APPLEIIGS_HEIGHT 5
|
||||
|
||||
@ -998,20 +1012,20 @@ void SystemUI::drawButtonAppleIIgs(SystemUIButtonEntry *button) {
|
||||
}
|
||||
|
||||
// draw base box for it
|
||||
_gfx->drawDisplayRect(button->rect.left, button->rect.bottom - 1, button->rect.width(), button->rect.height(), backgroundColor, false);
|
||||
_gfx->drawDisplayRect(button->rect.left, button->rect.top, button->rect.width(), button->rect.height(), backgroundColor, false);
|
||||
|
||||
// draw inner lines
|
||||
_gfx->drawDisplayRect(button->rect.left + 1, button->rect.top - 1, button->rect.width() - 2, 1, 0, false); // upper horizontal
|
||||
_gfx->drawDisplayRect(button->rect.left - 2, button->rect.bottom - 2, 2, button->rect.height() - 2, 0, false); // left vertical
|
||||
_gfx->drawDisplayRect(button->rect.right, button->rect.bottom - 2, 2, button->rect.height() - 2, 0, false); // right vertical
|
||||
_gfx->drawDisplayRect(button->rect.left + 1, button->rect.bottom, button->rect.width() - 2, 1, 0, false); // lower horizontal
|
||||
_gfx->drawDisplayRect(button->rect.left, +1, button->rect.top, -1, button->rect.width(), -2, 0, 1, 0, false); // lower horizontal
|
||||
_gfx->drawDisplayRect(button->rect.left, -2, button->rect.top, +1, 0, 2, button->rect.height(), -2, 0, false); // left vertical
|
||||
_gfx->drawDisplayRect(button->rect.right, 0, button->rect.top, +1, 0, 2, button->rect.height(), -2, 0, false); // right vertical
|
||||
_gfx->drawDisplayRect(button->rect.left, +1, button->rect.bottom, 0, button->rect.width(), -2, 0, 1, 0, false); // upper horizontal
|
||||
|
||||
if (button->isDefault) {
|
||||
// draw outer lines
|
||||
_gfx->drawDisplayRect(button->rect.left, button->rect.top - 3, button->rect.width(), 1, 0, false); // upper horizontal
|
||||
_gfx->drawDisplayRect(button->rect.left - 5, button->rect.bottom - 2, 2, button->rect.height() - 2, 0, false); // left vertical
|
||||
_gfx->drawDisplayRect(button->rect.right + 3, button->rect.bottom - 2, 2, button->rect.height() - 2, 0, false); // right vertical
|
||||
_gfx->drawDisplayRect(button->rect.left, button->rect.bottom + 2, button->rect.width(), 1, 0, false); // lower horizontal
|
||||
_gfx->drawDisplayRect(button->rect.left, 0, button->rect.top, -3, button->rect.width(), 0, 0, 1, 0, false); // upper horizontal
|
||||
_gfx->drawDisplayRect(button->rect.left, -5, button->rect.top, +2, 0, 2, button->rect.height(), -2, 0, false); // left vertical
|
||||
_gfx->drawDisplayRect(button->rect.right, +3, button->rect.top, +2, 0, 2, button->rect.height(), -2, 0, false); // right vertical
|
||||
_gfx->drawDisplayRect(button->rect.left, 0, button->rect.bottom, +2, button->rect.width(), 0, 0, 1, 0, false); // lower horizontal
|
||||
|
||||
if (button->active)
|
||||
edgeBitmap = buttonEdgeAppleIIgsDefaultActive;
|
||||
@ -1026,18 +1040,18 @@ void SystemUI::drawButtonAppleIIgs(SystemUIButtonEntry *button) {
|
||||
}
|
||||
|
||||
// draw edge graphics
|
||||
drawButtonAppleIIgsEdgePixels(button->rect.left - 5, button->rect.top - 3, edgeBitmap, false, false);
|
||||
drawButtonAppleIIgsEdgePixels(button->rect.right + 4, button->rect.top - 3, edgeBitmap, true, false);
|
||||
drawButtonAppleIIgsEdgePixels(button->rect.left - 5, button->rect.bottom + 2, edgeBitmap, false, true);
|
||||
drawButtonAppleIIgsEdgePixels(button->rect.right + 4, button->rect.bottom + 2, edgeBitmap, true, true);
|
||||
drawButtonAppleIIgsEdgePixels(button->rect.left, -5, button->rect.top, -3, edgeBitmap, false, false);
|
||||
drawButtonAppleIIgsEdgePixels(button->rect.right, +4, button->rect.top, -3, edgeBitmap, true, false);
|
||||
drawButtonAppleIIgsEdgePixels(button->rect.left, -5, button->rect.bottom, +2, edgeBitmap, false, true);
|
||||
drawButtonAppleIIgsEdgePixels(button->rect.right, +4, button->rect.bottom, +2, edgeBitmap, true, true);
|
||||
|
||||
// Button text
|
||||
_gfx->drawStringOnDisplay(button->rect.left + 7, button->rect.top + 3, button->text, foregroundColor, backgroundColor);
|
||||
_gfx->drawStringOnDisplay(button->rect.left, +7, button->rect.top, +3, button->text, foregroundColor, backgroundColor);
|
||||
|
||||
_gfx->copyDisplayRectToScreen(button->rect.left - 5, button->rect.top - 3, button->rect.width() + 10, button->rect.height() + 6);
|
||||
_gfx->copyDisplayRectToScreen(button->rect.left, -5, button->rect.top, -3, button->rect.width(), +10, button->rect.height(), +6);
|
||||
}
|
||||
|
||||
void SystemUI::drawButtonAppleIIgsEdgePixels(int16 x, int16 y, byte *edgeBitmap, bool mirrored, bool upsideDown) {
|
||||
void SystemUI::drawButtonAppleIIgsEdgePixels(int16 x, int16 adjX, int16 y, int16 adjY, byte *edgeBitmap, bool mirrored, bool upsideDown) {
|
||||
int8 directionY = upsideDown ? -1 : +1;
|
||||
int8 directionX = mirrored ? -1 : +1;
|
||||
int8 curY = 0;
|
||||
@ -1055,9 +1069,9 @@ void SystemUI::drawButtonAppleIIgsEdgePixels(int16 x, int16 y, byte *edgeBitmap,
|
||||
|
||||
while (widthLeft) {
|
||||
if (curBitmapByte & curBitmapBit) {
|
||||
_gfx->putPixelOnDisplay(x + curX, y + curY, 0);
|
||||
_gfx->putPixelOnDisplay(x, adjX + curX, y, adjY + curY, 0);
|
||||
} else {
|
||||
_gfx->putPixelOnDisplay(x + curX, y + curY, 15);
|
||||
_gfx->putPixelOnDisplay(x, adjX + curX, y, adjY + curY, 15);
|
||||
}
|
||||
|
||||
curBitmapBit = curBitmapBit >> 1;
|
||||
@ -1092,12 +1106,11 @@ void SystemUI::drawButtonAmiga(SystemUIButtonEntry *button) {
|
||||
}
|
||||
|
||||
// draw base box for it
|
||||
_gfx->drawDisplayRect(button->rect.left, button->rect.bottom - 1, button->rect.width(), button->rect.height(), backgroundColor, false);
|
||||
_gfx->drawDisplayRect(button->rect.left, button->rect.top, button->rect.width(), button->rect.height(), backgroundColor, false);
|
||||
|
||||
// Button text
|
||||
_gfx->drawStringOnDisplay(button->rect.left + 4, button->rect.top + 2, button->text, foregroundColor, backgroundColor);
|
||||
_gfx->drawStringOnDisplay(button->rect.left, +4, button->rect.top, +2, button->text, foregroundColor, backgroundColor);
|
||||
|
||||
// draw base box for it
|
||||
_gfx->copyDisplayRectToScreen(button->rect.left, button->rect.top, button->rect.width(), button->rect.height());
|
||||
}
|
||||
|
||||
|
@ -107,9 +107,12 @@ private:
|
||||
private:
|
||||
SystemUIButtonArray _buttonArray;
|
||||
|
||||
Common::Rect createRect(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight);
|
||||
//void moveRect(int16 x, int16 adjX, int16 y, int16 adjY);
|
||||
|
||||
void drawButton(SystemUIButtonEntry *button);
|
||||
void drawButtonAppleIIgs(SystemUIButtonEntry *buttonEntry);
|
||||
void drawButtonAppleIIgsEdgePixels(int16 x, int16 y, byte *edgeBitmap, bool mirrored, bool upsideDown);
|
||||
void drawButtonAppleIIgsEdgePixels(int16 x, int16 adjX, int16 y, int16 adjY, byte *edgeBitmap, bool mirrored, bool upsideDown);
|
||||
void drawButtonAmiga(SystemUIButtonEntry *buttonEntry);
|
||||
void drawButtonAtariST(SystemUIButtonEntry *buttonEntry);
|
||||
|
||||
|
@ -88,7 +88,7 @@ void TextMgr::configureScreen(uint16 row_Min) {
|
||||
_window_Row_Max = row_Min + 21;
|
||||
|
||||
// forward data to GfxMgr as well
|
||||
_gfx->setRenderStartOffset(row_Min * FONT_DISPLAY_HEIGHT);
|
||||
_gfx->setRenderStartOffset(row_Min * FONT_VISUAL_HEIGHT);
|
||||
}
|
||||
uint16 TextMgr::getWindowRowMin() {
|
||||
return _window_Row_Min;
|
||||
@ -466,7 +466,8 @@ void TextMgr::drawMessageBox(const char *textPtr, int16 forcedHeight, int16 want
|
||||
_messageState.backgroundSize_Width = (_messageState.textSize_Width * FONT_VISUAL_WIDTH) + 10;
|
||||
_messageState.backgroundSize_Height = (_messageState.textSize_Height * FONT_VISUAL_HEIGHT) + 10;
|
||||
_messageState.backgroundPos_x = (_messageState.textPos.column * FONT_VISUAL_WIDTH) - 5;
|
||||
_messageState.backgroundPos_y = (_messageState.textPos_Edge.row - _window_Row_Min + 1) * FONT_VISUAL_HEIGHT + 4;
|
||||
_messageState.backgroundPos_y = (startingRow * FONT_VISUAL_HEIGHT) - 5;
|
||||
// original AGI used lowerY here, calculated using (_messageState.textPos_Edge.row - _window_Row_Min + 1) * FONT_VISUAL_HEIGHT + 4;
|
||||
|
||||
// Hardcoded colors: white background and red lines
|
||||
_gfx->drawBox(_messageState.backgroundPos_x, _messageState.backgroundPos_y, _messageState.backgroundSize_Width, _messageState.backgroundSize_Height, 15, 4);
|
||||
@ -487,10 +488,11 @@ void TextMgr::getMessageBoxInnerDisplayDimensions(int16 &x, int16 &y, int16 &wid
|
||||
if (!_messageState.window_Active)
|
||||
return;
|
||||
|
||||
y = _messageState.textPos.row * FONT_DISPLAY_HEIGHT;
|
||||
x = _messageState.textPos.column * FONT_DISPLAY_WIDTH;
|
||||
width = _messageState.textSize_Width * FONT_DISPLAY_WIDTH;
|
||||
height = _messageState.textSize_Height * FONT_DISPLAY_HEIGHT;
|
||||
y = _messageState.textPos.row;
|
||||
x = _messageState.textPos.column;
|
||||
width = _messageState.textSize_Width;
|
||||
height = _messageState.textSize_Height;
|
||||
_gfx->translateFontRectToDisplayScreen(x, y, width, height);
|
||||
}
|
||||
|
||||
bool TextMgr::isMouseWithinMessageBox() {
|
||||
@ -499,10 +501,10 @@ bool TextMgr::isMouseWithinMessageBox() {
|
||||
int16 mouseX = _vm->_mouse.pos.x;
|
||||
|
||||
if (_messageState.window_Active) {
|
||||
_vm->adjustPosToGameScreen(mouseX, mouseY);
|
||||
_gfx->translateDisplayPosToGameScreen(mouseX, mouseY);
|
||||
|
||||
if ((mouseX >= _messageState.backgroundPos_x) && (mouseX <= (_messageState.backgroundPos_x + _messageState.backgroundSize_Width))) {
|
||||
if ((mouseY >= _messageState.backgroundPos_y - _messageState.backgroundSize_Height) && (mouseY <= (_messageState.backgroundPos_y))) {
|
||||
if ((mouseX >= _messageState.backgroundPos_x) && (mouseX < (_messageState.backgroundPos_x + _messageState.backgroundSize_Width))) {
|
||||
if ((mouseY >= _messageState.backgroundPos_y) && (mouseY < (_messageState.backgroundPos_y + _messageState.backgroundSize_Height))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -581,12 +583,12 @@ void TextMgr::clearBlock(int16 row_Upper, int16 column_Upper, int16 row_Lower, i
|
||||
charPos_Clip(row_Upper, column_Upper);
|
||||
charPos_Clip(row_Lower, column_Lower);
|
||||
|
||||
int16 x = column_Upper * FONT_DISPLAY_WIDTH;
|
||||
int16 y = row_Upper * FONT_DISPLAY_HEIGHT;
|
||||
int16 width = (column_Lower + 1 - column_Upper) * FONT_DISPLAY_WIDTH;
|
||||
int16 height = (row_Lower + 1 - row_Upper) * FONT_DISPLAY_HEIGHT;
|
||||
int16 x = column_Upper;
|
||||
int16 y = row_Upper;
|
||||
int16 width = (column_Lower + 1 - column_Upper);
|
||||
int16 height = (row_Lower + 1 - row_Upper);
|
||||
_gfx->translateFontRectToDisplayScreen(x, y, width, height);
|
||||
|
||||
y = y + height - 1; // drawDisplayRect wants lower Y-coordinate
|
||||
_gfx->drawDisplayRect(x, y, width, height, color);
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ struct MessageState_Struct {
|
||||
uint16 printed_Height;
|
||||
|
||||
int16 backgroundPos_x;
|
||||
int16 backgroundPos_y;
|
||||
int16 backgroundPos_y; // original AGI used lowerY here, we use upperY so that upscaling is easier
|
||||
int16 backgroundSize_Width;
|
||||
int16 backgroundSize_Height;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user