[Scummvm-git-logs] scummvm master -> 9aa749518b1ad59024ef6bf752168f0d341c2e9c
bluegr
noreply at scummvm.org
Fri Jan 24 06:23:58 UTC 2025
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
99e2cecb41 COMMON: Add a helper to Rect to get the origin point
d76f92ab6d VCRUISE: Make use of simpleBlitFrom and maskBlitFrom
9aa749518b VCRUISE: Simplify pixel format selection
Commit: 99e2cecb41d071dfd925e212922339198188f120
https://github.com/scummvm/scummvm/commit/99e2cecb41d071dfd925e212922339198188f120
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2025-01-24T08:23:54+02:00
Commit Message:
COMMON: Add a helper to Rect to get the origin point
Changed paths:
common/rect.h
diff --git a/common/rect.h b/common/rect.h
index 373b02a9b3d..9ff9ffcff8c 100644
--- a/common/rect.h
+++ b/common/rect.h
@@ -188,8 +188,9 @@ struct Rect {
*/
bool operator!=(const Rect &rhs) const { return !equals(rhs); }
- int16 width() const { return right - left; } /*!< Return the width of a rectangle. */
- int16 height() const { return bottom - top; } /*!< Return the height of a rectangle. */
+ Common::Point origin() const { return Common::Point(left, top); } /*!< Return the origin of a rectangle. */
+ int16 width() const { return right - left; } /*!< Return the width of a rectangle. */
+ int16 height() const { return bottom - top; } /*!< Return the height of a rectangle. */
void setWidth(int16 aWidth) { /*!< Set the width to @p aWidth value. */
right = left + aWidth;
Commit: d76f92ab6df6a0ca168ffefb7b47a8aa95ea69a7
https://github.com/scummvm/scummvm/commit/d76f92ab6df6a0ca168ffefb7b47a8aa95ea69a7
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2025-01-24T08:23:54+02:00
Commit Message:
VCRUISE: Make use of simpleBlitFrom and maskBlitFrom
Changed paths:
engines/vcruise/menu.cpp
engines/vcruise/menu.h
engines/vcruise/runtime.cpp
engines/vcruise/runtime.h
engines/vcruise/runtime_scriptexec.cpp
diff --git a/engines/vcruise/menu.cpp b/engines/vcruise/menu.cpp
index 892ee2e7670..2126bb519c3 100644
--- a/engines/vcruise/menu.cpp
+++ b/engines/vcruise/menu.cpp
@@ -78,12 +78,12 @@ protected:
struct Button {
Button();
- Button(Graphics::Surface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenRect, const Common::Rect &interactiveRect, const Common::Point &stateOffset, bool enabled);
- Button(Graphics::Surface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenRect, const Common::Rect &interactiveRect, const Common::Point &stateOffset, bool enabled, const Common::String (&states)[4]);
- Button(Graphics::Surface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenAndInteractiveRect, const Common::Point &stateOffset, bool enabled);
- Button(Graphics::Surface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenAndInteractiveRect, const Common::Point &stateOffset, bool enabled, const Common::String (&states)[4]);
+ Button(Graphics::ManagedSurface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenRect, const Common::Rect &interactiveRect, const Common::Point &stateOffset, bool enabled);
+ Button(Graphics::ManagedSurface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenRect, const Common::Rect &interactiveRect, const Common::Point &stateOffset, bool enabled, const Common::String (&states)[4]);
+ Button(Graphics::ManagedSurface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenAndInteractiveRect, const Common::Point &stateOffset, bool enabled);
+ Button(Graphics::ManagedSurface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenAndInteractiveRect, const Common::Point &stateOffset, bool enabled, const Common::String (&states)[4]);
- Graphics::Surface *_graphic;
+ Graphics::ManagedSurface *_graphic;
Common::Rect _graphicRect;
Common::Rect _screenRect;
Common::Rect _interactiveRect;
@@ -95,9 +95,9 @@ protected:
struct Slider {
Slider();
- Slider(Graphics::Surface *graphic, const Common::Rect &baseRect, int value, int maxValue);
+ Slider(Graphics::ManagedSurface *graphic, const Common::Rect &baseRect, int value, int maxValue);
- Graphics::Surface *_graphic;
+ Graphics::ManagedSurface *_graphic;
Common::Rect _baseRect;
int _value;
int _maxValue;
@@ -519,7 +519,7 @@ ReahMenuBarPage::ReahMenuBarPage(uint page, bool isSchizm) : ReahSchizmMenuPage(
}
void ReahMenuBarPage::start() {
- Graphics::Surface *graphic = _menuInterface->getUIGraphic(4);
+ Graphics::ManagedSurface *graphic = _menuInterface->getUIGraphic(4);
bool menuButtonsEnabled[5] = {true, true, true, true, true};
@@ -539,7 +539,7 @@ void ReahMenuBarPage::start() {
}
}
- Graphics::Surface *returnButtonGraphic = _menuInterface->getUIGraphic(9);
+ Graphics::ManagedSurface *returnButtonGraphic = _menuInterface->getUIGraphic(9);
if (returnButtonGraphic) {
Common::String states[4];
for (int i = 0; i < 4; i++)
@@ -554,10 +554,10 @@ void ReahMenuBarPage::start() {
_buttons.push_back(Button(returnButtonGraphic, Common::Rect(0, 0, 112, 44), screenRect, interactiveRect, Common::Point(0, 44), true, states));
}
- Graphics::Surface *lowerBarGraphic = _menuInterface->getUIGraphic(8);
+ Graphics::ManagedSurface *lowerBarGraphic = _menuInterface->getUIGraphic(8);
if (lowerBarGraphic) {
- _menuInterface->getMenuSurface()->blitFrom(*lowerBarGraphic, Common::Point(0, 392));
+ _menuInterface->getMenuSurface()->simpleBlitFrom(*lowerBarGraphic, Common::Point(0, 392));
_menuInterface->commitRect(Common::Rect(0, 392, 640, 480));
}
@@ -627,7 +627,7 @@ void ReahSchizmMenuPage::drawButtonFromListInState(const Common::Array<Button> &
graphicRect.translate(button._stateOffset.x * state, button._stateOffset.y * state);
Graphics::ManagedSurface *menuSurf = _menuInterface->getMenuSurface();
- menuSurf->blitFrom(*button._graphic, graphicRect, button._screenRect);
+ menuSurf->simpleBlitFrom(*button._graphic, graphicRect, button._screenRect.origin());
_menuInterface->drawLabel(menuSurf, button._buttonStates[state], button._screenRect);
@@ -637,21 +637,21 @@ void ReahSchizmMenuPage::drawButtonFromListInState(const Common::Array<Button> &
ReahSchizmMenuPage::Button::Button() : _graphic(nullptr), _enabled(true) {
}
-ReahSchizmMenuPage::Button::Button(Graphics::Surface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenRect, const Common::Rect &interactiveRect, const Common::Point &stateOffset, bool enabled)
+ReahSchizmMenuPage::Button::Button(Graphics::ManagedSurface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenRect, const Common::Rect &interactiveRect, const Common::Point &stateOffset, bool enabled)
: _graphic(graphic), _graphicRect(graphicRect), _screenRect(screenRect), _interactiveRect(interactiveRect), _stateOffset(stateOffset), _enabled(enabled) {
}
-ReahSchizmMenuPage::Button::Button(Graphics::Surface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenRect, const Common::Rect &interactiveRect, const Common::Point &stateOffset, bool enabled, const Common::String (&states)[4])
+ReahSchizmMenuPage::Button::Button(Graphics::ManagedSurface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenRect, const Common::Rect &interactiveRect, const Common::Point &stateOffset, bool enabled, const Common::String (&states)[4])
: _graphic(graphic), _graphicRect(graphicRect), _screenRect(screenRect), _interactiveRect(interactiveRect), _stateOffset(stateOffset), _enabled(enabled) {
for (int i = 0; i < 4; i++)
this->_buttonStates[i] = states[i];
}
-ReahSchizmMenuPage::Button::Button(Graphics::Surface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenAndInteractiveRect, const Common::Point &stateOffset, bool enabled)
+ReahSchizmMenuPage::Button::Button(Graphics::ManagedSurface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenAndInteractiveRect, const Common::Point &stateOffset, bool enabled)
: _graphic(graphic), _graphicRect(graphicRect), _screenRect(screenAndInteractiveRect), _interactiveRect(screenAndInteractiveRect), _stateOffset(stateOffset), _enabled(enabled) {
}
-ReahSchizmMenuPage::Button::Button(Graphics::Surface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenAndInteractiveRect, const Common::Point &stateOffset, bool enabled, const Common::String(&states)[4])
+ReahSchizmMenuPage::Button::Button(Graphics::ManagedSurface *graphic, const Common::Rect &graphicRect, const Common::Rect &screenAndInteractiveRect, const Common::Point &stateOffset, bool enabled, const Common::String(&states)[4])
: _graphic(graphic), _graphicRect(graphicRect), _screenRect(screenAndInteractiveRect), _interactiveRect(screenAndInteractiveRect), _stateOffset(stateOffset), _enabled(enabled) {
for (int i = 0; i < 4; i++)
this->_buttonStates[i] = states[i];
@@ -661,7 +661,7 @@ ReahSchizmMenuPage::Button::Button(Graphics::Surface *graphic, const Common::Rec
ReahSchizmMenuPage::Slider::Slider() : _graphic(nullptr), _value(0), _maxValue(1) {
}
-ReahSchizmMenuPage::Slider::Slider(Graphics::Surface *graphic, const Common::Rect &baseRect, int value, int maxValue)
+ReahSchizmMenuPage::Slider::Slider(Graphics::ManagedSurface *graphic, const Common::Rect &baseRect, int value, int maxValue)
: _graphic(graphic), _baseRect(baseRect), _value(value), _maxValue(maxValue) {
assert(_value >= 0 && _value <= maxValue);
}
@@ -672,10 +672,10 @@ ReahHelpMenuPage::ReahHelpMenuPage(bool isSchizm) : ReahMenuBarPage(kMenuBarButt
void ReahHelpMenuPage::addPageContents() {
Graphics::ManagedSurface *menuSurf = _menuInterface->getMenuSurface();
- Graphics::Surface *helpBG = _menuInterface->getUIGraphic(12);
+ Graphics::ManagedSurface *helpBG = _menuInterface->getUIGraphic(12);
if (helpBG) {
- menuSurf->blitFrom(*helpBG, Common::Point(0, 44));
+ menuSurf->simpleBlitFrom(*helpBG, Common::Point(0, 44));
_menuInterface->commitRect(Common::Rect(0, 44, helpBG->w, 44 + helpBG->h));
}
@@ -705,9 +705,9 @@ ReahSoundMenuPage::ReahSoundMenuPage(bool isSchizm) : ReahMenuBarPage(kMenuBarBu
}
void ReahSoundMenuPage::addPageContents() {
- Graphics::Surface *soundBG = _menuInterface->getUIGraphic(16);
+ Graphics::ManagedSurface *soundBG = _menuInterface->getUIGraphic(16);
if (soundBG) {
- _menuInterface->getMenuSurface()->blitFrom(*soundBG, Common::Point(0, 44));
+ _menuInterface->getMenuSurface()->simpleBlitFrom(*soundBG, Common::Point(0, 44));
_menuInterface->commitRect(Common::Rect(0, 44, soundBG->w, 44 + soundBG->h));
}
@@ -726,7 +726,7 @@ void ReahSoundMenuPage::addPageContents() {
_musicChecked = !musicMute;
_subtitleChecked = ConfMan.getBool("subtitles");
- Graphics::Surface *soundGraphics = _menuInterface->getUIGraphic(17);
+ Graphics::ManagedSurface *soundGraphics = _menuInterface->getUIGraphic(17);
if (soundGraphics) {
Common::Point checkboxSize = _isSchizm ? Common::Point(200, 44) : Common::Point(112, 44);
@@ -768,6 +768,10 @@ void ReahSoundMenuPage::addPageContents() {
int sliderGraphicLeftX = (_isSchizm ? 800 : 224);
+ assert(!srcFormat.isCLUT8());
+ assert(!dstFormat.isCLUT8());
+
+ // TODO: Use a mask instead of an alpha channel?
for (int y = 0; y < sliderSize.y; y++) {
for (int x = 0; x < sliderSize.x; x++) {
uint32 maskColor = soundGraphics->getPixel(sliderGraphicLeftX + x, y + 60);
@@ -795,8 +799,8 @@ void ReahSoundMenuPage::addPageContents() {
int soundSliderY = (_isSchizm ? kSchizmSoundSliderY : kReahSoundSliderY);
int musicSliderY = (_isSchizm ? kSchizmMusicSliderY : kReahMusicSliderY);
- _sliders.push_back(Slider(_sliderKeyGraphic->surfacePtr(), Common::Rect(sliderScreenLeftX, soundSliderY, sliderScreenLeftX + 40, soundSliderY + 60), sndVol * kSoundSliderWidth / Audio::Mixer::kMaxMixerVolume, kSoundSliderWidth));
- _sliders.push_back(Slider(_sliderKeyGraphic->surfacePtr(), Common::Rect(sliderScreenLeftX, musicSliderY, sliderScreenLeftX + 40, musicSliderY + 60), musVol * kSoundSliderWidth / Audio::Mixer::kMaxMixerVolume, kSoundSliderWidth));
+ _sliders.push_back(Slider(_sliderKeyGraphic.get(), Common::Rect(sliderScreenLeftX, soundSliderY, sliderScreenLeftX + 40, soundSliderY + 60), sndVol * kSoundSliderWidth / Audio::Mixer::kMaxMixerVolume, kSoundSliderWidth));
+ _sliders.push_back(Slider(_sliderKeyGraphic.get(), Common::Rect(sliderScreenLeftX, musicSliderY, sliderScreenLeftX + 40, musicSliderY + 60), musVol * kSoundSliderWidth / Audio::Mixer::kMaxMixerVolume, kSoundSliderWidth));
}
}
@@ -839,7 +843,7 @@ void ReahSoundMenuPage::onSettingsChanged() {
}
void ReahSoundMenuPage::eraseSlider(uint sliderIndex) const {
- Graphics::Surface *soundBG = _menuInterface->getUIGraphic(16);
+ Graphics::ManagedSurface *soundBG = _menuInterface->getUIGraphic(16);
if (soundBG) {
Common::Rect sliderRect = _sliders[sliderIndex]._baseRect;
@@ -848,7 +852,7 @@ void ReahSoundMenuPage::eraseSlider(uint sliderIndex) const {
Common::Rect backgroundSourceRect = sliderRect;
backgroundSourceRect.translate(0, -44);
- _menuInterface->getMenuSurface()->blitFrom(*soundBG, backgroundSourceRect, Common::Point(sliderRect.left, sliderRect.top));
+ _menuInterface->getMenuSurface()->simpleBlitFrom(*soundBG, backgroundSourceRect, Common::Point(sliderRect.left, sliderRect.top));
_menuInterface->commitRect(sliderRect);
}
}
@@ -910,7 +914,7 @@ void ReahQuitMenuPage::addPageContents() {
Graphics::ManagedSurface *menuSurf = _menuInterface->getMenuSurface();
menuSurf->fillRect(Common::Rect(0, 44, 640, 392), menuSurf->format.RGBToColor(0, 0, 0));
- Graphics::Surface *borderGraphic = _menuInterface->getUIGraphic(10);
+ Graphics::ManagedSurface *borderGraphic = _menuInterface->getUIGraphic(10);
if (borderGraphic) {
Graphics::PixelFormat borderGraphicFmt = borderGraphic->format;
@@ -919,6 +923,9 @@ void ReahQuitMenuPage::addPageContents() {
byte g = 0;
byte b = 0;
+ assert(!menuSurf->format.isCLUT8());
+ assert(!borderGraphic->format.isCLUT8());
+
const int xOffsets[2] = {0, 640 - 16};
for (int y = 0; y < borderGraphic->h; y++) {
@@ -941,17 +948,17 @@ void ReahQuitMenuPage::addPageContents() {
}
}
- Graphics::Surface *windowGraphic = _menuInterface->getUIGraphic(13);
+ Graphics::ManagedSurface *windowGraphic = _menuInterface->getUIGraphic(13);
if (windowGraphic)
- menuSurf->blitFrom(*windowGraphic, Common::Point(82, 114));
+ menuSurf->simpleBlitFrom(*windowGraphic, Common::Point(82, 114));
- Graphics::Surface *textGraphic = _menuInterface->getUIGraphic(14);
+ Graphics::ManagedSurface *textGraphic = _menuInterface->getUIGraphic(14);
if (textGraphic)
- menuSurf->blitFrom(*textGraphic, Common::Rect(0, 72, textGraphic->w, textGraphic->h), Common::Point(82, 174));
+ menuSurf->simpleBlitFrom(*textGraphic, Common::Rect(0, 72, textGraphic->w, textGraphic->h), Common::Point(82, 174));
- Graphics::Surface *buttonsGraphic = _menuInterface->getUIGraphic(15);
+ Graphics::ManagedSurface *buttonsGraphic = _menuInterface->getUIGraphic(15);
if (buttonsGraphic) {
int noButtonY = _isSchizm ? 246 : 248;
@@ -997,7 +1004,7 @@ ReahPauseMenuPage::ReahPauseMenuPage(bool isSchizm) : ReahMenuBarPage(static_cas
}
void ReahPauseMenuPage::addPageContents() {
- Graphics::Surface *pauseGraphic = _menuInterface->getUIGraphic(20);
+ Graphics::ManagedSurface *pauseGraphic = _menuInterface->getUIGraphic(20);
Graphics::ManagedSurface *menuSurf = _menuInterface->getMenuSurface();
@@ -1006,7 +1013,7 @@ void ReahPauseMenuPage::addPageContents() {
menuSurf->fillRect(Common::Rect(0, 44, 640, 392), blackColor);
if (pauseGraphic)
- menuSurf->blitFrom(*pauseGraphic, Common::Point(164, 186));
+ menuSurf->simpleBlitFrom(*pauseGraphic, Common::Point(164, 186));
if (_isSchizm) {
Common::Rect labelRect1 = Common::Rect(164, 192, 476, 216);
@@ -1031,17 +1038,17 @@ ReahSchizmMainMenuPage::ReahSchizmMainMenuPage(bool isSchizm) : ReahSchizmMenuPa
}
void ReahSchizmMainMenuPage::start() {
- Graphics::Surface *bgGraphic = _menuInterface->getUIGraphic(0);
+ Graphics::ManagedSurface *bgGraphic = _menuInterface->getUIGraphic(0);
Graphics::ManagedSurface *menuSurf = _menuInterface->getMenuSurface();
if (bgGraphic) {
- menuSurf->blitFrom(*bgGraphic, Common::Point(0, 0));
+ menuSurf->simpleBlitFrom(*bgGraphic, Common::Point(0, 0));
}
_menuInterface->commitRect(Common::Rect(0, 0, 640, 480));
- Graphics::Surface *buttonGraphic = _menuInterface->getUIGraphic(1);
+ Graphics::ManagedSurface *buttonGraphic = _menuInterface->getUIGraphic(1);
Common::Point buttonSize;
diff --git a/engines/vcruise/menu.h b/engines/vcruise/menu.h
index e1e31f9311d..6e68a21c8bf 100644
--- a/engines/vcruise/menu.h
+++ b/engines/vcruise/menu.h
@@ -51,7 +51,7 @@ public:
virtual void commitRect(const Common::Rect &rect) const = 0;
virtual bool popOSEvent(OSEvent &evt) const = 0;
- virtual Graphics::Surface *getUIGraphic(uint index) const = 0;
+ virtual Graphics::ManagedSurface *getUIGraphic(uint index) const = 0;
virtual Graphics::ManagedSurface *getMenuSurface() const = 0;
virtual bool hasDefaultSave() const = 0;
virtual bool hasAnySave() const = 0;
diff --git a/engines/vcruise/runtime.cpp b/engines/vcruise/runtime.cpp
index f4c0bdc8f8c..c1c52a9fbe1 100644
--- a/engines/vcruise/runtime.cpp
+++ b/engines/vcruise/runtime.cpp
@@ -180,7 +180,7 @@ public:
void commitRect(const Common::Rect &rect) const override;
bool popOSEvent(OSEvent &evt) const override;
- Graphics::Surface *getUIGraphic(uint index) const override;
+ Graphics::ManagedSurface *getUIGraphic(uint index) const override;
Graphics::ManagedSurface *getMenuSurface() const override;
bool hasDefaultSave() const override;
bool hasAnySave() const override;
@@ -213,7 +213,7 @@ bool RuntimeMenuInterface::popOSEvent(OSEvent &evt) const {
return _runtime->popOSEvent(evt);
}
-Graphics::Surface *RuntimeMenuInterface::getUIGraphic(uint index) const {
+Graphics::ManagedSurface *RuntimeMenuInterface::getUIGraphic(uint index) const {
if (index >= _runtime->_uiGraphics.size())
return nullptr;
return _runtime->_uiGraphics[index].get();
@@ -1818,10 +1818,10 @@ bool Runtime::bootGame(bool newGame) {
error("Don't have a start config for this game");
if (_gameID != GID_AD2044) {
- _trayBackgroundGraphic = loadGraphic("Pocket", "", true);
- _trayHighlightGraphic = loadGraphic("Select", "", true);
- _trayCompassGraphic = loadGraphic("Select_1", "", true);
- _trayCornerGraphic = loadGraphic("Select_2", "", true);
+ _trayBackgroundGraphic = loadGraphic("Pocket", true);
+ _trayHighlightGraphic = loadGraphic("Select", true);
+ _trayCompassGraphic = loadGraphic("Select_1", true);
+ _trayCornerGraphic = loadGraphic("Select_2", true);
}
if (_gameID == GID_AD2044)
@@ -1961,11 +1961,11 @@ bool Runtime::bootGame(bool newGame) {
_uiGraphics.resize(24);
for (uint i = 0; i < _uiGraphics.size(); i++) {
if (_gameID == GID_REAH) {
- _uiGraphics[i] = loadGraphic(Common::String::format("Image%03u", static_cast<uint>(_languageIndex * 100u + i)), "", false);
+ _uiGraphics[i] = loadGraphic(Common::String::format("Image%03u", static_cast<uint>(_languageIndex * 100u + i)), false);
if (_languageIndex != 0 && !_uiGraphics[i])
- _uiGraphics[i] = loadGraphic(Common::String::format("Image%03u", static_cast<uint>(i)), "", false);
+ _uiGraphics[i] = loadGraphic(Common::String::format("Image%03u", static_cast<uint>(i)), false);
} else if (_gameID == GID_SCHIZM) {
- _uiGraphics[i] = loadGraphic(Common::String::format("Data%03u", i), "", false);
+ _uiGraphics[i] = loadGraphic(Common::String::format("Data%03u", i), false);
}
}
}
@@ -2704,7 +2704,7 @@ void Runtime::continuePlayingAnimation(bool loop, bool useStopFrame, bool &outAn
if (copyRect.isValidRect() || !copyRect.isEmpty()) {
Graphics::Palette p(_animDecoder->getPalette(), 256);
- _gameSection.surf->blitFrom(*surface, copyRect, copyRect, &p);
+ _gameSection.surf->simpleBlitFrom(*surface, copyRect, copyRect.origin(), &p);
drawSectionToScreen(_gameSection, copyRect);
}
@@ -2729,7 +2729,7 @@ void Runtime::drawSectionToScreen(const RenderSection §ion, const Common::Re
const RenderSection *sourceSection = §ion;
if (_debugMode && (&_gameSection == §ion)) {
- _gameDebugBackBuffer.surf->blitFrom(*sourceSection->surf, rect, rect);
+ _gameDebugBackBuffer.surf->simpleBlitFrom(*sourceSection->surf, rect, rect.origin());
commitSectionToScreen(_gameDebugBackBuffer, rect);
} else
commitSectionToScreen(*sourceSection, rect);
@@ -3733,7 +3733,7 @@ void Runtime::changeToScreen(uint roomNumber, uint screenNumber) {
_placedItemBackBufferSection.init(renderRect, _placedItemBackBufferSection.pixFmt);
if (!_placedItemRect.isEmpty())
- _placedItemBackBufferSection.surf->blitFrom(*_gameSection.surf, _placedItemRect, Common::Point(0, 0));
+ _placedItemBackBufferSection.surf->simpleBlitFrom(*_gameSection.surf, _placedItemRect, Common::Point(0, 0));
updatePlacedItemCache();
@@ -5652,7 +5652,8 @@ void Runtime::inventoryAddItem(uint item) {
getFileNamesForItemGraphic(item, itemFileName, alphaFileName);
_inventory[firstOpenSlot].itemID = item;
- _inventory[firstOpenSlot].graphic = loadGraphic(itemFileName, alphaFileName, false);
+ _inventory[firstOpenSlot].graphic = loadGraphic(itemFileName, false);
+ _inventory[firstOpenSlot].mask = loadGraphic(alphaFileName, false);
drawInventory(firstOpenSlot);
}
@@ -5665,6 +5666,7 @@ void Runtime::inventoryRemoveItem(uint itemID) {
item.highlighted = false;
item.itemID = 0;
item.graphic.reset();
+ item.mask.reset();
drawInventory(slot);
break;
}
@@ -5673,7 +5675,7 @@ void Runtime::inventoryRemoveItem(uint itemID) {
void Runtime::clearScreen() {
if (_gameID == GID_AD2044) {
- _fullscreenMenuSection.surf->blitFrom(*_backgroundGraphic);
+ _fullscreenMenuSection.surf->simpleBlitFrom(*_backgroundGraphic);
commitSectionToScreen(_fullscreenMenuSection, _fullscreenMenuSection.rect);
} else
_system->fillScreen(_system->getScreenFormat().RGBToColor(0, 0, 0));
@@ -5696,7 +5698,7 @@ void Runtime::clearTray() {
if (_gameID == GID_AD2044) {
trayRect = _traySection.rect;
trayRect.translate(-trayRect.left, -trayRect.top);
- _traySection.surf->blitFrom(*_backgroundGraphic, _traySection.rect, trayRect);
+ _traySection.surf->simpleBlitFrom(*_backgroundGraphic, _traySection.rect, trayRect.origin());
} else {
uint32 blackColor = _traySection.surf->format.RGBToColor(0, 0, 0);
trayRect = Common::Rect(0, 0, _traySection.surf->w, _traySection.surf->h);
@@ -5742,7 +5744,7 @@ void Runtime::clearSubtitleSection() {
if (_gameID == GID_AD2044) {
stRect = _subtitleSection.rect;
stRect.translate(-stRect.left, -stRect.top);
- _subtitleSection.surf->blitFrom(*_backgroundGraphic, _subtitleSection.rect, stRect);
+ _subtitleSection.surf->simpleBlitFrom(*_backgroundGraphic, _subtitleSection.rect, stRect.origin());
}
this->commitSectionToScreen(_subtitleSection, stRect);
@@ -5801,11 +5803,12 @@ void Runtime::drawInventory(uint slot) {
const bool highlighted = _inventory[slot].highlighted;
if (highlighted)
- _traySection.surf->blitFrom(*_trayHighlightGraphic, sliceRect, sliceRect);
+ _traySection.surf->simpleBlitFrom(*_trayHighlightGraphic, sliceRect, sliceRect.origin());
else
_traySection.surf->fillRect(sliceRect, 0);
- const Graphics::Surface *surf = _inventory[slot].graphic.get();
+ const Graphics::ManagedSurface *surf = _inventory[slot].graphic.get();
+ const Graphics::ManagedSurface *mask = _inventory[slot].mask.get();
// TODO: Highlighted items
if (surf) {
@@ -5816,10 +5819,15 @@ void Runtime::drawInventory(uint slot) {
const uint itemLeftY = slotStartX + (slotWidth - itemWidth) / 2u;
if (highlighted) {
+ // TODO: Use simpleBlitFrom here as well?
+ assert(!mask);
+
uint32 blackColor = surf->format.ARGBToColor(255, 0, 0, 0);
_traySection.surf->transBlitFrom(*surf, Common::Point(itemLeftY, itemTopY), blackColor);
- } else
- _traySection.surf->blitFrom(*surf, Common::Point(itemLeftY, itemTopY));
+ } else if (mask)
+ _traySection.surf->maskBlitFrom(*surf, *mask, Common::Point(itemLeftY, itemTopY));
+ else
+ _traySection.surf->simpleBlitFrom(*surf, Common::Point(itemLeftY, itemTopY));
}
commitSectionToScreen(_traySection, sliceRect);
@@ -5873,7 +5881,7 @@ void Runtime::drawCompass() {
compassRect.translate(horizOffset, vertOffset);
- _traySection.surf->blitFrom(*_trayCompassGraphic, Common::Point(compassRect.left, compassRect.top));
+ _traySection.surf->simpleBlitFrom(*_trayCompassGraphic, Common::Point(compassRect.left, compassRect.top));
const uint32 blackColor = _traySection.surf->format.ARGBToColor(255, 0, 0, 0);
@@ -5891,16 +5899,16 @@ void Runtime::drawCompass() {
if (_gameID == GID_REAH) {
if (haveLocation)
- _traySection.surf->blitFrom(*_trayCornerGraphic, Common::Point(lowerRightRect.left, lowerRightRect.top));
+ _traySection.surf->simpleBlitFrom(*_trayCornerGraphic, Common::Point(lowerRightRect.left, lowerRightRect.top));
else
- _traySection.surf->blitFrom(*_trayBackgroundGraphic, lowerRightRect, Common::Point(lowerRightRect.left, lowerRightRect.top));
+ _traySection.surf->simpleBlitFrom(*_trayBackgroundGraphic, lowerRightRect, Common::Point(lowerRightRect.left, lowerRightRect.top));
} else if (_gameID == GID_SCHIZM) {
Common::Rect graphicRect = Common::Rect(0u + _hero * 176u, 0, 0u + _hero * 176u + 88, 88);
if (!haveLocation)
graphicRect.translate(88, 0);
- _traySection.surf->blitFrom(*_trayCornerGraphic, graphicRect, Common::Point(lowerRightRect.left, lowerRightRect.top));
+ _traySection.surf->simpleBlitFrom(*_trayCornerGraphic, graphicRect, Common::Point(lowerRightRect.left, lowerRightRect.top));
}
commitSectionToScreen(_traySection, compassRect);
@@ -5984,7 +5992,8 @@ void Runtime::updatePlacedItemCache() {
_inventoryPlacedItemCache.itemID = itemID;
getFileNamesForItemGraphic(itemID, itemFileName, alphaFileName);
- _inventoryPlacedItemCache.graphic = loadGraphic(itemFileName, alphaFileName, false);
+ _inventoryPlacedItemCache.graphic = loadGraphic(itemFileName, false);
+ _inventoryPlacedItemCache.mask = loadGraphic(alphaFileName, false);
}
} else {
_inventoryPlacedItemCache = InventoryItem();
@@ -5992,34 +6001,47 @@ void Runtime::updatePlacedItemCache() {
}
void Runtime::drawPlacedItemGraphic() {
- const Graphics::Surface *surf = _inventoryPlacedItemCache.graphic.get();
+ const Graphics::ManagedSurface *surf = _inventoryPlacedItemCache.graphic.get();
+ const Graphics::ManagedSurface *mask = _inventoryPlacedItemCache.mask.get();
+
if (surf) {
Common::Point drawPos((_placedItemRect.left + _placedItemRect.right - surf->w) / 2, (_placedItemRect.top + _placedItemRect.bottom - surf->h) / 2);
- _gameSection.surf->blitFrom(*surf, drawPos);
+ if (mask) {
+ _gameSection.surf->maskBlitFrom(*surf, *mask, drawPos);
+ } else {
+ _gameSection.surf->simpleBlitFrom(*surf, drawPos);
+ }
drawSectionToScreen(_gameSection, _placedItemRect);
}
}
void Runtime::clearPlacedItemGraphic() {
if (!_placedItemRect.isEmpty()) {
- _gameSection.surf->blitFrom(*_placedItemBackBufferSection.surf, Common::Point(_placedItemRect.left, _placedItemRect.top));
+ _gameSection.surf->simpleBlitFrom(*_placedItemBackBufferSection.surf, Common::Point(_placedItemRect.left, _placedItemRect.top));
drawSectionToScreen(_gameSection, _placedItemRect);
}
}
void Runtime::drawActiveItemGraphic() {
- if (_inventoryActiveItem.graphic) {
+ const Graphics::ManagedSurface *surf = _inventoryActiveItem.graphic.get();
+ const Graphics::ManagedSurface *mask = _inventoryActiveItem.mask.get();
+
+ if (surf) {
Common::Rect itemRect = AD2044Interface::getRectForUI(AD2044InterfaceRectID::ActiveItemRender);
- _fullscreenMenuSection.surf->blitFrom(*_inventoryActiveItem.graphic, Common::Point(itemRect.left, itemRect.top));
+ if (mask)
+ _fullscreenMenuSection.surf->maskBlitFrom(*surf, *mask, Common::Point(itemRect.left, itemRect.top));
+ else
+ _fullscreenMenuSection.surf->simpleBlitFrom(*surf, Common::Point(itemRect.left, itemRect.top));
+
drawSectionToScreen(_fullscreenMenuSection, itemRect);
}
if (g_ad2044ItemInfos[_inventoryActiveItem.itemID].canBeExamined && _hero == 0) {
Common::Rect examineRect = AD2044Interface::getRectForUI(AD2044InterfaceRectID::ExamineButton);
- _fullscreenMenuSection.surf->blitFrom(*_ad2044Graphics->examine, Common::Point(examineRect.left, examineRect.top));
+ _fullscreenMenuSection.surf->simpleBlitFrom(*_ad2044Graphics->examine, Common::Point(examineRect.left, examineRect.top));
drawSectionToScreen(_fullscreenMenuSection, examineRect);
}
}
@@ -6031,16 +6053,23 @@ void Runtime::clearActiveItemGraphic() {
};
for (const Common::Rect &rectToClear : rectsToClear) {
- _fullscreenMenuSection.surf->blitFrom(*_backgroundGraphic, rectToClear, rectToClear);
+ _fullscreenMenuSection.surf->simpleBlitFrom(*_backgroundGraphic, rectToClear, rectToClear.origin());
drawSectionToScreen(_fullscreenMenuSection, rectToClear);
}
}
void Runtime::drawInventoryItemGraphic(uint slot) {
- if (_inventory[slot].graphic) {
+ const Graphics::ManagedSurface *surf = _inventory[slot].graphic.get();
+ const Graphics::ManagedSurface *mask = _inventory[slot].mask.get();
+
+ if (surf) {
Common::Rect rect = AD2044Interface::getRectForUI(static_cast<AD2044InterfaceRectID>(static_cast<uint>(AD2044InterfaceRectID::InventoryRender0) + slot));
- _fullscreenMenuSection.surf->blitFrom(*_inventory[slot].graphic, Common::Point(rect.left, rect.top));
+ if (mask)
+ _fullscreenMenuSection.surf->maskBlitFrom(*surf, *mask, Common::Point(rect.left, rect.top));
+ else
+ _fullscreenMenuSection.surf->simpleBlitFrom(*surf, Common::Point(rect.left, rect.top));
+
drawSectionToScreen(_fullscreenMenuSection, rect);
}
}
@@ -6048,7 +6077,7 @@ void Runtime::drawInventoryItemGraphic(uint slot) {
void Runtime::clearInventoryItemGraphic(uint slot) {
Common::Rect rect = AD2044Interface::getRectForUI(static_cast<AD2044InterfaceRectID>(static_cast<uint>(AD2044InterfaceRectID::InventoryRender0) + slot));
- _fullscreenMenuSection.surf->blitFrom(*_backgroundGraphic, rect, rect);
+ _fullscreenMenuSection.surf->simpleBlitFrom(*_backgroundGraphic, rect, rect.origin());
drawSectionToScreen(_fullscreenMenuSection, rect);
}
@@ -6130,42 +6159,21 @@ void Runtime::getFileNamesForItemGraphic(uint itemID, Common::String &outFileNam
error("Unknown game, can't format inventory item");
}
-Common::SharedPtr<Graphics::Surface> Runtime::loadGraphic(const Common::String &graphicName, const Common::String &alphaName, bool required) {
+Common::SharedPtr<Graphics::ManagedSurface> Runtime::loadGraphic(const Common::String &graphicName, bool required) {
+ if (graphicName.empty())
+ return nullptr;
+
Common::Path filePath((_gameID == GID_AD2044) ? "rze/" : "Gfx/");
filePath.appendInPlace(graphicName);
filePath.appendInPlace((_gameID == GID_AD2044) ? ".BMP" : ".bmp");
- Common::SharedPtr<Graphics::Surface> surf = loadGraphicFromPath(filePath, required);
-
- if (surf && !alphaName.empty()) {
- Common::SharedPtr<Graphics::Surface> alphaSurf = loadGraphic(alphaName, "", required);
- if (alphaSurf) {
- if (surf->w != alphaSurf->w || surf->h != alphaSurf->h)
- error("Mismatched graphic sizes");
-
- int h = surf->h;
- int w = surf->w;
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- uint32 alphaSurfPixel = alphaSurf->getPixel(x, y);
-
- uint8 r = 0;
- uint8 g = 0;
- uint8 b = 0;
- uint8 a = 0;
- alphaSurf->format.colorToARGB(alphaSurfPixel, a, r, g, b);
- if (r < 128)
- surf->setPixel(x, y, 0);
- }
- }
- }
- }
+ Common::SharedPtr<Graphics::ManagedSurface> surf = loadGraphicFromPath(filePath, required);
return surf;
}
-Common::SharedPtr<Graphics::Surface> Runtime::loadGraphicFromPath(const Common::Path &filePath, bool required) {
+Common::SharedPtr<Graphics::ManagedSurface> Runtime::loadGraphicFromPath(const Common::Path &filePath, bool required) {
Common::File f;
if (!f.open(filePath)) {
warning("Couldn't open BMP file '%s'", filePath.toString(Common::Path::kNativeSeparator).c_str());
@@ -6182,9 +6190,14 @@ Common::SharedPtr<Graphics::Surface> Runtime::loadGraphicFromPath(const Common::
return nullptr;
}
- Common::SharedPtr<Graphics::Surface> surf(new Graphics::Surface(), Graphics::SurfaceDeleter());
- surf->copyFrom(*bmpDecoder.getSurface());
- surf = Common::SharedPtr<Graphics::Surface>(surf->convertTo(Graphics::createPixelFormat<8888>(), bmpDecoder.getPalette(), bmpDecoder.getPaletteColorCount()), Graphics::SurfaceDeleter());
+ // Preserve the palette if it has one, otherwise convert it to the current screen format.
+ Common::SharedPtr<Graphics::ManagedSurface> surf(new Graphics::ManagedSurface());
+ if (bmpDecoder.hasPalette()) {
+ surf->copyFrom(*bmpDecoder.getSurface());
+ surf->setPalette(bmpDecoder.getPalette(), 0, bmpDecoder.getPaletteColorCount());
+ } else {
+ surf->convertFrom(*bmpDecoder.getSurface(), _system->getScreenFormat());
+ }
return surf;
}
@@ -6570,7 +6583,7 @@ void Runtime::drawInGameMenuButton(uint element) {
Common::Rect buttonSrcRect = Common::Rect(buttonTopLeftPoint.x, buttonTopLeftPoint.y, buttonTopLeftPoint.x + 128, buttonTopLeftPoint.y + _menuSection.rect.height());
- _menuSection.surf->blitFrom(*_uiGraphics[4], buttonSrcRect, buttonDestRect);
+ _menuSection.surf->simpleBlitFrom(*_uiGraphics[4], buttonSrcRect, buttonDestRect.origin());
if (_gameID == GID_SCHIZM) {
int labelNumber = static_cast<int>(element) + 1 + buttonState * 5;
@@ -7054,15 +7067,18 @@ void Runtime::restoreSaveGameSnapshot() {
Common::String itemFileName;
Common::String alphaFileName;
getFileNamesForItemGraphic(invItem.itemID, itemFileName, alphaFileName);
- invItem.graphic = loadGraphic(itemFileName, alphaFileName, false);
+ invItem.graphic = loadGraphic(itemFileName, false);
+ invItem.mask = loadGraphic(alphaFileName, false);
}
}
for (uint page = 0; page < kNumInventoryPages; page++) {
for (uint slot = 0; slot < kNumInventorySlots; slot++) {
InventoryItem &invItem = _inventoryPages[page][slot];
- if (!invItem.itemID)
+ if (!invItem.itemID) {
invItem.graphic.reset();
+ invItem.mask.reset();
+ }
}
}
@@ -7071,9 +7087,11 @@ void Runtime::restoreSaveGameSnapshot() {
Common::String itemFileName;
Common::String alphaFileName;
getFileNamesForItemGraphic(_inventoryActiveItem.itemID, itemFileName, alphaFileName);
- _inventoryActiveItem.graphic = loadGraphic(itemFileName, alphaFileName, false);
+ _inventoryActiveItem.graphic = loadGraphic(itemFileName, false);
+ _inventoryActiveItem.mask = loadGraphic(alphaFileName, false);
} else {
_inventoryActiveItem.graphic.reset();
+ _inventoryActiveItem.mask.reset();
}
_inventoryPlacedItemCache = InventoryItem();
@@ -7100,9 +7118,11 @@ void Runtime::restoreSaveGameSnapshot() {
Common::String itemFileName;
Common::String alphaFileName;
getFileNamesForItemGraphic(saveItem.itemID, itemFileName, alphaFileName);
- _inventory[i].graphic = loadGraphic(itemFileName, alphaFileName, false);
+ _inventory[i].graphic = loadGraphic(itemFileName, false);
+ _inventory[i].mask = loadGraphic(alphaFileName, false);
} else {
_inventory[i].graphic.reset();
+ _inventory[i].mask.reset();
}
}
}
diff --git a/engines/vcruise/runtime.h b/engines/vcruise/runtime.h
index 4a21f066ce7..fd8bb712e56 100644
--- a/engines/vcruise/runtime.h
+++ b/engines/vcruise/runtime.h
@@ -395,7 +395,8 @@ struct AnimFrameRange {
struct InventoryItem {
InventoryItem();
- Common::SharedPtr<Graphics::Surface> graphic;
+ Common::SharedPtr<Graphics::ManagedSurface> graphic;
+ Common::SharedPtr<Graphics::ManagedSurface> mask;
uint itemID;
bool highlighted;
};
@@ -1007,8 +1008,8 @@ private:
void pickupInventoryItem(uint slot);
void getFileNamesForItemGraphic(uint itemID, Common::String &outGraphicFileName, Common::String &outAlphaFileName) const;
- Common::SharedPtr<Graphics::Surface> loadGraphic(const Common::String &graphicName, const Common::String &alphaName, bool required);
- Common::SharedPtr<Graphics::Surface> loadGraphicFromPath(const Common::Path &path, bool required);
+ Common::SharedPtr<Graphics::ManagedSurface> loadGraphic(const Common::String &graphicName, bool required);
+ Common::SharedPtr<Graphics::ManagedSurface> loadGraphicFromPath(const Common::Path &path, bool required);
bool loadSubtitles(Common::CodePage codePage, bool guessCodePage);
@@ -1254,13 +1255,13 @@ private:
InventoryItem _inventoryPlacedItemCache;
Common::Rect _placedItemRect;
- Common::SharedPtr<Graphics::Surface> _trayCompassGraphic;
- Common::SharedPtr<Graphics::Surface> _trayBackgroundGraphic;
- Common::SharedPtr<Graphics::Surface> _trayHighlightGraphic;
- Common::SharedPtr<Graphics::Surface> _trayCornerGraphic;
- Common::SharedPtr<Graphics::Surface> _backgroundGraphic;
+ Common::SharedPtr<Graphics::ManagedSurface> _trayCompassGraphic;
+ Common::SharedPtr<Graphics::ManagedSurface> _trayBackgroundGraphic;
+ Common::SharedPtr<Graphics::ManagedSurface> _trayHighlightGraphic;
+ Common::SharedPtr<Graphics::ManagedSurface> _trayCornerGraphic;
+ Common::SharedPtr<Graphics::ManagedSurface> _backgroundGraphic;
- Common::Array<Common::SharedPtr<Graphics::Surface> > _uiGraphics;
+ Common::Array<Common::SharedPtr<Graphics::ManagedSurface> > _uiGraphics;
uint _panCursors[kPanCursorMaxCount];
diff --git a/engines/vcruise/runtime_scriptexec.cpp b/engines/vcruise/runtime_scriptexec.cpp
index 8960baece5e..173f150ec33 100644
--- a/engines/vcruise/runtime_scriptexec.cpp
+++ b/engines/vcruise/runtime_scriptexec.cpp
@@ -542,6 +542,7 @@ void Runtime::scriptOpItemClear(ScriptArg_t arg) {
item.highlighted = false;
item.itemID = 0;
item.graphic.reset();
+ item.mask.reset();
drawInventory(slot);
}
}
@@ -2314,7 +2315,8 @@ void Runtime::scriptOpRSet(ScriptArg_t arg) {
_inventoryActiveItem.itemID = itemID;
getFileNamesForItemGraphic(itemID, itemFileName, alphaFileName);
- _inventoryActiveItem.graphic = loadGraphic(itemFileName, alphaFileName, false);
+ _inventoryActiveItem.graphic = loadGraphic(itemFileName, false);
+ _inventoryActiveItem.mask = loadGraphic(alphaFileName, false);
clearActiveItemGraphic();
drawActiveItemGraphic();
Commit: 9aa749518b1ad59024ef6bf752168f0d341c2e9c
https://github.com/scummvm/scummvm/commit/9aa749518b1ad59024ef6bf752168f0d341c2e9c
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2025-01-24T08:23:54+02:00
Commit Message:
VCRUISE: Simplify pixel format selection
Changed paths:
engines/vcruise/vcruise.cpp
diff --git a/engines/vcruise/vcruise.cpp b/engines/vcruise/vcruise.cpp
index cce7b4df6fd..0267f94e8aa 100644
--- a/engines/vcruise/vcruise.cpp
+++ b/engines/vcruise/vcruise.cpp
@@ -82,8 +82,6 @@ void VCruiseEngine::handleMidiTimer() {
}
Common::Error VCruiseEngine::run() {
- Common::List<Graphics::PixelFormat> pixelFormats = _system->getSupportedFormats();
-
#if !defined(USE_JPEG)
if (_gameDescription->desc.flags & VCRUISE_GF_NEED_JPEG) {
return Common::Error(Common::kUnknownError, _s("This game requires JPEG support, which was not compiled in."));
@@ -136,19 +134,6 @@ Common::Error VCruiseEngine::run() {
syncSoundSettings();
- const Graphics::PixelFormat *fmt16_565 = nullptr;
- const Graphics::PixelFormat *fmt16_555 = nullptr;
- const Graphics::PixelFormat *fmt32 = nullptr;
-
- for (const Graphics::PixelFormat &fmt : pixelFormats) {
- if (fmt32 == nullptr && fmt.bytesPerPixel == 4 && fmt.rBits() == 8 && fmt.gBits() == 8 && fmt.bBits() == 8)
- fmt32 = &fmt;
- if (fmt16_555 == nullptr && fmt.rBits() == 5 && fmt.gBits() == 5 && fmt.bBits() == 5)
- fmt16_555 = &fmt;
- if (fmt16_565 == nullptr && fmt.rBits() == 5 && fmt.gBits() == 6 && fmt.bBits() == 5)
- fmt16_565 = &fmt;
- }
-
// Figure out screen layout
Common::Point size;
@@ -199,14 +184,10 @@ Common::Error VCruiseEngine::run() {
_trayRect = Common::Rect(trayTL.x, trayTL.y, trayTL.x + traySize.x, trayTL.y + traySize.y);
}
- if (fmt32)
- initGraphics(size.x, size.y, fmt32);
- else if (fmt16_565)
- initGraphics(size.x, size.y, fmt16_565);
- else if (fmt16_555)
- initGraphics(size.x, size.y, fmt16_555);
- else
- error("Unable to find a suitable graphics format");
+ // TODO: Optionally support CLUT8 for AD 2044
+ initGraphics(size.x, size.y, nullptr);
+ if (_system->getScreenFormat().isCLUT8())
+ return Common::kUnsupportedColorMode;
_system->fillScreen(0);
More information about the Scummvm-git-logs
mailing list