[Scummvm-git-logs] scummvm master -> ce2410f7a3241ed4e7da15049be8ae6c96327b8c
sluicebox
noreply at scummvm.org
Tue Oct 29 04:04:38 UTC 2024
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
7c46ab8ce8 AGI: Cleanup GfxMgr, PictureMgr
a5909e5f60 AGI: Move AGI256 picture opcode into function
f15c08bfb6 AGI: Remove extra AGI256 picture render
ce2410f7a3 AGI: Update Apple IIgs opcodes
Commit: 7c46ab8ce86e367f285a3bbbb6164cd4015e7fea
https://github.com/scummvm/scummvm/commit/7c46ab8ce86e367f285a3bbbb6164cd4015e7fea
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2024-10-28T21:02:51-07:00
Commit Message:
AGI: Cleanup GfxMgr, PictureMgr
Changed paths:
engines/agi/graphics.cpp
engines/agi/graphics.h
engines/agi/picture.cpp
engines/agi/picture.h
engines/agi/preagi/mickey.cpp
engines/agi/preagi/winnie.cpp
engines/agi/sound_coco3.cpp
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index e8c457b9aa1..1bb1d202320 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -235,14 +235,15 @@ void GfxMgr::setRenderStartOffset(uint16 offsetY) {
_renderStartVisualOffsetY = offsetY;
_renderStartDisplayOffsetY = offsetY * (1 + _displayHeightMulAdjust);
}
-uint16 GfxMgr::getRenderStartDisplayOffsetY() {
+
+uint16 GfxMgr::getRenderStartDisplayOffsetY() const {
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) {
+void GfxMgr::translateGamePosToDisplayScreen(int16 &x, int16 &y) const {
x = x * (2 + _displayWidthMulAdjust);
y = y * (1 + _displayHeightMulAdjust) + _renderStartDisplayOffsetY;
}
@@ -250,7 +251,7 @@ void GfxMgr::translateGamePosToDisplayScreen(int16 &x, int16 &y) {
// 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) {
+void GfxMgr::translateVisualPosToDisplayScreen(int16 &x, int16 &y) const {
x = x * (2 + _displayWidthMulAdjust);
y = y * (1 + _displayHeightMulAdjust);
}
@@ -258,7 +259,7 @@ void GfxMgr::translateVisualPosToDisplayScreen(int16 &x, int16 &y) {
// 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) {
+void GfxMgr::translateDisplayPosToGameScreen(int16 &x, int16 &y) const {
y -= _renderStartDisplayOffsetY; // remove status bar line
x = x / (2 + _displayWidthMulAdjust);
y = y / (1 + _displayHeightMulAdjust);
@@ -269,35 +270,35 @@ void GfxMgr::translateDisplayPosToGameScreen(int16 &x, int16 &y) {
}
// Translates dimension from visual screen to display screen
-void GfxMgr::translateVisualDimensionToDisplayScreen(int16 &width, int16 &height) {
+void GfxMgr::translateVisualDimensionToDisplayScreen(int16 &width, int16 &height) const {
width = width * (2 + _displayWidthMulAdjust);
height = height * (1 + _displayHeightMulAdjust);
}
// Translates dimension from display screen to visual screen
-void GfxMgr::translateDisplayDimensionToVisualScreen(int16 &width, int16 &height) {
+void GfxMgr::translateDisplayDimensionToVisualScreen(int16 &width, int16 &height) const {
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) {
+void GfxMgr::translateGameRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) const {
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) {
+void GfxMgr::translateVisualRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) const {
translateVisualPosToDisplayScreen(x, y);
translateVisualDimensionToDisplayScreen(width, height);
}
-uint32 GfxMgr::getDisplayOffsetToGameScreenPos(int16 x, int16 y) {
+uint32 GfxMgr::getDisplayOffsetToGameScreenPos(int16 x, int16 y) const {
translateGamePosToDisplayScreen(x, y);
return (y * _displayScreenWidth) + x;
}
-uint32 GfxMgr::getDisplayOffsetToVisualScreenPos(int16 x, int16 y) {
+uint32 GfxMgr::getDisplayOffsetToVisualScreenPos(int16 x, int16 y) const {
translateVisualPosToDisplayScreen(x, y);
return (y * _displayScreenWidth) + x;
}
@@ -313,6 +314,7 @@ void GfxMgr::copyDisplayRectToScreen(int16 x, int16 y, int16 width, int16 height
_vm->_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:
@@ -329,35 +331,42 @@ void GfxMgr::copyDisplayRectToScreen(int16 x, int16 adjX, int16 y, int16 adjY, i
width += adjWidth; height += adjHeight;
_vm->_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);
_vm->_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);
_vm->_system->copyRectToScreen(_displayScreen + (y * _displayScreenWidth) + x, _displayScreenWidth, x, y, width, height);
}
+
void GfxMgr::copyDisplayToScreen() {
_vm->_system->copyRectToScreen(_displayScreen, _displayScreenWidth, 0, 0, _displayScreenWidth, _displayScreenHeight);
}
-void GfxMgr::translateFontPosToDisplayScreen(int16 &x, int16 &y) {
+void GfxMgr::translateFontPosToDisplayScreen(int16 &x, int16 &y) const {
x *= _displayFontWidth;
y *= _displayFontHeight;
}
-void GfxMgr::translateDisplayPosToFontScreen(int16 &x, int16 &y) {
+
+void GfxMgr::translateDisplayPosToFontScreen(int16 &x, int16 &y) const {
x /= _displayFontWidth;
y /= _displayFontHeight;
}
-void GfxMgr::translateFontDimensionToDisplayScreen(int16 &width, int16 &height) {
+
+void GfxMgr::translateFontDimensionToDisplayScreen(int16 &width, int16 &height) const {
width *= _displayFontWidth;
height *= _displayFontHeight;
}
-void GfxMgr::translateFontRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) {
+
+void GfxMgr::translateFontRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) const {
translateFontPosToDisplayScreen(x, y);
translateFontDimensionToDisplayScreen(width, height);
}
-Common::Rect GfxMgr::getFontRectForDisplayScreen(int16 column, int16 row, int16 width, int16 height) {
+
+Common::Rect GfxMgr::getFontRectForDisplayScreen(int16 column, int16 row, int16 width, int16 height) const {
Common::Rect displayRect(width * _displayFontWidth, height * _displayFontHeight);
displayRect.moveTo(column * _displayFontWidth, row * _displayFontHeight);
return displayRect;
@@ -378,11 +387,17 @@ void GfxMgr::debugShowMap(int mapNr) {
render_Block(0, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT);
}
+/**
+ * Clears the game and priority screens
+ */
void GfxMgr::clear(byte color, byte priority) {
memset(_gameScreen, color, _pixels);
memset(_priorityScreen, priority, _pixels);
}
+/**
+ * Clears the display screen and copies it to screen
+ */
void GfxMgr::clearDisplay(byte color, bool copyToScreen) {
memset(_displayScreen, color, _displayPixels);
@@ -391,6 +406,9 @@ void GfxMgr::clearDisplay(byte color, bool copyToScreen) {
}
}
+/**
+ * Puts a pixel on the game and/or priority screens
+ */
void GfxMgr::putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority) {
int offset = y * SCRIPT_WIDTH + x;
@@ -402,6 +420,10 @@ void GfxMgr::putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority
}
}
+/**
+ * Puts a pixel on the display screen.
+ * If upscaling is enabled then the pixel and coordinates are upscaled.
+ */
void GfxMgr::putPixelOnDisplay(int16 x, int16 y, byte color) {
uint32 offset = 0;
@@ -424,6 +446,10 @@ void GfxMgr::putPixelOnDisplay(int16 x, int16 y, byte color) {
}
}
+/**
+ * Puts a pixel on the display screen.
+ * If upscaling is enabled then the pixel and coordinates are upscaled.
+ */
void GfxMgr::putPixelOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, byte color) {
switch (_upscaledHires) {
case DISPLAY_UPSCALED_DISABLED:
@@ -440,6 +466,11 @@ void GfxMgr::putPixelOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, byte co
putPixelOnDisplay(x, y, color);
}
+/**
+ * Puts a font pixel on the display screen.
+ * If upscaling is enabled then isHires determines if the pixel and coordinates
+ * are to be used as is or upscaled.
+ */
void GfxMgr::putFontPixelOnDisplay(int16 baseX, int16 baseY, int16 addX, int16 addY, byte color, bool isHires) {
uint32 offset = 0;
@@ -465,13 +496,19 @@ void GfxMgr::putFontPixelOnDisplay(int16 baseX, int16 baseY, int16 addX, int16 a
}
}
-byte GfxMgr::getColor(int16 x, int16 y) {
+/**
+ * Returns a color from the game screen
+ */
+byte GfxMgr::getColor(int16 x, int16 y) const {
int offset = y * SCRIPT_WIDTH + x;
return _gameScreen[offset];
}
-byte GfxMgr::getPriority(int16 x, int16 y) {
+/**
+ * Returns a priority from the priority screen
+ */
+byte GfxMgr::getPriority(int16 x, int16 y) const {
int offset = y * SCRIPT_WIDTH + x;
return _priorityScreen[offset];
@@ -479,7 +516,7 @@ byte GfxMgr::getPriority(int16 x, int16 y) {
// used, when a control pixel is found
// will search downwards and compare priority in case any is found
-bool GfxMgr::checkControlPixel(int16 x, int16 y, byte viewPriority) {
+bool GfxMgr::checkControlPixel(int16 x, int16 y, byte viewPriority) const {
int offset = y * SCRIPT_WIDTH + x;
byte curPriority;
@@ -499,19 +536,23 @@ bool GfxMgr::checkControlPixel(int16 x, int16 y, byte viewPriority) {
return false; // view priority is lower, don't draw
}
-static byte CGA_MixtureColorTable[] = {
+static const byte CGA_MixtureColorTable[] = {
0x00, 0x08, 0x04, 0x0C, 0x01, 0x09, 0x02, 0x05,
0x0A, 0x0D, 0x06, 0x0E, 0x0B, 0x03, 0x07, 0x0F
};
-byte GfxMgr::getCGAMixtureColor(byte color) {
+byte GfxMgr::getCGAMixtureColor(byte color) const {
return CGA_MixtureColorTable[color & 0x0F];
}
+/**
+ * Renders a block of the game screen on to the display screen.
+ * Optionally copies the display block to screen immediately.
+ */
// 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)) {
+ if (!render_Clip(x, y, width, height, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT)) {
warning("render_Block ignored by clipping. x: %d, y: %d, w: %d, h: %d", x, y, width, height);
return;
}
@@ -912,8 +953,11 @@ void GfxMgr::transition_AtariSt() {
_vm->_system->updateScreen();
}
+/**
+ * Copies a block of the game and priority screens to a buffer
+ */
// Attention: y coordinate is here supposed to be the upper one!
-void GfxMgr::block_save(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr) {
+void GfxMgr::block_save(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr) const {
int16 startOffset = y * SCRIPT_WIDTH + x;
int16 offset = startOffset;
int16 remainingHeight = height;
@@ -938,6 +982,9 @@ void GfxMgr::block_save(int16 x, int16 y, int16 width, int16 height, byte *buffe
}
}
+/**
+ * Copies a buffer filled by block_save back to the game and priority screens
+ */
// Attention: y coordinate is here supposed to be the upper one!
void GfxMgr::block_restore(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr) {
int16 startOffset = y * SCRIPT_WIDTH + x;
@@ -964,18 +1011,23 @@ void GfxMgr::block_restore(int16 x, int16 y, int16 width, int16 height, byte *bu
}
}
-// 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,
-// because at least during the intro one message box goes beyond playscreen
-// 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.
+/**
+ * Draw a box with a border on the display screen.
+ * Currently only used when drawing a message box or an expanded menu.
+ * Coordinates are for the visual screen instead of the game screen, because
+ * while boxes are generally within the game area, there are exceptions:
+ * - KQ4 intro displays a message box that extends below the game area.
+ * This would normally result in the message box not being fully removed,
+ * but the script clears the screen afterwards so it works.
+ * - MMMG nursery rhyme message boxes appear over the menu bar.
+ * The scripts pass a y-coordinate of zero to print.at(). Bug #13820
+ * The original interpreter didn't do any clipping; we clip against the visual
+ * screen to prevent out of bounds writes while allowing boxes to be drawn outside
+ * of the game area. The visual screen is 160x200 normally, 140x192 for Apple II.
+ * The x, y parameters are the upper left of the box in our implementation.
+ * Sierra passed the lower left. We change that to make upscaling easier.
+ */
void GfxMgr::drawBox(int16 x, int16 y, int16 width, int16 height, byte backgroundColor, byte lineColor) {
- // Allow rendering all the way to the top of the visual screen, even if there
- // is a menu bar. MMMG nursery rhyme message boxes appear over the menu bar
- // when the scripts pass a y-coordinate of zero to print.at(). Bug #13820
const int16 minY = 0 - _renderStartDisplayOffsetY;
if (!render_Clip(x, y, width, height, minY, VISUAL_WIDTH, VISUAL_HEIGHT - _renderStartVisualOffsetY)) {
warning("drawBox ignored by clipping. x: %d, y: %d, w: %d, h: %d", x, y, width, height);
@@ -1024,7 +1076,9 @@ void GfxMgr::drawBox(int16 x, int16 y, int16 width, int16 height, byte backgroun
}
}
-// coordinates are directly for display screen
+/**
+ * Draw a rectangle to the display screen
+ */
void GfxMgr::drawDisplayRect(int16 x, int16 y, int16 width, int16 height, byte color, bool copyToScreen) {
switch (_vm->_renderMode) {
case Common::kRenderCGA:
@@ -1100,7 +1154,9 @@ void GfxMgr::drawDisplayRectCGA(int16 x, int16 y, int16 width, int16 height, byt
}
}
-// row + column are text-coordinates
+/**
+ * Draw a character to the display screen using text row and column coordinates
+ */
void GfxMgr::drawCharacter(int16 row, int16 column, byte character, byte foreground, byte background, bool disabledLook) {
int16 x = column;
int16 y = row;
@@ -1124,7 +1180,10 @@ void GfxMgr::drawCharacter(int16 row, int16 column, byte character, byte foregro
drawCharacterOnDisplay(x, y, character, foreground, background, transformXOR, transformOR);
}
-// only meant for internal use (SystemUI)
+/**
+ * Draw a string to the display screen using display coordinates.
+ * For internal use by SystemUI.
+ */
void GfxMgr::drawStringOnDisplay(int16 x, int16 y, const char *text, byte foregroundColor, byte backgroundColor) {
while (*text) {
drawCharacterOnDisplay(x, y, *text, foregroundColor, backgroundColor);
@@ -1133,6 +1192,10 @@ void GfxMgr::drawStringOnDisplay(int16 x, int16 y, const char *text, byte foregr
}
}
+/**
+ * Draw a string to the display screen using display coordinates.
+ * For internal use by SystemUI.
+ */
void GfxMgr::drawStringOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, const char *text, byte foregroundColor, byte backgroundColor) {
switch (_upscaledHires) {
case DISPLAY_UPSCALED_DISABLED:
@@ -1150,6 +1213,9 @@ void GfxMgr::drawStringOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, const
drawStringOnDisplay(x, y, text, foregroundColor, backgroundColor);
}
+/**
+ * Draw a character to the display screen using text row and column coordinates
+ */
void GfxMgr::drawCharacterOnDisplay(int16 x, int16 y, const byte character, byte foreground, byte background, byte transformXOR, byte transformOR) {
int16 curX, curY;
const byte *fontData;
@@ -1249,11 +1315,12 @@ void GfxMgr::setPriorityTable(int16 priorityBase) {
}
// used for saving
-int16 GfxMgr::saveLoadGetPriority(int16 yPos) {
+int16 GfxMgr::saveLoadGetPriority(int16 yPos) const {
assert(yPos < SCRIPT_HEIGHT);
return _priorityTable[yPos];
}
-bool GfxMgr::saveLoadWasPriorityTableModified() {
+
+bool GfxMgr::saveLoadWasPriorityTableModified() const {
return _priorityTableSet;
}
@@ -1262,9 +1329,11 @@ void GfxMgr::saveLoadSetPriority(int16 yPos, int16 priority) {
assert(yPos < SCRIPT_HEIGHT);
_priorityTable[yPos] = priority;
}
+
void GfxMgr::saveLoadSetPriorityTableModifiedBool(bool wasModified) {
_priorityTableSet = wasModified;
}
+
void GfxMgr::saveLoadFigureOutPriorityTableModifiedBool() {
uint8 defaultPriorityTable[SCRIPT_HEIGHT]; /**< priority table */
@@ -1281,7 +1350,7 @@ void GfxMgr::saveLoadFigureOutPriorityTableModifiedBool() {
/**
* Convert sprite priority to y value.
*/
-int16 GfxMgr::priorityToY(int16 priority) {
+int16 GfxMgr::priorityToY(int16 priority) const {
if (!_priorityTableSet) {
// priority table wasn't set by scripts? calculate directly
return (priority - 5) * 12 + 48;
@@ -1317,7 +1386,7 @@ int16 GfxMgr::priorityToY(int16 priority) {
return currentY;
}
-int16 GfxMgr::priorityFromY(int16 yPos) {
+int16 GfxMgr::priorityFromY(int16 yPos) const {
assert(yPos < SCRIPT_HEIGHT);
return _priorityTable[yPos];
}
@@ -1417,7 +1486,7 @@ void GfxMgr::setAGIPal(int p0) {
debug(1, "Using AGIPAL palette from '%s'", filename);
}
-int GfxMgr::getAGIPalFileNum() {
+int GfxMgr::getAGIPalFileNum() const {
return _agipalFileNum;
}
diff --git a/engines/agi/graphics.h b/engines/agi/graphics.h
index 9ef4e438750..320019fa50c 100644
--- a/engines/agi/graphics.h
+++ b/engines/agi/graphics.h
@@ -71,30 +71,30 @@ public:
void initVideo();
void deinitVideo();
- void initPalette(uint8 *destPalette, const uint8 *paletteData, uint colorCount = 16, uint fromBits = 6, uint toBits = 8);
- void initPaletteCLUT(uint8 *destPalette, const uint16 *paletteCLUTData, uint colorCount = 16);
+ static void initPalette(uint8 *destPalette, const uint8 *paletteData, uint colorCount = 16, uint fromBits = 6, uint toBits = 8);
+ static void initPaletteCLUT(uint8 *destPalette, const uint16 *paletteCLUTData, uint colorCount = 16);
void setAGIPal(int);
- int getAGIPalFileNum();
+ int getAGIPalFileNum() const;
void setPalette(bool GfxModePalette);
void initMouseCursor(MouseCursorData *mouseCursor, const byte *bitmapData, uint16 width, uint16 height, int hotspotX, int hotspotY);
void setMouseCursor(bool busy = false);
void setRenderStartOffset(uint16 offsetY);
- uint16 getRenderStartDisplayOffsetY();
+ uint16 getRenderStartDisplayOffsetY() const;
- void translateGamePosToDisplayScreen(int16 &x, int16 &y);
- void translateVisualPosToDisplayScreen(int16 &x, int16 &y);
- void translateDisplayPosToGameScreen(int16 &x, int16 &y);
+ void translateGamePosToDisplayScreen(int16 &x, int16 &y) const;
+ void translateVisualPosToDisplayScreen(int16 &x, int16 &y) const;
+ void translateDisplayPosToGameScreen(int16 &x, int16 &y) const;
- void translateVisualDimensionToDisplayScreen(int16 &width, int16 &height);
- void translateDisplayDimensionToVisualScreen(int16 &width, int16 &height);
+ void translateVisualDimensionToDisplayScreen(int16 &width, int16 &height) const;
+ void translateDisplayDimensionToVisualScreen(int16 &width, int16 &height) const;
- void translateGameRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height);
- void translateVisualRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height);
+ void translateGameRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) const;
+ void translateVisualRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) const;
- uint32 getDisplayOffsetToGameScreenPos(int16 x, int16 y);
- uint32 getDisplayOffsetToVisualScreenPos(int16 x, int16 y);
+ uint32 getDisplayOffsetToGameScreenPos(int16 x, int16 y) const;
+ uint32 getDisplayOffsetToVisualScreenPos(int16 x, int16 y) const;
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);
@@ -102,11 +102,11 @@ public:
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);
+ void translateFontPosToDisplayScreen(int16 &x, int16 &y) const;
+ void translateDisplayPosToFontScreen(int16 &x, int16 &y) const;
+ void translateFontDimensionToDisplayScreen(int16 &width, int16 &height) const;
+ void translateFontRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) const;
+ Common::Rect getFontRectForDisplayScreen(int16 column, int16 row, int16 width, int16 height) const;
private:
uint _pixels;
@@ -143,17 +143,17 @@ private:
uint16 _renderStartDisplayOffsetY;
public:
- uint16 getDisplayScreenWidth() {
+ uint16 getDisplayScreenWidth() const {
return _displayScreenWidth;
}
- uint16 getDisplayFontWidth() {
+ uint16 getDisplayFontWidth() const {
return _displayFontWidth;
}
- uint16 getDisplayFontHeight() {
+ uint16 getDisplayFontHeight() const {
return _displayFontHeight;
}
- GfxScreenUpscaledMode getUpscaledHires() {
+ GfxScreenUpscaledMode getUpscaledHires() const {
return _upscaledHires;
}
@@ -166,16 +166,16 @@ public:
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);
- bool checkControlPixel(int16 x, int16 y, byte newPriority);
+ byte getColor(int16 x, int16 y) const;
+ byte getPriority(int16 x, int16 y) const;
+ bool checkControlPixel(int16 x, int16 y, byte newPriority) const;
- byte getCGAMixtureColor(byte color);
+ byte getCGAMixtureColor(byte color) const;
void render_Block(int16 x, int16 y, int16 width, int16 height, bool copyToScreen = true);
- bool render_Clip(int16 &x, int16 &y, int16 &width, int16 &height, const int16 minY = 0, const int16 clipAgainstWidth = SCRIPT_WIDTH, const int16 clipAgainstHeight = SCRIPT_HEIGHT);
private:
+ static bool render_Clip(int16 &x, int16 &y, int16 &width, int16 &height, const int16 minY, const int16 clipAgainstWidth, const int16 clipAgainstHeight);
void render_BlockEGA(int16 x, int16 y, int16 width, int16 height);
void render_BlockCGA(int16 x, int16 y, int16 width, int16 height);
void render_BlockHercules(int16 x, int16 y, int16 width, int16 height);
@@ -184,7 +184,7 @@ public:
void transition_Amiga();
void transition_AtariSt();
- void block_save(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr);
+ void block_save(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr) const;
void block_restore(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr);
void drawBox(int16 x, int16 y, int16 width, int16 height, byte backgroundColor, byte lineColor);
@@ -204,16 +204,16 @@ public:
void updateScreen();
void initPriorityTable();
- void createDefaultPriorityTable(uint8 *priorityTable);
+ static void createDefaultPriorityTable(uint8 *priorityTable);
void setPriorityTable(int16 priorityBase);
- bool saveLoadWasPriorityTableModified();
- int16 saveLoadGetPriority(int16 yPos);
+ bool saveLoadWasPriorityTableModified() const;
+ int16 saveLoadGetPriority(int16 yPos) const;
void saveLoadSetPriorityTableModifiedBool(bool wasModified);
void saveLoadSetPriority(int16 yPos, int16 priority);
void saveLoadFigureOutPriorityTableModifiedBool();
- int16 priorityToY(int16 priority);
- int16 priorityFromY(int16 yPos);
+ int16 priorityToY(int16 priority) const;
+ int16 priorityFromY(int16 yPos) const;
};
} // End of namespace Agi
diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp
index a42e4d5afd5..d226c52a790 100644
--- a/engines/agi/picture.cpp
+++ b/engines/agi/picture.cpp
@@ -36,15 +36,23 @@ PictureMgr::PictureMgr(AgiBase *agi, GfxMgr *gfx) {
_dataOffset = 0;
_dataOffsetNibble = false;
- _patCode = _patNum = _priOn = _scrOn = _scrColor = _priColor = 0;
- _xOffset = _yOffset = 0;
+ _patCode = 0;
+ _patNum = 0;
+ _priOn = 0;
+ _scrOn = 0;
+ _scrColor = 0;
+ _priColor = 0;
- _pictureVersion = AGIPIC_V2;
_minCommand = 0xf0;
+
+ _pictureVersion = AGIPIC_V2;
+ _width = 0;
+ _height = 0;
+ _xOffset = 0;
+ _yOffset = 0;
+
_flags = 0;
_currentStep = 0;
-
- _width = _height = 0;
}
void PictureMgr::putVirtPixel(int x, int y) {
@@ -98,7 +106,7 @@ byte PictureMgr::getNextNibble() {
**
** Draws an xCorner (drawing action 0xF5)
**************************************************************************/
-void PictureMgr::draw_xCorner(bool skipOtherCoords) {
+void PictureMgr::xCorner(bool skipOtherCoords) {
byte x1, x2, y1, y2, dummy;
if (!(getNextParamByte(x1) && getNextParamByte(y1)))
@@ -342,14 +350,12 @@ void PictureMgr::drawPicture() {
}
void PictureMgr::drawPictureC64() {
- byte curByte;
-
debugC(8, kDebugLevelMain, "Drawing C64 picture");
_scrColor = 0x0;
while (_dataOffset < _dataSize) {
- curByte = getNextByte();
+ byte curByte = getNextByte();
if ((curByte >= 0xF0) && (curByte <= 0xFE)) {
_scrColor = curByte & 0x0F;
@@ -358,7 +364,7 @@ void PictureMgr::drawPictureC64() {
switch (curByte) {
case 0xe0: // x-corner
- draw_xCorner();
+ xCorner();
break;
case 0xe1: // y-corner
yCorner();
@@ -391,12 +397,10 @@ void PictureMgr::drawPictureC64() {
}
void PictureMgr::drawPictureV1() {
- byte curByte;
-
debugC(8, kDebugLevelMain, "Drawing V1 picture");
while (_dataOffset < _dataSize) {
- curByte = getNextByte();
+ byte curByte = getNextByte();
switch (curByte) {
case 0xf1:
@@ -430,12 +434,10 @@ void PictureMgr::drawPictureV1() {
}
void PictureMgr::drawPictureV15() {
- byte curByte;
-
debugC(8, kDebugLevelMain, "Drawing V1.5 picture");
while (_dataOffset < _dataSize) {
- curByte = getNextByte();
+ byte curByte = getNextByte();
switch (curByte) {
case 0xf0:
@@ -454,7 +456,7 @@ void PictureMgr::drawPictureV15() {
yCorner(true);
break;
case 0xf9:
- draw_xCorner(true);
+ xCorner(true);
break;
case 0xfa:
// TODO: is this really correct?
@@ -479,7 +481,6 @@ void PictureMgr::drawPictureV15() {
}
void PictureMgr::drawPictureV2() {
- byte curByte;
bool nibbleMode = false;
bool mickeyCrystalAnimation = false;
int mickeyIteration = 0;
@@ -496,7 +497,7 @@ void PictureMgr::drawPictureV2() {
}
while (_dataOffset < _dataSize) {
- curByte = getNextByte();
+ byte curByte = getNextByte();
switch (curByte) {
case 0xf0:
@@ -525,7 +526,7 @@ void PictureMgr::drawPictureV2() {
yCorner();
break;
case 0xf5:
- draw_xCorner();
+ xCorner();
break;
case 0xf6:
draw_LineAbsolute();
@@ -562,8 +563,8 @@ void PictureMgr::drawPictureV2() {
// One frame of the crystal animation is shown on each iteration, based on _currentStep
if (mickeyCrystalAnimation) {
if (_currentStep == mickeyIteration) {
- int storedXOffset = _xOffset;
- int storedYOffset = _yOffset;
+ int16 storedXOffset = _xOffset;
+ int16 storedYOffset = _yOffset;
// Note that picture coordinates are correct for Mickey only
showPic(10, 0, _width, _height);
_xOffset = storedXOffset;
@@ -586,12 +587,11 @@ void PictureMgr::drawPictureAGI256() {
int16 y = 0;
byte *dataPtr = _data;
byte *dataEndPtr = _data + _dataSize;
- byte color = 0;
debugC(8, kDebugLevelMain, "Drawing AGI256 picture");
while (dataPtr < dataEndPtr) {
- color = *dataPtr++;
+ byte color = *dataPtr++;
_gfx->putPixel(x, y, GFX_SCREEN_MASK_VISUAL, color, 0);
x++;
@@ -625,12 +625,8 @@ void PictureMgr::draw_SetColor() {
return;
// For CGA, replace the color with its mixture color
- switch (_vm->_renderMode) {
- case Common::kRenderCGA:
+ if (_vm->_renderMode == Common::kRenderCGA) {
_scrColor = _gfx->getCGAMixtureColor(_scrColor);
- break;
- default:
- break;
}
}
@@ -644,12 +640,8 @@ void PictureMgr::draw_SetNibbleColor() {
_scrColor = getNextNibble();
// For CGA, replace the color with its mixture color
- switch (_vm->_renderMode) {
- case Common::kRenderCGA:
+ if (_vm->_renderMode == Common::kRenderCGA) {
_scrColor = _gfx->getCGAMixtureColor(_scrColor);
- break;
- default:
- break;
}
}
@@ -672,8 +664,6 @@ void PictureMgr::draw_Line(int16 x1, int16 y1, int16 x2, int16 y2) {
y1 = CLIP<int16>(y1, 0, _height - 1);
y2 = CLIP<int16>(y2, 0, _height - 1);
- int i, x, y, deltaX, deltaY, stepX, stepY, errorX, errorY, detdelta;
-
// Vertical line
if (x1 == x2) {
@@ -698,23 +688,21 @@ void PictureMgr::draw_Line(int16 x1, int16 y1, int16 x2, int16 y2) {
return;
}
- y = y1;
- x = x1;
+ int stepX = 1;
+ int deltaX = x2 - x1;
+ if (deltaX < 0) {
+ stepX = -1;
+ deltaX = -deltaX;
+ }
- stepY = 1;
- deltaY = y2 - y1;
+ int stepY = 1;
+ int deltaY = y2 - y1;
if (deltaY < 0) {
stepY = -1;
deltaY = -deltaY;
}
- stepX = 1;
- deltaX = x2 - x1;
- if (deltaX < 0) {
- stepX = -1;
- deltaX = -deltaX;
- }
-
+ int i, detdelta, errorX, errorY;
if (deltaY > deltaX) {
i = deltaY;
detdelta = deltaY;
@@ -727,6 +715,8 @@ void PictureMgr::draw_Line(int16 x1, int16 y1, int16 x2, int16 y2) {
errorY = deltaX / 2;
}
+ int x = x1;
+ int y = y1;
putVirtPixel(x, y);
do {
@@ -819,17 +809,17 @@ void PictureMgr::draw_Fill(int16 x, int16 y) {
// Exit if stack is empty
while (!stack.empty()) {
Common::Point p = stack.pop();
- unsigned int c;
- bool newspanUp, newspanDown;
if (!draw_FillCheck(p.x, p.y))
continue;
// Scan for left border
+ uint c;
for (c = p.x - 1; draw_FillCheck(c, p.y); c--)
;
- newspanUp = newspanDown = true;
+ bool newspanUp = true;
+ bool newspanDown = true;
for (c++; draw_FillCheck(c, p.y); c++) {
putVirtPixel(c, p.y);
if (draw_FillCheck(c, p.y - 1)) {
@@ -853,18 +843,15 @@ void PictureMgr::draw_Fill(int16 x, int16 y) {
}
}
-int PictureMgr::draw_FillCheck(int16 x, int16 y) {
- byte screenColor;
- byte screenPriority;
-
+bool PictureMgr::draw_FillCheck(int16 x, int16 y) {
if (x < 0 || x >= _width || y < 0 || y >= _height)
return false;
x += _xOffset;
y += _yOffset;
- screenColor = _gfx->getColor(x, y);
- screenPriority = _gfx->getPriority(x, y);
+ byte screenColor = _gfx->getColor(x, y);
+ byte screenPriority = _gfx->getPriority(x, y);
if (_flags & kPicFTrollMode)
return ((screenColor != 11) && (screenColor != _scrColor));
@@ -873,7 +860,7 @@ int PictureMgr::draw_FillCheck(int16 x, int16 y) {
return (screenColor == 15);
if (_priOn && !_scrOn && _priColor != 4)
- return screenPriority == 4;
+ return (screenPriority == 4);
return (_scrOn && screenColor == 15 && _scrColor != 15);
}
@@ -887,9 +874,7 @@ int PictureMgr::draw_FillCheck(int16 x, int16 y) {
* @param clear clear AGI screen before drawing
* @param agi256 load an AGI256 picture resource
*/
-int PictureMgr::decodePicture(int16 resourceNr, bool clearScreen, bool agi256, int16 pic_width, int16 pic_height) {
- debugC(8, kDebugLevelResources, "(%d)", resourceNr);
-
+void PictureMgr::decodePicture(int16 resourceNr, bool clearScreen, bool agi256, int16 width, int16 height) {
_patCode = 0;
_patNum = 0;
_priOn = _scrOn = false;
@@ -902,8 +887,8 @@ int PictureMgr::decodePicture(int16 resourceNr, bool clearScreen, bool agi256, i
_dataOffset = 0;
_dataOffsetNibble = false;
- _width = pic_width;
- _height = pic_height;
+ _width = width;
+ _height = height;
if (clearScreen && !agi256) { // 256 color pictures should always fill the whole screen, so no clearing for them.
_gfx->clear(15, 4); // Clear 16 color AGI screen (Priority 4, color white).
@@ -915,11 +900,10 @@ int PictureMgr::decodePicture(int16 resourceNr, bool clearScreen, bool agi256, i
drawPictureAGI256();
}
- if (clearScreen)
+ if (clearScreen) {
_vm->clearImageStack();
+ }
_vm->recordImageStackCall(ADD_PIC, resourceNr, clearScreen, agi256, 0, 0, 0, 0);
-
- return errOK;
}
/**
@@ -931,7 +915,7 @@ int PictureMgr::decodePicture(int16 resourceNr, bool clearScreen, bool agi256, i
* @param length the size of the picture data buffer
* @param clear clear AGI screen before drawing
*/
-int PictureMgr::decodePicture(byte *data, uint32 length, int clr, int pic_width, int pic_height) {
+void PictureMgr::decodePictureFromBuffer(byte *data, uint32 length, bool clearScreen, int16 width, int16 height) {
_patCode = 0;
_patNum = 0;
_priOn = _scrOn = false;
@@ -943,15 +927,14 @@ int PictureMgr::decodePicture(byte *data, uint32 length, int clr, int pic_width,
_dataOffset = 0;
_dataOffsetNibble = false;
- _width = pic_width;
- _height = pic_height;
+ _width = width;
+ _height = height;
- if (clr) // 256 color pictures should always fill the whole screen, so no clearing for them.
+ if (clearScreen) {
clear();
+ }
drawPicture(); // Draw 16 color picture.
-
- return errOK;
}
/**
diff --git a/engines/agi/picture.h b/engines/agi/picture.h
index a00016da113..37d19237f8e 100644
--- a/engines/agi/picture.h
+++ b/engines/agi/picture.h
@@ -70,10 +70,10 @@ class PictureMgr {
public:
PictureMgr(AgiBase *agi, GfxMgr *gfx);
- int16 getResourceNr() { return _resourceNr; };
+ int16 getResourceNr() const { return _resourceNr; };
private:
- void draw_xCorner(bool skipOtherCoords = false);
+ void xCorner(bool skipOtherCoords = false);
void yCorner(bool skipOtherCoords = false);
void plotBrush();
@@ -84,8 +84,8 @@ private:
public:
void putVirtPixel(int x, int y);
- int decodePicture(int16 resourceNr, bool clearScreen, bool agi256 = false, int16 pic_width = _DEFAULT_WIDTH, int16 pic_height = _DEFAULT_HEIGHT);
- int decodePicture(byte *data, uint32 length, int clear, int pic_width = _DEFAULT_WIDTH, int pic_height = _DEFAULT_HEIGHT);
+ void decodePicture(int16 resourceNr, bool clearScreen, bool agi256 = false, int16 width = _DEFAULT_WIDTH, int16 height = _DEFAULT_HEIGHT);
+ void decodePictureFromBuffer(byte *data, uint32 length, bool clearScreen, int16 width = _DEFAULT_WIDTH, int16 height = _DEFAULT_HEIGHT);
void unloadPicture(int picNr);
void drawPicture();
private:
@@ -104,7 +104,7 @@ private:
void draw_LineShort();
void draw_LineAbsolute();
- int draw_FillCheck(int16 x, int16 y);
+ bool draw_FillCheck(int16 x, int16 y);
void draw_Fill(int16 x, int16 y);
void draw_Fill();
@@ -151,8 +151,10 @@ private:
uint8 _minCommand;
AgiPictureVersion _pictureVersion;
- int16 _width, _height;
- int16 _xOffset, _yOffset;
+ int16 _width;
+ int16 _height;
+ int16 _xOffset;
+ int16 _yOffset;
int _flags;
int _currentStep;
diff --git a/engines/agi/preagi/mickey.cpp b/engines/agi/preagi/mickey.cpp
index 6230ddc893e..49db9570240 100644
--- a/engines/agi/preagi/mickey.cpp
+++ b/engines/agi/preagi/mickey.cpp
@@ -739,7 +739,7 @@ void MickeyEngine::drawObj(ENUM_MSA_OBJECT iObj, int x0, int y0) {
_picture->setPictureFlags(kPicFStep);
_picture->setOffset(x0, y0);
- _picture->decodePicture(buffer, size, false, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+ _picture->decodePictureFromBuffer(buffer, size, false, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
_picture->setOffset(0, 0);
_picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
}
@@ -759,7 +759,7 @@ void MickeyEngine::drawPic(int iPic) {
// Note that decodePicture clears the screen
_picture->setOffset(10, 0);
- _picture->decodePicture(buffer, size, true, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+ _picture->decodePictureFromBuffer(buffer, size, true, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
_picture->setOffset(0, 0);
_picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
}
diff --git a/engines/agi/preagi/winnie.cpp b/engines/agi/preagi/winnie.cpp
index 0e4103e4175..918896fa130 100644
--- a/engines/agi/preagi/winnie.cpp
+++ b/engines/agi/preagi/winnie.cpp
@@ -1082,7 +1082,7 @@ void WinnieEngine::drawPic(const char *szName) {
file.close();
_picture->setOffset(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0);
- _picture->decodePicture(buffer, size, 1, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _picture->decodePictureFromBuffer(buffer, size, true, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
_picture->setOffset(0, 0);
_picture->showPic(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
@@ -1099,7 +1099,7 @@ void WinnieEngine::drawObjPic(int iObj, int x0, int y0) {
parseObjHeader(&objhdr, buffer, sizeof(WTP_OBJ_HDR));
_picture->setOffset(x0, y0);
- _picture->decodePicture(buffer + objhdr.ofsPic - _objOffset, objSize, 0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _picture->decodePictureFromBuffer(buffer + objhdr.ofsPic - _objOffset, objSize, false, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
_picture->setOffset(0, 0);
_picture->showPic(10, 0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
@@ -1119,7 +1119,7 @@ void WinnieEngine::drawRoomPic() {
// draw room picture
_picture->setOffset(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0);
- _picture->decodePicture(buffer + roomhdr.ofsPic - _roomOffset, 4096, 1, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _picture->decodePictureFromBuffer(buffer + roomhdr.ofsPic - _roomOffset, 4096, false, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
_picture->setOffset(0, 0);
_picture->showPic(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
diff --git a/engines/agi/sound_coco3.cpp b/engines/agi/sound_coco3.cpp
index 3fcc1797008..1da61e3929d 100644
--- a/engines/agi/sound_coco3.cpp
+++ b/engines/agi/sound_coco3.cpp
@@ -78,7 +78,7 @@ void SoundGenCoCo3::play(int resnum) {
// LSL1 (Int, 2.072) stored the duration in 1/60 of a second.
// Fan ports have been made using both interpreters, but our
// detection table doesn't capture this. For now, treat KQ3
- // as the early interpreter all others as the later one.
+ // as the early interpreter and all others as the later one.
// TODO: create detection heuristic
bool isEarlySound = (_vm->getGameID() == GID_KQ3);
Commit: a5909e5f60c0ab87a962e47b1e997ece3ab12bb1
https://github.com/scummvm/scummvm/commit/a5909e5f60c0ab87a962e47b1e997ece3ab12bb1
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2024-10-28T21:02:51-07:00
Commit Message:
AGI: Move AGI256 picture opcode into function
Changed paths:
engines/agi/op_cmd.cpp
engines/agi/opcodes.cpp
engines/agi/opcodes.h
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index eb6efdb42fe..47272e4bb19 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -756,7 +756,7 @@ void cmdResetScanStart(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
void cmdSaveGame(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
if (vm->getVersion() >= 0x2272) {
- // this was only donce since 2.272
+ // this was only done since 2.272
vm->_sound->stopSound();
}
@@ -950,56 +950,28 @@ void cmdObjStatusF(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
// unk_177: Disable menus completely -- j5
// unk_181: Deactivate keypressed control (default control of ego)
void cmdSetSimple(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
- if (!(vm->getFeatures() & GF_AGI256)) {
- // set.simple is called by Larry 1 on Apple IIgs at the store, after answering the 555-6969 phone.
- // load.sound(16) is called right before it. Interpreter is 2.440-like.
- // it's called with parameter 16.
- // Original interpreter doesn't seem to play any sound.
- // TODO: Figure out what's going on. It can't be automatic saving of course.
- // Also getting called in KQ1, when planting beans - parameter 12.
- // And when killing the witch - parameter 40.
- if ((vm->getVersion() < 0x2425) || (vm->getVersion() == 0x2440)) {
- // was not available before 2.2425, but also not available in 2.440
- warning("set.simple called, although not available for current AGI version");
- return;
- }
-
- int16 stringNr = parameter[0];
- state->automaticSave = false;
+ // set.simple is called by Larry 1 on Apple IIgs at the store, after answering the 555-6969 phone.
+ // load.sound(16) is called right before it. Interpreter is 2.440-like.
+ // it's called with parameter 16.
+ // Original interpreter doesn't seem to play any sound.
+ // TODO: Figure out what's going on. It can't be automatic saving of course.
+ // Also getting called in KQ1, when planting beans - parameter 12.
+ // And when killing the witch - parameter 40.
+ if ((vm->getVersion() < 0x2425) || (vm->getVersion() == 0x2440)) {
+ // was not available before 2.2425, but also not available in 2.440
+ warning("set.simple called, although not available for current AGI version");
+ return;
+ }
- // Try to get description for automatic saves
- const char *textPtr = state->getString(stringNr);
+ int16 stringNr = parameter[0];
- strncpy(state->automaticSaveDescription, textPtr, sizeof(state->automaticSaveDescription));
- state->automaticSaveDescription[sizeof(state->automaticSaveDescription) - 1] = 0;
+ // Try to get description for automatic saves
+ const char *textPtr = state->getString(stringNr);
+ strncpy(state->automaticSaveDescription, textPtr, sizeof(state->automaticSaveDescription));
+ state->automaticSaveDescription[sizeof(state->automaticSaveDescription) - 1] = '\0';
- if (state->automaticSaveDescription[0]) {
- // We got it and it's set, so enable automatic saving
- state->automaticSave = true;
- }
- } else { // AGI256 and AGI256-2 use this unknown170 command to load 256 color pictures.
- // Load the picture. Similar to void cmdLoad_pic(AgiGame *state, AgiEngine *vm, uint8 *p).
- SpritesMgr *spritesMgr = vm->_sprites;
- uint16 varNr = parameter[0];
- uint16 resourceNr = vm->getVar(varNr);
-
- spritesMgr->eraseSprites();
- vm->loadResource(RESOURCETYPE_PICTURE, resourceNr);
-
- // Draw the picture. Similar to void cmdDraw_pic(AgiGame *state, AgiEngine *vm, uint8 *p).
- vm->_picture->decodePicture(resourceNr, false, true);
- spritesMgr->drawAllSpriteLists();
- state->pictureShown = false;
-
- // Loading trigger
- vm->artificialDelayTrigger_DrawPicture(resourceNr);
-
- // Show the picture. Similar to void cmdShow_pic(AgiGame *state, AgiEngine *vm, uint8 *p).
- vm->setFlag(VM_FLAG_OUTPUT_MODE, false);
- vm->_text->closeWindow();
- vm->_picture->showPic();
- state->pictureShown = true;
- }
+ // enable automatic saving if description isn't empty
+ state->automaticSave = (state->automaticSaveDescription[0] != '\0');
}
// pop.script was not available until 2.425, and also not available in 2.440
@@ -2242,13 +2214,6 @@ void cmdPushScript(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
debug(0, "push.script");
}
-// The AGIMOUSE interpreter modified push.script to set variables 27-29 to mouse state
-void cmdAgiMousePushScript(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
- vm->setVar(VM_VAR_MOUSE_BUTTONSTATE, vm->_mouse.button);
- vm->setVar(VM_VAR_MOUSE_X, vm->_mouse.pos.x / 2);
- vm->setVar(VM_VAR_MOUSE_Y, vm->_mouse.pos.y);
-}
-
void cmdSetPriBase(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
if ((vm->getVersion() != 0x2425) && (vm->getVersion() < 0x2936)) {
// was only available in the 2.425 interpreter and from 2.936 (last AGI2 version) onwards
@@ -2342,6 +2307,38 @@ void cmdNewRoomVV1(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
vm->setVar(13, 1);
}
+// The AGI256 interpreter modified opcode 170 to load 256 color pictures
+void cmdAgi256LoadPic(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
+ // Load the picture. Similar to void cmdLoadPic.
+ SpritesMgr *spritesMgr = vm->_sprites;
+ uint16 varNr = parameter[0];
+ uint16 resourceNr = vm->getVar(varNr);
+
+ spritesMgr->eraseSprites();
+ vm->loadResource(RESOURCETYPE_PICTURE, resourceNr);
+
+ // Draw the picture. Similar to void cmdDrawPic.
+ vm->_picture->decodePicture(resourceNr, false, true);
+ spritesMgr->drawAllSpriteLists();
+ state->pictureShown = false;
+
+ // Loading trigger
+ vm->artificialDelayTrigger_DrawPicture(resourceNr);
+
+ // Show the picture. Similar to void cmdShowPic.
+ vm->setFlag(VM_FLAG_OUTPUT_MODE, false);
+ vm->_text->closeWindow();
+ vm->_picture->showPic();
+ state->pictureShown = true;
+}
+
+// The AGIMOUSE interpreter modified opcode 171 to set variables 27-29 to mouse state
+void cmdAgiMouseGetMouseState(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
+ vm->setVar(VM_VAR_MOUSE_BUTTONSTATE, vm->_mouse.button);
+ vm->setVar(VM_VAR_MOUSE_X, vm->_mouse.pos.x / 2);
+ vm->setVar(VM_VAR_MOUSE_Y, vm->_mouse.pos.y);
+}
+
void cmdUnknown(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
byte opcode = *(state->_curLogic->data + state->_curLogic->cIP - 1);
Common::String parameterString;
diff --git a/engines/agi/opcodes.cpp b/engines/agi/opcodes.cpp
index fb3f159ea96..12a805d631f 100644
--- a/engines/agi/opcodes.cpp
+++ b/engines/agi/opcodes.cpp
@@ -463,9 +463,14 @@ void AgiEngine::setupOpCodes(uint16 version) {
}
}
- // AGIMOUSE games use a modified push.script that updates mouse state
+ // AGI256 games use a modified opcode (set.simple) that loads 256 color pictures
+ if (getFeatures() & GF_AGI256) {
+ _opCodes[0xaa].functionPtr = &cmdAgi256LoadPic;
+ }
+
+ // AGIMOUSE games use a modified opcode (push.script) that gets mouse state
if (getFeatures() & GF_AGIMOUSE) {
- _opCodes[0xab].functionPtr = &cmdAgiMousePushScript;
+ _opCodes[0xab].functionPtr = &cmdAgiMouseGetMouseState;
}
// add invalid entries for every opcode, that is not defined at all
@@ -485,11 +490,11 @@ void AgiEngine::setupOpCodes(uint16 version) {
// calculate parameter size
for (int opCodeNr = 0; opCodeNr < opCodesTableSize; opCodeNr++) {
- _opCodes[opCodeNr].parameterSize = strlen( _opCodes[opCodeNr].parameters);
+ _opCodes[opCodeNr].parameterSize = strlen(_opCodes[opCodeNr].parameters);
}
for (int opCodeNr = 0; opCodeNr < opCodesCondTableSize; opCodeNr++) {
- _opCodesCond[opCodeNr].parameterSize = strlen( _opCodesCond[opCodeNr].parameters);
+ _opCodesCond[opCodeNr].parameterSize = strlen(_opCodesCond[opCodeNr].parameters);
}
}
diff --git a/engines/agi/opcodes.h b/engines/agi/opcodes.h
index a52e5d2bdc5..4d3f745736e 100644
--- a/engines/agi/opcodes.h
+++ b/engines/agi/opcodes.h
@@ -207,8 +207,9 @@ void cmdDivN(AgiGame *state, AgiEngine *vm, uint8 *p);
void cmdDivV(AgiGame *state, AgiEngine *vm, uint8 *p); // 0xa8
void cmdCloseWindow(AgiGame *state, AgiEngine *vm, uint8 *p);
void cmdSetSimple(AgiGame *state, AgiEngine *vm, uint8 *p);
+void cmdAgi256LoadPic(AgiGame *state, AgiEngine *vm, uint8 *p); // modified 0xaa
void cmdPushScript(AgiGame *state, AgiEngine *vm, uint8 *p);
-void cmdAgiMousePushScript(AgiGame *state, AgiEngine *vm, uint8 *p); // modified 0xab
+void cmdAgiMouseGetMouseState(AgiGame *state, AgiEngine *vm, uint8 *p); // modified 0xab
void cmdPopScript(AgiGame *state, AgiEngine *vm, uint8 *p);
void cmdHoldKey(AgiGame *state, AgiEngine *vm, uint8 *p);
void cmdSetPriBase(AgiGame *state, AgiEngine *vm, uint8 *p);
Commit: f15c08bfb6fb53e56574317bebe36f72e5626097
https://github.com/scummvm/scummvm/commit/f15c08bfb6fb53e56574317bebe36f72e5626097
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2024-10-28T21:02:51-07:00
Commit Message:
AGI: Remove extra AGI256 picture render
We duplicated show.pic in the AGI256 opcode for loading pictures,
but AGI256 already required scripts to call show.pic after loading.
Changed paths:
engines/agi/op_cmd.cpp
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index 47272e4bb19..fde780ae627 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -2324,12 +2324,6 @@ void cmdAgi256LoadPic(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
// Loading trigger
vm->artificialDelayTrigger_DrawPicture(resourceNr);
-
- // Show the picture. Similar to void cmdShowPic.
- vm->setFlag(VM_FLAG_OUTPUT_MODE, false);
- vm->_text->closeWindow();
- vm->_picture->showPic();
- state->pictureShown = true;
}
// The AGIMOUSE interpreter modified opcode 171 to set variables 27-29 to mouse state
Commit: ce2410f7a3241ed4e7da15049be8ae6c96327b8c
https://github.com/scummvm/scummvm/commit/ce2410f7a3241ed4e7da15049be8ae6c96327b8c
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2024-10-28T21:02:52-07:00
Commit Message:
AGI: Update Apple IIgs opcodes
- discard.sound has three potential opcode values depending on the
interpreter version; this is now handled and documented.
- Unknown opcode 175 is now handled and its presence is documented.
- Fixes AGIDEMO and PQ1 calling set.simple instead of discard.sound.
- Reverted SQ2 workaround now that its discard.sound calls are
correctly handled: 736d7cd533255d1fa9b3a6d20158ed7c917ac4a6
Changed paths:
engines/agi/detection_tables.h
engines/agi/op_cmd.cpp
engines/agi/opcodes.cpp
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
index 7c89d847f8f..2e2a24ee708 100644
--- a/engines/agi/detection_tables.h
+++ b/engines/agi/detection_tables.h
@@ -184,7 +184,7 @@ static const AGIGameDescription gameDescriptions[] = {
A2("agidemo", "Demo 1987", "1abef8018f42dc21a59e03f3d227024f", 0x2917, GID_AGIDEMO),
// AGI Demo 2 (IIgs) 1.0C (Censored)
- GAME_P("agidemo", "Demo 2 1987-11-24 1.0C", "580ffdc569ff158f56fb92761604f70e", 0x2917, GID_AGIDEMO, Common::kPlatformApple2GS),
+ GAME_P("agidemo", "Demo 2 1987-11-24 1.0C", "580ffdc569ff158f56fb92761604f70e", 0x2440, GID_AGIDEMO, Common::kPlatformApple2GS),
// AGI Demo 2 (PC 3.5") 11/87 [AGI 2.915]
GAME("agidemo", "Demo 2 1987-11-24 3.5\"", "e8ebeb0bbe978172fe166f91f51598c7", 0x2917, GID_AGIDEMO),
@@ -662,7 +662,7 @@ static const AGIGameDescription gameDescriptions[] = {
GAME_P("pq1", "2.0G 1987-12-03", "805750b66c1c5b88a214e67bfdca17a1", 0x2440, GID_PQ1, Common::kPlatformMacintosh),
// Police Quest 1 (Apple II) 1.0I 11/23/88 (A2 Int. 0.099)
- A2("pq1", "1.0I 1988-11-23", "581e54c4d89bd53e775482cee9cd3ea0", 0x2917, GID_PQ1),
+ A2("pq1", "1.0I 1988-11-23", "581e54c4d89bd53e775482cee9cd3ea0", 0x2440, GID_PQ1),
// Police Quest 1 (IIgs) 2.0B-88421
GAME_PO("pq1", "2.0B 1988-04-21", "e7c175918372336461e3811d594f482f", 0x2917, GID_PQ1, Common::kPlatformApple2GS, GAMEOPTIONS_APPLE2GS),
@@ -760,14 +760,7 @@ static const AGIGameDescription gameDescriptions[] = {
A2("sq2", "2.0F", "5ca2c0e49918acb2517742922717201c", 0x2917, GID_SQ2),
// Space Quest 2 (IIgs) 2.0A 7/25/88 (CE)
- // We have to see this as AGI < 2.936, because otherwise a set.pri.base call would somewhat break
- // priority in SQ2, when entering Vohaul's vault.
- // The Apple IIgs AGI included with SQ2 is the same as the one included with KQ3.
- // We currently consider KQ3 IIgs to be a 2.917-equivalent.
- // The SQ2 IIgs AGI definitely has 177 kernel functions, but it seems that Sierra shuffled the last few around / added a few extras at the end.
- // For KQ3 set.pri.base is called with parameters that seem to be sound resources, which means
- // set.pri.base was possibly discard.sound. For KQ4 onwards it seems this was cleaned up.
- GAME_PO("sq2", "2.0A 1988-07-25 (CE)", "5dfdac98dd3c01fcfb166529f917e911", 0x2917, GID_SQ2, Common::kPlatformApple2GS, GAMEOPTIONS_APPLE2GS),
+ GAME_PO("sq2", "2.0A 1988-07-25 (CE)", "5dfdac98dd3c01fcfb166529f917e911", 0x2936, GID_SQ2, Common::kPlatformApple2GS, GAMEOPTIONS_APPLE2GS),
{
// Space Quest 2 (Amiga) 2.0F
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index fde780ae627..d403d771288 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -941,22 +941,8 @@ void cmdObjStatusF(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
vm->_text->messageBox(msg);
}
-// unknown commands:
-// unk_170: Force savegame name -- j5
-// unk_171: script save -- j5
-// unk_172: script restore -- j5
-// unk_173: Activate keypressed control (ego only moves while key is pressed)
-// unk_174: Change priority table (used in KQ4) -- j5
-// unk_177: Disable menus completely -- j5
-// unk_181: Deactivate keypressed control (default control of ego)
+// only known to used by MMMG for setting the player's name as the save description
void cmdSetSimple(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
- // set.simple is called by Larry 1 on Apple IIgs at the store, after answering the 555-6969 phone.
- // load.sound(16) is called right before it. Interpreter is 2.440-like.
- // it's called with parameter 16.
- // Original interpreter doesn't seem to play any sound.
- // TODO: Figure out what's going on. It can't be automatic saving of course.
- // Also getting called in KQ1, when planting beans - parameter 12.
- // And when killing the witch - parameter 40.
if ((vm->getVersion() < 0x2425) || (vm->getVersion() == 0x2440)) {
// was not available before 2.2425, but also not available in 2.440
warning("set.simple called, although not available for current AGI version");
@@ -985,10 +971,10 @@ void cmdPopScript(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
debug(0, "pop.script");
}
+// discard.sound only existed on Apple IIgs. Apple IIgs sound resources were
+// relatively large, so scripts would unload them from memory when finished.
void cmdDiscardSound(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
- if (vm->getVersion() >= 0x2936) {
- debug(0, "discard.sound");
- }
+ debug(0, "discard.sound");
}
void cmdShowMouse(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
@@ -1075,6 +1061,9 @@ void cmdAdjEgoMoveToXY(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
const AgiOpCodeEntry *opCodeTable = vm->getOpCodesTable();
int8 x, y;
+ // There are apparently two versions of this opcode: one that takes
+ // two parameters and one that takes none. The only games that call
+ // this opcode use the two parameter version.
switch (opCodeTable[182].parameterSize) {
// The 2 parameter version is used in:
// Amiga/Atari ST Gold Rush! - Logic 130, 150
@@ -1103,8 +1092,8 @@ void cmdAdjEgoMoveToXY(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
debugC(4, kDebugLevelScripts, "adj.ego.move.to.x.y(%d, %d)", x, y);
break;
- // TODO: Check where (if anywhere) the 0 arguments version is used
- case 0:
+
+ // No games call this; all games call the 2 parameter version
default:
state->screenObjTable[SCREENOBJECTS_EGO_ENTRY].flags |= fAdjEgoXY;
break;
@@ -2217,14 +2206,6 @@ void cmdPushScript(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
void cmdSetPriBase(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
if ((vm->getVersion() != 0x2425) && (vm->getVersion() < 0x2936)) {
// was only available in the 2.425 interpreter and from 2.936 (last AGI2 version) onwards
- // Called during KQ3 (Apple IIgs):
- // - picking up chicken (parameter = 50)
- // - opening store/tavern door (parameter = 19)
- // - when pirates say "Land Ho" (parameter = 16)
- // - when killing the dragon (parameter = 4)
- // Also called by SQ2 (Apple IIgs):
- // - in Vohaul's lair (SQ2 currently gets this call through, which breaks some priority)
- // TODO: Figure out what's going on
warning("set.pri.base called, although not available for current AGI version");
return;
}
diff --git a/engines/agi/opcodes.cpp b/engines/agi/opcodes.cpp
index 12a805d631f..1ad3b709cb1 100644
--- a/engines/agi/opcodes.cpp
+++ b/engines/agi/opcodes.cpp
@@ -347,12 +347,12 @@ static const AgiOpCodeDefinitionEntry opCodesV2[] = {
{ "div.n", "vn", &cmdDivN }, // A7
{ "div.v", "vv", &cmdDivV }, // A8
{ "close.window", "", &cmdCloseWindow }, // A9
- { "set.simple", "n", &cmdSetSimple }, // AA AGI2.425+, *BUT* not included in AGI2.440
+ { "set.simple", "n", &cmdSetSimple }, // AA AGI2.425+, *BUT* not included in AGI2.440, discard.sound in some Apple IIgs
{ "push.script", "", &cmdPushScript }, // AB
{ "pop.script", "", &cmdPopScript }, // AC
{ "hold.key", "", &cmdHoldKey }, // AD
- { "set.pri.base", "n", &cmdSetPriBase }, // AE AGI2.936+ *AND* also inside AGI2.425
- { "discard.sound", "n", &cmdDiscardSound }, // AF was skip for PC
+ { "set.pri.base", "n", &cmdSetPriBase }, // AE AGI2.936+ *AND* also inside AGI2.425, discard.sound in some Apple IIgs
+ { "discard.sound", "n", &cmdDiscardSound }, // AF Apple IIGS only
{ "hide.mouse", "", &cmdHideMouse }, // B0 1 arg for AGI3 Apple IIGS and AGI 3.002.086. AGI3+ only starts here
{ "allow.menu", "n", &cmdAllowMenu }, // B1
{ "show.mouse", "", &cmdShowMouse }, // B2 1 arg for AGI3 Apple IIGS
@@ -403,7 +403,7 @@ void AgiEngine::setupOpCodes(uint16 version) {
}
// Alter opcode parameters for specific games
- if ((version >= 0x2000) && (version < 0x3000)) {
+ if (0x2000 <= version && version < 0x3000) {
// AGI2 adjustments
// 'quit' takes 0 args for 2.089
@@ -418,22 +418,12 @@ void AgiEngine::setupOpCodes(uint16 version) {
_opCodes[0x97].parameters = "vvv";
_opCodes[0x98].parameters = "vvv";
}
-
- // TODO: Opcode B0 is used by SQ2 Apple IIgs, but its purpose is
- // currently unknown. It takes one parameter, and that parameter
- // appears to be a variable number. It is not hide.mouse from AGI3.
- // No other AGI2 games have been discovered that call this opcode.
- // Logic 1: during the spaceship cutscene in the intro, called with 53
- // Logic 23: called twice with 39.
- _opCodes[0xb0].name = "unknown";
- _opCodes[0xb0].parameters = "v";
- _opCodes[0xb0].functionPtr = &cmdUnknown;
}
if (version >= 0x3000) {
// AGI3 adjustments
- // hide.mouse and hide.key take 1 parameter for 3.002.086.
+ // hide.mouse and hold.key take 1 parameter for 3.002.086.
// KQ4 is the only known game with this interpreter and
// its scripts do not call either opcode. no game scripts
// have been discovered that call hold.key with 1 parameter.
@@ -463,6 +453,46 @@ void AgiEngine::setupOpCodes(uint16 version) {
}
}
+ // Apple IIgs adjustments
+ if (getPlatform() == Common::kPlatformApple2GS) {
+ // A2GS has platform-specific opcodes whose values changed over time.
+ // Our A2GS version numbering isn't as precise as for DOS interpreters,
+ // so the following version checks are just meant to separate A2GS games
+ // into three broad groups. The use of these opcodes has been audited in
+ // all known A2GS games and versions. Although all of these are currently
+ // no-ops in our implementation, what's important is that they prevent
+ // the "normal" opcodes from being unexpectedly called.
+
+ if (version <= 0x2440) {
+ // opcode 170: discard.sound.
+ // called by AGIDEMO, KQ1, LSL1, PQ1.
+ memcpy(&_opCodes[0xaa], &_opCodes[0xaf], sizeof(AgiOpCodeDefinitionEntry));
+ } else if (version < 0x3000) {
+ // opcode 174: discard.sound.
+ // called by MMMG, KQ2, KQ3, SQ2.
+ memcpy(&_opCodes[0xae], &_opCodes[0xaf], sizeof(AgiOpCodeDefinitionEntry));
+
+ // TODO: opcode 175: unknown opcode that takes one unknown parameter.
+ // called by KQ3 and SQ2. possibly related to sound. example:
+ // SQ2 Logic 20: called once during music after kicking spores
+ _opCodes[0xaf].name = "unknown";
+ _opCodes[0xaf].parameters = "n";
+ _opCodes[0xaf].functionPtr = &cmdUnknown;
+
+ // TODO: opcode 176: unknown opcode that takes one variable parameter.
+ // called by SQ2 in only two places:
+ // Logic 1: during the spaceship cutscene in the intro, called with 53
+ // Logic 23: called twice with 39.
+ _opCodes[0xb0].name = "unknown";
+ _opCodes[0xb0].parameters = "v";
+ _opCodes[0xb0].functionPtr = &cmdUnknown;
+ } else {
+ // AGI3 opcodes are already in the table:
+ // opcode 175: discard sound.
+ // called by KQ4 and MH1.
+ }
+ }
+
// AGI256 games use a modified opcode (set.simple) that loads 256 color pictures
if (getFeatures() & GF_AGI256) {
_opCodes[0xaa].functionPtr = &cmdAgi256LoadPic;
More information about the Scummvm-git-logs
mailing list