aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/supernova/detection.cpp19
-rw-r--r--engines/supernova/graphics.cpp25
-rw-r--r--engines/supernova/graphics.h6
-rw-r--r--engines/supernova/imageid.h654
-rw-r--r--engines/supernova/module.mk7
-rw-r--r--engines/supernova/msn_def.h292
-rw-r--r--engines/supernova/resman.cpp395
-rw-r--r--engines/supernova/resman.h77
-rw-r--r--engines/supernova/rooms.cpp404
-rw-r--r--engines/supernova/rooms.h45
-rw-r--r--engines/supernova/screen.cpp636
-rw-r--r--engines/supernova/screen.h197
-rw-r--r--engines/supernova/screenstatic.cpp328
-rw-r--r--engines/supernova/sound.cpp65
-rw-r--r--engines/supernova/sound.h80
-rw-r--r--engines/supernova/state.cpp363
-rw-r--r--engines/supernova/state.h36
-rw-r--r--engines/supernova/supernova.cpp858
-rw-r--r--engines/supernova/supernova.h174
19 files changed, 3040 insertions, 1621 deletions
diff --git a/engines/supernova/detection.cpp b/engines/supernova/detection.cpp
index 7fd2da1760..b172b7fa49 100644
--- a/engines/supernova/detection.cpp
+++ b/engines/supernova/detection.cpp
@@ -32,7 +32,7 @@
static const PlainGameDescriptor supernovaGames[] = {
{"msn1", "Mission Supernova 1"},
{"msn2", "Mission Supernova 2"},
- {NULL, NULL}
+ {nullptr, nullptr}
};
namespace Supernova {
@@ -40,7 +40,7 @@ static const ADGameDescription gameDescriptions[] = {
// Mission Supernova 1
{
"msn1",
- NULL,
+ nullptr,
AD_ENTRY1s("msn_data.000", "f64f16782a86211efa919fbae41e7568", 24163),
Common::DE_DEU,
Common::kPlatformDOS,
@@ -49,7 +49,7 @@ static const ADGameDescription gameDescriptions[] = {
},
{
"msn1",
- NULL,
+ nullptr,
AD_ENTRY1s("msn_data.000", "f64f16782a86211efa919fbae41e7568", 24163),
Common::EN_ANY,
Common::kPlatformDOS,
@@ -60,13 +60,22 @@ static const ADGameDescription gameDescriptions[] = {
// Mission Supernova 2
{
"msn2",
- NULL,
+ nullptr,
AD_ENTRY1s("ms2_data.000", "e595610cba4a6d24a763e428d05cc83f", 24805),
Common::DE_DEU,
Common::kPlatformDOS,
ADGF_UNSTABLE,
GUIO1(GUIO_NONE)
},
+ {
+ "msn2",
+ nullptr,
+ AD_ENTRY1s("ms2_data.000", "e595610cba4a6d24a763e428d05cc83f", 24805),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NONE)
+ },
AD_TABLE_END_MARKER
};
@@ -122,7 +131,7 @@ bool SupernovaMetaEngine::createInstance(OSystem *syst, Engine **engine, const A
*engine = new Supernova::SupernovaEngine(syst);
}
- return desc != NULL;
+ return desc != nullptr;
}
SaveStateList SupernovaMetaEngine::listSaves(const char *target) const {
diff --git a/engines/supernova/graphics.cpp b/engines/supernova/graphics.cpp
index 3a29bacacc..9a05a424ca 100644
--- a/engines/supernova/graphics.cpp
+++ b/engines/supernova/graphics.cpp
@@ -28,13 +28,14 @@
#include "graphics/palette.h"
#include "graphics/surface.h"
-#include "graphics.h"
-#include "msn_def.h"
-#include "supernova.h"
+#include "supernova/graphics.h"
+#include "supernova/msn_def.h"
+#include "supernova/screen.h"
+#include "supernova/supernova.h"
namespace Supernova {
-MSNImageDecoder::MSNImageDecoder() {
+MSNImage::MSNImage() {
_palette = nullptr;
_encodedImage = nullptr;
_filenumber = -1;
@@ -43,11 +44,11 @@ MSNImageDecoder::MSNImageDecoder() {
_numClickFields = 0;
}
-MSNImageDecoder::~MSNImageDecoder() {
+MSNImage::~MSNImage() {
destroy();
}
-bool MSNImageDecoder::init(int filenumber) {
+bool MSNImage::init(int filenumber) {
Common::File file;
if (!file.open(Common::String::format("msn_data.%03d", filenumber))) {
warning("Image data file msn_data.%03d could not be read!", filenumber);
@@ -60,7 +61,7 @@ bool MSNImageDecoder::init(int filenumber) {
return true;
}
-bool MSNImageDecoder::loadFromEngineDataFile() {
+bool MSNImage::loadFromEngineDataFile() {
Common::String name;
if (_filenumber == 1)
name = "IMG1";
@@ -102,7 +103,7 @@ bool MSNImageDecoder::loadFromEngineDataFile() {
return false;
}
-bool MSNImageDecoder::loadStream(Common::SeekableReadStream &stream) {
+bool MSNImage::loadStream(Common::SeekableReadStream &stream) {
destroy();
uint size = 0;
@@ -199,7 +200,7 @@ bool MSNImageDecoder::loadStream(Common::SeekableReadStream &stream) {
return true;
}
-bool MSNImageDecoder::loadSections() {
+bool MSNImage::loadSections() {
bool isNewspaper = _filenumber == 1 || _filenumber == 2;
int imageWidth = isNewspaper ? 640 : 320;
int imageHeight = isNewspaper ? 480 : 200;
@@ -238,14 +239,14 @@ bool MSNImageDecoder::loadSections() {
return true;
}
-void MSNImageDecoder::destroy() {
+void MSNImage::destroy() {
if (_palette) {
delete[] _palette;
- _palette = NULL;
+ _palette = nullptr;
}
if (_encodedImage) {
delete[] _encodedImage;
- _encodedImage = NULL;
+ _encodedImage = nullptr;
}
for (Common::Array<Graphics::Surface *>::iterator it = _sectionSurfaces.begin();
it != _sectionSurfaces.end(); ++it) {
diff --git a/engines/supernova/graphics.h b/engines/supernova/graphics.h
index 2a820c9432..058da45ba8 100644
--- a/engines/supernova/graphics.h
+++ b/engines/supernova/graphics.h
@@ -36,10 +36,10 @@ struct Surface;
namespace Supernova {
-class MSNImageDecoder : public Image::ImageDecoder {
+class MSNImage : public Image::ImageDecoder {
public:
- MSNImageDecoder();
- virtual ~MSNImageDecoder();
+ MSNImage();
+ virtual ~MSNImage();
virtual void destroy();
virtual bool loadStream(Common::SeekableReadStream &stream);
diff --git a/engines/supernova/imageid.h b/engines/supernova/imageid.h
new file mode 100644
index 0000000000..7cfa08370e
--- /dev/null
+++ b/engines/supernova/imageid.h
@@ -0,0 +1,654 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef SUPERNOVA_IMAGEID_H
+#define SUPERNOVA_IMAGEID_H
+
+namespace Supernova {
+
+enum ImageId {
+ // file 0
+ kAxacussanShipBackground,
+ kAxacussanShipCenterMouthOpen,
+ kAxacussanShipRightMouthOpen,
+ // file 1
+ kNewspaper1,
+ // file 2
+ kNewspaper2,
+ // file 3
+ kElevatorBackground,
+ kElevatorGreenButton,
+ kElevatorRedButton,
+ kElevatorDoorAnimation1,
+ kElevatorDoorAnimation2,
+ kElevatorDoorAnimation3,
+ kElevatorDoorAnimation4,
+ kElevatorDoorAnimation5,
+ kElevatorDummy1,
+ kElevatorDummy2,
+ kElevatorDummy3,
+ kElevatorDummy4,
+ // file 4
+ kShipSpaceBackground,
+ kShipSpaceRope,
+ kShipSpaceDummy1,
+ kShipSpaceDummy2,
+ // file 5
+ kBusStationBackground,
+ kBusStationArrived,
+ kBusStationPlantAnimation1,
+ kBusStationPlantAnimation2,
+ kBusStationPlantAnimation3,
+ kBusStationPlantAnimation4,
+ kBusStationPlantAnimation5,
+ kBusStationPlantAnimation6,
+ kBusStationPlantAnimation7,
+ kBusStationDoorOpened,
+ // file 6
+ kOfficesBackground,
+ kOfficesDoorOpenTopLeft,
+ kOfficesDoorOpenBottomLeft,
+ kOfficesDoorOpenTopRight,
+ kOfficesDoorOpenBottomRight,
+ kOfficesAlienCorridorAnimation1,
+ kOfficesAlienCorridorAnimation2,
+ kOfficesAlienCorridorAnimation3,
+ kOfficesAlienCorridorAnimation4,
+ kOfficesAlienCorridorAnimation5,
+ kOfficesAlienCorridorAnimation6,
+ kOfficesAlienTopOfficeAnimation1,
+ kOfficesAlienTopOfficeAnimation2,
+ kOfficesAlienTopOfficeAnimation3,
+ kOfficesAlienTopOfficeAnimation4,
+ kOfficesAlienTopOfficeAnimation5,
+ kOfficesAlienBottomOfficeAnimation1,
+ kOfficesAlienBottomOfficeAnimation2,
+ kOfficesAlienBottomOfficeAnimation3,
+ kOfficesAlienBottomOfficeAnimation4,
+ kOfficesAlienBottomOfficeAnimation5,
+ kOfficesAlienBottom,
+ // file 7
+ kOfficeLeftBackground,
+ kOfficeLeftDecoration,
+ kOfficeLeftMemo,
+ kOfficeLeftGraffiti,
+ kOfficeLeftTerminalSmashed,
+ kOfficeLeftDrawerMoney,
+ kOfficeLeftSafeOpen,
+ kOfficeLeftSafeClosed,
+ kOfficeLeftSafeMoney,
+ kOfficeLeftDoorOpen,
+ kOfficeLeftAlienShootAnimation1,
+ kOfficeLeftAlienShootAnimation2,
+ kOfficeLeftAlienShootAnimation3,
+ kOfficeLeftAlienShootAnimation4,
+ kOfficeLeftAlienShootAnimation5,
+ kOfficeLeftAlienShootAnimation6,
+ kOfficeLeftTerminalText,
+ kOfficeLeftDoorClosed,
+ kOfficeLeftDummy1,
+ kOfficeLeftDummy2,
+ kOfficeLeftDummy3,
+ kOfficeLeftDummy4,
+ kOfficeLeftDummy5,
+ // file 8
+ kOfficeRightBackground,
+ kOfficeRightDecorationPictures,
+ kOfficeRightDecorationPlants,
+ kOfficeRightDoorOpen,
+ kOfficeRightTerminalSmashed,
+ kOfficeRightAlienShootAnimation1,
+ kOfficeRightAlienShootAnimation2,
+ kOfficeRightAlienShootAnimation3,
+ kOfficeRightAlienTalking,
+ kOfficeRightDummy1,
+ kOfficeRightDummy2,
+ kOfficeRightDummy3,
+ kOfficeRightDummy4,
+ // file 9
+ kShipCockpitBackground,
+ kShipCockpitPilotAnimation1,
+ kShipCockpitPilotAnimation2,
+ kShipCockpitPilotAnimation3,
+ kShipCockpitPilotAnimation4,
+ kShipCockpitPilotAnimation5,
+ kShipCockpitPilotAnimation6,
+ kShipCockpitPilotAnimation7,
+ kShipCockpitPilotAnimation8,
+ kShipCockpitPilotAnimation9,
+ kShipCockpitPilotAnimation10,
+ kShipCockpitPilotAnimation11,
+ kShipCockpitPilotAnimation12,
+ kShipCockpitPilotAnimation13,
+ kShipCockpitPilotAnimation14,
+ kShipCockpitPilotAnimation15,
+ kShipCockpitPilotAnimation16,
+ kShipCockpitPilotAnimation17,
+ kShipCockpitPilotAnimation18,
+ kShipCockpitPilotAnimation19,
+ kShipCockpitPilotAnimation20,
+ kShipCockpitDisplayStatusAnimation1,
+ kShipCockpitDisplayStatusAnimation2,
+ kShipCockpitWindowRocks,
+ // file 10
+ kRestaurantEntranceBackground,
+ kRestaurantEntrancePorterAnimation1,
+ kRestaurantEntrancePorterAnimation2,
+ kRestaurantEntrancePorterAnimation3,
+ kRestaurantEntrancePorterAnimation4,
+ kRestaurantEntranceBathroomDoorAnimation1,
+ kRestaurantEntranceBathroomDoorAnimation2,
+ kRestaurantEntranceBathroomDoorAnimation3,
+ kRestaurantEntranceBathroomDoorAnimation4,
+ kRestaurantEntranceBathroomDoorAnimation5,
+ kRestaurantEntranceGreenCandy,
+ kRestaurantEntranceBlueCandy,
+ kRestaurantEntrancePinkCandy,
+ kRestaurantEntranceWhiteCandy,
+ kRestaurantEntranceBlackCandy,
+ kRestaurantEntraceDummy1,
+ kRestaurantEntraceDummy2,
+ // file 11
+ kDeathScreen,
+ // file 12
+ kRocksBackground,
+ kRocksRockAnimation1,
+ kRocksRockAnimation2,
+ kRocksRockAnimation3,
+ // file 13
+ kBluePlanetBackground,
+ kBluePlanetShipAnimation1,
+ kBluePlanetShipAnimation2,
+ kBluePlanetShipAnimation3,
+ kBluePlanetShipAnimation4,
+ kBluePlanetShipAnimation5,
+ kBluePlanetShipAnimation6,
+ kBluePlanetShipAnimation7,
+ kBluePlanetShipAnimation8,
+ kBluePlanetShipAnimation9,
+ kBluePlanetShipAnimation10,
+ kBluePlanetShipAnimation11,
+ kBluePlanetShipAnimation12,
+ kBluePlanetShipAnimation13,
+ // file 14
+ kRogerCrashBackground,
+ kRogerCrashAnimation1,
+ kRogerCrashAnimation2,
+ kRogerCrashAnimation3,
+ kRogerCrashAnimation4,
+ kRogerCrashAnimation5,
+ kRogerCrashAnimation6,
+ kRogerCrashAnimation7,
+ kRogerCrashAnimation8,
+ kRogerCrashAnimation9,
+ kRogerCrashAnimation10,
+ kRogerCrashAnimation11,
+ kRogerCrashAnimation12,
+ kRogerCrashAnimation13,
+ kRogerCrashAnimation14,
+ kRogerCrashAnimation15,
+ kRogerCrashAnimation16,
+ kRogerCrashAnimation17,
+ kRogerCrashAnimation18,
+ kRogerCrashAnimation19,
+ // file 15
+ kShipCorridorBackground,
+ kShipCorridorCockpitDoorOpen,
+ kShipCorridorSleepCabinDoorAnimation1,
+ kShipCorridorSleepCabinDoorAnimation2,
+ kShipCorridorSleepCabinDoorAnimation3,
+ kShipCorridorDummy1,
+ // file 16
+ kAxacussCorridorTileWalled,
+ kAxacussCorridorToLeft,
+ kAxacussCorridorToRight,
+ kAxacussCorridorToTop,
+ kAxacussCorridorToBottom,
+ kAxacussCorridorTile,
+ kAxacussCorridorDoorClosed,
+ kAxacussCorridorDoorOpen,
+ kAxacussCorridorDesk,
+ kAxacussCorridorLaptop,
+ kAxacussCorridorStuff10,
+ kAxacussCorridorStuff11,
+ kAxacussCorridorStuff12,
+ kAxacussCorridorStuff13,
+ kAxacussCorridorStuff14,
+ kAxacussCorridorStuff15,
+ kAxacussCorridorStuff16,
+ kAxacussCorridorStuff17,
+ kAxacussCorridorStuff18,
+ kAxacussCorridorStuff19,
+ kAxacussCorridorStuff21,
+ kAxacussCorridorStuff22,
+ kAxacussCorridorStuff23,
+ kAxacussCorridorStuff24,
+ kAxacussCorridorStuff25,
+ kAxacussCorridorStuff26,
+ kAxacussCorridorStuff27,
+ kAxacussCorridorStuff28,
+ kAxacussCorridorAlarmStatus,
+ kAxacussCorridorAlienRight,
+ kAxacussCorridorAlienLeft,
+ kAxacussCorridorAlienBottom,
+ kAxacussCorridorAlienTop,
+ kAxacussCorridorDummy1,
+ // file 17
+ kShipCorridorCabinBackground,
+ kShipCorridorCabinL1Open,
+ kShipCorridorCabinL2Open,
+ kShipCorridorCabinL3Open,
+ kShipCorridorCabinR1Open,
+ kShipCorridorCabinR2Open,
+ kShipCorridorCabinR3Open,
+ kShipCorridorCabinAirlockDoorAnimation1,
+ kShipCorridorCabinAirlockDoorAnimation2,
+ kShipCorridorCabinAirlockDoorAnimation3,
+ kShipCorridorCabinDummy1,
+ kShipCorridorCabinDummy2,
+ kShipCorridorCabinDummy3,
+ kShipCorridorCabinDummy4,
+ kShipCorridorCabinDummy5,
+ kShipCorridorCabinDummy6,
+ // file 18
+ kShipGeneratorBackground,
+ kShipGeneratorHatchOpen,
+ kShipGeneratorJunctionBoxOpen,
+ kShipGeneratorJunctionBoxOffline,
+ kShipGeneratorJunctionBoxDisplay,
+ kShipGeneratorKeycard,
+ kShipGeneratorSpoolFloating,
+ kShipGeneratorSpoolOnGround,
+ kShipGeneratorCableUnplugged,
+ kShipGeneratorCablePluggedIn,
+ kShipGeneratorHatchRocks,
+ kShipGeneratorRopeRocks,
+ kShipGeneratorRopeSpace,
+ kShipGeneratorRopeFloor,
+ kShipGeneratorDummy1,
+ kShipGeneratorDummy2,
+ kShipGeneratorDummy3,
+ kShipGeneratorDummy4,
+ kShipGeneratorDummy5,
+ kShipGeneratorDummy6,
+ kShipGeneratorDummy7,
+ kShipGeneratorDummy8,
+ // file 19
+ kRogerShipBackground,
+ kRogerShipButtonPressed1,
+ kRogerShipButtonPressed2,
+ kRogerShipButtonPressed3,
+ kRogerShipButtonPressed4,
+ kRogerShipCardInSlot,
+ kRogerShipCompartmentOpen,
+ kRogerShipUnknown7,
+ kRogerShipDisplayLeftOn,
+ kRogerShipGreenDisplayAnimation1,
+ kRogerShipGreenDisplayAnimation2,
+ kRogerShipGreenDisplayAnimation3,
+ kRogerShipGreenDisplayAnimation4,
+ kRogerShipGreenDisplayAnimation5,
+ kRogerShipGreenDisplayAnimation6,
+ kRogerShipGreenDisplayAnimation7,
+ kRogerShipBlueDisplayAnimation1,
+ kRogerShipBlueDisplayAnimation2,
+ kRogerShipBlueDisplayAnimation3,
+ kRogerShipBlueDisplayAnimation4,
+ kRogerShipBlueDisplayAnimation5,
+ kRogerShipBlueDisplayAnimation6,
+ kRogerShipBlueDisplayAnimation7,
+ kRogerShipUnknown23,
+ kRogerShipDisplaySinewaveAnimation1,
+ kRogerShipDisplaySinewaveAnimation2,
+ kRogerShipDisplaySinewaveAnimation3,
+ kRogerShipDisplaySinewaveAnimation4,
+ kRogerShipDisplaySinewaveAnimation5,
+ kRogerShipDisplaySinewaveAnimation6,
+ kRogerShipDisplaySinewaveAnimation7,
+ kRogerShipDisplaySinewaveAnimation8,
+ kRogerShipDisplaySinewaveAnimation9,
+ kRogerShipDisplaySinewaveAnimation10,
+ kRogerShipDisplaySinewaveAnimation11,
+ kRogerShipDisplaySinewaveAnimation12,
+ kRogerShipDisplaySinewaveAnimation13,
+ kRogerShipDisplaySinewaveAnimation14,
+ kRogerShipCompartmentContent,
+ kRogerShipDummy1,
+ kRogerShipDummy2,
+ // file 20
+ kHelpScreen,
+ // file 21
+ kShipCabinLeftBackground,
+ kShipCabinLeftPaintingSunset,
+ kShipCabinLeftPaintingLandscape,
+ kShipCabinLeftPaintingAbstract,
+ kShipCabinLeftTableStuff1,
+ kShipCabinLeftCeilingPencil,
+ kShipCabinLeft3Decoration,
+ kShipCabinLeftSocketPluggedIn,
+ kShipCabinLeftVinyl,
+ kShipCabinLeftTurntable,
+ kShipCabinLeftSocketUnplugged,
+ kShipCabinLeftTurntableCableCut,
+ kShipCabinLeftTurntableCable,
+ kShipCabinLeftTurntableAnimation1,
+ kShipCabinLeftTurntableAnimation2,
+ kShipCabinLeftTurntableAnimation3,
+ kShipCabinLeftTableStuff2,
+ kShipCabinLeftLockerOpen,
+ kShipCabinLeftLockerBooksOpen,
+ kShipCabinLeftLockerSpoolOpen,
+ kShipCabinLeftLockerPistolRemoved,
+ kShipCabinLeftLockerSpoolRemoved,
+ kShipCabinLeftBedSafeOpen,
+ kShipCabinLeftBedSafeEmpty,
+ kShipCabinLeftDoorClosed,
+ kShipCabinLeftTurntableCableSparks,
+ kShipCabinLeftTurntableCableCutEnd,
+ kShipCabinLeftDummy1,
+ kShipCabinLeftDummy2,
+ kShipCabinLeftDummy3,
+ kShipCabinLeftDummy4,
+ kShipCabinLeftDummy5,
+ kShipCabinLeftDummy6,
+ kShipCabinLeftDummy7,
+ kShipCabinLeftDummy8,
+ kShipCabinLeftDummy9,
+ kShipCabinLeftDummy10,
+ kShipCabinLeftDummy11,
+ kShipCabinLeftDummy12,
+ // file 22
+ kShipCabinRightBackground,
+ kShipCabinRightPosterSnowman,
+ kShipCabinRightTableStuff,
+ kShipCabinRightCeilingChess,
+ kShipCabinRightTennisRacket,
+ kShipCabinRightTennisBallsFloating,
+ kShipCabinRightTennisBallsOnGround,
+ kShipCabinRightTableChess,
+ kShipCabinRight2Bed,
+ kShipCabinRightLockerBooksOpen,
+ kShipCabinRightLockerRopeOpen,
+ kShipCabinRightLockerOpen,
+ kShipCabinRightLockerRopeRemoved,
+ kShipCabinRightBedSafeOpen,
+ kShipCabinRightBedSafeEmpty,
+ kShipCabinRightDoorClosed,
+ kShipCabinRightLockerDiscmanRemoved,
+ kShipCabinRightDummy1,
+ kShipCabinRightDummy2,
+ // file 23
+ kShipBathroomBackground,
+ // file 24
+ kShipHoldBackgroundFloating,
+ kShipHoldBackgroundOnGround,
+ kShipHoldLandingModuleDoorOpen,
+ kShipHoldGeneratorHatchOpen,
+ kShipHoldLandingModuleSpool,
+ kShipHoldCableToGeneratorUnplugged,
+ kShipHoldCableToGeneratorPluggedIn,
+ kShipHoldDummy1,
+ kShipHoldDummy2,
+ // file 25
+ kShipLandingModuleBackground,
+ kShipLandingModuleDoorClosed,
+ kShipLandingModuleDisplayLeftOn,
+ kShipLandingModuleCablePluggedIn,
+ kShipLandingModuleCableSpoolConnected,
+ kShipLandingModuleCableToHold,
+ kShipLandingModuleDisplayRightOn,
+ kShipLandingModuleDisplayTop1On,
+ kShipLandingModuleDisplayTop2On,
+ kShipLandingModuleDisplayTop3On,
+ kShipLandingModuleCableWithTerminalStrip,
+ kShipLandingModuleDummy1,
+ kShipLandingModuleDummy2,
+ kShipLandingModuleDummy3,
+ kShipLandingModuleDummy4,
+ kShipLandingModuleDummy5,
+ kShipLandingModuleDummy6,
+ kShipLandingModuleDummy7,
+ kShipLandingModuleDummy8,
+ // file 26
+ kArsanoStar,
+ // file 27
+ kSaveLoadScreen,
+ // file 28
+ kRestaurantBackground,
+ kRestaurantAnimation1,
+ kRestaurantAnimation2,
+ kRestaurantAnimation3,
+ kRestaurantAnimation4,
+ kRestaurantAnimation5,
+ kRestaurantAnimation6,
+ kRestaurantAnimation7,
+ kRestaurantAnimation8,
+ kRestaurantAnimation9,
+ kRestaurantAnimation10,
+ kRestaurantAnimation11,
+ kRestaurantAnimation12,
+ kRestaurantAnimation13,
+ kRestaurantAnimation14,
+ kRestaurantAnimation15,
+ kRestaurantAnimation16,
+ kRestaurantAnimation17,
+ kRestaurantAnimation18,
+ kRestaurantAnimation19,
+ kRestaurantAnimation20,
+ kRestaurantAnimation21,
+ kRestaurantAnimation22,
+ // file 29
+ kRestaurantRogerBackground,
+ kRestaurantRogerEyes1Closed,
+ kRestaurantRogerMouthOpen,
+ kRestaurantRogerPlayingChess,
+ kRestaurantRogerWalletRemoved,
+ kRestaurantRogerHandAnimation1,
+ kRestaurantRogerHandAnimation2,
+ kRestaurantRogerHandAnimation3,
+ kRestaurantRogerHandAnimation4,
+ kRestaurantRogerHandAnimation5,
+ kRestaurantRogerEyes2Closed,
+ kRestaurantRogerChessBoard,
+ kRestaurantRogerEyes2Open,
+ kRestaurantRogerDummy1,
+ // file 30
+ kRogerOutsideBackground,
+ kRogerOutsideMouthOpen,
+ // file 31
+ kIntroScreenBackground,
+ kIntroScreenShipAnimation1,
+ kIntroScreenShipAnimation2,
+ kIntroScreenShipAnimation3,
+ kIntroScreenShipAnimation4,
+ kIntroScreenShipAnimation5,
+ kIntroScreenShipAnimation6,
+ // file 32
+ kBusStationSignBackground,
+ kBusStationSignPrice,
+ kBusStationSignPleaseWait,
+ kBusStationSignPleasantFlight,
+ // file 33
+ kShipSleepCabinBackground,
+ kShipSleepCabinTerminalWarning,
+ kShipSleepCabinTerminal1,
+ kShipSleepCabinTerminal2,
+ kShipSleepCabinStatusLight,
+ kShipSleepCabinTerminal3,
+ // file 34
+ kShipAirlockBackground,
+ kShipAirlockDoorLeftAnimation1,
+ kShipAirlockDoorLeftAnimation2,
+ kShipAirlockDoorLeftAnimation3,
+ kShipAirlockDoorRightAnimation1,
+ kShipAirlockDoorRightAnimation2,
+ kShipAirlockDoorRightAnimation3,
+ kShipAirlockHelmetRemoved,
+ kShipAirlockSpacesuitRemoved,
+ kShipAirlockSupplyRemoved,
+ kShipAirlockDoorLeftButton,
+ kShipAirlockDoorRightButton,
+ kShipAirlockManometerAnimation1,
+ kShipAirlockManometerAnimation2,
+ kShipAirlockManometerAnimation3,
+ kShipAirlockManometerAnimation4,
+ kShipAirlockManometerAnimation5,
+ kShipAirlockManometerAnimation6,
+ // file 35
+ kAxacussSpaceBackground,
+ kAxacussSpaceShipAnimation1,
+ kAxacussSpaceShipAnimation2,
+ kAxacussSpaceShipAnimation3,
+ kAxacussSpaceShipAnimation4,
+ kAxacussSpaceShipAnimation5,
+ kAxacussSpaceShipAnimation6,
+ kAxacussSpaceShipAnimation7,
+ kAxacussSpaceBusAnimation1,
+ kAxacussSpaceBusAnimation2,
+ kAxacussSpaceBusAnimation3,
+ kAxacussSpaceBusAnimation4,
+ kAxacussSpaceBusAnimation5,
+ kAxacussSpaceBusAnimation6,
+ kAxacussSpaceBusAnimation7,
+ kAxacussSpaceBusAnimation8,
+ kAxacussSpaceBusAnimation9,
+ kAxacussSpaceBusAnimation10,
+ kAxacussSpaceBusAnimation11,
+ kAxacussSpaceBusAnimation12,
+ kAxacussSpaceBusAnimation13,
+ kAxacussSpaceBusAnimation14,
+ // file 36
+ kAxacussanCapsuleBackground,
+ kAxacussanCapsuleRobotAnimation1,
+ kAxacussanCapsuleRobotAnimation2,
+ kAxacussanCapsuleRobotAnimation3,
+ kAxacussanCapsuleRobotAnimation4,
+ kAxacussanCapsuleDummy1,
+ // file 37
+ kArsanoMeetupBackground,
+ kArsanoMeetupRestaurantLightAnimation1,
+ kArsanoMeetupRestaurantLightAnimation2,
+ kArsanoMeetupRestaurantLightAnimation3,
+ kArsanoMeetupRestaurantLightAnimation4,
+ kArsanoMeetupRestaurantLightAnimation5,
+ kArsanoMeetupRestaurantDoorAnimation1,
+ kArsanoMeetupRestaurantDoorAnimation2,
+ kArsanoMeetupRestaurantDoorSignAnimation1,
+ kArsanoMeetupRestaurantDoorSignAnimation2,
+ kArsanoMeetupRestaurantDoorSignAnimation3,
+ kArsanoMeetupRestaurantDoorSignAnimation4,
+ kArsanoMeetupRestaurantDoorSignAnimation5,
+ kArsanoMeetupRestaurantSignAnimation1,
+ kArsanoMeetupRestaurantSignAnimation2,
+ kArsanoMeetupRestaurantSignAnimation3,
+ kArsanoMeetupRestaurantSignAnimation4,
+ kArsanoMeetupRestaurantSignAnimation5,
+ kArsanoMeetupRestaurantSignAnimation6,
+ kArsanoMeetupRestaurantSignAnimation7,
+ kArsanoMeetupRestaurantSignAnimation8,
+ kArsanoMeetupRestaurantSignAnimation9,
+ kArsanoMeetupRestaurantSignAnimation10,
+ kArsanoMeetupRestaurantSignAnimation11,
+ kArsanoMeetupRestaurantSignAnimation12,
+ kArsanoMeetupRestaurantSignAnimation13,
+ kArsanoMeetupRestaurantSignAnimation14,
+ // file 38
+ kArsanoAfterNovaBackground,
+ kArsanoAfterNovaRogerShipAnimation1,
+ kArsanoAfterNovaRogerShipAnimation2,
+ kArsanoAfterNovaRogerShipAnimation3,
+ kArsanoAfterNovaRogerShipAnimation4,
+ kArsanoAfterNovaRogerShipAnimation5,
+ kArsanoAfterNovaRogerShipAnimation6,
+ kArsanoAfterNovaRogerShipAnimation7,
+ kArsanoAfterNovaRogerShipAnimation8,
+ kArsanoAfterNovaRogerShipAnimation9,
+ kArsanoAfterNovaRogerShipAnimation10,
+ kArsanoAfterNovaRogerShipAnimation11,
+ kArsanoAfterNovaRoger,
+ // file 39
+ kArsanoDesolate,
+ // file 40
+ kIntersectionBackground,
+ kIntersectionGuardRemoved,
+ kIntersectionGuardMouthOpen,
+ kIntersectionGuardShootAnimation1,
+ kIntersectionGuardShootAnimation2,
+ kIntersectionGuardMouthClosed,
+ kIntersectionDoorOpen,
+ kIntersectoinKeycard,
+ // file 41
+ kInformationDeskBackground,
+ kInformationDeskAlienMouthOpen,
+ kInformationDeskAlienHandMoved,
+ kInformationDeskAlienShoot,
+ // file 42
+ kArtGalleryBackground,
+ kArtGalleryAlienShootAnimation1,
+ kArtGalleryAlienShootAnimation2,
+ kArtGalleryAlienShootAnimation3,
+ kArtGalleryThrowingBlockAnimation1,
+ kArtGalleryThrowingBlockAnimation2,
+ kArtGalleryThrowingBlockAnimation3,
+ kArtGalleryThrowingBlockAnimation4,
+ kArtGalleryThrowingBlockAnimation5,
+ kArtGalleryThrowingBlockAnimation6,
+ kArtGalleryThrowingBlockAnimation7,
+ kArtGalleryDummy1,
+ // file 43
+ kCellBackground,
+ kCellCablePluggedIn,
+ kCellCableUnplugged,
+ kCellCableCutUnplugged,
+ kCellCableCutPluggedIn,
+ kCellCableCutTableUnplugged,
+ kCellCableCutTablePluggedIn,
+ kCellTableTablet,
+ kCellRobotComesAnimation1,
+ kCellRobotComesAnimation2,
+ kCellRobotComesAnimation3,
+ kCellRobotComesAnimation4,
+ kCellRobotComesAnimation5,
+ kCellRobotComesAnimation6,
+ kCellRobotComesAnimation7,
+ kCellRobotComesAnimation8,
+ kCellRobotComesAnimation9,
+ kCellRobotComesAnimation10,
+ kCellRobotComesAnimation11,
+ kCellRobotLeavesAnimation1,
+ kCellRobotLeavesAnimation2,
+ kCellRobotLeavesAnimation3,
+ kCellRobotLeavesAnimation4,
+ kCellRobotLeavesAnimation5,
+ kCellRobotLeavesAnimation6,
+ kCellRobotLeavesAnimation7,
+ kCellRobotLeavesAnimation8,
+ kCellRobotLeavesAnimation9,
+ kCellRobotSparks,
+ kCellRobotBroken,
+ kCellDoorClosed,
+ kCellDummy1
+};
+
+}
+
+#endif
diff --git a/engines/supernova/module.mk b/engines/supernova/module.mk
index 9baf196c7c..722a230cde 100644
--- a/engines/supernova/module.mk
+++ b/engines/supernova/module.mk
@@ -4,9 +4,12 @@ MODULE_OBJS := \
console.o \
detection.o \
graphics.o \
- supernova.o \
+ resman.o \
rooms.o \
- state.o
+ screen.o \
+ sound.o \
+ state.o \
+ supernova.o
MODULE_DIRS += \
engines/supernova
diff --git a/engines/supernova/msn_def.h b/engines/supernova/msn_def.h
index c18baa068c..6ce16b8283 100644
--- a/engines/supernova/msn_def.h
+++ b/engines/supernova/msn_def.h
@@ -25,10 +25,6 @@
namespace Supernova {
-const int kScreenWidth = 320;
-const int kScreenHeight = 200;
-const int kFontWidth = 5;
-const int kFontHeight = 8;
const int kTextSpeed[] = {19, 14, 10, 7, 4};
const int kMsecPerTick = 55;
@@ -50,266 +46,6 @@ enum MessagePosition {
kMessageTop
};
-enum AudioIndex {
- kAudioFoundLocation, // 44|0
- kAudioCrash, // 45|0
- kAudioVoiceHalt, // 46|0
- kAudioGunShot, // 46|2510
- kAudioSmash, // 46|4020
- kAudioVoiceSupernova, // 47|0
- kAudioVoiceYeah, // 47|24010
- kAudioRobotShock, // 48|0
- kAudioRobotBreaks, // 48|2510
- kAudioShock, // 48|10520
- kAudioTurntable, // 48|13530
- kAudioSiren, // 50|0
- kAudioSnoring, // 50|12786
- kAudioRocks, // 51|0
- kAudioDeath, // 53|0
- kAudioAlarm, // 54|0
- kAudioSuccess, // 54|8010
- kAudioSlideDoor, // 54|24020
- kAudioDoorOpen, // 54|30030
- kAudioDoorClose, // 54|31040
- kAudioNumSamples
-};
-
-enum MusicIndex {
- kMusicIntro = 52,
- kMusicOutro = 49
-};
-
-struct AudioInfo {
- int _filenumber;
- int _offsetStart;
- int _offsetEnd;
-};
-
-const int kColorBlack = 0;
-const int kColorWhite25 = 1;
-const int kColorWhite35 = 2;
-const int kColorWhite44 = 3;
-const int kColorWhite99 = 4;
-const int kColorDarkGreen = 5;
-const int kColorGreen = 6;
-const int kColorDarkRed = 7;
-const int kColorRed = 8;
-const int kColorDarkBlue = 9;
-const int kColorBlue = 10;
-const int kColorWhite63 = 11;
-const int kColorLightBlue = 12;
-const int kColorLightGreen = 13;
-const int kColorLightYellow = 14;
-const int kColorLightRed = 15;
-const int kColorCursorTransparent = kColorWhite25;
-
-const byte mouseNormal[64] = {
- 0xff,0x3f,0xff,0x1f,0xff,0x0f,0xff,0x07,
- 0xff,0x03,0xff,0x01,0xff,0x00,0x7f,0x00,
- 0x3f,0x00,0x1f,0x00,0x0f,0x00,0x0f,0x00,
- 0xff,0x00,0x7f,0x18,0x7f,0x38,0x7f,0xfc,
-
- 0x00,0x00,0x00,0x40,0x00,0x60,0x00,0x70,
- 0x00,0x78,0x00,0x7c,0x00,0x7e,0x00,0x7f,
- 0x80,0x7f,0xc0,0x7f,0xe0,0x7f,0x00,0x7e,
- 0x00,0x66,0x00,0x43,0x00,0x03,0x00,0x00
-};
-
-const byte mouseWait[64] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,
- 0x01,0x80,0x01,0x80,0x11,0x88,0x31,0x8c,
- 0x31,0x8c,0x11,0x88,0x01,0x80,0x01,0x80,
- 0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0xfe,0x7f,0xf4,0x2f,0xf4,0x2f,
- 0x14,0x28,0x24,0x24,0x44,0x22,0x84,0x21,
- 0x84,0x21,0xc4,0x23,0xe4,0x27,0x74,0x2e,
- 0x34,0x2c,0x14,0x28,0xfe,0x7f,0x00,0x00
-};
-
-const byte font[][5] = {
- {0x00,0x00,0x00,0xff,0x00},
- {0x5f,0xff,0x00,0x00,0x00},
- {0x03,0x00,0x03,0xff,0x00},
- {0x14,0x7f,0x14,0x7f,0x14},
- {0x24,0x2a,0x7f,0x2a,0x12},
- {0x61,0x10,0x08,0x04,0x43},
- {0x38,0x4e,0x59,0x26,0x50},
- {0x03,0xff,0x00,0x00,0x00},
- {0x3e,0x41,0xff,0x00,0x00},
- {0x41,0x3e,0xff,0x00,0x00},
- {0x10,0x54,0x38,0x54,0x10},
- {0x10,0x10,0x7c,0x10,0x10},
- {0x80,0x40,0xff,0x00,0x00},
- {0x10,0x10,0x10,0x10,0x10},
- {0x40,0xff,0x00,0x00,0x00},
- {0x60,0x10,0x08,0x04,0x03},
-
- {0x3e,0x41,0x41,0x41,0x3e}, /* digits */
- {0x04,0x02,0x7f,0xff,0x00},
- {0x42,0x61,0x51,0x49,0x46},
- {0x22,0x41,0x49,0x49,0x36},
- {0x18,0x14,0x12,0x7f,0x10},
- {0x27,0x45,0x45,0x45,0x39},
- {0x3e,0x49,0x49,0x49,0x32},
- {0x01,0x61,0x19,0x07,0x01},
- {0x36,0x49,0x49,0x49,0x36},
- {0x26,0x49,0x49,0x49,0x3e},
-
- {0x44,0xff,0x00,0x00,0x00},
- {0x80,0x44,0xff,0x00,0x00},
- {0x10,0x28,0x44,0xff,0x00},
- {0x28,0x28,0x28,0x28,0x28},
- {0x44,0x28,0x10,0xff,0x00},
- {0x02,0x01,0x51,0x09,0x06},
- {0x3e,0x41,0x5d,0x5d,0x1e},
-
- {0x7c,0x12,0x11,0x12,0x7c}, /* uppercase letters*/
- {0x7f,0x49,0x49,0x49,0x36},
- {0x3e,0x41,0x41,0x41,0x22},
- {0x7f,0x41,0x41,0x22,0x1c},
- {0x7f,0x49,0x49,0x49,0xff},
- {0x7f,0x09,0x09,0x09,0xff},
- {0x3e,0x41,0x41,0x49,0x3a},
- {0x7f,0x08,0x08,0x08,0x7f},
- {0x41,0x7f,0x41,0xff,0x00},
- {0x20,0x40,0x40,0x3f,0xff},
- {0x7f,0x08,0x14,0x22,0x41},
- {0x7f,0x40,0x40,0x40,0xff},
- {0x7f,0x02,0x04,0x02,0x7f},
- {0x7f,0x02,0x0c,0x10,0x7f},
- {0x3e,0x41,0x41,0x41,0x3e},
- {0x7f,0x09,0x09,0x09,0x06},
- {0x3e,0x41,0x51,0x21,0x5e},
- {0x7f,0x09,0x19,0x29,0x46},
- {0x26,0x49,0x49,0x49,0x32},
- {0x01,0x01,0x7f,0x01,0x01},
- {0x3f,0x40,0x40,0x40,0x3f},
- {0x07,0x18,0x60,0x18,0x07},
- {0x1f,0x60,0x18,0x60,0x1f},
- {0x63,0x14,0x08,0x14,0x63},
- {0x03,0x04,0x78,0x04,0x03},
- {0x61,0x51,0x49,0x45,0x43},
-
- {0x7f,0x41,0x41,0xff,0x00},
- {0x03,0x04,0x08,0x10,0x60},
- {0x41,0x41,0x7f,0xff,0x00},
- {0x02,0x01,0x02,0xff,0x00},
- {0x80,0x80,0x80,0x80,0x80},
- {0x01,0x02,0xff,0x00,0x00},
-
- {0x38,0x44,0x44,0x44,0x7c}, /* lowercase letters */
- {0x7f,0x44,0x44,0x44,0x38},
- {0x38,0x44,0x44,0x44,0x44},
- {0x38,0x44,0x44,0x44,0x7f},
- {0x38,0x54,0x54,0x54,0x58},
- {0x04,0x7e,0x05,0x01,0xff},
- {0x98,0xa4,0xa4,0xa4,0x7c},
- {0x7f,0x04,0x04,0x04,0x78},
- {0x7d,0xff,0x00,0x00,0x00},
- {0x80,0x80,0x7d,0xff,0x00},
- {0x7f,0x10,0x28,0x44,0xff},
- {0x7f,0xff,0x00,0x00,0x00},
- {0x7c,0x04,0x7c,0x04,0x78},
- {0x7c,0x04,0x04,0x04,0x78},
- {0x38,0x44,0x44,0x44,0x38},
- {0xfc,0x24,0x24,0x24,0x18},
- {0x18,0x24,0x24,0x24,0xfc},
- {0x7c,0x08,0x04,0x04,0xff},
- {0x48,0x54,0x54,0x54,0x24},
- {0x04,0x3e,0x44,0x40,0xff},
- {0x7c,0x40,0x40,0x40,0x3c},
- {0x0c,0x30,0x40,0x30,0x0c},
- {0x3c,0x40,0x3c,0x40,0x3c},
- {0x44,0x28,0x10,0x28,0x44},
- {0x9c,0xa0,0xa0,0xa0,0x7c},
- {0x44,0x64,0x54,0x4c,0x44},
-
- {0x08,0x36,0x41,0xff,0x00},
- {0x77,0xff,0x00,0x00,0x00},
- {0x41,0x36,0x08,0xff,0x00},
- {0x02,0x01,0x02,0x01,0xff},
- {0xff,0x00,0x00,0x00,0x00},
-
- {0xfe,0x49,0x49,0x4e,0x30}, /* sharp S */
-
- {0x7c,0x41,0x40,0x41,0x3c}, /* umlauts */
-
- {0x04,0x06,0x7f,0x06,0x04}, /* arrows */
- {0x20,0x60,0xfe,0x60,0x20},
-
- {0x38,0x45,0x44,0x45,0x7c}, /* umlauts */
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0x79,0x14,0x12,0x14,0x79},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0x38,0x45,0x44,0x45,0x38},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0x3d,0x42,0x42,0x42,0x3d},
- {0x3d,0x40,0x40,0x40,0x3d},
-};
-
-// Default palette
-const byte initVGAPalette[768] = {
- 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x58, 0x58, 0x58, 0x70, 0x70, 0x70, 0xfc, 0xfc, 0xfc, 0x00, 0xd0, 0x00,
- 0x00, 0xfc, 0x00, 0xd8, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xb0, 0xa0, 0xa0, 0xa0,
- 0x50, 0xc8, 0xfc, 0x28, 0xfc, 0x28, 0xf0, 0xf0, 0x00, 0xfc, 0x28, 0x28, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14,
- 0x20, 0x20, 0x20, 0x2c, 0x2c, 0x2c, 0x38, 0x38, 0x38, 0x44, 0x44, 0x44, 0x50, 0x50, 0x50, 0x60, 0x60, 0x60,
- 0x70, 0x70, 0x70, 0x80, 0x80, 0x80, 0x90, 0x90, 0x90, 0xa0, 0xa0, 0xa0, 0xb4, 0xb4, 0xb4, 0xc8, 0xc8, 0xc8,
- 0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00, 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc,
- 0xfc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc, 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00,
- 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc, 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x00,
- 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00, 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc,
- 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c, 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc,
- 0xfc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc, 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c,
- 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc, 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0x7c,
- 0x7c, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c, 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc,
- 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4, 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc,
- 0xfc, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc, 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4,
- 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc, 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0xb4,
- 0xb4, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4, 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc,
- 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70,
- 0x70, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70, 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x00, 0x00, 0x70, 0x1c, 0x00,
- 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70, 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x00,
- 0x00, 0x70, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70,
- 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38, 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70,
- 0x70, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70, 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38,
- 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70, 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x38,
- 0x38, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38, 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70,
- 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50, 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70,
- 0x70, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70, 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50,
- 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70, 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x50,
- 0x50, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50, 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70,
- 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x00, 0x00, 0x40, 0x10, 0x00, 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40,
- 0x40, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40, 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x00, 0x00, 0x40, 0x10, 0x00,
- 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40, 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x00,
- 0x00, 0x40, 0x00, 0x00, 0x40, 0x10, 0x00, 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40,
- 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20, 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40,
- 0x40, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40, 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20,
- 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40, 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x20,
- 0x20, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20, 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40,
- 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c, 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40,
- 0x40, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40, 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c,
- 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40, 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x2c,
- 0x2c, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c, 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40,
- 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
enum ObjectType {
NULLTYPE = 0,
TAKE = 1,
@@ -341,7 +77,7 @@ enum Action {
ACTION_GIVE
};
-enum RoomID {
+enum RoomId {
INTRO,CORRIDOR,HALL,SLEEP,COCKPIT,AIRLOCK,
HOLD,LANDINGMODULE,GENERATOR,OUTSIDE,
CABIN_R1,CABIN_R2,CABIN_R3,CABIN_L1,CABIN_L2,CABIN_L3,BATHROOM,
@@ -353,7 +89,7 @@ enum RoomID {
ELEVATOR,STATION,SIGN,OUTRO,NUMROOMS,NULLROOM
};
-enum ObjectID {
+enum ObjectId {
INVALIDOBJECT = -1,
NULLOBJECT = 0,
KEYCARD,KNIFE,WATCH,
@@ -397,7 +133,7 @@ enum ObjectID {
JUNGLE,STATION_SLOT,STATION_SIGN
};
-enum StringID {
+enum StringId {
kNoString = -1,
// 0
kStringCommandGo = 0, kStringCommandLook, kStringCommandTake, kStringCommandOpen, kStringCommandClose,
@@ -568,8 +304,6 @@ ObjectType &operator&=(ObjectType &a, ObjectType b);
ObjectType &operator^=(ObjectType &a, ObjectType b);
struct Object {
- static const Object nullObject;
-
Object()
: _name(kNoString)
, _description(kStringDefaultDescription)
@@ -582,8 +316,8 @@ struct Object {
, _exitRoom(NULLROOM)
, _direction(0)
{}
- Object(byte roomId, StringID name, StringID description, ObjectID id, ObjectType type,
- byte click, byte click2, byte section = 0, RoomID exitRoom = NULLROOM, byte direction = 0)
+ Object(byte roomId, StringId name, StringId description, ObjectId id, ObjectType type,
+ byte click, byte click2, byte section = 0, RoomId exitRoom = NULLROOM, byte direction = 0)
: _name(name)
, _description(description)
, _id(id)
@@ -596,12 +330,6 @@ struct Object {
, _direction(direction)
{}
- static void setObjectNull(Object *&obj) {
- obj = const_cast<Object *>(&nullObject);
- }
- static bool isNullObject(Object *obj) {
- return obj == &nullObject;
- }
void resetProperty(ObjectType type = NULLTYPE) {
_type = type;
}
@@ -618,7 +346,7 @@ struct Object {
return _type & type;
}
- static bool combine(Object &obj1, Object &obj2, ObjectID id1, ObjectID id2) {
+ static bool combine(Object &obj1, Object &obj2, ObjectId id1, ObjectId id2) {
if (obj1.hasProperty(COMBINABLE))
return (((obj1._id == id1) && (obj2._id == id2)) ||
((obj1._id == id2) && (obj2._id == id1)));
@@ -627,14 +355,14 @@ struct Object {
}
byte _roomId;
- StringID _name;
- StringID _description;
- ObjectID _id;
+ StringId _name;
+ StringId _description;
+ ObjectId _id;
ObjectTypes _type;
byte _click;
byte _click2;
byte _section;
- RoomID _exitRoom;
+ RoomId _exitRoom;
byte _direction;
};
diff --git a/engines/supernova/resman.cpp b/engines/supernova/resman.cpp
new file mode 100644
index 0000000000..1c178846ed
--- /dev/null
+++ b/engines/supernova/resman.cpp
@@ -0,0 +1,395 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "audio/audiostream.h"
+#include "audio/decoders/raw.h"
+#include "audio/mixer.h"
+#include "audio/mods/protracker.h"
+#include "common/memstream.h"
+#include "common/system.h"
+#include "graphics/cursorman.h"
+#include "graphics/palette.h"
+
+#include "supernova/graphics.h"
+#include "supernova/resman.h"
+#include "supernova/screen.h"
+#include "supernova/supernova.h"
+
+namespace Supernova {
+
+struct AudioInfo {
+ int _filenumber;
+ int _offsetStart;
+ int _offsetEnd;
+};
+
+static Common::MemoryReadStream *convertToMod(const char *filename, int version = 1);
+
+static const AudioInfo audioInfo[kAudioNumSamples] = {
+ {44, 0, -1},
+ {45, 0, -1},
+ {46, 0, 2510},
+ {46, 2510, 4020},
+ {46, 4020, -1},
+ {47, 0, 24010},
+ {47, 24010, -1},
+ {48, 0, 2510},
+ {48, 2510, 10520},
+ {48, 10520, 13530},
+ {48, 13530, -1},
+ {50, 0, 12786},
+ {50, 12786, -1},
+ {51, 0, -1},
+ {53, 0, -1},
+ {54, 0, 8010},
+ {54, 8010, 24020},
+ {54, 24020, 30030},
+ {54, 30030, 31040},
+ {54, 31040, -1}
+};
+
+static const byte mouseNormal[64] = {
+ 0xff,0x3f,0xff,0x1f,0xff,0x0f,0xff,0x07,
+ 0xff,0x03,0xff,0x01,0xff,0x00,0x7f,0x00,
+ 0x3f,0x00,0x1f,0x00,0x0f,0x00,0x0f,0x00,
+ 0xff,0x00,0x7f,0x18,0x7f,0x38,0x7f,0xfc,
+
+ 0x00,0x00,0x00,0x40,0x00,0x60,0x00,0x70,
+ 0x00,0x78,0x00,0x7c,0x00,0x7e,0x00,0x7f,
+ 0x80,0x7f,0xc0,0x7f,0xe0,0x7f,0x00,0x7e,
+ 0x00,0x66,0x00,0x43,0x00,0x03,0x00,0x00
+};
+
+static const byte mouseWait[64] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,
+ 0x01,0x80,0x01,0x80,0x11,0x88,0x31,0x8c,
+ 0x31,0x8c,0x11,0x88,0x01,0x80,0x01,0x80,
+ 0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0xfe,0x7f,0xf4,0x2f,0xf4,0x2f,
+ 0x14,0x28,0x24,0x24,0x44,0x22,0x84,0x21,
+ 0x84,0x21,0xc4,0x23,0xe4,0x27,0x74,0x2e,
+ 0x34,0x2c,0x14,0x28,0xfe,0x7f,0x00,0x00
+};
+
+
+ResourceManager::ResourceManager()
+ : _audioRate(11931) {
+ initSoundFiles();
+ initGraphics();
+}
+
+void ResourceManager::initSoundFiles() {
+ // Sound
+ // Note:
+ // - samples start with a header of 6 bytes: 01 SS SS 00 AD 00
+ // where SS SS (LE uint16) is the size of the sound sample + 2
+ // - samples end with a footer of 4 bytes: 00 00
+ // Skip those in the buffer
+ Common::File file;
+
+ for (int i = 0; i < kAudioNumSamples; ++i) {
+ if (!file.open(Common::String::format("msn_data.%03d", audioInfo[i]._filenumber))) {
+ error("File %s could not be read!", file.getName());
+ }
+
+ int length = 0;
+ byte *buffer = nullptr;
+
+ if (audioInfo[i]._offsetEnd == -1) {
+ file.seek(0, SEEK_END);
+ length = file.pos() - audioInfo[i]._offsetStart - 10;
+ } else {
+ length = audioInfo[i]._offsetEnd - audioInfo[i]._offsetStart - 10;
+ }
+ buffer = new byte[length];
+ file.seek(audioInfo[i]._offsetStart + 6);
+ file.read(buffer, length);
+ file.close();
+
+ byte streamFlag = Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN;
+ _soundSamples[i].reset(Audio::makeRawStream(buffer, length, _audioRate,
+ streamFlag, DisposeAfterUse::YES));
+ }
+
+ _musicIntroBuffer.reset(convertToMod("msn_data.052"));
+ _musicOutroBuffer.reset(convertToMod("msn_data.049"));
+}
+
+void ResourceManager::initGraphics() {
+ Screen::initPalette();
+ initCursorGraphics();
+ initImages();
+}
+
+void ResourceManager::initCursorGraphics() {
+ const uint16 *bufferNormal = reinterpret_cast<const uint16 *>(mouseNormal);
+ const uint16 *bufferWait = reinterpret_cast<const uint16 *>(mouseWait);
+ for (uint i = 0; i < sizeof(mouseNormal) / 4; ++i) {
+ for (uint bit = 0; bit < 16; ++bit) {
+ uint mask = 0x8000 >> bit;
+ uint bitIndex = i * 16 + bit;
+
+ _cursorNormal[bitIndex] = (READ_LE_UINT16(bufferNormal + i) & mask) ?
+ kColorCursorTransparent : kColorBlack;
+ if (READ_LE_UINT16(bufferNormal + i + 16) & mask)
+ _cursorNormal[bitIndex] = kColorLightRed;
+
+ _cursorWait[bitIndex] = (READ_LE_UINT16(bufferWait + i) & mask) ?
+ kColorCursorTransparent : kColorBlack;
+ if (READ_LE_UINT16(bufferWait + i + 16) & mask)
+ _cursorWait[bitIndex] = kColorLightRed;
+ }
+ }
+}
+
+void ResourceManager::initImages() {
+ for (int i = 0; i < kNumImageFiles; ++i) {
+ if (!_images[i].init(i))
+ error("Failed reading image file msn_data.%03d", i);
+ }
+}
+
+Audio::SeekableAudioStream *ResourceManager::getSoundStream(AudioId index) {
+ Audio::SeekableAudioStream *stream = _soundSamples[index].get();
+ stream->rewind();
+
+ return stream;
+}
+
+Audio::AudioStream *ResourceManager::getSoundStream(MusicId index) {
+ switch (index) {
+ case kMusicIntro:
+ _musicIntro.reset(Audio::makeProtrackerStream(_musicIntroBuffer.get()));
+ return _musicIntro.get();
+ case kMusicOutro:
+ _musicOutro.reset(Audio::makeProtrackerStream(_musicOutroBuffer.get()));
+ return _musicOutro.get();
+ default:
+ error("Invalid music constant in playAudio()");
+ }
+}
+
+const MSNImage *ResourceManager::getImage(int filenumber) const {
+ assert(filenumber < kNumImageFiles);
+
+ return &_images[filenumber];
+}
+
+const byte *ResourceManager::getImage(CursorId id) const {
+ switch (id) {
+ case kCursorNormal:
+ return _cursorNormal;
+ case kCursorWait:
+ return _cursorWait;
+ default:
+ return nullptr;
+ }
+}
+
+static Common::MemoryReadStream *convertToMod(const char *filename, int version) {
+ // MSN format
+ struct {
+ uint16 seg;
+ uint16 start;
+ uint16 end;
+ uint16 loopStart;
+ uint16 loopEnd;
+ char volume;
+ char dummy[5];
+ } instr2[22];
+ int nbInstr2; // 22 for version1, 15 for version 2
+ int16 songLength;
+ char arrangement[128];
+ int16 patternNumber;
+ int32 note2[28][64][4];
+
+ nbInstr2 = ((version == 1) ? 22 : 15);
+
+ Common::File msnFile;
+ msnFile.open(filename);
+ if (!msnFile.isOpen()) {
+ warning("Data file '%s' not found", msnFile.getName());
+ return nullptr;
+ }
+
+ for (int i = 0 ; i < nbInstr2 ; ++i) {
+ instr2[i].seg = msnFile.readUint16LE();
+ instr2[i].start = msnFile.readUint16LE();
+ instr2[i].end = msnFile.readUint16LE();
+ instr2[i].loopStart = msnFile.readUint16LE();
+ instr2[i].loopEnd = msnFile.readUint16LE();
+ instr2[i].volume = msnFile.readByte();
+ msnFile.read(instr2[i].dummy, 5);
+ }
+ songLength = msnFile.readSint16LE();
+ msnFile.read(arrangement, 128);
+ patternNumber = msnFile.readSint16LE();
+ for (int p = 0 ; p < patternNumber ; ++p) {
+ for (int n = 0 ; n < 64 ; ++n) {
+ for (int k = 0 ; k < 4 ; ++k) {
+ note2[p][n][k] = msnFile.readSint32LE();
+ }
+ }
+ }
+
+ /* MOD format */
+ struct {
+ char iname[22];
+ uint16 length;
+ char finetune;
+ char volume;
+ uint16 loopStart;
+ uint16 loopLength;
+ } instr[31];
+ int32 note[28][64][4];
+
+ // We can't recover some MOD effects since several of them are mapped to 0.
+ // Assume the MSN effect of value 0 is Arpeggio (MOD effect of value 0).
+ const char invConvEff[8] = {0, 1, 2, 3, 10, 12, 13 ,15};
+
+ // Reminder from convertToMsn
+ // 31 30 29 28 27 26 25 24 - 23 22 21 20 19 18 17 16 - 15 14 13 12 11 10 09 08 - 07 06 05 04 03 02 01 00
+ // h h h h g g g g f f f f e e e e d d d d c c c c b b b b a a a a
+ //
+ // MSN:
+ // hhhh (4 bits) Cleared to 0
+ // dddd c (5 bits) Sample index | after mapping through convInstr
+ // ccc (3 bits) Effect type | after mapping through convEff
+ // bbbb aaaa (8 bits) Effect value | unmodified
+ // gggg ffff eeee (12 bits) Sample period | unmodified
+ //
+ // MS2:
+ // hhhh (4 bits) Cleared to 0
+ // dddd (4 bits) Sample index | after mapping through convInstr
+ // cccc (4 bits) Effect type | unmodified
+ // bbbb aaaa (8 bits) Effect value | unmodified
+ // gggg ffff eeee (12 bits) Sample period | transformed (0xE000 / p) - 256
+ //
+ // MOD:
+ // hhhh dddd (8 bits) Sample index
+ // cccc (4 bits) Effect type for this channel/division
+ // bbbb aaaa (8 bits) Effect value
+ // gggg ffff eeee (12 bits) Sample period
+
+ // Can we recover the instruments mapping? I don't think so as part of the original instrument index is cleared.
+ // And it doesn't really matter as long as we are consistent.
+ // However we need to make sure 31 (or 15 in MS2) is mapped to 0 in MOD.
+ // We just add 1 to all other values, and this means a 1 <-> 1 mapping for the instruments
+ for (int p = 0; p < patternNumber; ++p) {
+ for (int n = 0; n < 64; ++n) {
+ for (int k = 0; k < 4; ++k) {
+ int32* l = &(note[p][n][k]);
+ *l = note2[p][n][k];
+ int32 i = 0;
+ if (nbInstr2 == 22) { // version 1
+ i = ((*l & 0xF800) >> 11);
+ int32 e = ((*l & 0x0700) >> 8);
+ int32 e1 = invConvEff[e];
+ *l &= 0x0FFF00FF;
+ *l |= (e1 << 8);
+ } else { // version 2
+ int32 h = (*l >> 16);
+ i = ((*l & 0xF000) >> 12);
+ *l &= 0x00000FFF;
+ if (h)
+ h = 0xE000 / (h + 256);
+ *l |= (h << 16);
+ if (i == 15)
+ i = 31;
+ }
+
+ // Add back index in note
+ if (i != 31) {
+ ++i;
+ *l |= ((i & 0x0F) << 12);
+ *l |= ((i & 0xF0) << 24);
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < 31; ++i) {
+ // iname is not stored in the mod file. Just set it to 'instrument#'
+ // finetune is not stored either. Assume 0.
+ memset(instr[i].iname, 0, 22);
+ sprintf(instr[i].iname, "instrument%d", i+1);
+ instr[i].length = 0;
+ instr[i].finetune = 0;
+ instr[i].volume = 0;
+ instr[i].loopStart = 0;
+ instr[i].loopLength = 0;
+
+ if (i < nbInstr2) {
+ instr[i].length = ((instr2[i].end - instr2[i].start) >> 1);
+ instr[i].loopStart = ((instr2[i].loopStart - instr2[i].start) >> 1);
+ instr[i].loopLength = (( instr2[i].loopEnd - instr2[i].loopStart) >> 1);
+ instr[i].volume = instr2[i].volume;
+ }
+ }
+
+ // The ciaaSpeed is kind of useless and not present in the MSN file.
+ // Traditionally 0x78 in SoundTracker. Was used in NoiseTracker as a restart point.
+ // ProTracker uses 0x7F. FastTracker uses it as a restart point, whereas ScreamTracker 3 uses 0x7F like ProTracker.
+ // You can use this to roughly detect which tracker made a MOD, and detection gets more accurate for more obscure MOD types.
+ char ciaaSpeed = 0x7F;
+
+ // The mark cannot be recovered either. Since we have 4 channels and 31 instrument it can be either ID='M.K.' or ID='4CHN'.
+ // Assume 'M.K.'
+ const char mark[4] = { 'M', '.', 'K', '.' };
+
+ Common::MemoryWriteStreamDynamic buffer(DisposeAfterUse::NO);
+
+ buffer.write(msnFile.getName(), 19);
+ buffer.writeByte(0);
+
+ for (int i = 0 ; i < 31 ; ++i) {
+ buffer.write(instr[i].iname, 22);
+ buffer.writeUint16BE(instr[i].length);
+ buffer.writeByte(instr[i].finetune);
+ buffer.writeByte(instr[i].volume);
+ buffer.writeUint16BE(instr[i].loopStart);
+ buffer.writeUint16BE(instr[i].loopLength);
+ }
+ buffer.writeByte((char)songLength);
+ buffer.writeByte(ciaaSpeed);
+ buffer.write(arrangement, 128);
+ buffer.write(mark, 4);
+
+ for (int p = 0 ; p < patternNumber ; ++p) {
+ for (int n = 0 ; n < 64 ; ++n) {
+ for (int k = 0 ; k < 4 ; ++k) {
+// buffer.writeUint32BE(*((uint32*)(note[p][n]+k)));
+ buffer.writeSint32BE(note[p][n][k]);
+ }
+ }
+ }
+
+ uint nb;
+ char buf[4096];
+ while ((nb = msnFile.read(buf, 4096)) > 0)
+ buffer.write(buf, nb);
+
+ return new Common::MemoryReadStream(buffer.getData(), buffer.size(), DisposeAfterUse::YES);
+}
+
+}
diff --git a/engines/supernova/resman.h b/engines/supernova/resman.h
new file mode 100644
index 0000000000..080ecc5da4
--- /dev/null
+++ b/engines/supernova/resman.h
@@ -0,0 +1,77 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef SUPERNOVA_RESOURCES_H
+#define SUPERNOVA_RESOURCES_H
+
+#include "audio/audiostream.h"
+#include "common/ptr.h"
+
+#include "supernova/graphics.h"
+#include "supernova/sound.h"
+
+
+namespace Common {
+class MemoryReadStream;
+}
+
+namespace Supernova {
+
+class ResourceManager {
+public:
+ enum CursorId {
+ kCursorNormal,
+ kCursorWait
+ };
+
+public:
+ static const int kNumImageFiles = 44;
+
+public:
+ ResourceManager();
+
+ Audio::SeekableAudioStream *getSoundStream(AudioId index);
+ Audio::AudioStream *getSoundStream(MusicId index);
+ const MSNImage *getImage(int filenumber) const;
+ const byte *getImage(CursorId id) const;
+
+private:
+ void initSoundFiles();
+ void initGraphics();
+ void initCursorGraphics();
+ void initImages();
+
+private:
+ Common::ScopedPtr<Audio::SeekableAudioStream> _soundSamples[kAudioNumSamples];
+ Common::ScopedPtr<Common::MemoryReadStream> _musicIntroBuffer;
+ Common::ScopedPtr<Common::MemoryReadStream> _musicOutroBuffer;
+ Common::ScopedPtr<Audio::AudioStream> _musicIntro;
+ Common::ScopedPtr<Audio::AudioStream> _musicOutro;
+ int _audioRate;
+ MSNImage _images[kNumImageFiles];
+ byte _cursorNormal[256];
+ byte _cursorWait[256];
+};
+
+}
+
+#endif
diff --git a/engines/supernova/rooms.cpp b/engines/supernova/rooms.cpp
index 83147c1630..9360d58aa1 100644
--- a/engines/supernova/rooms.cpp
+++ b/engines/supernova/rooms.cpp
@@ -24,6 +24,7 @@
#include "graphics/palette.h"
#include "graphics/cursorman.h"
+#include "supernova/screen.h"
#include "supernova/supernova.h"
#include "supernova/state.h"
@@ -79,15 +80,15 @@ bool Room::deserialize(Common::ReadStream *in, int version) {
int numObjects = in->readSint32LE();
for (int i = 0; i < numObjects; ++i) {
- _objectState[i]._name = static_cast<StringID>(in->readSint32LE());
- _objectState[i]._description = static_cast<StringID>(in->readSint32LE());
+ _objectState[i]._name = static_cast<StringId>(in->readSint32LE());
+ _objectState[i]._description = static_cast<StringId>(in->readSint32LE());
_objectState[i]._roomId = in->readByte();
- _objectState[i]._id = static_cast<ObjectID>(in->readSint32LE());
+ _objectState[i]._id = static_cast<ObjectId>(in->readSint32LE());
_objectState[i]._type = static_cast<ObjectType>(in->readSint32LE());
_objectState[i]._click = in->readByte();
_objectState[i]._click2 = in->readByte();
_objectState[i]._section = in->readByte();
- _objectState[i]._exitRoom = static_cast<RoomID>(in->readSint32LE());
+ _objectState[i]._exitRoom = static_cast<RoomId>(in->readSint32LE());
_objectState[i]._direction = in->readByte();
}
@@ -147,102 +148,11 @@ void Intro::onEntrance() {
leaveCutscene();
}
-class Marquee {
-public:
- enum MarqueeIndex {
- kMarqueeIntro,
- kMarqueeOutro
- };
-
- Marquee(SupernovaEngine *vm, MarqueeIndex id, const char *text)
- : _text(text)
- , _textBegin(text)
- , _delay(0)
- , _color(kColorLightBlue)
- , _loop(false)
- , _vm(vm)
- {
- if (id == kMarqueeIntro) {
- _y = 191;
- _loop = true;
- } else if (id == kMarqueeOutro) {
- _y = 1;
- }
- _textWidth = _vm->textWidth(_text);
- _x = kScreenWidth / 2 - _textWidth / 2;
- _vm->_textCursorX = _x;
- _vm->_textCursorY = _y;
- _vm->_textColor = _color;
- }
-
- void renderCharacter();
-
-private:
- void clearText();
-
- SupernovaEngine *_vm;
- MarqueeIndex _id;
- const char *const _textBegin;
- const char *_text;
- bool _loop;
- int _delay;
- int _color;
- int _x;
- int _y;
- int _textWidth;
-};
-
-void Marquee::clearText() {
- _vm->renderBox(_x, _y - 1, _textWidth + 1, 9, kColorBlack);
-}
-
-void Marquee::renderCharacter() {
- if (_delay != 0) {
- _delay--;
- return;
- }
-
- switch (*_text) {
- case '\233':
- if (_loop) {
- _loop = false;
- _text = _textBegin;
- clearText();
- _textWidth = _vm->textWidth(_text);
- _x = kScreenWidth / 2 - _textWidth / 2;
- _vm->_textCursorX = _x;
- }
- break;
- case '\0':
- clearText();
- _text++;
- _textWidth = _vm->textWidth(_text);
- _x = kScreenWidth / 2 - _textWidth / 2;
- _vm->_textCursorX = _x;
- _color = kColorLightBlue;
- _vm->_textColor = _color;
- break;
- case '^':
- _color = kColorLightYellow;
- _vm->_textColor = _color;
- _text++;
- break;
- case '#':
- _delay = 50;
- _text++;
- break;
- default:
- _vm->renderText((uint16)*_text++);
- _delay = 1;
- break;
- }
-}
-
void Intro::titleScreen() {
// Newspaper
CursorMan.showMouse(false);
- _vm->_brightness = 0;
- _vm->_menuBrightness = 0;
+ _vm->_screen->setViewportBrightness(0);
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
_vm->setCurrentImage(1);
_vm->renderImage(0);
@@ -254,25 +164,25 @@ void Intro::titleScreen() {
_vm->setCurrentImage(31);
_vm->renderImage(0);
_vm->paletteFadeIn();
- _gm->wait2(1);
+ _gm->wait(1);
_vm->playSound(kAudioVoiceSupernova);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
titleFadeIn();
_vm->renderText(kStringTitleVersion, 295, 190, kColorWhite44);
const Common::String& title1 = _vm->getGameString(kStringTitle1);
const Common::String& title2 = _vm->getGameString(kStringTitle2);
const Common::String& title3 = _vm->getGameString(kStringTitle3);
- _vm->renderText(title1, 78 - _vm->textWidth(title1) / 2, 120, kColorLightBlue);
- _vm->renderText(title2, 78 - _vm->textWidth(title2) / 2, 132, kColorWhite99);
- _vm->renderText(title3, 78 - _vm->textWidth(title3) / 2, 142, kColorWhite99);
- _gm->wait2(1);
+ _vm->_screen->renderText(title1, 78 - Screen::textWidth(title1) / 2, 120, kColorLightBlue);
+ _vm->_screen->renderText(title2, 78 - Screen::textWidth(title2) / 2, 132, kColorWhite99);
+ _vm->_screen->renderText(title3, 78 - Screen::textWidth(title3) / 2, 142, kColorWhite99);
+ _gm->wait(1);
CursorMan.showMouse(true);
- _vm->playSoundMod(kMusicIntro);
+ _vm->playSound(kMusicIntro);
- Marquee marquee(_vm, Marquee::kMarqueeIntro, _introText.c_str());
+ Marquee marquee(_vm->_screen, Marquee::kMarqueeIntro, _introText.c_str());
while (!_vm->shouldQuit()) {
- _vm->updateEvents();
+ _gm->updateEvents();
marquee.renderCharacter();
if (_gm->_mouseClicked || _gm->_keyPressed)
break;
@@ -280,8 +190,8 @@ void Intro::titleScreen() {
g_system->delayMillis(_vm->_delay);
}
_vm->playSound(kAudioVoiceYeah);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
_vm->paletteFadeOut();
}
@@ -319,7 +229,7 @@ bool Intro::animate(int section1, int section2, int duration) {
}
bool Intro::animate(int section1, int section2, int duration,
- MessagePosition position, StringID textId) {
+ MessagePosition position, StringId textId) {
Common::KeyCode key = Common::KEYCODE_INVALID;
const Common::String& text = _vm->getGameString(textId);
_vm->renderMessage(text, position);
@@ -344,7 +254,7 @@ bool Intro::animate(int section1, int section2, int duration,
}
bool Intro::animate(int section1, int section2, int section3, int section4,
- int duration, MessagePosition position, StringID textId) {
+ int duration, MessagePosition position, StringId textId) {
Common::KeyCode key = Common::KEYCODE_INVALID;
const Common::String& text = _vm->getGameString(textId);
_vm->renderMessage(text, position);
@@ -381,11 +291,11 @@ void Intro::cutscene() {
_vm->_system->fillScreen(kColorBlack);
_vm->setCurrentImage(31);
- _vm->_menuBrightness = 255;
+ _vm->_screen->setGuiBrightness(255);
_vm->paletteBrightness();
if (!animate(0, 0, 0, kMessageNormal, kStringIntroCutscene1))
return;
- _vm->_menuBrightness = 0;
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
exitOnEscape(1);
@@ -423,7 +333,7 @@ void Intro::cutscene() {
exitOnEscape(28);
_vm->removeMessage();
- StringID textCounting[4] =
+ StringId textCounting[4] =
{kStringIntroCutscene7, kStringIntroCutscene8, kStringIntroCutscene9, kStringIntroCutscene10};
_vm->setCurrentImage(31);
_vm->renderImage(0);
@@ -527,15 +437,15 @@ void Intro::cutscene() {
return;
_vm->paletteFadeOut();
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
+ while (_vm->_sound->isPlaying())
exitOnEscape(1);
_vm->_system->fillScreen(kColorBlack);
- _vm->_menuBrightness = 255;
+ _vm->_screen->setGuiBrightness(255);
_vm->paletteBrightness();
if (!animate(0, 0, 0, kMessageNormal, kStringIntroCutscene25))
return;
- _vm->_menuBrightness = 5;
+ _vm->_screen->setGuiBrightness(5);
_vm->paletteBrightness();
_vm->setCurrentImage(31);
@@ -558,20 +468,20 @@ void Intro::cutscene() {
return;
CursorMan.showMouse(false);
- _vm->_brightness = 0;
+ _vm->_screen->setViewportBrightness(0);
_vm->paletteBrightness();
exitOnEscape(10);
_vm->playSound(kAudioSnoring);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
exitOnEscape(10);
_vm->playSound(kAudioSnoring);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
exitOnEscape(10);
_vm->playSound(kAudioSnoring);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
exitOnEscape(30);
CursorMan.showMouse(true);
@@ -605,7 +515,7 @@ void Intro::cutscene() {
}
void Intro::leaveCutscene() {
- _vm->_brightness = 255;
+ _vm->_screen->setViewportBrightness(255);
_vm->removeMessage();
_gm->changeRoom(CABIN_R3);
_gm->_guiEnabled = true;
@@ -620,19 +530,19 @@ bool ShipCorridor::interact(Action verb, Object &obj1, Object &obj2) {
_objectState[6].disableProperty(OPENED);
_vm->renderImage(8);
setSectionVisible(9, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(7);
setSectionVisible(8, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(7));
} else {
_vm->playSound(kAudioSlideDoor);
_objectState[6].setProperty(OPENED);
_vm->renderImage(7);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(8);
setSectionVisible(7, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(9);
setSectionVisible(8, false);
}
@@ -649,18 +559,18 @@ bool ShipHall::interact(Action verb, Object &obj1, Object &obj2) {
_objectState[2].disableProperty(OPENED);
_vm->renderImage(3);
setSectionVisible(4, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(2);
setSectionVisible(3, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(2));
} else {
_objectState[2].setProperty(OPENED);
_vm->renderImage(2);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(3);
setSectionVisible(2, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(4);
setSectionVisible(3, false);
_gm->great(1);
@@ -727,13 +637,13 @@ bool ShipSleepCabin::interact(Action verb, Object &obj1, Object &obj2) {
if (daysSleep != 0) {
_gm->_state._timeSleep = daysSleep;
_vm->renderText(kStringShipSleepCabin8, 30, 105, kColorWhite99);
- _gm->wait2(18);
+ _gm->wait(18);
setSectionVisible(5, true);
}
} while (daysSleep == 0);
} else {
_vm->renderText(kStringShipSleepCabin9, 100, 125, kColorLightRed);
- _gm->wait2(18);
+ _gm->wait(18);
}
}
}
@@ -813,12 +723,12 @@ bool ShipSleepCabin::interact(Action verb, Object &obj1, Object &obj2) {
_gm->_state._dream = true;
_gm->loadTime();
}
- _gm->wait2(18);
+ _gm->wait(18);
_vm->paletteFadeIn();
if (_gm->_state._arrivalDaysLeft == 0) {
_vm->playSound(kAudioCrash);
_gm->screenShake();
- _gm->wait2(18);
+ _gm->wait(18);
_vm->renderMessage(kStringShipSleepCabin12);
}
}
@@ -860,10 +770,10 @@ void ShipSleepCabin::animation() {
void ShipSleepCabin::onEntrance() {
if (_gm->_state._dream && (_gm->_rooms[CAVE]->getObject(1)->_exitRoom == MEETUP3)) {
_vm->renderMessage(kStringShipSleepCabin14);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringShipSleepCabin15);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringShipSleepCabin16);
_gm->_state._dream = false;
@@ -1004,7 +914,7 @@ bool ShipCabinL3::interact(Action verb, Object &obj1, Object &obj2) {
setSectionVisible(15, false);
for (int i = 3; i; i--) {
_vm->playSound(kAudioTurntable);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle)) {
+ while (_vm->_sound->isPlaying()) {
if (isSectionVisible(13)) {
_vm->renderImage(14);
setSectionVisible(13, false);
@@ -1012,7 +922,7 @@ bool ShipCabinL3::interact(Action verb, Object &obj1, Object &obj2) {
_vm->renderImage(13);
setSectionVisible(14, false);
}
- _gm->wait2(3);
+ _gm->wait(3);
}
}
@@ -1037,7 +947,7 @@ bool ShipCabinL3::interact(Action verb, Object &obj1, Object &obj2) {
setSectionVisible(10, false);
getObject(10)->_click = 20;
} else if ((verb == ACTION_USE) && Object::combine(obj1, obj2, KNIFE, WIRE2))
- _vm->renderMessage(kStringShipCabinL3_4);
+ _vm->renderMessage(kStringShipCabinL3_4); // cutting near plug
else if ((verb == ACTION_USE) && Object::combine(obj1, obj2, KNIFE, WIRE)) {
r = _gm->_rooms[AIRLOCK];
if (!isSectionVisible(10) && !r->getObject(5)->hasProperty(WORN)) {
@@ -1125,20 +1035,20 @@ bool ShipAirlock::interact(Action verb, Object &obj1, Object &obj2) {
if (getObject(0)->hasProperty(OPENED)) {
getObject(0)->disableProperty(OPENED);
_vm->renderImage(1);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(2);
setSectionVisible(1, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(3);
setSectionVisible(2, false);
} else {
getObject(0)->setProperty(OPENED);
_vm->renderImage(2);
setSectionVisible(3, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(1);
setSectionVisible(2, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(1));
}
_vm->renderImage(_gm->invertSection(10));
@@ -1150,53 +1060,53 @@ bool ShipAirlock::interact(Action verb, Object &obj1, Object &obj2) {
_vm->playSound(kAudioSlideDoor);
getObject(1)->disableProperty(OPENED);
_vm->renderImage(4);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(5);
setSectionVisible(4, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(6);
setSectionVisible(5, false);
_vm->renderImage(16);
setSectionVisible(17, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(15);
setSectionVisible(16, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(14);
setSectionVisible(15, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(13);
setSectionVisible(14, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(12);
setSectionVisible(13, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(_gm->invertSection(12));
} else {
getObject(1)->setProperty(OPENED);
_vm->renderImage(12);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(13);
setSectionVisible(12, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(14);
setSectionVisible(13, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(15);
setSectionVisible(14, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(16);
setSectionVisible(15, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(17);
setSectionVisible(16, false);
_vm->playSound(kAudioSlideDoor);
_vm->renderImage(5);
setSectionVisible(6, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(4);
setSectionVisible(5, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(4));
r = _gm->_rooms[AIRLOCK];
if (!r->getObject(4)->hasProperty(WORN) ||
@@ -1302,13 +1212,13 @@ bool ShipLandingModule::interact(Action verb, Object &obj1, Object &obj2) {
r = _gm->_rooms[SLEEP];
r->setSectionVisible(1, false);
r->setSectionVisible(2, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(2);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(8);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(9);
- _gm->wait2(1);
+ _gm->wait(1);
_vm->renderImage(10);
}
}
@@ -1529,9 +1439,9 @@ bool ArsanoRocks::interact(Action verb, Object &obj1, Object &obj2) {
if (((verb == ACTION_PULL) || (verb == ACTION_PRESS)) &&
(obj1._id == STONE) && !isSectionVisible(3)) {
_vm->renderImage(1);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(2);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(3);
_vm->playSound(kAudioRocks);
obj1._click = 3;
@@ -1544,10 +1454,10 @@ bool ArsanoRocks::interact(Action verb, Object &obj1, Object &obj2) {
void ArsanoMeetup::onEntrance() {
if (isSectionVisible(7)) {
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(6);
setSectionVisible(7, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(_gm->invertSection(6));
}
if (!(_gm->_state._greatFlag & 0x8000)) {
@@ -1591,10 +1501,10 @@ bool ArsanoMeetup::interact(Action verb, Object &obj1, Object &obj2) {
_vm->paletteBrightness();
} else if ((verb == ACTION_WALK) && (obj1._id == DOOR)) {
_vm->renderImage(6);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(7);
setSectionVisible(6, false);
- _gm->wait2(3);
+ _gm->wait(3);
return false;
} else if ((verb == ACTION_LOOK) && (obj1._id == MEETUP_SIGN) && _gm->_state._language) {
@@ -1616,21 +1526,21 @@ bool ArsanoMeetup::interact(Action verb, Object &obj1, Object &obj2) {
}
void ArsanoEntrance::animation() {
- if (!_vm->_messageDisplayed && isSectionVisible(kMaxSection - 5)) {
+ if (!_vm->_screen->isMessageShown() && isSectionVisible(kMaxSection - 5)) {
_gm->animationOff(); // to avoid recursive call
_vm->playSound(kAudioSlideDoor);
_vm->renderImage(8);
setSectionVisible(9, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(7);
setSectionVisible(8, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(6);
setSectionVisible(7, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(5);
setSectionVisible(6, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(5));
getObject(11)->_click = 255;
setSectionVisible(kMaxSection - 5, false);
@@ -1695,7 +1605,7 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
}
} else if ((verb == ACTION_WALK) && (obj1._id == STAIRCASE) && (_gm->_state._shoes != 3)) {
_vm->renderImage(3);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(4);
setSectionVisible(3, false);
if (_gm->_rooms[AIRLOCK]->getObject(4)->hasProperty(WORN))
@@ -1706,7 +1616,7 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
_gm->reply(kStringArsanoEntrance12, 1, _gm->invertSection(1));
_vm->renderImage(3);
setSectionVisible(4, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(3));
if (!_gm->_rooms[AIRLOCK]->getObject(4)->hasProperty(WORN)) {
if (_gm->_state._language) {
@@ -1732,13 +1642,13 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
break;
case 3:
_vm->renderImage(3);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(4);
setSectionVisible(3, false);
_gm->reply(kStringArsanoEntrance16, 1, 1 + 128);
_vm->renderImage(3);
setSectionVisible(4, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(3));
break;
}
@@ -1752,16 +1662,16 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
} else if ((verb == ACTION_PRESS) && (obj1._id == BATHROOM_BUTTON)) {
_vm->playSound(kAudioSlideDoor);
_vm->renderImage(5);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(6);
setSectionVisible(5, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(7);
setSectionVisible(6, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(8);
setSectionVisible(7, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(9);
setSectionVisible(8, false);
getObject(11)->_click = 9;
@@ -1782,7 +1692,7 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
_vm->renderMessage(kStringArsanoEntrance20);
else {
_vm->renderMessage(kStringArsanoEntrance21);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringArsanoEntrance22);
_gm->takeObject(*getObject(16));
@@ -1829,7 +1739,7 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
_gm->_rooms[AIRLOCK]->getObject(4)->setProperty(WORN);
_gm->_rooms[AIRLOCK]->getObject(5)->setProperty(WORN);
_gm->_rooms[AIRLOCK]->getObject(6)->setProperty(WORN);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
}
return false;
@@ -2097,12 +2007,12 @@ bool ArsanoRoger::interact(Action verb, Object &obj1, Object &obj2) {
_vm->paletteFadeOut();
_gm->_inventory.remove(*_gm->_rooms[CABIN_R3]->getObject(0)); // Chess board
g_system->fillScreen(kColorBlack);
- _vm->_menuBrightness = 255;
+ _vm->_screen->setGuiBrightness(255);
_vm->paletteBrightness();
_vm->renderMessage(kStringArsanoRoger39);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
- _vm->_menuBrightness = 0;
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
_gm->_state._time += ticksToMsec(125000); // 2 hours
_gm->_state._alarmOn = (_gm->_state._timeAlarm > _gm->_state._time);
@@ -2117,7 +2027,7 @@ bool ArsanoRoger::interact(Action verb, Object &obj1, Object &obj2) {
getObject(6)->_click = 7;
_vm->paletteFadeIn();
_vm->renderMessage(kStringArsanoRoger40);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
} else
return false;
@@ -2140,7 +2050,7 @@ bool ArsanoGlider::interact(Action verb, Object &obj1, Object &obj2) {
static char l, r;
if ((verb == ACTION_USE) && Object::combine(obj1, obj2, KEYCARD_R, GLIDER_SLOT)) {
_vm->renderImage(5);
- _gm->wait2(7);
+ _gm->wait(7);
_vm->renderImage(8);
getObject(5)->_click = 10;
_gm->_inventory.remove(*_gm->_rooms[ROGER]->getObject(8));
@@ -2192,7 +2102,7 @@ bool ArsanoGlider::interact(Action verb, Object &obj1, Object &obj2) {
}
}
}
- _gm->wait2(4);
+ _gm->wait(4);
_vm->renderImage(_gm->invertSection(i));
} else if ((verb == ACTION_USE) && (obj1._id == GLIDER_BUTTONS))
_vm->renderMessage(kStringArsanoGlider1);
@@ -2264,40 +2174,40 @@ bool ArsanoMeetup2::interact(Action verb, Object &obj1, Object &obj2) {
_vm->setCurrentImage(13);
_vm->renderImage(0);
_vm->paletteBrightness();
- _gm->wait2(36);
+ _gm->wait(36);
for (int i = 1; i <= 13; i++) {
if (i > 1)
_vm->renderImage(_gm->invertSection(i - 1));
_vm->renderImage(i);
- _gm->wait2(2);
+ _gm->wait(2);
}
_vm->renderImage(_gm->invertSection(13));
- _gm->wait2(20);
+ _gm->wait(20);
_vm->setCurrentImage(14);
_vm->renderImage(0);
_vm->paletteBrightness();
- _gm->wait2(36);
+ _gm->wait(36);
for (int i = 1; i <= 13; i++) {
if (i > 1)
_vm->renderImage(_gm->invertSection(i - 1));
_vm->renderImage(i);
- _gm->wait2(2);
+ _gm->wait(2);
}
_vm->renderImage(_gm->invertSection(13));
- _gm->wait2(9);
+ _gm->wait(9);
_vm->playSound(kAudioCrash);
for (int i = 14; i <= 19; i++) {
_vm->renderImage(i);
- _gm->wait2(3);
+ _gm->wait(3);
}
_vm->paletteFadeOut();
_vm->setCurrentImage(11);
_vm->renderImage(0);
_vm->paletteFadeIn();
- _gm->wait2(18);
+ _gm->wait(18);
_vm->renderMessage(kStringArsanoMeetup2_12);
_gm->great(0);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
_vm->paletteFadeOut();
g_system->fillScreen(kColorBlack);
@@ -2321,14 +2231,14 @@ bool ArsanoMeetup2::interact(Action verb, Object &obj1, Object &obj2) {
}
void ArsanoMeetup2::shipStart() {
- _gm->wait2(12);
+ _gm->wait(12);
for (int i = 2; i <= 11; ++i) {
if (i >= 9)
_vm->renderImage(i - 1 + 128);
else
setSectionVisible(i - 1, false);
_vm->renderImage(i);
- _gm->wait2(2);
+ _gm->wait(2);
}
_vm->renderImage(11 + 128);
}
@@ -2354,34 +2264,34 @@ bool ArsanoMeetup3::interact(Action verb, Object &obj1, Object &obj2) {
_vm->paletteBrightness();
_gm->dialog(3, rowsX, _dialogsX, 0);
_vm->renderImage(1);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(2);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(3);
- _gm->wait2(6);
+ _gm->wait(6);
_vm->renderImage(4);
_vm->playSound(kAudioGunShot);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
_vm->renderImage(5);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(4);
_vm->playSound(kAudioGunShot);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
_vm->renderImage(5);
_vm->paletteFadeOut();
- _gm->wait2(12);
+ _gm->wait(12);
_vm->setCurrentImage(0);
_vm->renderImage(0);
_vm->paletteFadeIn();
- _gm->wait2(18);
+ _gm->wait(18);
_gm->reply(kStringArsanoMeetup3_1, 2, 2 + 128);
- _gm->wait2(10);
+ _gm->wait(10);
_gm->reply(kStringArsanoMeetup3_2, 1, 1 + 128);
do {
@@ -2604,8 +2514,8 @@ bool AxacussCell::interact(Action verb, Object &obj1, Object &obj2) {
return false;
_vm->playSound(kAudioGunShot);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
_vm->playSound(kAudioGunShot);
_vm->playSound(kAudioGunShot);
@@ -2693,27 +2603,29 @@ bool AxacussCorridor5::handleMoneyDialog() {
}
switch (_gm->dialog(4, _rows, _dialog3, 2)) {
case 1:
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(1);
_vm->playSound(kAudioVoiceHalt);
_vm->renderImage(_gm->invertSection(1));
- _gm->wait2(5);
+ _gm->wait(5);
_vm->renderImage(2);
- _gm->wait2(2);
+ _gm->wait(2);
_gm->shot(3, _gm->invertSection(3));
break;
- case 3:
- if (_gm->_state._money >= 900) {
- stopInteract(_gm->_state._money);
- return true;
- }
- // fall through
case 2:
if (_gm->_state._money > 1100) {
stopInteract(_gm->_state._money - 200);
return true;
}
_gm->reply(kStringAxacussCorridor5_6, 1, 1 + 128);
+ break;
+ case 3:
+ if (_gm->_state._money >= 900) {
+ stopInteract(_gm->_state._money);
+ return true;
+ }
+ _gm->reply(kStringAxacussCorridor5_6, 1, 1 + 128);
+ break;
}
}
return false;
@@ -2959,7 +2871,7 @@ bool AxacussExit::interact(Action verb, Object &obj1, Object &obj2) {
_vm->renderImage(i);
if (i == 11)
_vm->playSound(kAudioSmash); // 046/4020
- _gm->wait2(1);
+ _gm->wait(1);
_vm->renderImage(i + 128);
}
_gm->_state._powerOff = true;
@@ -3176,9 +3088,9 @@ bool AxacussElevator::interact(Action verb, Object &obj1, Object &obj2) {
_vm->renderImage(1);
getObject(2)->resetProperty();
_vm->playSound(kAudioSlideDoor);
- _gm->wait2(25);
+ _gm->wait(25);
for (int i = 3; i <= 7; i++) {
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(i);
}
getObject(3)->resetProperty(EXIT);
@@ -3196,10 +3108,10 @@ bool AxacussElevator::interact(Action verb, Object &obj1, Object &obj2) {
getObject(3)->_click = 255;
_vm->playSound(kAudioSlideDoor);
for (int i = 7; i >= 3; i--) {
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(i));
}
- _gm->wait2(25);
+ _gm->wait(25);
_vm->playSound(kAudioSlideDoor);
getObject(2)->resetProperty(EXIT);
_vm->renderImage(_gm->invertSection(2));
@@ -3207,12 +3119,12 @@ bool AxacussElevator::interact(Action verb, Object &obj1, Object &obj2) {
} else if ((verb == ACTION_WALK) && (obj1._id == JUNGLE)) {
_vm->paletteFadeOut();
g_system->fillScreen(kColorBlack);
- _vm->_menuBrightness = 255;
+ _vm->_screen->setGuiBrightness(255);
_vm->paletteBrightness();
_vm->renderMessage(kStringAxacussElevator_3);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
- _vm->_menuBrightness = 0;
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
_gm->_state._time += ticksToMsec(125000); // 2 hours
_gm->_state._alarmOn = (_gm->_state._timeAlarm > _gm->_state._time);
@@ -3281,24 +3193,24 @@ void Outro::onEntrance() {
_vm->renderImage(0);
_vm->renderImage(1);
_vm->paletteFadeIn();
- _gm->wait2(10);
+ _gm->wait(10);
for (int i = 8; i <= 21; i++) {
_vm->renderImage(i);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(i));
}
- _gm->wait2(18);
+ _gm->wait(18);
_vm->renderImage(_gm->invertSection(1));
for (int i = 2; i <= 7; i++) {
_vm->renderImage(i);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(_gm->invertSection(i));
}
- _vm->playSoundMod(kMusicOutro);
- Marquee marquee(_vm, Marquee::kMarqueeOutro, _outroText.c_str());
+ _vm->playSound(kMusicOutro);
+ Marquee marquee(_vm->_screen, Marquee::kMarqueeOutro, _outroText.c_str());
while (!_vm->shouldQuit()) {
- _vm->updateEvents();
+ _gm->updateEvents();
marquee.renderCharacter();
if (_gm->_mouseClicked || _gm->_keyPressed)
break;
@@ -3311,7 +3223,7 @@ void Outro::onEntrance() {
_vm->paletteFadeIn();
_gm->getInput();
_vm->paletteFadeOut();
- _vm->_brightness = 1;
+ _vm->_screen->setViewportBrightness(1);
Common::Event event;
event.type = Common::EVENT_RTL;
@@ -3325,9 +3237,9 @@ void Outro::animate(int filenumber, int section1, int section2, int duration) {
_vm->setCurrentImage(filenumber);
while (duration) {
_vm->renderImage(section1);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(section2);
- _gm->wait2(2);
+ _gm->wait(2);
--duration;
}
}
@@ -3340,10 +3252,10 @@ void Outro::animate(int filenumber, int section1, int section2, int duration,
while (delay) {
if (section1)
_vm->renderImage(section1);
- _gm->wait2(2);
+ _gm->wait(2);
if (section2)
_vm->renderImage(section2);
- _gm->wait2(2);
+ _gm->wait(2);
--delay;
}
_vm->removeMessage();
@@ -3359,10 +3271,10 @@ void Outro::animate(int filenumber, int section1, int section2, int section3, in
while(duration) {
_vm->renderImage(section1);
_vm->renderImage(section3);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(section2);
_vm->renderImage(section4);
- _gm->wait2(2);
+ _gm->wait(2);
duration--;
}
_vm->removeMessage();
diff --git a/engines/supernova/rooms.h b/engines/supernova/rooms.h
index 3cedc356db..5c9b283dcd 100644
--- a/engines/supernova/rooms.h
+++ b/engines/supernova/rooms.h
@@ -27,6 +27,11 @@
#include "msn_def.h"
+namespace Common {
+class ReadStream;
+class WriteStream;
+}
+
namespace Supernova {
class GameManager;
@@ -52,7 +57,7 @@ public:
int getFileNumber() const {
return _fileNumber;
}
- RoomID getId() const {
+ RoomId getId() const {
return _id;
}
@@ -112,7 +117,7 @@ protected:
bool _shown[kMaxSection];
byte _sentenceRemoved[kMaxDialog];
Object _objectState[kMaxObject];
- RoomID _id;
+ RoomId _id;
SupernovaEngine *_vm;
GameManager *_gm;
@@ -129,9 +134,9 @@ public:
private:
bool animate(int section1, int section2, int duration);
bool animate(int section1, int section2, int duration, MessagePosition position,
- StringID text);
+ StringId text);
bool animate(int section1, int section2, int section3, int section4, int duration,
- MessagePosition position, StringID text);
+ MessagePosition position, StringId text);
void titleScreen();
void titleFadeIn();
@@ -681,9 +686,9 @@ public:
virtual void animation();
private:
- StringID _dialog1[5];
- StringID _dialog2[5];
- StringID _dialog3[5];
+ StringId _dialog1[5];
+ StringId _dialog2[5];
+ StringId _dialog3[5];
byte _eyewitness;
};
class ArsanoRemaining : public Room {
@@ -742,7 +747,7 @@ public:
virtual bool interact(Action verb, Object &obj1, Object &obj2);
private:
- StringID _dialog1[4];
+ StringId _dialog1[4];
byte _eyewitness;
byte _hands;
};
@@ -809,10 +814,10 @@ public:
private:
// TODO: change to 6, fix initialization
- StringID _dialog1[2];
- StringID _dialog2[2];
- StringID _dialog3[4];
- StringID _dialog4[3];
+ StringId _dialog1[2];
+ StringId _dialog2[2];
+ StringId _dialog3[4];
+ StringId _dialog4[3];
bool _found;
bool _flug;
@@ -846,11 +851,11 @@ public:
virtual bool interact(Action verb, Object &obj1, Object &obj2);
private:
- StringID _dialog2[4];
- StringID _dialog3[2];
+ StringId _dialog2[4];
+ StringId _dialog3[2];
// TODO: Hack, to be move away and renamed when the other uses are found
- StringID _dialogsX[6];
+ StringId _dialogsX[6];
//
};
@@ -1025,9 +1030,9 @@ private:
bool handleMoneyDialog();
// TODO: Change to 6, or change struct, and fix initialization
- StringID _dialog1[2];
- StringID _dialog2[2];
- StringID _dialog3[4];
+ StringId _dialog1[2];
+ StringId _dialog2[2];
+ StringId _dialog3[4];
byte _rows[6];
};
@@ -1176,7 +1181,7 @@ public:
virtual bool interact(Action verb, Object &obj1, Object &obj2);
private:
- StringID _dialogsX[6];
+ StringId _dialogsX[6];
};
class AxacussExit : public Room {
@@ -1205,7 +1210,7 @@ public:
virtual bool interact(Action verb, Object &obj1, Object &obj2);
private:
- StringID _dialogsX[6];
+ StringId _dialogsX[6];
};
class AxacussOffice1 : public Room {
public:
diff --git a/engines/supernova/screen.cpp b/engines/supernova/screen.cpp
new file mode 100644
index 0000000000..5404b13254
--- /dev/null
+++ b/engines/supernova/screen.cpp
@@ -0,0 +1,636 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "common/str.h"
+#include "common/system.h"
+#include "engines/util.h"
+#include "graphics/cursorman.h"
+#include "graphics/palette.h"
+#include "graphics/surface.h"
+
+#include "supernova/imageid.h"
+#include "supernova/resman.h"
+#include "supernova/state.h"
+#include "supernova/screen.h"
+#include "supernova/supernova.h"
+
+#include "supernova/screenstatic.cpp"
+
+namespace Supernova {
+
+ScreenBuffer::ScreenBuffer()
+ : _x(0)
+ , _y(0)
+ , _width(0)
+ , _height(0)
+ , _pixels(nullptr) {
+}
+
+ScreenBufferStack::ScreenBufferStack()
+ : _last(_buffer) {
+}
+
+void ScreenBufferStack::push(int x, int y, int width, int height) {
+ if (_last == ARRAYEND(_buffer))
+ return;
+
+ Graphics::Surface *screenSurface = g_system->lockScreen();
+
+ if (x < 0) {
+ width += x;
+ x = 0;
+ }
+
+ if (x + width > screenSurface->w)
+ width = screenSurface->w - x;
+
+ if (y < 0) {
+ height += y;
+ y = 0;
+ }
+
+ if (y + height > screenSurface->h)
+ height = screenSurface->h - y;
+
+ _last->_pixels = new byte[width * height];
+ byte *pixels = _last->_pixels;
+ const byte *screen = static_cast<const byte *>(screenSurface->getBasePtr(x, y));
+ for (int i = 0; i < height; ++i) {
+ Common::copy(screen, screen + width, pixels);
+ screen += screenSurface->pitch;
+ pixels += width;
+ }
+ g_system->unlockScreen();
+
+ _last->_x = x;
+ _last->_y = y;
+ _last->_width = width;
+ _last->_height = height;
+
+ ++_last;
+}
+
+void ScreenBufferStack::restore() {
+ if (_last == _buffer)
+ return;
+
+ --_last;
+ g_system->lockScreen()->copyRectToSurface(_last->_pixels, _last->_width, _last->_x,
+ _last->_y, _last->_width, _last->_height);
+ g_system->unlockScreen();
+
+ delete[] _last->_pixels;
+}
+
+Marquee::Marquee(Screen *screen, MarqueeId id, const char *text)
+ : _text(text)
+ , _textBegin(text)
+ , _delay(0)
+ , _color(kColorLightBlue)
+ , _loop(false)
+ , _screen(screen) {
+ if (id == kMarqueeIntro) {
+ _y = 191;
+ _loop = true;
+ } else if (id == kMarqueeOutro) {
+ _y = 1;
+ }
+
+ _textWidth = Screen::textWidth(_text);
+ _x = kScreenWidth / 2 - _textWidth / 2;
+ _screen->_textCursorX = _x;
+ _screen->_textCursorY = _y;
+ _screen->_textColor = _color;
+}
+
+void Marquee::clearText() {
+ _screen->renderBox(_x, _y - 1, _textWidth + 1, 9, kColorBlack);
+}
+
+void Marquee::renderCharacter() {
+ if (_delay != 0) {
+ _delay--;
+ return;
+ }
+
+ switch (*_text) {
+ case '\233':
+ if (_loop) {
+ _loop = false;
+ _text = _textBegin;
+ clearText();
+ _textWidth = Screen::textWidth(_text);
+ _x = kScreenWidth / 2 - _textWidth / 2;
+ _screen->_textCursorX = _x;
+ }
+ break;
+ case '\0':
+ clearText();
+ _text++;
+ _textWidth = Screen::textWidth(_text);
+ _x = kScreenWidth / 2 - _textWidth / 2;
+ _screen->_textCursorX = _x;
+ _color = kColorLightBlue;
+ _screen->_textColor = _color;
+ break;
+ case '^':
+ _color = kColorLightYellow;
+ _screen->_textColor = _color;
+ _text++;
+ break;
+ case '#':
+ _delay = 50;
+ _text++;
+ break;
+ default:
+ _screen->renderText((uint16)*_text++);
+ _delay = 1;
+ break;
+ }
+}
+
+Screen::Screen(SupernovaEngine *vm, GameManager *gm, ResourceManager *resMan)
+ : _vm(vm)
+ , _gm(gm)
+ , _resMan(resMan)
+ , _currentImage(nullptr)
+ , _viewportBrightness(255)
+ , _guiBrightness(255)
+ , _screenWidth(320)
+ , _screenHeight(200)
+ , _textColor(kColorBlack)
+ , _textCursorX(0)
+ , _textCursorY(0)
+ , _messageShown(false) {
+
+ CursorMan.replaceCursor(_resMan->getImage(ResourceManager::kCursorNormal),
+ 16, 16, 0, 0, kColorCursorTransparent);
+ CursorMan.replaceCursorPalette(initVGAPalette, 0, 16);
+ CursorMan.showMouse(true);
+}
+
+int Screen::getGuiBrightness() const {
+ return _guiBrightness;
+}
+
+void Screen::setViewportBrightness(int brightness) {
+ _viewportBrightness = brightness;
+}
+
+int Screen::getViewportBrightness() const {
+ return _viewportBrightness;
+}
+
+void Screen::setGuiBrightness(int brightness) {
+ _guiBrightness = brightness;
+}
+
+const MSNImage *Screen::getCurrentImage() const {
+ return _currentImage;
+}
+
+bool Screen::isMessageShown() const {
+ return _messageShown;
+}
+
+Common::Point Screen::getTextCursorPos() {
+ return Common::Point(_textCursorX, _textCursorY);
+}
+
+void Screen::setTextCursorPos(int x, int y) {
+ _textCursorX = x;
+ _textCursorY = y;
+}
+
+byte Screen::getTextCursorColor() {
+ return _textColor;
+}
+
+void Screen::setTextCursorColor(byte color) {
+ _textColor = color;
+}
+
+void Screen::renderMessage(StringId stringId, MessagePosition position,
+ Common::String var1, Common::String var2) {
+ Common::String text = _vm->getGameString(stringId);
+
+ if (!var1.empty()) {
+ if (!var2.empty())
+ text = Common::String::format(text.c_str(), var1.c_str(), var2.c_str());
+ else
+ text = Common::String::format(text.c_str(), var1.c_str());
+ }
+
+ renderMessage(text, position);
+}
+
+void Screen::renderMessage(const Common::String &text, MessagePosition position) {
+ if (!text.empty())
+ renderMessage(text.c_str(), position);
+}
+
+void Screen::renderText(const uint16 character) {
+ char text[2];
+ text[0] = character & 0xFF;
+ text[1] = 0;
+ renderText(text, _textCursorX, _textCursorY, _textColor);
+}
+
+void Screen::renderText(const char *text) {
+ renderText(text, _textCursorX, _textCursorY, _textColor);
+}
+
+void Screen::renderText(StringId stringId) {
+ renderText(_vm->getGameString(stringId));
+}
+
+void Screen::renderText(const Common::String &text) {
+ if (!text.empty())
+ renderText(text.c_str());
+}
+
+void Screen::renderText(const GuiElement &guiElement) {
+ renderText(guiElement.getText(), guiElement.getTextPos().x,
+ guiElement.getTextPos().y, guiElement.getTextColor());
+}
+
+void Screen::renderText(const uint16 character, int x, int y, byte color) {
+ char text[2];
+ text[0] = character & 0xFF;
+ text[1] = 0;
+ renderText(text, x, y, color);
+}
+
+void Screen::renderText(const char *text, int x, int y, byte color) {
+ Graphics::Surface *screen = _vm->_system->lockScreen();
+ byte *cursor = static_cast<byte *>(screen->getBasePtr(x, y));
+ const byte *basePtr = cursor;
+
+ byte c;
+ while ((c = *text++) != '\0') {
+ if (c < 32) {
+ continue;
+ } else if (c == 225) {
+ c = 128;
+ }
+
+ for (uint i = 0; i < 5; ++i) {
+ if (font[c - 32][i] == 0xff) {
+ break;
+ }
+
+ byte *ascentLine = cursor;
+ for (byte j = font[c - 32][i]; j != 0; j >>= 1) {
+ if (j & 1) {
+ *cursor = color;
+ }
+ cursor += kScreenWidth;
+ }
+ cursor = ++ascentLine;
+ }
+ ++cursor;
+ }
+ _vm->_system->unlockScreen();
+
+ uint numChars = cursor - basePtr;
+ uint absPosition = y * kScreenWidth + x + numChars;
+ _textCursorX = absPosition % kScreenWidth;
+ _textCursorY = absPosition / kScreenWidth;
+ _textColor = color;
+}
+
+void Screen::renderText(const Common::String &text, int x, int y, byte color) {
+ if (!text.empty())
+ renderText(text.c_str(), x, y, color);
+}
+
+void Screen::renderText(StringId stringId, int x, int y, byte color) {
+ renderText(_vm->getGameString(stringId), x, y, color);
+}
+
+void Screen::renderImageSection(const MSNImage *image, int section) {
+ // Note: inverting means we are removing the section. So we should get the rect for that
+ // section but draw the background (section 0) instead.
+ bool invert = false;
+ if (section > 128) {
+ section -= 128;
+ invert = true;
+ }
+ if (section > image->_numSections - 1)
+ return;
+
+ Common::Rect sectionRect(image->_section[section].x1,
+ image->_section[section].y1,
+ image->_section[section].x2 + 1,
+ image->_section[section].y2 + 1) ;
+ if (image->_filenumber == 1 || image->_filenumber == 2) {
+ sectionRect.setWidth(640);
+ sectionRect.setHeight(480);
+ if (_screenWidth != 640) {
+ _screenWidth = 640;
+ _screenHeight = 480;
+ initGraphics(_screenWidth, _screenHeight);
+ }
+ } else {
+ if (_screenWidth != 320) {
+ _screenWidth = 320;
+ _screenHeight = 200;
+ initGraphics(_screenWidth, _screenHeight);
+ }
+ }
+
+ uint offset = 0;
+ int pitch = sectionRect.width();
+ if (invert) {
+ pitch = image->_pitch;
+ offset = image->_section[section].y1 * pitch +
+ image->_section[section].x1;
+ section = 0;
+ }
+
+ void *pixels = image->_sectionSurfaces[section]->getPixels();
+ _vm->_system->copyRectToScreen(static_cast<const byte *>(pixels) + offset,
+ pitch, sectionRect.left, sectionRect.top,
+ sectionRect.width(), sectionRect.height());
+}
+
+void Screen::renderImage(ImageId id, bool removeImage) {
+ ImageInfo info = imageInfo[id];
+ const MSNImage *image = _resMan->getImage(info.filenumber);
+
+ if (_currentImage != image) {
+ _currentImage = image;
+ _vm->_system->getPaletteManager()->setPalette(image->getPalette(), 16, 239);
+ }
+
+ do {
+ if (removeImage)
+ renderImageSection(image, info.section + 128);
+ else
+ renderImageSection(image, info.section);
+
+ info.section = image->_section[info.section].next;
+ } while (info.section != 0);
+}
+
+void Screen::renderImage(int section) {
+ if (!_currentImage)
+ return;
+
+ bool sectionVisible = true;
+
+ if (section > 128) {
+ sectionVisible = false;
+ section -= 128;
+ }
+
+ _gm->_currentRoom->setSectionVisible(section, sectionVisible);
+
+ do {
+ if (sectionVisible)
+ renderImageSection(_currentImage, section);
+ else
+ renderImageSection(_currentImage, section + 128);
+ section = _currentImage->_section[section].next;
+ } while (section != 0);
+}
+
+bool Screen::setCurrentImage(int filenumber) {
+ _currentImage = _resMan->getImage(filenumber);
+ _vm->_system->getPaletteManager()->setPalette(_currentImage->getPalette(), 16, 239);
+ paletteBrightness();
+
+ return true;
+}
+
+void Screen::saveScreen(int x, int y, int width, int height) {
+ _screenBuffer.push(x, y, width, height);
+}
+
+void Screen::saveScreen(const GuiElement &guiElement) {
+ saveScreen(guiElement.left, guiElement.top, guiElement.width(), guiElement.height());
+}
+
+void Screen::restoreScreen() {
+ _screenBuffer.restore();
+}
+
+void Screen::renderRoom(Room &room) {
+ if (room.getId() == INTRO)
+ return;
+
+ if (setCurrentImage(room.getFileNumber())) {
+ for (int i = 0; i < _currentImage->_numSections; ++i) {
+ int section = i;
+ if (room.isSectionVisible(section)) {
+ do {
+ renderImageSection(_currentImage, section);
+ section = _currentImage->_section[section].next;
+ } while (section != 0);
+ }
+ }
+ }
+}
+
+int Screen::textWidth(const uint16 key) {
+ char text[2];
+ text[0] = key & 0xFF;
+ text[1] = 0;
+ return textWidth(text);
+}
+
+int Screen::textWidth(const char *text) {
+ int charWidth = 0;
+ while (*text != '\0') {
+ byte c = *text++;
+ if (c < 32) {
+ continue;
+ } else if (c == 225) {
+ c = 35;
+ }
+
+ for (uint i = 0; i < 5; ++i) {
+ if (font[c - 32][i] == 0xff) {
+ break;
+ }
+ ++charWidth;
+ }
+ ++charWidth;
+ }
+
+ return charWidth;
+}
+
+int Screen::textWidth(const Common::String &text) {
+ return Screen::textWidth(text.c_str());
+}
+
+void Screen::renderMessage(const char *text, MessagePosition position) {
+ Common::String t(text);
+ char *row[20];
+ Common::String::iterator p = t.begin();
+ uint numRows = 0;
+ int rowWidthMax = 0;
+ int x = 0;
+ int y = 0;
+ byte textColor = 0;
+
+ while (*p != '\0') {
+ row[numRows] = p;
+ ++numRows;
+ while ((*p != '\0') && (*p != '|')) {
+ ++p;
+ }
+ if (*p == '|') {
+ *p = '\0';
+ ++p;
+ }
+ }
+ for (uint i = 0; i < numRows; ++i) {
+ int rowWidth = textWidth(row[i]);
+ if (rowWidth > rowWidthMax)
+ rowWidthMax = rowWidth;
+ }
+
+ switch (position) {
+ case kMessageNormal:
+ x = 160 - rowWidthMax / 2;
+ textColor = kColorWhite99;
+ break;
+ case kMessageTop:
+ x = 160 - rowWidthMax / 2;
+ textColor = kColorLightYellow;
+ break;
+ case kMessageCenter:
+ x = 160 - rowWidthMax / 2;
+ textColor = kColorLightRed;
+ break;
+ case kMessageLeft:
+ x = 3;
+ textColor = kColorLightYellow;
+ break;
+ case kMessageRight:
+ x = 317 - rowWidthMax;
+ textColor = kColorLightGreen;
+ break;
+ }
+
+ if (position == kMessageNormal) {
+ y = 70 - ((numRows * 9) / 2);
+ } else if (position == kMessageTop) {
+ y = 5;
+ } else {
+ y = 142;
+ }
+
+ int message_columns = x - 3;
+ int message_rows = y - 3;
+ int message_width = rowWidthMax + 6;
+ int message_height = numRows * 9 + 5;
+ saveScreen(message_columns, message_rows, message_width, message_height);
+ renderBox(message_columns, message_rows, message_width, message_height, kColorWhite35);
+ for (uint i = 0; i < numRows; ++i) {
+ renderText(row[i], x, y, textColor);
+ y += 9;
+ }
+
+ _messageShown = true;
+ _gm->_messageDuration = (Common::strnlen(text, 512) + 20) * _vm->_textSpeed / 10;
+}
+
+void Screen::removeMessage() {
+ if (_messageShown) {
+ restoreScreen();
+ _messageShown = false;
+ }
+}
+
+void Screen::renderBox(int x, int y, int width, int height, byte color) {
+ Graphics::Surface *screen = _vm->_system->lockScreen();
+ screen->fillRect(Common::Rect(x, y, x + width, y + height), color);
+ _vm->_system->unlockScreen();
+}
+
+void Screen::renderBox(const GuiElement &guiElement) {
+ renderBox(guiElement.left, guiElement.top, guiElement.width(),
+ guiElement.height(), guiElement.getBackgroundColor());
+}
+
+void Screen::initPalette() {
+ g_system->getPaletteManager()->setPalette(initVGAPalette, 0, 256);
+}
+
+void Screen::paletteBrightness() {
+ byte palette[768];
+
+ _vm->_system->getPaletteManager()->grabPalette(palette, 0, 255);
+ for (uint i = 0; i < 48; ++i) {
+ palette[i] = (initVGAPalette[i] * _guiBrightness) >> 8;
+ }
+ for (uint i = 0; i < 717; ++i) {
+ const byte *imagePalette;
+ if (_currentImage && _currentImage->getPalette()) {
+ imagePalette = _currentImage->getPalette();
+ } else {
+ imagePalette = palette + 48;
+ }
+ palette[i + 48] = (imagePalette[i] * _viewportBrightness) >> 8;
+ }
+ _vm->_system->getPaletteManager()->setPalette(palette, 0, 255);
+}
+
+void Screen::paletteFadeOut() {
+ while (_guiBrightness > 10) {
+ _guiBrightness -= 10;
+ if (_viewportBrightness > _guiBrightness)
+ _viewportBrightness = _guiBrightness;
+ paletteBrightness();
+ _vm->_system->updateScreen();
+ _vm->_system->delayMillis(_vm->_delay);
+ }
+ _guiBrightness = 0;
+ _viewportBrightness = 0;
+ paletteBrightness();
+ _vm->_system->updateScreen();
+}
+
+void Screen::paletteFadeIn() {
+ while (_guiBrightness < 245) {
+ if (_viewportBrightness < _gm->_roomBrightness)
+ _viewportBrightness += 10;
+ _guiBrightness += 10;
+ paletteBrightness();
+ _vm->_system->updateScreen();
+ _vm->_system->delayMillis(_vm->_delay);
+ }
+ _guiBrightness = 255;
+ _viewportBrightness = _gm->_roomBrightness;
+ paletteBrightness();
+ _vm->_system->updateScreen();
+}
+
+void Screen::setColor63(byte value) {
+ byte color[3] = {value, value, value};
+ _vm->_system->getPaletteManager()->setPalette(color, 63, 1);
+}
+
+}
diff --git a/engines/supernova/screen.h b/engines/supernova/screen.h
new file mode 100644
index 0000000000..d57fb53ed2
--- /dev/null
+++ b/engines/supernova/screen.h
@@ -0,0 +1,197 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef SUPERNOVA_SCREEN_H
+#define SUPERNOVA_SCREEN_H
+
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/scummsys.h"
+
+#include "supernova/imageid.h"
+#include "supernova/msn_def.h"
+
+namespace Supernova {
+
+class SupernovaEngine;
+class GameManager;
+class ResourceManager;
+class GuiElement;
+class Room;
+class MSNImage;
+class Screen;
+
+const int kScreenWidth = 320;
+const int kScreenHeight = 200;
+const int kFontWidth = 5;
+const int kFontHeight = 8;
+
+enum Color {
+ kColorBlack = 0,
+ kColorWhite25 = 1,
+ kColorWhite35 = 2,
+ kColorWhite44 = 3,
+ kColorWhite99 = 4,
+ kColorDarkGreen = 5,
+ kColorGreen = 6,
+ kColorDarkRed = 7,
+ kColorRed = 8,
+ kColorDarkBlue = 9,
+ kColorBlue = 10,
+ kColorWhite63 = 11,
+ kColorLightBlue = 12,
+ kColorLightGreen = 13,
+ kColorLightYellow = 14,
+ kColorLightRed = 15,
+ kColorCursorTransparent = kColorWhite25
+};
+
+class ScreenBuffer {
+ friend class ScreenBufferStack;
+
+public:
+ ScreenBuffer();
+
+private:
+ byte *_pixels;
+ int _x;
+ int _y;
+ int _width;
+ int _height;
+};
+
+class ScreenBufferStack {
+public:
+ ScreenBufferStack();
+
+ void push(int x, int y, int width, int height);
+ void restore();
+
+private:
+ ScreenBuffer _buffer[8];
+ ScreenBuffer *_last;
+};
+
+class Marquee {
+public:
+ enum MarqueeId {
+ kMarqueeIntro,
+ kMarqueeOutro
+ };
+
+ Marquee(Screen *screen, MarqueeId id, const char *text);
+
+ void renderCharacter();
+
+private:
+ void clearText();
+
+ Screen *_screen;
+ const char *const _textBegin;
+ const char *_text;
+ bool _loop;
+ int _delay;
+ int _color;
+ int _x;
+ int _y;
+ int _textWidth;
+};
+
+class Screen {
+ friend class Marquee;
+
+public:
+ struct ImageInfo {
+ int filenumber;
+ int section;
+ };
+
+public:
+ static void initPalette();
+ static int textWidth(const uint16 key);
+ static int textWidth(const char *text);
+ static int textWidth(const Common::String &text);
+
+public:
+ Screen(SupernovaEngine *vm, GameManager *gm, ResourceManager *resMan);
+
+ int getViewportBrightness() const;
+ void setViewportBrightness(int brightness);
+ int getGuiBrightness() const;
+ void setGuiBrightness(int brightness);
+ const MSNImage *getCurrentImage() const;
+ bool isMessageShown() const;
+ void paletteFadeIn();
+ void paletteFadeOut();
+ void paletteBrightness();
+ void renderImage(ImageId id, bool removeImage = false);
+ void renderImage(int section);
+ bool setCurrentImage(int filenumber);
+ void saveScreen(int x, int y, int width, int height);
+ void saveScreen(const GuiElement &guiElement);
+ void restoreScreen();
+ void renderRoom(Room &room);
+ void renderMessage(const char *text, MessagePosition position = kMessageNormal);
+ void renderMessage(const Common::String &text, MessagePosition position = kMessageNormal);
+ void renderMessage(StringId stringId, MessagePosition position = kMessageNormal,
+ Common::String var1 = "", Common::String var2 = "");
+ void removeMessage();
+ void renderText(const uint16 character);
+ void renderText(const char *text);
+ void renderText(const Common::String &text);
+ void renderText(StringId stringId);
+ void renderText(const uint16 character, int x, int y, byte color);
+ void renderText(const char *text, int x, int y, byte color);
+ void renderText(const Common::String &text, int x, int y, byte color);
+ void renderText(StringId stringId, int x, int y, byte color);
+ void renderText(const GuiElement &guiElement);
+ void renderBox(int x, int y, int width, int height, byte color);
+ void renderBox(const GuiElement &guiElement);
+ void setColor63(byte value);
+ Common::Point getTextCursorPos();
+ void setTextCursorPos(int x, int y);
+ byte getTextCursorColor();
+ void setTextCursorColor(byte color);
+ void update();
+
+private:
+ void renderImageSection(const MSNImage *image, int section);
+
+private:
+ SupernovaEngine *_vm;
+ GameManager *_gm;
+ ResourceManager *_resMan;
+ const MSNImage *_currentImage;
+ ScreenBufferStack _screenBuffer;
+ int _screenWidth;
+ int _screenHeight;
+ int _textCursorX;
+ int _textCursorY;
+ int _textColor;
+ byte _viewportBrightness;
+ byte _guiBrightness;
+ bool _messageShown;
+};
+
+}
+
+#endif
diff --git a/engines/supernova/screenstatic.cpp b/engines/supernova/screenstatic.cpp
new file mode 100644
index 0000000000..db987bf2fb
--- /dev/null
+++ b/engines/supernova/screenstatic.cpp
@@ -0,0 +1,328 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+namespace Supernova {
+
+static const Screen::ImageInfo imageInfo[] = {
+ { 0, 0}, { 0, 1}, { 0, 2},
+ { 1, 0},
+ { 2, 0},
+ { 3, 0}, { 3, 1}, { 3, 2}, { 3, 3}, { 3, 4}, { 3, 5},
+ { 3, 6}, { 3, 7}, { 3, 8}, { 3, 9}, { 3, 10}, { 3, 11},
+ { 4, 0}, { 4, 1}, { 4, 2}, { 4, 3},
+ { 5, 0}, { 5, 1}, { 5, 2}, { 5, 3}, { 5, 4}, { 5, 5},
+ { 5, 6}, { 5, 7}, { 5, 8}, { 5, 9},
+ { 6, 0}, { 6, 1}, { 6, 2}, { 6, 3}, { 6, 4}, { 6, 5},
+ { 6, 6}, { 6, 7}, { 6, 8}, { 6, 9}, { 6, 10}, { 6, 11},
+ { 6, 12}, { 6, 13}, { 6, 14}, { 6, 15}, { 6, 16}, { 6, 17},
+ { 6, 18}, { 6, 19}, { 6, 20}, { 6, 21},
+ { 7, 0}, { 7, 1}, { 7, 2}, { 7, 3}, { 7, 4}, { 7, 5},
+ { 7, 6}, { 7, 7}, { 7, 8}, { 7, 9}, { 7, 10}, { 7, 11},
+ { 7, 12}, { 7, 13}, { 7, 14}, { 7, 15}, { 7, 16}, { 7, 17},
+ { 7, 18}, { 7, 19}, { 7, 20}, { 7, 21}, { 7, 22},
+ { 8, 0}, { 8, 1}, { 8, 2}, { 8, 3}, { 8, 4}, { 8, 5},
+ { 8, 6}, { 8, 7}, { 8, 8}, { 8, 9}, { 8, 10}, { 8, 11},
+ { 8, 12},
+ { 9, 0}, { 9, 1}, { 9, 2}, { 9, 3}, { 9, 4}, { 9, 5},
+ { 9, 6}, { 9, 7}, { 9, 8}, { 9, 9}, { 9, 10}, { 9, 11},
+ { 9, 12}, { 9, 13}, { 9, 14}, { 9, 15}, { 9, 16}, { 9, 17},
+ { 9, 18}, { 9, 19}, { 9, 20}, { 9, 21}, { 9, 22}, { 9, 23},
+ {10, 0}, {10, 1}, {10, 2}, {10, 3}, {10, 4}, {10, 5},
+ {10, 6}, {10, 7}, {10, 8}, {10, 9}, {10, 10}, {10, 11},
+ {10, 12}, {10, 13}, {10, 14}, {10, 15}, {10, 16},
+ {11, 0},
+ {12, 0}, {12, 1}, {12, 2}, {12, 3},
+ {13, 0}, {13, 1}, {13, 2}, {13, 3}, {13, 4}, {13, 5},
+ {13, 6}, {13, 7}, {13, 8}, {13, 9}, {13, 10}, {13, 11},
+ {13, 12}, {13, 13},
+ {14, 0}, {14, 1}, {14, 2}, {14, 3}, {14, 4}, {14, 5},
+ {14, 6}, {14, 7}, {14, 8}, {14, 9}, {14, 10}, {14, 11},
+ {14, 12}, {14, 13}, {14, 14}, {14, 15}, {14, 16}, {14, 17},
+ {14, 18}, {14, 19},
+ {15, 0}, {15, 1}, {15, 2}, {15, 3}, {15, 4}, {15, 5},
+ {16, 0}, {16, 1}, {16, 2}, {16, 3}, {16, 4}, {16, 5},
+ {16, 6}, {16, 7}, {16, 8}, {16, 9}, {16, 10}, {16, 11},
+ {16, 12}, {16, 13}, {16, 14}, {16, 15}, {16, 16}, {16, 17},
+ {16, 18}, {16, 19}, {16, 20}, {16, 21}, {16, 22}, {16, 23},
+ {16, 24}, {16, 25}, {16, 26}, {16, 27}, {16, 28}, {16, 29},
+ {16, 30}, {16, 31}, {16, 32}, {16, 33},
+ {17, 0}, {17, 1}, {17, 2}, {17, 3}, {17, 4}, {17, 5},
+ {17, 6}, {17, 7}, {17, 8}, {17, 9}, {17, 10}, {17, 11},
+ {17, 12}, {17, 13}, {17, 14}, {17, 15},
+ {18, 0}, {18, 1}, {18, 2}, {18, 3}, {18, 4}, {18, 5},
+ {18, 6}, {18, 7}, {18, 8}, {18, 9}, {18, 10}, {18, 11},
+ {18, 12}, {18, 13}, {18, 14}, {18, 15}, {18, 16}, {18, 17},
+ {18, 18}, {18, 19}, {18, 20}, {18, 21},
+ {19, 0}, {19, 1}, {19, 2}, {19, 3}, {19, 4}, {19, 5},
+ {19, 6}, {19, 7}, {19, 8}, {19, 9}, {19, 10}, {19, 11},
+ {19, 12}, {19, 13}, {19, 14}, {19, 15}, {19, 16}, {19, 17},
+ {19, 18}, {19, 19}, {19, 20}, {19, 21}, {19, 22}, {19, 23},
+ {19, 24}, {19, 25}, {19, 26}, {19, 27}, {19, 28}, {19, 29},
+ {19, 30}, {19, 31}, {19, 32}, {19, 33}, {19, 34}, {19, 35},
+ {19, 36}, {19, 37}, {19, 38}, {19, 39}, {19, 40},
+ {20, 0},
+ {21, 0}, {21, 1}, {21, 2}, {21, 3}, {21, 4}, {21, 5},
+ {21, 6}, {21, 7}, {21, 8}, {21, 9}, {21, 10}, {21, 11},
+ {21, 12}, {21, 13}, {21, 14}, {21, 15}, {21, 16}, {21, 17},
+ {21, 18}, {21, 19}, {21, 20}, {21, 21}, {21, 22}, {21, 23},
+ {21, 24}, {21, 25}, {21, 26}, {21, 27}, {21, 28}, {21, 29},
+ {21, 30}, {21, 31}, {21, 32}, {21, 33}, {21, 34}, {21, 35},
+ {21, 36}, {21, 37}, {21, 38},
+ {22, 0}, {22, 1}, {22, 2}, {22, 3}, {22, 4}, {22, 5},
+ {22, 6}, {22, 7}, {22, 8}, {22, 9}, {22, 10}, {22, 11},
+ {22, 12}, {22, 13}, {22, 14}, {22, 15}, {22, 16}, {22, 17},
+ {22, 18},
+ {23, 0},
+ {24, 0}, {24, 1}, {24, 2}, {24, 3}, {24, 4}, {24, 5},
+ {24, 6}, {24, 7}, {24, 8},
+ {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
+ {25, 6}, {25, 7}, {25, 8}, {25, 9}, {25, 10}, {25, 11},
+ {25, 12}, {25, 13}, {25, 14}, {25, 15}, {25, 16}, {25, 17},
+ {25, 18},
+ {26, 0},
+ {27, 0},
+ {28, 0}, {28, 1}, {28, 2}, {28, 3}, {28, 4}, {28, 5},
+ {28, 6}, {28, 7}, {28, 8}, {28, 9}, {28, 10}, {28, 11},
+ {28, 12}, {28, 13}, {28, 14}, {28, 15}, {28, 16}, {28, 17},
+ {28, 18}, {28, 19}, {28, 20}, {28, 21}, {28, 22},
+ {29, 0}, {29, 1}, {29, 2}, {29, 3}, {29, 4}, {29, 5},
+ {29, 6}, {29, 7}, {29, 8}, {29, 9}, {29, 10}, {29, 11},
+ {29, 12}, {29, 13},
+ {30, 0}, {30, 1},
+ {31, 0}, {31, 1}, {31, 2}, {31, 3}, {31, 4}, {31, 5},
+ {31, 6},
+ {32, 0}, {32, 1}, {32, 2}, {32, 3},
+ {33, 0}, {33, 1}, {33, 2}, {33, 3}, {33, 4}, {33, 5},
+ {34, 0}, {34, 1}, {34, 2}, {34, 3}, {34, 4}, {34, 5},
+ {34, 6}, {34, 7}, {34, 8}, {34, 9}, {34, 10}, {34, 11},
+ {34, 12}, {34, 13}, {34, 14}, {34, 15}, {34, 16}, {34, 17},
+ {35, 0}, {35, 1}, {35, 2}, {35, 3}, {35, 4}, {35, 5},
+ {35, 6}, {35, 7}, {35, 8}, {35, 9}, {35, 10}, {35, 11},
+ {35, 12}, {35, 13}, {35, 14}, {35, 15}, {35, 16}, {35, 17},
+ {35, 18}, {35, 19}, {35, 20}, {35, 21},
+ {36, 0}, {36, 1}, {36, 2}, {36, 3}, {36, 4}, {36, 5},
+ {37, 0}, {37, 1}, {37, 2}, {37, 3}, {37, 4}, {37, 5},
+ {37, 6}, {37, 7}, {37, 8}, {37, 9}, {37, 10}, {37, 11},
+ {37, 12}, {37, 13}, {37, 14}, {37, 15}, {37, 16}, {37, 17},
+ {37, 18}, {37, 19}, {37, 20}, {37, 21}, {37, 22}, {37, 23},
+ {37, 24}, {37, 25}, {37, 26},
+ {38, 0}, {38, 1}, {38, 2}, {38, 3}, {38, 4}, {38, 5},
+ {38, 6}, {38, 7}, {38, 8}, {38, 9}, {38, 10}, {38, 11},
+ {38, 12},
+ {39, 0},
+ {40, 0}, {40, 1}, {40, 2}, {40, 3}, {40, 4}, {40, 5},
+ {40, 6}, {40, 7},
+ {41, 0}, {41, 1}, {41, 2}, {41, 3},
+ {42, 0}, {42, 1}, {42, 2}, {42, 3}, {42, 4}, {42, 5},
+ {42, 6}, {42, 7}, {42, 8}, {42, 9}, {42, 10}, {42, 11},
+ {43, 0}, {43, 1}, {43, 2}, {43, 3}, {43, 4}, {43, 5},
+ {43, 6}, {43, 7}, {43, 8}, {43, 9}, {43, 10}, {43, 11},
+ {43, 12}, {43, 13}, {43, 14}, {43, 15}, {43, 16}, {43, 17},
+ {43, 18}, {43, 19}, {43, 20}, {43, 21}, {43, 22}, {43, 23},
+ {43, 24}, {43, 25}, {43, 26}, {43, 27}, {43, 28}, {43, 29},
+ {43, 30}, {43, 31}
+};
+
+// Default palette
+static const byte initVGAPalette[768] = {
+ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x58, 0x58, 0x58, 0x70, 0x70, 0x70, 0xfc, 0xfc, 0xfc, 0x00, 0xd0, 0x00,
+ 0x00, 0xfc, 0x00, 0xd8, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xb0, 0xa0, 0xa0, 0xa0,
+ 0x50, 0xc8, 0xfc, 0x28, 0xfc, 0x28, 0xf0, 0xf0, 0x00, 0xfc, 0x28, 0x28, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14,
+ 0x20, 0x20, 0x20, 0x2c, 0x2c, 0x2c, 0x38, 0x38, 0x38, 0x44, 0x44, 0x44, 0x50, 0x50, 0x50, 0x60, 0x60, 0x60,
+ 0x70, 0x70, 0x70, 0x80, 0x80, 0x80, 0x90, 0x90, 0x90, 0xa0, 0xa0, 0xa0, 0xb4, 0xb4, 0xb4, 0xc8, 0xc8, 0xc8,
+ 0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00, 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc,
+ 0xfc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc, 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00,
+ 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc, 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x00,
+ 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00, 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc,
+ 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c, 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc,
+ 0xfc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc, 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c,
+ 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc, 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0x7c,
+ 0x7c, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c, 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc,
+ 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4, 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc,
+ 0xfc, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc, 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4,
+ 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc, 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0xb4,
+ 0xb4, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4, 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc,
+ 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70,
+ 0x70, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70, 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x00, 0x00, 0x70, 0x1c, 0x00,
+ 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70, 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x00,
+ 0x00, 0x70, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70,
+ 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38, 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70,
+ 0x70, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70, 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38,
+ 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70, 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x38,
+ 0x38, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38, 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70,
+ 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50, 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70,
+ 0x70, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70, 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50,
+ 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70, 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x50,
+ 0x50, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50, 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70,
+ 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x00, 0x00, 0x40, 0x10, 0x00, 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40,
+ 0x40, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40, 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x00, 0x00, 0x40, 0x10, 0x00,
+ 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40, 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x40, 0x10, 0x00, 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40,
+ 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20, 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40,
+ 0x40, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40, 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20,
+ 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40, 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x20,
+ 0x20, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20, 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40,
+ 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c, 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40,
+ 0x40, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40, 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c,
+ 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40, 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x2c,
+ 0x2c, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c, 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40,
+ 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const byte font[][5] = {
+ {0x00,0x00,0x00,0xff,0x00},
+ {0x5f,0xff,0x00,0x00,0x00},
+ {0x03,0x00,0x03,0xff,0x00},
+ {0x14,0x7f,0x14,0x7f,0x14},
+ {0x24,0x2a,0x7f,0x2a,0x12},
+ {0x61,0x10,0x08,0x04,0x43},
+ {0x38,0x4e,0x59,0x26,0x50},
+ {0x03,0xff,0x00,0x00,0x00},
+ {0x3e,0x41,0xff,0x00,0x00},
+ {0x41,0x3e,0xff,0x00,0x00},
+ {0x10,0x54,0x38,0x54,0x10},
+ {0x10,0x10,0x7c,0x10,0x10},
+ {0x80,0x40,0xff,0x00,0x00},
+ {0x10,0x10,0x10,0x10,0x10},
+ {0x40,0xff,0x00,0x00,0x00},
+ {0x60,0x10,0x08,0x04,0x03},
+
+ {0x3e,0x41,0x41,0x41,0x3e}, /* digits */
+ {0x04,0x02,0x7f,0xff,0x00},
+ {0x42,0x61,0x51,0x49,0x46},
+ {0x22,0x41,0x49,0x49,0x36},
+ {0x18,0x14,0x12,0x7f,0x10},
+ {0x27,0x45,0x45,0x45,0x39},
+ {0x3e,0x49,0x49,0x49,0x32},
+ {0x01,0x61,0x19,0x07,0x01},
+ {0x36,0x49,0x49,0x49,0x36},
+ {0x26,0x49,0x49,0x49,0x3e},
+
+ {0x44,0xff,0x00,0x00,0x00},
+ {0x80,0x44,0xff,0x00,0x00},
+ {0x10,0x28,0x44,0xff,0x00},
+ {0x28,0x28,0x28,0x28,0x28},
+ {0x44,0x28,0x10,0xff,0x00},
+ {0x02,0x01,0x51,0x09,0x06},
+ {0x3e,0x41,0x5d,0x5d,0x1e},
+
+ {0x7c,0x12,0x11,0x12,0x7c}, /* uppercase letters*/
+ {0x7f,0x49,0x49,0x49,0x36},
+ {0x3e,0x41,0x41,0x41,0x22},
+ {0x7f,0x41,0x41,0x22,0x1c},
+ {0x7f,0x49,0x49,0x49,0xff},
+ {0x7f,0x09,0x09,0x09,0xff},
+ {0x3e,0x41,0x41,0x49,0x3a},
+ {0x7f,0x08,0x08,0x08,0x7f},
+ {0x41,0x7f,0x41,0xff,0x00},
+ {0x20,0x40,0x40,0x3f,0xff},
+ {0x7f,0x08,0x14,0x22,0x41},
+ {0x7f,0x40,0x40,0x40,0xff},
+ {0x7f,0x02,0x04,0x02,0x7f},
+ {0x7f,0x02,0x0c,0x10,0x7f},
+ {0x3e,0x41,0x41,0x41,0x3e},
+ {0x7f,0x09,0x09,0x09,0x06},
+ {0x3e,0x41,0x51,0x21,0x5e},
+ {0x7f,0x09,0x19,0x29,0x46},
+ {0x26,0x49,0x49,0x49,0x32},
+ {0x01,0x01,0x7f,0x01,0x01},
+ {0x3f,0x40,0x40,0x40,0x3f},
+ {0x07,0x18,0x60,0x18,0x07},
+ {0x1f,0x60,0x18,0x60,0x1f},
+ {0x63,0x14,0x08,0x14,0x63},
+ {0x03,0x04,0x78,0x04,0x03},
+ {0x61,0x51,0x49,0x45,0x43},
+
+ {0x7f,0x41,0x41,0xff,0x00},
+ {0x03,0x04,0x08,0x10,0x60},
+ {0x41,0x41,0x7f,0xff,0x00},
+ {0x02,0x01,0x02,0xff,0x00},
+ {0x80,0x80,0x80,0x80,0x80},
+ {0x01,0x02,0xff,0x00,0x00},
+
+ {0x38,0x44,0x44,0x44,0x7c}, /* lowercase letters */
+ {0x7f,0x44,0x44,0x44,0x38},
+ {0x38,0x44,0x44,0x44,0x44},
+ {0x38,0x44,0x44,0x44,0x7f},
+ {0x38,0x54,0x54,0x54,0x58},
+ {0x04,0x7e,0x05,0x01,0xff},
+ {0x98,0xa4,0xa4,0xa4,0x7c},
+ {0x7f,0x04,0x04,0x04,0x78},
+ {0x7d,0xff,0x00,0x00,0x00},
+ {0x80,0x80,0x7d,0xff,0x00},
+ {0x7f,0x10,0x28,0x44,0xff},
+ {0x7f,0xff,0x00,0x00,0x00},
+ {0x7c,0x04,0x7c,0x04,0x78},
+ {0x7c,0x04,0x04,0x04,0x78},
+ {0x38,0x44,0x44,0x44,0x38},
+ {0xfc,0x24,0x24,0x24,0x18},
+ {0x18,0x24,0x24,0x24,0xfc},
+ {0x7c,0x08,0x04,0x04,0xff},
+ {0x48,0x54,0x54,0x54,0x24},
+ {0x04,0x3e,0x44,0x40,0xff},
+ {0x7c,0x40,0x40,0x40,0x3c},
+ {0x0c,0x30,0x40,0x30,0x0c},
+ {0x3c,0x40,0x3c,0x40,0x3c},
+ {0x44,0x28,0x10,0x28,0x44},
+ {0x9c,0xa0,0xa0,0xa0,0x7c},
+ {0x44,0x64,0x54,0x4c,0x44},
+
+ {0x08,0x36,0x41,0xff,0x00},
+ {0x77,0xff,0x00,0x00,0x00},
+ {0x41,0x36,0x08,0xff,0x00},
+ {0x02,0x01,0x02,0x01,0xff},
+ {0xff,0x00,0x00,0x00,0x00},
+
+ {0xfe,0x49,0x49,0x4e,0x30}, /* sharp S */
+
+ {0x7c,0x41,0x40,0x41,0x3c}, /* umlauts */
+
+ {0x04,0x06,0x7f,0x06,0x04}, /* arrows */
+ {0x20,0x60,0xfe,0x60,0x20},
+
+ {0x38,0x45,0x44,0x45,0x7c}, /* umlauts */
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0x79,0x14,0x12,0x14,0x79},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0x38,0x45,0x44,0x45,0x38},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0x3d,0x42,0x42,0x42,0x3d},
+ {0x3d,0x40,0x40,0x40,0x3d},
+};
+
+}
diff --git a/engines/supernova/sound.cpp b/engines/supernova/sound.cpp
new file mode 100644
index 0000000000..e7f3ce83bd
--- /dev/null
+++ b/engines/supernova/sound.cpp
@@ -0,0 +1,65 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/raw.h"
+#include "audio/mods/protracker.h"
+#include "common/system.h"
+
+#include "supernova/resman.h"
+#include "supernova/sound.h"
+#include "supernova/supernova.h"
+
+namespace Supernova {
+
+Sound::Sound(Audio::Mixer *mixer, ResourceManager *resMan)
+ : _mixer(mixer)
+ , _resMan(resMan) {
+}
+
+void Sound::play(AudioId index) {
+ Audio::AudioStream *stream = _resMan->getSoundStream(index);
+
+ stop();
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, stream,
+ -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+}
+
+void Sound::play(MusicId index) {
+ Audio::AudioStream *stream = _resMan->getSoundStream(index);
+
+ stop();
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, stream,
+ -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+}
+
+bool Sound::isPlaying() {
+ return _mixer->isSoundHandleActive(_soundHandle);
+}
+
+void Sound::stop() {
+ if (_mixer->isSoundHandleActive(_soundHandle))
+ _mixer->stopHandle(_soundHandle);
+}
+
+}
diff --git a/engines/supernova/sound.h b/engines/supernova/sound.h
new file mode 100644
index 0000000000..100c9a372b
--- /dev/null
+++ b/engines/supernova/sound.h
@@ -0,0 +1,80 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SUPERNOVA_SOUND_H
+#define SUPERNOVA_SOUND_H
+
+#include "audio/mixer.h"
+
+namespace Supernova {
+
+class SupernovaEngine;
+class ResourceManager;
+
+enum AudioId {
+ kAudioFoundLocation, // 44|0
+ kAudioCrash, // 45|0
+ kAudioVoiceHalt, // 46|0
+ kAudioGunShot, // 46|2510
+ kAudioSmash, // 46|4020
+ kAudioVoiceSupernova, // 47|0
+ kAudioVoiceYeah, // 47|24010
+ kAudioRobotShock, // 48|0
+ kAudioRobotBreaks, // 48|2510
+ kAudioShock, // 48|10520
+ kAudioTurntable, // 48|13530
+ kAudioSiren, // 50|0
+ kAudioSnoring, // 50|12786
+ kAudioRocks, // 51|0
+ kAudioDeath, // 53|0
+ kAudioAlarm, // 54|0
+ kAudioSuccess, // 54|8010
+ kAudioSlideDoor, // 54|24020
+ kAudioDoorOpen, // 54|30030
+ kAudioDoorClose, // 54|31040
+ kAudioNumSamples
+};
+
+enum MusicId {
+ kMusicIntro = 49,
+ kMusicOutro = 52
+};
+
+class Sound {
+public:
+
+public:
+ Sound(Audio::Mixer *mixer, ResourceManager *resMan);
+
+ void play(AudioId index);
+ void play(MusicId index);
+ void stop();
+ bool isPlaying();
+private:
+ Audio::Mixer *_mixer;
+ ResourceManager *_resMan;
+ Audio::SoundHandle _soundHandle;
+};
+
+}
+
+#endif
diff --git a/engines/supernova/state.cpp b/engines/supernova/state.cpp
index e41edbf1d5..00a35055b7 100644
--- a/engines/supernova/state.cpp
+++ b/engines/supernova/state.cpp
@@ -21,11 +21,13 @@
*/
#include "common/system.h"
+#include "graphics/cursorman.h"
#include "graphics/palette.h"
#include "gui/message.h"
+
+#include "supernova/screen.h"
#include "supernova/supernova.h"
#include "supernova/state.h"
-#include "graphics/cursorman.h"
namespace Supernova {
@@ -136,13 +138,13 @@ bool GameManager::deserialize(Common::ReadStream *in, int version) {
_inventoryScroll = in->readSint32LE();
_inventory.clear();
for (int i = 0; i < inventorySize; ++i) {
- RoomID objectRoom = static_cast<RoomID>(in->readSint32LE());
+ RoomId objectRoom = static_cast<RoomId>(in->readSint32LE());
int objectIndex = in->readSint32LE();
_inventory.add(*_rooms[objectRoom]->getObject(objectIndex));
}
// Rooms
- RoomID curRoomId = static_cast<RoomID>(in->readByte());
+ RoomId curRoomId = static_cast<RoomId>(in->readByte());
for (int i = 0; i < NUMROOMS; ++i) {
_rooms[i]->deserialize(in, version);
}
@@ -194,16 +196,16 @@ Object *Inventory::get(int index) const {
if (index < _numObjects)
return _inventory[index];
- return const_cast<Object *>(&Object::nullObject);
+ return _nullObject;
}
-Object *Inventory::get(ObjectID id) const {
+Object *Inventory::get(ObjectId id) const {
for (int i = 0; i < _numObjects; ++i) {
if (_inventory[i]->_id == id)
return _inventory[i];
}
- return const_cast<Object *>(&Object::nullObject);
+ return _nullObject;
}
@@ -275,19 +277,20 @@ static Common::String timeToString(int msec) {
return Common::String(s);
}
-StringID GameManager::guiCommands[] = {
+StringId GameManager::guiCommands[] = {
kStringCommandGo, kStringCommandLook, kStringCommandTake, kStringCommandOpen, kStringCommandClose,
kStringCommandPress, kStringCommandPull, kStringCommandUse, kStringCommandTalk, kStringCommandGive
};
-StringID GameManager::guiStatusCommands[] = {
+StringId GameManager::guiStatusCommands[] = {
kStringStatusCommandGo, kStringStatusCommandLook, kStringStatusCommandTake, kStringStatusCommandOpen, kStringStatusCommandClose,
kStringStatusCommandPress, kStringStatusCommandPull, kStringStatusCommandUse, kStringStatusCommandTalk, kStringStatusCommandGive
};
-GameManager::GameManager(SupernovaEngine *vm)
- : _inventory(_inventoryScroll)
- , _vm(vm) {
+GameManager::GameManager(SupernovaEngine *vm, Sound *sound)
+ : _inventory(&_nullObject, _inventoryScroll)
+ , _vm(vm)
+ , _sound(sound) {
initRooms();
changeRoom(INTRO);
initState();
@@ -351,11 +354,10 @@ void GameManager::destroyRooms() {
delete _rooms[OUTRO];
}
-
void GameManager::initState() {
- Object::setObjectNull(_currentInputObject);
- Object::setObjectNull(_inputObject[0]);
- Object::setObjectNull(_inputObject[1]);
+ _currentInputObject = &_nullObject;
+ _inputObject[0] = &_nullObject;
+ _inputObject[1] = &_nullObject;
_inputVerb = ACTION_WALK;
_processInput = false;
_guiEnabled = true;
@@ -370,7 +372,7 @@ void GameManager::initState() {
_oldTime = g_system->getMillis();
_timerPaused = 0;
_timePaused = false;
- _timer1 = 0;
+ _messageDuration = 0;
_animationTimer = 0;
_currentSentence = -1;
@@ -466,7 +468,7 @@ void GameManager::initGui() {
int cmdAvailableSpace = 320 - (cmdCount - 1) * 2;
for (int i = 0; i < cmdCount; ++i) {
const Common::String &text = _vm->getGameString(guiCommands[i]);
- cmdAvailableSpace -= _vm->textWidth(text);
+ cmdAvailableSpace -= Screen::textWidth(text);
}
int commandButtonX = 0;
@@ -476,7 +478,7 @@ void GameManager::initGui() {
if (i < cmdCount - 1) {
int space = cmdAvailableSpace / (cmdCount - i);
cmdAvailableSpace -= space;
- width = _vm->textWidth(text) + space;
+ width = Screen::textWidth(text) + space;
} else
width = 320 - commandButtonX;
@@ -503,6 +505,75 @@ void GameManager::initGui() {
_guiInventoryArrow[1].setTextPosition(273, 186);
}
+void GameManager::updateEvents() {
+ handleTime();
+ if (_animationEnabled && !_vm->_screen->isMessageShown() && _animationTimer == 0)
+ _currentRoom->animation();
+
+ if (_state._eventCallback != kNoFn && _state._time >= _state._eventTime) {
+ _vm->_allowLoadGame = false;
+ _vm->_allowSaveGame = false;
+ _state._eventTime = kMaxTimerValue;
+ EventFunction fn = _state._eventCallback;
+ _state._eventCallback = kNoFn;
+ switch (fn) {
+ case kNoFn:
+ break;
+ case kSupernovaFn:
+ supernovaEvent();
+ break;
+ case kGuardReturnedFn:
+ guardReturnedEvent();
+ break;
+ case kGuardWalkFn:
+ guardWalkEvent();
+ break;
+ case kTaxiFn:
+ taxiEvent();
+ break;
+ case kSearchStartFn:
+ searchStartEvent();
+ break;
+ }
+ _vm->_allowLoadGame = true;
+ _vm->_allowSaveGame = true;
+ return;
+ }
+
+ if (_state._alarmOn && _state._timeAlarm <= _state._time) {
+ _state._alarmOn = false;
+ alarm();
+ return;
+ }
+
+ _mouseClicked = false;
+ _keyPressed = false;
+ Common::Event event;
+ while (g_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ _keyPressed = true;
+ processInput(event.kbd);
+ break;
+ case Common::EVENT_LBUTTONUP:
+ // fallthrough
+ case Common::EVENT_RBUTTONUP:
+ if (_currentRoom->getId() != INTRO && _sound->isPlaying())
+ return;
+ _mouseClicked = true;
+ // fallthrough
+ case Common::EVENT_MOUSEMOVE:
+ _mouseClickType = event.type;
+ _mouseX = event.mouse.x;
+ _mouseY = event.mouse.y;
+ if (_guiEnabled)
+ processInput();
+ break;
+ default:
+ break;
+ }
+ }
+}
void GameManager::processInput(Common::KeyState &state) {
_key = state;
@@ -529,14 +600,18 @@ void GameManager::processInput(Common::KeyState &state) {
_vm->quitGame();
}
break;
+ case Common::KEYCODE_d:
+ if (state.flags & Common::KBD_CTRL)
+ _vm->_console->attach();
+ break;
default:
break;
}
}
void GameManager::resetInputState() {
- Object::setObjectNull(_inputObject[0]);
- Object::setObjectNull(_inputObject[1]);
+ setObjectNull(_inputObject[0]);
+ setObjectNull(_inputObject[1]);
_inputVerb = ACTION_WALK;
_processInput = false;
_mouseClicked = false;
@@ -571,7 +646,7 @@ void GameManager::processInput() {
mouseLocation = onNone;
if (_mouseClickType == Common::EVENT_LBUTTONUP) {
- if (_vm->_messageDisplayed) {
+ if (_vm->_screen->isMessageShown()) {
// Hide the message and consume the event
_vm->removeMessage();
if (mouseLocation != onCmdButton)
@@ -583,7 +658,7 @@ void GameManager::processInput() {
case onInventory:
// Fallthrough
if (_inputVerb == ACTION_GIVE || _inputVerb == ACTION_USE) {
- if (Object::isNullObject(_inputObject[0])) {
+ if (isNullObject(_inputObject[0])) {
_inputObject[0] = _currentInputObject;
if (!_inputObject[0]->hasProperty(COMBINABLE))
_processInput = true;
@@ -593,7 +668,7 @@ void GameManager::processInput() {
}
} else {
_inputObject[0] = _currentInputObject;
- if (!Object::isNullObject(_currentInputObject))
+ if (!isNullObject(_currentInputObject))
_processInput = true;
}
break;
@@ -614,13 +689,13 @@ void GameManager::processInput() {
}
} else if (_mouseClickType == Common::EVENT_RBUTTONUP) {
- if (_vm->_messageDisplayed) {
+ if (_vm->_screen->isMessageShown()) {
// Hide the message and consume the event
_vm->removeMessage();
return;
}
- if (Object::isNullObject(_currentInputObject))
+ if (isNullObject(_currentInputObject))
return;
if (mouseLocation == onObject || mouseLocation == onInventory) {
@@ -666,8 +741,9 @@ void GameManager::processInput() {
for (int i = 0; (_currentRoom->getObject(i)->_id != INVALIDOBJECT) &&
(field == -1) && i < kMaxObject; i++) {
click = _currentRoom->getObject(i)->_click;
- if (click != 255 && _vm->_currentImage) {
- MSNImageDecoder::ClickField *clickField = _vm->_currentImage->_clickField;
+ const MSNImage *image = _vm->_screen->getCurrentImage();
+ if (click != 255 && image) {
+ const MSNImage::ClickField *clickField = image->_clickField;
do {
if ((_mouseX >= clickField[click].x1) && (_mouseX <= clickField[click].x2) &&
(_mouseY >= clickField[click].y1) && (_mouseY <= clickField[click].y2))
@@ -698,7 +774,7 @@ void GameManager::processInput() {
break;
}
- Object::setObjectNull(_currentInputObject);
+ setObjectNull(_currentInputObject);
_mouseField = field;
if (_mouseField >= 0 && _mouseField < 256)
@@ -737,6 +813,14 @@ void GameManager::processInput() {
}
}
+void GameManager::setObjectNull(Object *&obj) {
+ obj = &_nullObject;
+}
+
+bool GameManager::isNullObject(Object *obj) {
+ return obj == &_nullObject;
+}
+
void GameManager::corridorOnEntrance() {
if (_state._corridorSearch)
busted(0);
@@ -761,7 +845,7 @@ void GameManager::telomat(int nr) {
"Alga Hurz Li"
};
- StringID dial1[4];
+ StringId dial1[4];
dial1[0] = kStringTelomat1;
dial1[1] = kNoString;
dial1[2] = kStringTelomat3;
@@ -769,7 +853,7 @@ void GameManager::telomat(int nr) {
static byte rows1[3] = {1, 2, 1};
- StringID dial2[4];
+ StringId dial2[4];
dial2[0] = kStringTelomat4;
dial2[1] = kStringTelomat5;
dial2[2] = kStringTelomat6;
@@ -813,7 +897,7 @@ void GameManager::telomat(int nr) {
i >>= 1;
if (i == 4) {
_vm->renderText(kStringTelomat14, 50, 120, kColorGreen);
- wait2(10);
+ wait(10);
_vm->renderBox(0, 0, 320, 200, kColorBlack);
_vm->renderRoom(*_currentRoom);
_vm->paletteBrightness();
@@ -824,7 +908,7 @@ void GameManager::telomat(int nr) {
if ((i == nr) || _rooms[BCORRIDOR]->getObject(4 + i)->hasProperty(CAUGHT)) {
_vm->renderText(kStringTelomat15, 50, 120, kColorGreen);
- wait2(10);
+ wait(10);
_vm->renderBox(0, 0, 320, 200, kColorBlack);
_vm->renderRoom(*_currentRoom);
_vm->paletteBrightness();
@@ -834,12 +918,12 @@ void GameManager::telomat(int nr) {
}
_vm->renderText(kStringTelomat16, 50, 120, kColorGreen);
- wait2(10);
+ wait(10);
_vm->renderBox(0, 0, 320, 200, kColorBlack);
_vm->renderRoom(*_currentRoom);
_vm->paletteBrightness();
_vm->renderMessage(kStringTelomat17, kMessageTop, name2[i]);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
if (_state._nameSeen[nr]) {
Common::String string = _vm->getGameString(kStringTelomat2);
@@ -851,7 +935,7 @@ void GameManager::telomat(int nr) {
switch (dialog(3, rows1, dial1, 1)) {
case 1: _vm->renderMessage(kStringTelomat18, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
if ((_state._destination == 255) && !_rooms[BCORRIDOR]->isSectionVisible(7)) {
_state._eventTime = _state._time + ticksToMsec(150);
@@ -861,10 +945,10 @@ void GameManager::telomat(int nr) {
}
break;
case 0: _vm->renderMessage(kStringTelomat19, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
if (dialog(4, rows2, dial2, 0) != 3) {
- wait2(10);
+ wait(10);
say(kStringTelomat20);
}
_rooms[BCORRIDOR]->setSectionVisible(7, true);
@@ -888,7 +972,7 @@ void GameManager::telomat(int nr) {
if (_key.keycode == Common::KEYCODE_RETURN) {
_vm->renderText(kStringShipSleepCabin9, 100, 120, kColorGreen);
- wait2(10);
+ wait(10);
}
// fallthrough
case Common::KEYCODE_ESCAPE:
@@ -926,7 +1010,7 @@ void GameManager::guardNoticed() {
_vm->paletteFadeIn();
_vm->renderImage(2);
reply(kStringGuardNoticed1, 2, 5);
- wait2(2);
+ wait(2);
reply(kStringGuardNoticed2, 2, 5);
_vm->paletteFadeOut();
_currentRoom->setSectionVisible(2, false);
@@ -947,19 +1031,19 @@ void GameManager::busted(int i) {
i = 5;
if (!_currentRoom->getObject(0)->hasProperty(OPENED)) {
_vm->renderImage(i - 1);
- _vm->playSound(kAudioDoorOpen);
- wait2(2);
+ _sound->play(kAudioDoorOpen);
+ wait(2);
}
_vm->renderImage(i);
- wait2(3);
+ wait(3);
_vm->renderImage(i + 3);
- _vm->playSound(kAudioVoiceHalt);
+ _sound->play(kAudioVoiceHalt);
_vm->renderImage(i);
- wait2(5);
+ wait(5);
if (_currentRoom->getId() == OFFICE_L2)
i = 13;
_vm->renderImage(i + 1);
- wait2(3);
+ wait(3);
_vm->renderImage(i + 2);
shot(0, 0);
} else if (_currentRoom->getId() == BCORRIDOR)
@@ -973,8 +1057,8 @@ void GameManager::busted(int i) {
else
_vm->renderImage(33); // above
}
- _vm->playSound(kAudioVoiceHalt);
- wait2(3);
+ _sound->play(kAudioVoiceHalt);
+ wait(3);
shot(0, 0);
}
@@ -1025,7 +1109,7 @@ void GameManager::supernovaEvent() {
CursorMan.showMouse(false);
if (_currentRoom->getId() <= CAVE) {
_vm->renderMessage(kStringSupernova1);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->paletteFadeOut();
changeRoom(MEETUP);
@@ -1038,7 +1122,7 @@ void GameManager::supernovaEvent() {
_vm->paletteFadeIn();
}
_vm->renderMessage(kStringSupernova2);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->setCurrentImage(26);
_vm->renderImage(0);
@@ -1046,28 +1130,28 @@ void GameManager::supernovaEvent() {
novaScroll();
_vm->paletteFadeOut();
_vm->renderBox(0, 0, 320, 200, kColorBlack);
- _vm->_menuBrightness = 255;
+ _vm->_screen->setGuiBrightness(255);
_vm->paletteBrightness();
if (_currentRoom->getId() == GLIDER) {
_vm->renderMessage(kStringSupernova3);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
- _vm->_menuBrightness = 0;
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
_vm->renderRoom(*_currentRoom);
_vm->paletteFadeIn();
_vm->renderMessage(kStringSupernova4, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringSupernova5, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringSupernova6, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringSupernova7, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
changeRoom(MEETUP2);
_rooms[MEETUP2]->setSectionVisible(1, true);
@@ -1077,9 +1161,9 @@ void GameManager::supernovaEvent() {
_inventory.remove(*(_rooms[ROGER]->getObject(8)));
} else {
_vm->renderMessage(kStringSupernova8);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
- _vm->_menuBrightness = 0;
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
changeRoom(MEETUP2);
if (_rooms[ROGER]->getObject(3)->hasProperty(CARRIED) && !_rooms[GLIDER]->isSectionVisible(5)) {
@@ -1121,7 +1205,7 @@ void GameManager::walk(int imgId) {
_vm->renderImage(_prevImgId + 128);
_vm->renderImage(imgId);
_prevImgId = imgId;
- wait2(3);
+ wait(3);
}
void GameManager::guardWalkEvent() {
@@ -1130,14 +1214,14 @@ void GameManager::guardWalkEvent() {
_rooms[BCORRIDOR]->getObject(_state._origin + 4)->hasProperty(OPENED));
_rooms[BCORRIDOR]->getObject(_state._origin + 4)->disableProperty(OCCUPIED);
if (_currentRoom == _rooms[BCORRIDOR]) {
- if (_vm->_messageDisplayed)
+ if (_vm->_screen->isMessageShown())
_vm->removeMessage();
if (!behind) {
_vm->renderImage(_state._origin + 1);
_prevImgId = _state._origin + 1;
- _vm->playSound(kAudioDoorOpen);
- wait2(3);
+ _sound->play(kAudioDoorOpen);
+ wait(3);
}
int imgId;
@@ -1158,13 +1242,13 @@ void GameManager::guardWalkEvent() {
}
_vm->renderImage(imgId);
if (!behind) {
- wait2(3);
+ wait(3);
_vm->renderImage(_prevImgId + 128);
- _vm->playSound(kAudioDoorClose);
+ _sound->play(kAudioDoorClose);
}
_prevImgId = imgId;
- wait2(3);
+ wait(3);
switch (_state._origin) {
case 0:
walk(12);
@@ -1221,12 +1305,12 @@ void GameManager::guardWalkEvent() {
if (behind) {
_vm->renderImage(_state._destination + 1);
- _vm->playSound(kAudioDoorOpen);
- wait2(3);
+ _sound->play(kAudioDoorOpen);
+ wait(3);
_vm->renderImage(_prevImgId + 128);
- wait2(3);
+ wait(3);
_vm->renderImage(_state._destination + 1 + 128);
- _vm->playSound(kAudioDoorClose);
+ _sound->play(kAudioDoorClose);
_rooms[BCORRIDOR]->getObject(_state._destination + 4)->setProperty(OCCUPIED);
_state._destination = 255;
} else if (_rooms[BCORRIDOR]->isSectionVisible(_state._destination + 1)) {
@@ -1236,7 +1320,7 @@ void GameManager::guardWalkEvent() {
_state._eventTime = _state._time + ticksToMsec(60);
_state._eventCallback = kGuardWalkFn;
} else {
- wait2(18);
+ wait(18);
SWAP(_state._origin, _state._destination);
_state._eventCallback = kGuardWalkFn;
}
@@ -1266,7 +1350,7 @@ void GameManager::taxiEvent() {
_vm->renderImage(1);
_vm->renderImage(2);
- _vm->playSound(kAudioRocks);
+ _sound->play(kAudioRocks);
screenShake();
_vm->renderImage(9);
_currentRoom->getObject(1)->setProperty(OPENED);
@@ -1274,7 +1358,7 @@ void GameManager::taxiEvent() {
_currentRoom->setSectionVisible(2, false);
_vm->renderImage(3);
for (int i = 4; i <= 8; i++) {
- wait2(2);
+ wait(2);
_vm->renderImage(invertSection(i - 1));
_vm->renderImage(i);
}
@@ -1292,7 +1376,7 @@ void GameManager::great(uint number) {
if (number && (_state._greatFlag & (1 << number)))
return;
- _vm->playSound(kAudioSuccess);
+ _sound->play(kAudioSuccess);
_state._greatFlag |= 1 << number;
}
@@ -1321,7 +1405,7 @@ void GameManager::sentence(int number, bool brightness) {
}
}
-void GameManager::say(StringID textId) {
+void GameManager::say(StringId textId) {
Common::String str = _vm->getGameString(textId);
if (!str.empty())
say(str.c_str());
@@ -1351,7 +1435,7 @@ void GameManager::say(const char *text) {
_vm->renderBox(0, 138, 320, 62, kColorBlack);
}
-void GameManager::reply(StringID textId, int aus1, int aus2) {
+void GameManager::reply(StringId textId, int aus1, int aus2) {
Common::String str = _vm->getGameString(textId);
if (!str.empty())
reply(str.c_str(), aus1, aus2);
@@ -1375,7 +1459,7 @@ void GameManager::reply(const char *text, int aus1, int aus2) {
_vm->removeMessage();
}
-int GameManager::dialog(int num, byte rowLength[6], StringID text[6], int number) {
+int GameManager::dialog(int num, byte rowLength[6], StringId text[6], int number) {
_vm->_allowLoadGame = false;
_guiEnabled = false;
@@ -1407,7 +1491,12 @@ int GameManager::dialog(int num, byte rowLength[6], StringID text[6], int number
_currentSentence = -1;
do {
- mouseInput3();
+ do {
+ updateEvents();
+ mousePosDialog(_mouseX, _mouseY);
+ g_system->updateScreen();
+ g_system->delayMillis(_vm->_delay);
+ } while (!_mouseClicked && !_vm->shouldQuit());
} while (_currentSentence == -1 && !_vm->shouldQuit());
_vm->renderBox(0, 138, 320, 62, kColorBlack);
@@ -1443,7 +1532,7 @@ void GameManager::turnOn() {
return;
_state._powerOff = false;
- _vm->_brightness = 255;
+ _vm->_screen->setViewportBrightness(255);
_rooms[SLEEP]->setSectionVisible(1, false);
_rooms[SLEEP]->setSectionVisible(2, false);
_rooms[COCKPIT]->setSectionVisible(22, false);
@@ -1462,7 +1551,7 @@ void GameManager::takeObject(Object &obj) {
void GameManager::drawCommandBox() {
for (int i = 0; i < ARRAYSIZE(_guiCommandButton); ++i) {
_vm->renderBox(_guiCommandButton[i]);
- int space = (_guiCommandButton[i].width() - _vm->textWidth(_guiCommandButton[i].getText())) / 2;
+ int space = (_guiCommandButton[i].width() - Screen::textWidth(_guiCommandButton[i].getText())) / 2;
_vm->renderText(_guiCommandButton[i].getText(),
_guiCommandButton[i].getTextPos().x + space,
_guiCommandButton[i].getTextPos().y,
@@ -1491,7 +1580,7 @@ void GameManager::drawInventory() {
uint16 GameManager::getKeyInput(bool blockForPrintChar) {
while (!_vm->shouldQuit()) {
- _vm->updateEvents();
+ updateEvents();
if (_keyPressed) {
if (blockForPrintChar) {
if (Common::isPrint(_key.keycode) ||
@@ -1521,7 +1610,7 @@ uint16 GameManager::getKeyInput(bool blockForPrintChar) {
Common::EventType GameManager::getMouseInput() {
while (!_vm->shouldQuit()) {
- _vm->updateEvents();
+ updateEvents();
if (_mouseClicked)
return _mouseClickType;
g_system->updateScreen();
@@ -1532,7 +1621,7 @@ Common::EventType GameManager::getMouseInput() {
void GameManager::getInput() {
while (!_vm->shouldQuit()) {
- _vm->updateEvents();
+ updateEvents();
if (_mouseClicked || _keyPressed)
break;
g_system->updateScreen();
@@ -1540,15 +1629,6 @@ void GameManager::getInput() {
}
}
-void GameManager::mouseInput3() {
- do {
- _vm->updateEvents();
- mousePosDialog(_mouseX, _mouseY);
- g_system->updateScreen();
- g_system->delayMillis(_vm->_delay);
- } while (!_mouseClicked && !_vm->shouldQuit());
-}
-
void GameManager::roomBrightness() {
_roomBrightness = 255;
if ((_currentRoom->getId() != OUTSIDE) && (_currentRoom->getId() < ROCKS) && _state._powerOff)
@@ -1558,22 +1638,22 @@ void GameManager::roomBrightness() {
else if ((_currentRoom->getId() == GUARD3) && _state._powerOff)
_roomBrightness = 0;
- if (_vm->_brightness != 0)
- _vm->_brightness = _roomBrightness;
+ if (_vm->_screen->getViewportBrightness() != 0)
+ _vm->_screen->setViewportBrightness(_roomBrightness);
_vm->paletteBrightness();
}
-void GameManager::changeRoom(RoomID id) {
+void GameManager::changeRoom(RoomId id) {
_currentRoom = _rooms[id];
_newRoom = true;
}
-void GameManager::wait2(int ticks) {
+void GameManager::wait(int ticks) {
int32 end = _state._time + ticksToMsec(ticks);
do {
g_system->delayMillis(_vm->_delay);
- _vm->updateEvents();
+ updateEvents();
g_system->updateScreen();
} while (_state._time < end && !_vm->shouldQuit());
}
@@ -1582,7 +1662,7 @@ void GameManager::waitOnInput(int ticks) {
int32 end = _state._time + ticksToMsec(ticks);
do {
g_system->delayMillis(_vm->_delay);
- _vm->updateEvents();
+ updateEvents();
g_system->updateScreen();
} while (_state._time < end && !_vm->shouldQuit() && !_keyPressed && !_mouseClicked);
}
@@ -1592,7 +1672,7 @@ bool GameManager::waitOnInput(int ticks, Common::KeyCode &keycode) {
int32 end = _state._time + ticksToMsec(ticks);
do {
g_system->delayMillis(_vm->_delay);
- _vm->updateEvents();
+ updateEvents();
g_system->updateScreen();
if (_keyPressed) {
keycode = _key.keycode;
@@ -1652,14 +1732,14 @@ void GameManager::saveTime() {
void GameManager::screenShake() {
for (int i = 0; i < 12; ++i) {
_vm->_system->setShakePos(8);
- wait2(1);
+ wait(1);
_vm->_system->setShakePos(0);
- wait2(1);
+ wait(1);
}
}
void GameManager::shock() {
- _vm->playSound(kAudioShock);
+ _sound->play(kAudioShock);
dead(kStringShock);
}
@@ -1704,24 +1784,24 @@ void GameManager::edit(Common::String &input, int x, int y, uint length) {
kScreenWidth - x : (length + 1) * (kFontWidth + 2);
while (isEditing) {
- _vm->_textCursorX = x;
- _vm->_textCursorY = y;
- _vm->_textColor = kColorWhite99;
+ _vm->_screen->setTextCursorPos(x, y);
+ _vm->_screen->setTextCursorColor(kColorWhite99);
_vm->renderBox(x, y - 1, overdrawWidth, 9, kColorDarkBlue);
for (uint i = 0; i < input.size(); ++i) {
// Draw char highlight depending on cursor position
if (i == cursorIndex) {
- _vm->renderBox(_vm->_textCursorX, y - 1, _vm->textWidth(input[i]), 9, kColorWhite99);
- _vm->_textColor = kColorDarkBlue;
+ _vm->renderBox(_vm->_screen->getTextCursorPos().x, y - 1,
+ Screen::textWidth(input[i]), 9, kColorWhite99);
+ _vm->_screen->setTextCursorColor(kColorDarkBlue);
_vm->renderText(input[i]);
- _vm->_textColor = kColorWhite99;
+ _vm->_screen->setTextCursorColor(kColorWhite99);
} else
_vm->renderText(input[i]);
}
if (cursorIndex == input.size()) {
- _vm->renderBox(_vm->_textCursorX + 1, y - 1, 6, 9, kColorDarkBlue);
- _vm->renderBox(_vm->_textCursorX , y - 1, 1, 9, kColorWhite99);
+ _vm->renderBox(_vm->_screen->getTextCursorPos().x + 1, y - 1, 6, 9, kColorDarkBlue);
+ _vm->renderBox(_vm->_screen->getTextCursorPos().x, y - 1, 1, 9, kColorWhite99);
}
getKeyInput(true);
@@ -1767,15 +1847,15 @@ void GameManager::edit(Common::String &input, int x, int y, uint length) {
void GameManager::shot(int a, int b) {
if (a)
_vm->renderImage(a);
- _vm->playSound(kAudioGunShot);
- wait2(2);
+ _sound->play(kAudioGunShot);
+ wait(2);
if (b)
_vm->renderImage(b);
- wait2(2);
+ wait(2);
if (a)
_vm->renderImage(a);
- _vm->playSound(kAudioGunShot);
- wait2(2);
+ _sound->play(kAudioGunShot);
+ wait(2);
if (b)
_vm->renderImage(b);
@@ -1801,7 +1881,7 @@ void GameManager::drawStatus() {
_vm->renderBox(0, 140, 320, 9, kColorWhite25);
_vm->renderText(_vm->getGameString(guiStatusCommands[index]), 1, 141, kColorDarkGreen);
- if (Object::isNullObject(_inputObject[0]))
+ if (isNullObject(_inputObject[0]))
_vm->renderText(_currentInputObject->_name);
else {
_vm->renderText(_inputObject[0]->_name);
@@ -1832,19 +1912,18 @@ void GameManager::closeLocker(const Room *room, Object *obj, Object *lock, int s
}
}
-void GameManager::dead(StringID messageId) {
+void GameManager::dead(StringId messageId) {
_vm->paletteFadeOut();
_guiEnabled = false;
_vm->setCurrentImage(11);
_vm->renderImage(0);
_vm->renderMessage(messageId);
- _vm->playSound(kAudioDeath);
+ _sound->play(kAudioDeath);
_vm->paletteFadeIn();
getInput();
_vm->paletteFadeOut();
_vm->removeMessage();
- // TODO: Load screen
destroyRooms();
initRooms();
initState();
@@ -1926,10 +2005,10 @@ bool GameManager::genericInteract(Action verb, Object &obj1, Object &obj2) {
}
} else if ((verb == ACTION_LOOK) && (obj1._id == NEWSPAPER)) {
_vm->renderMessage(kStringGenericInteract_10);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringGenericInteract_11);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->setCurrentImage(2);
_vm->renderImage(0);
@@ -2127,7 +2206,7 @@ bool GameManager::genericInteract(Action verb, Object &obj1, Object &obj2) {
_vm->renderMessage(kStringGenericInteract_30);
else if ((verb == ACTION_LOOK) && (obj1._id == BOOK2)) {
_vm->renderMessage(kStringGenericInteract_31);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringGenericInteract_32);
} else
@@ -2192,7 +2271,7 @@ void GameManager::handleInput() {
byte i = _inputObject[0]->_click;
_inputObject[0]->_click = _inputObject[0]->_click2;
_inputObject[0]->_click2 = i;
- _vm->playSound(kAudioDoorOpen);
+ _sound->play(kAudioDoorOpen);
}
break;
@@ -2211,7 +2290,7 @@ void GameManager::handleInput() {
byte i = _inputObject[0]->_click;
_inputObject[0]->_click = _inputObject[0]->_click2;
_inputObject[0]->_click2 = i;
- _vm->playSound(kAudioDoorClose);
+ _sound->play(kAudioDoorClose);
}
break;
@@ -2230,7 +2309,7 @@ void GameManager::handleInput() {
}
void GameManager::executeRoom() {
- if (_processInput && !_vm->_messageDisplayed && _guiEnabled) {
+ if (_processInput && !_vm->_screen->isMessageShown() && _guiEnabled) {
handleInput();
if (_mouseClicked) {
Common::Event event;
@@ -2246,7 +2325,7 @@ void GameManager::executeRoom() {
}
if (_guiEnabled) {
- if (!_vm->_messageDisplayed) {
+ if (!_vm->_screen->isMessageShown()) {
g_system->fillScreen(kColorBlack);
_vm->renderRoom(*_currentRoom);
}
@@ -2257,7 +2336,7 @@ void GameManager::executeRoom() {
}
roomBrightness();
- if (_vm->_brightness == 0)
+ if (_vm->_screen->getViewportBrightness() == 0)
_vm->paletteFadeIn();
if (!_currentRoom->hasSeen() && _newRoom) {
@@ -2269,31 +2348,31 @@ void GameManager::executeRoom() {
void GameManager::guardShot() {
_vm->renderImage(2);
_vm->renderImage(5);
- wait2(3);
+ wait(3);
_vm->renderImage(2);
- _vm->playSound(kAudioVoiceHalt);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- wait2(1);
+ _sound->play(kAudioVoiceHalt);
+ while (_sound->isPlaying())
+ wait(1);
_vm->renderImage(5);
- wait2(5);
+ wait(5);
_vm->renderImage(3);
- wait2(3);
+ wait(3);
shot(4, 3);
}
void GameManager::guard3Shot() {
_vm->renderImage(1);
- wait2(3);
- _vm->playSound(kAudioVoiceHalt); // 46/0
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- wait2(1);
+ wait(3);
+ _sound->play(kAudioVoiceHalt); // 46/0
+ while (_sound->isPlaying())
+ wait(1);
- wait2(5);
+ wait(5);
_vm->renderImage(2);
- wait2(3);
+ wait(3);
shot(3,2);
}
@@ -2337,12 +2416,12 @@ void GameManager::alarmSound() {
_vm->removeMessage();
_vm->renderMessage(kStringAlarm);
- int32 end = _state._time + ticksToMsec(_timer1);
+ int32 end = _state._time + ticksToMsec(_messageDuration);
do {
- _vm->playSound(kAudioAlarm);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle)) {
+ _sound->play(kAudioAlarm);
+ while (_sound->isPlaying()) {
g_system->delayMillis(_vm->_delay);
- _vm->updateEvents();
+ updateEvents();
g_system->updateScreen();
}
} while (_state._time < end && !_vm->shouldQuit());
diff --git a/engines/supernova/state.h b/engines/supernova/state.h
index ab21842296..1b885ccbdd 100644
--- a/engines/supernova/state.h
+++ b/engines/supernova/state.h
@@ -23,9 +23,11 @@
#ifndef SUPERNOVA_STATE_H
#define SUPERNOVA_STATE_H
+#include "common/events.h"
#include "common/rect.h"
#include "common/keyboard.h"
#include "supernova/rooms.h"
+#include "supernova/sound.h"
namespace Supernova {
@@ -63,8 +65,9 @@ struct GameState {
class Inventory {
public:
- Inventory(int &inventoryScroll)
+ Inventory(Object *nullObject, int &inventoryScroll)
: _numObjects(0)
+ , _nullObject(nullObject)
, _inventoryScroll(inventoryScroll)
{}
@@ -72,11 +75,12 @@ public:
void remove(Object &obj);
void clear();
Object *get(int index) const;
- Object *get(ObjectID id) const;
+ Object *get(ObjectId id) const;
int getSize() const { return _numObjects; }
private:
Object *_inventory[kMaxCarry];
+ Object *_nullObject;
int &_inventoryScroll;
int _numObjects;
};
@@ -121,18 +125,20 @@ private:
class GameManager {
public:
- GameManager(SupernovaEngine *vm);
+ GameManager(SupernovaEngine *vm, Sound *sound);
~GameManager();
+ void updateEvents();
void processInput(Common::KeyState &state);
void processInput();
void executeRoom();
bool serialize(Common::WriteStream *out);
bool deserialize(Common::ReadStream *in, int version);
- static StringID guiCommands[];
- static StringID guiStatusCommands[];
+ static StringId guiCommands[];
+ static StringId guiStatusCommands[];
SupernovaEngine *_vm;
+ Sound *_sound;
Common::KeyState _key;
Common::EventType _mouseClickType;
bool _mouseClicked;
@@ -150,13 +156,14 @@ public:
bool _animationEnabled;
byte _roomBrightness;
Action _inputVerb;
+ Object _nullObject;
Object *_currentInputObject;
Object *_inputObject[2];
bool _waitEvent;
int32 _oldTime;
uint _timePaused;
bool _timerPaused;
- int32 _timer1;
+ int32 _messageDuration;
int32 _animationTimer;
int _inventoryScroll;
int _exitList[25];
@@ -166,11 +173,13 @@ public:
// Dialog
int _currentSentence;
int _sentenceNumber[6];
- StringID _texts[6];
+ StringId _texts[6];
byte _rows[6];
byte _rowsStart[6];
void takeObject(Object &obj);
+ void setObjectNull(Object *&obj);
+ bool isNullObject(Object *obj);
void initState();
void initRooms();
@@ -184,8 +193,7 @@ public:
Common::EventType getMouseInput();
uint16 getKeyInput(bool blockForPrintChar = false);
void getInput();
- void mouseInput3();
- void wait2(int ticks);
+ void wait(int ticks);
void waitOnInput(int ticks);
bool waitOnInput(int ticks, Common::KeyCode &keycode);
void turnOff();
@@ -203,7 +211,7 @@ public:
void drawStatus();
void drawCommandBox();
void drawInventory();
- void changeRoom(RoomID id);
+ void changeRoom(RoomId id);
void resetInputState();
void handleInput();
void handleTime();
@@ -211,12 +219,12 @@ public:
void loadTime();
void saveTime();
void setAnimationTimer(int ticks);
- void dead(StringID messageId);
- int dialog(int num, byte rowLength[6], StringID text[6], int number);
+ void dead(StringId messageId);
+ int dialog(int num, byte rowLength[6], StringId text[6], int number);
void sentence(int number, bool brightness);
- void say(StringID textId);
+ void say(StringId textId);
void say(const char *text);
- void reply(StringID textId, int aus1, int aus2);
+ void reply(StringId textId, int aus1, int aus2);
void reply(const char *text, int aus1, int aus2);
void mousePosDialog(int x, int y);
void shot(int a, int b);
diff --git a/engines/supernova/supernova.cpp b/engines/supernova/supernova.cpp
index 50731ae52f..c47e476de7 100644
--- a/engines/supernova/supernova.cpp
+++ b/engines/supernova/supernova.cpp
@@ -20,7 +20,6 @@
*
*/
-#include "audio/mods/protracker.h"
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/debug-channels.h"
@@ -42,36 +41,14 @@
#include "graphics/thumbnail.h"
#include "gui/saveload.h"
+#include "supernova/resman.h"
+#include "supernova/screen.h"
+#include "supernova/sound.h"
#include "supernova/supernova.h"
#include "supernova/state.h"
namespace Supernova {
-const AudioInfo audioInfo[kAudioNumSamples] = {
- {44, 0, -1},
- {45, 0, -1},
- {46, 0, 2510},
- {46, 2510, 4020},
- {46, 4020, -1},
- {47, 0, 24010},
- {47, 24010, -1},
- {48, 0, 2510},
- {48, 2510, 10520},
- {48, 10520, 13530},
- {48, 13530, -1},
- {50, 0, 12786},
- {50, 12786, -1},
- {51, 0, -1},
- {53, 0, -1},
- {54, 0, 8010},
- {54, 8010, 24020},
- {54, 24020, 30030},
- {54, 30030, 31040},
- {54, 31040, -1}
-};
-
-const Object Object::nullObject;
-
ObjectType operator|(ObjectType a, ObjectType b) {
return static_cast<ObjectType>(+a | +b);
}
@@ -98,74 +75,37 @@ ObjectType &operator^=(ObjectType &a, ObjectType b) {
SupernovaEngine::SupernovaEngine(OSystem *syst)
: Engine(syst)
- , _console(NULL)
- , _gm(NULL)
- , _currentImage(NULL)
- , _soundMusicIntro(NULL)
- , _soundMusicOutro(NULL)
- , _rnd("supernova")
- , _brightness(255)
- , _menuBrightness(255)
+ , _console(nullptr)
+ , _gm(nullptr)
+ , _sound(nullptr)
+ , _resMan(nullptr)
+ , _screen(nullptr)
, _delay(33)
, _textSpeed(kTextSpeed[2])
- , _screenWidth(320)
- , _screenHeight(200)
- , _messageDisplayed(false)
, _allowLoadGame(true)
- , _allowSaveGame(true)
-{
-// const Common::FSNode gameDataDir(ConfMan.get("path"));
-// SearchMan.addSubDirectoryMatching(gameDataDir, "sound");
-
+ , _allowSaveGame(true) {
if (ConfMan.hasKey("textspeed"))
_textSpeed = ConfMan.getInt("textspeed");
- // setup engine specific debug channels
DebugMan.addDebugChannel(kDebugGeneral, "general", "Supernova general debug channel");
}
SupernovaEngine::~SupernovaEngine() {
DebugMan.clearAllDebugChannels();
- delete _currentImage;
delete _console;
delete _gm;
- delete _soundMusicIntro;
- delete _soundMusicOutro;
+ delete _sound;
+ delete _resMan;
+ delete _screen;
}
Common::Error SupernovaEngine::run() {
- Graphics::ModeList modes;
- modes.push_back(Graphics::Mode(320, 200));
- modes.push_back(Graphics::Mode(640, 480));
- initGraphicsModes(modes);
- initGraphics(_screenWidth, _screenHeight);
-
- Common::Error status = loadGameStrings();
- if (status.getCode() != Common::kNoError)
- return status;
-
- _gm = new GameManager(this);
- _console = new Console(this, _gm);
-
- initData();
- initPalette();
-
- CursorMan.replaceCursor(_mouseNormal, 16, 16, 0, 0, kColorCursorTransparent);
- CursorMan.replaceCursorPalette(initVGAPalette, 0, 16);
- CursorMan.showMouse(true);
-
- setTotalPlayTime(0);
-
- int saveSlot = ConfMan.getInt("save_slot");
- if (saveSlot >= 0) {
- if (loadGameState(saveSlot).getCode() != Common::kNoError)
- error("Failed to load save game from slot %i", saveSlot);
- }
+ init();
while (!shouldQuit()) {
uint32 start = _system->getMillis();
- updateEvents();
+ _gm->updateEvents();
_gm->executeRoom();
_console->onFrame();
_system->updateScreen();
@@ -174,89 +114,34 @@ Common::Error SupernovaEngine::run() {
_system->delayMillis(end);
}
- stopSound();
+ _mixer->stopAll();
return Common::kNoError;
}
-void SupernovaEngine::updateEvents() {
- _gm->handleTime();
- if (_gm->_animationEnabled && !_messageDisplayed && _gm->_animationTimer == 0)
- _gm->_currentRoom->animation();
-
- if (_gm->_state._eventCallback != kNoFn && _gm->_state._time >= _gm->_state._eventTime) {
- _allowLoadGame = false;
- _allowSaveGame = false;
- _gm->_state._eventTime = kMaxTimerValue;
- EventFunction fn = _gm->_state._eventCallback;
- _gm->_state._eventCallback = kNoFn;
- switch (fn) {
- case kNoFn:
- break;
- case kSupernovaFn:
- _gm->supernovaEvent();
- break;
- case kGuardReturnedFn:
- _gm->guardReturnedEvent();
- break;
- case kGuardWalkFn:
- _gm->guardWalkEvent();
- break;
- case kTaxiFn:
- _gm->taxiEvent();
- break;
- case kSearchStartFn:
- _gm->searchStartEvent();
- break;
- }
- _allowLoadGame = true;
- _allowSaveGame = true;
- return;
- }
-
- if (_gm->_state._alarmOn && _gm->_state._timeAlarm <= _gm->_state._time) {
- _gm->_state._alarmOn = false;
- _gm->alarm();
- return;
- }
+void SupernovaEngine::init() {
+ Graphics::ModeList modes;
+ modes.push_back(Graphics::Mode(320, 200));
+ modes.push_back(Graphics::Mode(640, 480));
+ initGraphicsModes(modes);
+ initGraphics(320, 200);
- _gm->_mouseClicked = false;
- _gm->_keyPressed = false;
- Common::Event event;
- while (g_system->getEventManager()->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- _gm->_keyPressed = true;
- if (event.kbd.keycode == Common::KEYCODE_d &&
- (event.kbd.flags & Common::KBD_CTRL)) {
- _console->attach();
- }
- if (event.kbd.keycode == Common::KEYCODE_x &&
- (event.kbd.flags & Common::KBD_CTRL)) {
- // TODO: Draw exit box
- }
+ Common::Error status = loadGameStrings();
+ if (status.getCode() != Common::kNoError)
+ error("Failed reading game strings");
- _gm->processInput(event.kbd);
- break;
+ _resMan = new ResourceManager();
+ _sound = new Sound(_mixer, _resMan);
+ _gm = new GameManager(this, _sound);
+ _screen = new Screen(this, _gm, _resMan);
+ _console = new Console(this, _gm);
- case Common::EVENT_LBUTTONUP:
- // fallthrough
- case Common::EVENT_RBUTTONUP:
- if (_gm->_currentRoom->getId() != INTRO && _mixer->isSoundHandleActive(_soundHandle))
- return;
- _gm->_mouseClicked = true;
- // fallthrough
- case Common::EVENT_MOUSEMOVE:
- _gm->_mouseClickType = event.type;
- _gm->_mouseX = event.mouse.x;
- _gm->_mouseY = event.mouse.y;
- if (_gm->_guiEnabled)
- _gm->processInput();
- break;
+ setTotalPlayTime(0);
- default:
- break;
- }
+ int saveSlot = ConfMan.getInt("save_slot");
+ if (saveSlot >= 0) {
+ if (loadGameState(saveSlot).getCode() != Common::kNoError)
+ error("Failed to load save game from slot %i", saveSlot);
}
}
@@ -337,440 +222,133 @@ Common::Error SupernovaEngine::loadGameStrings() {
return Common::kReadingFailed;
}
-void SupernovaEngine::initData() {
- // Sound
- // Note:
- // - samples start with a header of 6 bytes: 01 SS SS 00 AD 00
- // where SS SS (LE uint16) is the size of the sound sample + 2
- // - samples end with a footer of 4 bytes: 00 00
- // Skip those in the buffer
- Common::File file;
-
- for (int i = 0; i < kAudioNumSamples; ++i) {
- if (!file.open(Common::String::format("msn_data.%03d", audioInfo[i]._filenumber))) {
- error("File %s could not be read!", file.getName());
- }
-
- if (audioInfo[i]._offsetEnd == -1) {
- file.seek(0, SEEK_END);
- _soundSamples[i]._length = file.pos() - audioInfo[i]._offsetStart - 10;
- } else {
- _soundSamples[i]._length = audioInfo[i]._offsetEnd - audioInfo[i]._offsetStart - 10;
- }
- _soundSamples[i]._buffer = new byte[_soundSamples[i]._length];
- file.seek(audioInfo[i]._offsetStart + 6);
- file.read(_soundSamples[i]._buffer, _soundSamples[i]._length);
- file.close();
- }
-
- _soundMusicIntro = convertToMod("msn_data.049");
- _soundMusicOutro = convertToMod("msn_data.052");
-
- // Cursor
- const uint16 *bufferNormal = reinterpret_cast<const uint16 *>(mouseNormal);
- const uint16 *bufferWait = reinterpret_cast<const uint16 *>(mouseWait);
- for (uint i = 0; i < sizeof(mouseNormal) / 4; ++i) {
- for (uint bit = 0; bit < 16; ++bit) {
- uint mask = 0x8000 >> bit;
- uint bitIndex = i * 16 + bit;
-
- _mouseNormal[bitIndex] = (READ_LE_UINT16(bufferNormal + i) & mask) ? kColorCursorTransparent : kColorBlack;
- if (READ_LE_UINT16(bufferNormal + i + 16) & mask)
- _mouseNormal[bitIndex] = kColorLightRed;
- _mouseWait[bitIndex] = (READ_LE_UINT16(bufferWait + i) & mask) ? kColorCursorTransparent : kColorBlack;
- if (READ_LE_UINT16(bufferWait + i + 16) & mask)
- _mouseWait[bitIndex] = kColorLightRed;
- }
- }
+const Common::String &SupernovaEngine::getGameString(int idx) const {
+ if (idx < 0 || idx >= (int)_gameStrings.size())
+ return _nullString;
+ return _gameStrings[idx];
}
-void SupernovaEngine::initPalette() {
- _system->getPaletteManager()->setPalette(initVGAPalette, 0, 256);
-}
-
-void SupernovaEngine::playSound(AudioIndex sample) {
- if (sample > kAudioNumSamples - 1)
+void SupernovaEngine::setGameString(int idx, const Common::String &string) {
+ if (idx < 0)
return;
-
- Audio::SeekableAudioStream *audioStream = Audio::makeRawStream(
- _soundSamples[sample]._buffer, _soundSamples[sample]._length,
- 11931, Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN, DisposeAfterUse::NO);
- stopSound();
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, audioStream);
-}
-
-void SupernovaEngine::stopSound() {
- if (_mixer->isSoundHandleActive(_soundHandle))
- _mixer->stopHandle(_soundHandle);
+ while ((int)_gameStrings.size() <= idx)
+ _gameStrings.push_back(Common::String());
+ _gameStrings[idx] = string;
}
-void SupernovaEngine::playSoundMod(int filenumber)
-{
- Audio::AudioStream *audioStream;
- if (filenumber == 49)
- audioStream = Audio::makeProtrackerStream(_soundMusicIntro);
- else if (filenumber == 52)
- audioStream = Audio::makeProtrackerStream(_soundMusicOutro);
- else
- return;
-
- stopSound();
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, audioStream,
- -1, Audio::Mixer::kMaxChannelVolume, 0);
+void SupernovaEngine::playSound(AudioId sample) {
+ _sound->play(sample);
}
-void SupernovaEngine::renderImageSection(int section) {
- // Note: inverting means we are removing the section. So we should get the rect for that
- // section but draw the background (section 0) instead.
- bool invert = false;
- if (section > 128) {
- section -= 128;
- invert = true;
- }
- if (!_currentImage || section > _currentImage->_numSections - 1)
- return;
-
- Common::Rect sectionRect(_currentImage->_section[section].x1,
- _currentImage->_section[section].y1,
- _currentImage->_section[section].x2 + 1,
- _currentImage->_section[section].y2 + 1) ;
- if (_currentImage->_filenumber == 1 || _currentImage->_filenumber == 2) {
- sectionRect.setWidth(640);
- sectionRect.setHeight(480);
- if (_screenWidth != 640) {
- _screenWidth = 640;
- _screenHeight = 480;
- initGraphics(_screenWidth, _screenHeight);
- }
- } else {
- if (_screenWidth != 320) {
- _screenWidth = 320;
- _screenHeight = 200;
- initGraphics(_screenWidth, _screenHeight);
- }
- }
-
- uint offset = 0;
- int pitch = sectionRect.width();
- if (invert) {
- pitch = _currentImage->_pitch;
- offset = _currentImage->_section[section].y1 * pitch + _currentImage->_section[section].x1;
- section = 0;
- }
-
- _system->copyRectToScreen(static_cast<const byte *>(_currentImage->_sectionSurfaces[section]->getPixels()) + offset,
- pitch,
- sectionRect.left, sectionRect.top,
- sectionRect.width(), sectionRect.height());
+void SupernovaEngine::playSound(MusicId index) {
+ _sound->play(index);
}
void SupernovaEngine::renderImage(int section) {
- if (!_currentImage)
- return;
-
- bool sectionVisible = true;
-
- if (section > 128) {
- sectionVisible = false;
- section -= 128;
- }
-
- _gm->_currentRoom->setSectionVisible(section, sectionVisible);
-
- do {
- if (sectionVisible)
- renderImageSection(section);
- else
- renderImageSection(section + 128);
- section = _currentImage->_section[section].next;
- } while (section != 0);
+ _screen->renderImage(section);
}
bool SupernovaEngine::setCurrentImage(int filenumber) {
- if (_currentImage && _currentImage->_filenumber == filenumber)
- return true;
-
- delete _currentImage;
- _currentImage = new MSNImageDecoder();
- if (!_currentImage->init(filenumber)) {
- delete _currentImage;
- _currentImage = NULL;
- return false;
- }
-
- _system->getPaletteManager()->setPalette(_currentImage->getPalette(), 16, 239);
- paletteBrightness();
- return true;
+ return _screen->setCurrentImage(filenumber);
}
void SupernovaEngine::saveScreen(int x, int y, int width, int height) {
- _screenBuffer.push(x, y, width, height);
+ _screen->saveScreen(x, y, width, height);
}
void SupernovaEngine::saveScreen(const GuiElement &guiElement) {
- saveScreen(guiElement.left, guiElement.top, guiElement.width(), guiElement.height());
+ _screen->saveScreen(guiElement);
}
void SupernovaEngine::restoreScreen() {
- _screenBuffer.restore();
+ _screen->restoreScreen();
}
void SupernovaEngine::renderRoom(Room &room) {
- if (room.getId() == INTRO)
- return;
-
- if (setCurrentImage(room.getFileNumber())) {
- for (int i = 0; i < _currentImage->_numSections; ++i) {
- int section = i;
- if (room.isSectionVisible(section)) {
- do {
- renderImageSection(section);
- section = _currentImage->_section[section].next;
- } while (section != 0);
- }
- }
- }
+ _screen->renderRoom(room);
}
-int SupernovaEngine::textWidth(const uint16 key) {
- char text[2];
- text[0] = key & 0xFF;
- text[1] = 0;
- return textWidth(text);
+void SupernovaEngine::renderMessage(const char *text, MessagePosition position) {
+ _screen->renderMessage(text, position);
}
-int SupernovaEngine::textWidth(const char *text) {
- int charWidth = 0;
- while (*text != '\0') {
- byte c = *text++;
- if (c < 32) {
- continue;
- } else if (c == 225) {
- c = 35;
- }
-
- for (uint i = 0; i < 5; ++i) {
- if (font[c - 32][i] == 0xff) {
- break;
- }
- ++charWidth;
- }
- ++charWidth;
- }
-
- return charWidth;
+void SupernovaEngine::renderMessage(const Common::String &text, MessagePosition position) {
+ _screen->renderMessage(text, position);
}
-void SupernovaEngine::renderMessage(const char *text, MessagePosition position) {
- Common::String t(text);
- char *row[20];
- Common::String::iterator p = t.begin();
- uint numRows = 0;
- int rowWidthMax = 0;
- int x = 0;
- int y = 0;
- byte textColor = 0;
-
- while (*p != '\0') {
- row[numRows] = p;
- ++numRows;
- while ((*p != '\0') && (*p != '|')) {
- ++p;
- }
- if (*p == '|') {
- *p = '\0';
- ++p;
- }
- }
- for (uint i = 0; i < numRows; ++i) {
- int rowWidth = textWidth(row[i]);
- if (rowWidth > rowWidthMax)
- rowWidthMax = rowWidth;
- }
-
- switch (position) {
- case kMessageNormal:
- x = 160 - rowWidthMax / 2;
- textColor = kColorWhite99;
- break;
- case kMessageTop:
- x = 160 - rowWidthMax / 2;
- textColor = kColorLightYellow;
- break;
- case kMessageCenter:
- x = 160 - rowWidthMax / 2;
- textColor = kColorLightRed;
- break;
- case kMessageLeft:
- x = 3;
- textColor = kColorLightYellow;
- break;
- case kMessageRight:
- x = 317 - rowWidthMax;
- textColor = kColorLightGreen;
- break;
- }
-
- if (position == kMessageNormal) {
- y = 70 - ((numRows * 9) / 2);
- } else if (position == kMessageTop) {
- y = 5;
- } else {
- y = 142;
- }
-
- int message_columns = x - 3;
- int message_rows = y - 3;
- int message_width = rowWidthMax + 6;
- int message_height = numRows * 9 + 5;
- saveScreen(message_columns, message_rows, message_width, message_height);
- renderBox(message_columns, message_rows, message_width, message_height, kColorWhite35);
- for (uint i = 0; i < numRows; ++i) {
- renderText(row[i], x, y, textColor);
- y += 9;
- }
-
- _messageDisplayed = true;
- _gm->_timer1 = (Common::strnlen(text, 512) + 20) * _textSpeed / 10;
+void SupernovaEngine::renderMessage(StringId stringId, MessagePosition position, Common::String var1, Common::String var2) {
+ _screen->renderMessage(stringId, position, var1, var2);
}
void SupernovaEngine::removeMessage() {
- if (_messageDisplayed) {
- restoreScreen();
- _messageDisplayed = false;
- }
+ _screen->removeMessage();
}
-void SupernovaEngine::renderText(const char *text, int x, int y, byte color) {
- Graphics::Surface *screen = _system->lockScreen();
- byte *cursor = static_cast<byte *>(screen->getBasePtr(x, y));
- const byte *basePtr = cursor;
-
- byte c;
- while ((c = *text++) != '\0') {
- if (c < 32) {
- continue;
- } else if (c == 225) {
- c = 128;
- }
+void SupernovaEngine::renderText(const uint16 character) {
+ _screen->renderText(character);
+}
- for (uint i = 0; i < 5; ++i) {
- if (font[c - 32][i] == 0xff) {
- break;
- }
+void SupernovaEngine::renderText(const char *text) {
+ _screen->renderText(text);
+}
- byte *ascentLine = cursor;
- for (byte j = font[c - 32][i]; j != 0; j >>= 1) {
- if (j & 1) {
- *cursor = color;
- }
- cursor += kScreenWidth;
- }
- cursor = ++ascentLine;
- }
- ++cursor;
- }
- _system->unlockScreen();
+void SupernovaEngine::renderText(const Common::String &text) {
+ _screen->renderText(text);
+}
- uint numChars = cursor - basePtr;
- uint absPosition = y * kScreenWidth + x + numChars;
- _textCursorX = absPosition % kScreenWidth;
- _textCursorY = absPosition / kScreenWidth;
- _textColor = color;
+void SupernovaEngine::renderText(StringId stringId) {
+ _screen->renderText(stringId);
+}
+
+void SupernovaEngine::renderText(const GuiElement &guiElement) {
+ _screen->renderText(guiElement);
}
void SupernovaEngine::renderText(const uint16 character, int x, int y, byte color) {
- char text[2];
- text[0] = character & 0xFF;
- text[1] = 0;
- renderText(text, x, y, color);
+ _screen->renderText(character, x, y, color);
}
-void SupernovaEngine::renderText(const char *text) {
- renderText(text, _textCursorX, _textCursorY, _textColor);
+void SupernovaEngine::renderText(const char *text, int x, int y, byte color) {
+ _screen->renderText(text, x, y, color);
}
-void SupernovaEngine::renderText(const uint16 character) {
- char text[2];
- text[0] = character & 0xFF;
- text[1] = 0;
- renderText(text, _textCursorX, _textCursorY, _textColor);
+void SupernovaEngine::renderText(const Common::String &text, int x, int y, byte color) {
+ _screen->renderText(text, x, y, color);
}
-void SupernovaEngine::renderText(const GuiElement &guiElement) {
- renderText(guiElement.getText(), guiElement.getTextPos().x,
- guiElement.getTextPos().y, guiElement.getTextColor());
+
+void SupernovaEngine::renderText(StringId stringId, int x, int y, byte color) {
+ _screen->renderText(stringId, x, y, color);
}
void SupernovaEngine::renderBox(int x, int y, int width, int height, byte color) {
- Graphics::Surface *screen = _system->lockScreen();
- screen->fillRect(Common::Rect(x, y, x + width, y + height), color);
- _system->unlockScreen();
+ _screen->renderBox(x, y, width, height, color);
}
void SupernovaEngine::renderBox(const GuiElement &guiElement) {
- renderBox(guiElement.left, guiElement.top, guiElement.width(),
- guiElement.height(), guiElement.getBackgroundColor());
+ _screen->renderBox(guiElement);
}
void SupernovaEngine::paletteBrightness() {
- byte palette[768];
-
- _system->getPaletteManager()->grabPalette(palette, 0, 255);
- for (uint i = 0; i < 48; ++i) {
- palette[i] = (initVGAPalette[i] * _menuBrightness) >> 8;
- }
- for (uint i = 0; i < 717; ++i) {
- const byte *imagePalette;
- if (_currentImage && _currentImage->getPalette()) {
- imagePalette = _currentImage->getPalette();
- } else {
- imagePalette = palette + 48;
- }
- palette[i + 48] = (imagePalette[i] * _brightness) >> 8;
- }
- _system->getPaletteManager()->setPalette(palette, 0, 255);
+ _screen->paletteBrightness();
}
void SupernovaEngine::paletteFadeOut() {
- while (_menuBrightness > 10) {
- _menuBrightness -= 10;
- if (_brightness > _menuBrightness)
- _brightness = _menuBrightness;
- paletteBrightness();
- _system->updateScreen();
- _system->delayMillis(_delay);
- }
- _menuBrightness = 0;
- _brightness = 0;
- paletteBrightness();
- _system->updateScreen();
+ _screen->paletteFadeOut();
}
void SupernovaEngine::paletteFadeIn() {
- while (_menuBrightness < 245) {
- if (_brightness < _gm->_roomBrightness)
- _brightness += 10;
- _menuBrightness += 10;
- paletteBrightness();
- _system->updateScreen();
- _system->delayMillis(_delay);
- }
- _menuBrightness = 255;
- _brightness = _gm->_roomBrightness;
- paletteBrightness();
- _system->updateScreen();
+ _screen->paletteFadeIn();
}
void SupernovaEngine::setColor63(byte value) {
- byte color[3] = {value, value, value};
- _system->getPaletteManager()->setPalette(color, 63, 1);
+ _screen->setColor63(value);
}
void SupernovaEngine::setTextSpeed() {
- const Common::String& textSpeedString = getGameString(kStringTextSpeed);
- int stringWidth = textWidth(textSpeedString);
- int textX = (320 - stringWidth) / 2;
+ const Common::String &textSpeedString = getGameString(kStringTextSpeed);
+ int stringWidth = Screen::textWidth(textSpeedString);
+ int textX = (kScreenWidth - stringWidth) / 2;
int textY = 100;
stringWidth += 4;
- int boxX = stringWidth > 110 ? (320 - stringWidth) / 2 : 105;
+ int boxX = stringWidth > 110 ? (kScreenWidth - stringWidth) / 2 : 105;
int boxY = 97;
int boxWidth = stringWidth > 110 ? stringWidth : 110;
int boxHeight = 27;
@@ -878,191 +456,6 @@ bool SupernovaEngine::quitGameDialog() {
return quit;
}
-Common::MemoryReadStream *SupernovaEngine::convertToMod(const char *filename, int version) {
- // MSN format
- struct {
- uint16 seg;
- uint16 start;
- uint16 end;
- uint16 loopStart;
- uint16 loopEnd;
- char volume;
- char dummy[5];
- } instr2[22];
- int nbInstr2; // 22 for version1, 15 for version 2
- int16 songLength;
- char arrangement[128];
- int16 patternNumber;
- int32 note2[28][64][4];
-
- nbInstr2 = ((version == 1) ? 22 : 15);
-
- Common::File msnFile;
- msnFile.open(filename);
- if (!msnFile.isOpen()) {
- warning("Data file '%s' not found", msnFile.getName());
- return NULL;
- }
-
- for (int i = 0 ; i < nbInstr2 ; ++i) {
- instr2[i].seg = msnFile.readUint16LE();
- instr2[i].start = msnFile.readUint16LE();
- instr2[i].end = msnFile.readUint16LE();
- instr2[i].loopStart = msnFile.readUint16LE();
- instr2[i].loopEnd = msnFile.readUint16LE();
- instr2[i].volume = msnFile.readByte();
- msnFile.read(instr2[i].dummy, 5);
- }
- songLength = msnFile.readSint16LE();
- msnFile.read(arrangement, 128);
- patternNumber = msnFile.readSint16LE();
- for (int p = 0 ; p < patternNumber ; ++p) {
- for (int n = 0 ; n < 64 ; ++n) {
- for (int k = 0 ; k < 4 ; ++k) {
- note2[p][n][k] = msnFile.readSint32LE();
- }
- }
- }
-
- /* MOD format */
- struct {
- char iname[22];
- uint16 length;
- char finetune;
- char volume;
- uint16 loopStart;
- uint16 loopLength;
- } instr[31];
- int32 note[28][64][4];
-
- // We can't recover some MOD effects since several of them are mapped to 0.
- // Assume the MSN effect of value 0 is Arpeggio (MOD effect of value 0).
- const char invConvEff[8] = {0, 1, 2, 3, 10, 12, 13 ,15};
-
- // Reminder from convertToMsn
- // 31 30 29 28 27 26 25 24 - 23 22 21 20 19 18 17 16 - 15 14 13 12 11 10 09 08 - 07 06 05 04 03 02 01 00
- // h h h h g g g g f f f f e e e e d d d d c c c c b b b b a a a a
- //
- // MSN:
- // hhhh (4 bits) Cleared to 0
- // dddd c (5 bits) Sample index | after mapping through convInstr
- // ccc (3 bits) Effect type | after mapping through convEff
- // bbbb aaaa (8 bits) Effect value | unmodified
- // gggg ffff eeee (12 bits) Sample period | unmodified
- //
- // MS2:
- // hhhh (4 bits) Cleared to 0
- // dddd (4 bits) Sample index | after mapping through convInstr
- // cccc (4 bits) Effect type | unmodified
- // bbbb aaaa (8 bits) Effect value | unmodified
- // gggg ffff eeee (12 bits) Sample period | transformed (0xE000 / p) - 256
- //
- // MOD:
- // hhhh dddd (8 bits) Sample index
- // cccc (4 bits) Effect type for this channel/division
- // bbbb aaaa (8 bits) Effect value
- // gggg ffff eeee (12 bits) Sample period
-
- // Can we recover the instruments mapping? I don't think so as part of the original instrument index is cleared.
- // And it doesn't really matter as long as we are consistent.
- // However we need to make sure 31 (or 15 in MS2) is mapped to 0 in MOD.
- // We just add 1 to all other values, and this means a 1 <-> 1 mapping for the instruments
- for (int p = 0; p < patternNumber; ++p) {
- for (int n = 0; n < 64; ++n) {
- for (int k = 0; k < 4; ++k) {
- int32* l = &(note[p][n][k]);
- *l = note2[p][n][k];
- int32 i = 0;
- if (nbInstr2 == 22) { // version 1
- i = ((*l & 0xF800) >> 11);
- int32 e = ((*l & 0x0700) >> 8);
- int32 e1 = invConvEff[e];
- *l &= 0x0FFF00FF;
- *l |= (e1 << 8);
- } else { // version 2
- int32 h = (*l >> 16);
- i = ((*l & 0xF000) >> 12);
- *l &= 0x00000FFF;
- if (h)
- h = 0xE000 / (h + 256);
- *l |= (h << 16);
- if (i == 15)
- i = 31;
- }
-
- // Add back index in note
- if (i != 31) {
- ++i;
- *l |= ((i & 0x0F) << 12);
- *l |= ((i & 0xF0) << 24);
- }
- }
- }
- }
-
- for (int i = 0; i < 31; ++i) {
- // iname is not stored in the mod file. Just set it to 'instrument#'
- // finetune is not stored either. Assume 0.
- memset(instr[i].iname, 0, 22);
- sprintf(instr[i].iname, "instrument%d", i+1);
- instr[i].length = 0;
- instr[i].finetune = 0;
- instr[i].volume = 0;
- instr[i].loopStart = 0;
- instr[i].loopLength = 0;
-
- if (i < nbInstr2) {
- instr[i].length = ((instr2[i].end - instr2[i].start) >> 1);
- instr[i].loopStart = ((instr2[i].loopStart - instr2[i].start) >> 1);
- instr[i].loopLength = (( instr2[i].loopEnd - instr2[i].loopStart) >> 1);
- instr[i].volume = instr2[i].volume;
- }
- }
-
- // The ciaaSpeed is kind of useless and not present in the MSN file.
- // Traditionally 0x78 in SoundTracker. Was used in NoiseTracker as a restart point.
- // ProTracker uses 0x7F. FastTracker uses it as a restart point, whereas ScreamTracker 3 uses 0x7F like ProTracker.
- // You can use this to roughly detect which tracker made a MOD, and detection gets more accurate for more obscure MOD types.
- char ciaaSpeed = 0x7F;
-
- // The mark cannot be recovered either. Since we have 4 channels and 31 instrument it can be either ID='M.K.' or ID='4CHN'.
- // Assume 'M.K.'
- const char mark[4] = { 'M', '.', 'K', '.' };
-
- Common::MemoryWriteStreamDynamic buffer(DisposeAfterUse::NO);
-
- buffer.write(msnFile.getName(), 19);
- buffer.writeByte(0);
-
- for (int i = 0 ; i < 31 ; ++i) {
- buffer.write(instr[i].iname, 22);
- buffer.writeUint16BE(instr[i].length);
- buffer.writeByte(instr[i].finetune);
- buffer.writeByte(instr[i].volume);
- buffer.writeUint16BE(instr[i].loopStart);
- buffer.writeUint16BE(instr[i].loopLength);
- }
- buffer.writeByte((char)songLength);
- buffer.writeByte(ciaaSpeed);
- buffer.write(arrangement, 128);
- buffer.write(mark, 4);
-
- for (int p = 0 ; p < patternNumber ; ++p) {
- for (int n = 0 ; n < 64 ; ++n) {
- for (int k = 0 ; k < 4 ; ++k) {
-// buffer.writeUint32BE(*((uint32*)(note[p][n]+k)));
- buffer.writeSint32BE(note[p][n][k]);
- }
- }
- }
-
- uint nb;
- char buf[4096];
- while ((nb = msnFile.read(buf, 4096)) > 0)
- buffer.write(buf, nb);
-
- return new Common::MemoryReadStream(buffer.getData(), buffer.size(), DisposeAfterUse::YES);
-}
bool SupernovaEngine::canLoadGameStateCurrently() {
return _allowLoadGame;
@@ -1117,10 +510,11 @@ bool SupernovaEngine::loadGame(int slot) {
_gm->deserialize(savefile, saveVersion);
if (saveVersion >= 5) {
- _menuBrightness = savefile->readByte();
- _brightness = savefile->readByte();
+ _screen->setGuiBrightness(savefile->readByte());
+ _screen->setViewportBrightness(savefile->readByte());
} else {
- _menuBrightness = _brightness = 255;
+ _screen->setGuiBrightness(255);
+ _screen->setViewportBrightness(255);
}
delete savefile;
@@ -1153,8 +547,8 @@ bool SupernovaEngine::saveGame(int slot, const Common::String &description) {
Graphics::saveThumbnail(*savefile);
_gm->serialize(savefile);
- savefile->writeByte(_menuBrightness);
- savefile->writeByte(_brightness);
+ savefile->writeByte(_screen->getGuiBrightness());
+ savefile->writeByte(_screen->getViewportBrightness());
savefile->finalize();
delete savefile;
@@ -1169,59 +563,5 @@ void SupernovaEngine::errorTempSave(bool saving) {
error("Unrecoverable error");
}
-ScreenBufferStack::ScreenBufferStack()
- : _last(_buffer) {
-}
-
-void ScreenBufferStack::push(int x, int y, int width, int height) {
- if (_last == ARRAYEND(_buffer))
- return;
-
- Graphics::Surface* screenSurface = g_system->lockScreen();
-
- if (x < 0) {
- width += x;
- x = 0;
- }
- if (x + width > screenSurface->w)
- width = screenSurface->w - x;
-
- if (y < 0) {
- height += y;
- y = 0;
- }
- if (y + height > screenSurface->h)
- height = screenSurface->h - y;
-
- _last->_pixels = new byte[width * height];
- byte *pixels = _last->_pixels;
- const byte *screen = static_cast<const byte *>(screenSurface->getBasePtr(x, y));
- for (int i = 0; i < height; ++i) {
- Common::copy(screen, screen + width, pixels);
- screen += screenSurface->pitch;
- pixels += width;
- }
- g_system->unlockScreen();
-
- _last->_x = x;
- _last->_y = y;
- _last->_width = width;
- _last->_height = height;
-
- ++_last;
-}
-
-void ScreenBufferStack::restore() {
- if (_last == _buffer)
- return;
-
- --_last;
- g_system->lockScreen()->copyRectToSurface(
- _last->_pixels, _last->_width, _last->_x, _last->_y,
- _last->_width, _last->_height);
- g_system->unlockScreen();
-
- delete[] _last->_pixels;
-}
}
diff --git a/engines/supernova/supernova.h b/engines/supernova/supernova.h
index e01fb778a5..132e25deeb 100644
--- a/engines/supernova/supernova.h
+++ b/engines/supernova/supernova.h
@@ -23,9 +23,6 @@
#ifndef SUPERNOVA_SUPERNOVA_H
#define SUPERNOVA_SUPERNOVA_H
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-#include "audio/decoders/raw.h"
#include "common/array.h"
#include "common/events.h"
#include "common/random.h"
@@ -38,6 +35,7 @@
#include "supernova/graphics.h"
#include "supernova/msn_def.h"
#include "supernova/rooms.h"
+#include "supernova/sound.h"
namespace Supernova {
@@ -48,96 +46,55 @@ namespace Supernova {
#define SUPERNOVA_DAT "supernova.dat"
#define SUPERNOVA_DAT_VERSION 1
-
-struct ScreenBuffer {
- ScreenBuffer()
- : _x(0)
- , _y(0)
- , _width(0)
- , _height(0)
- , _pixels(NULL)
- {}
-
- byte *_pixels;
- int _x;
- int _y;
- int _width;
- int _height;
-};
-class ScreenBufferStack {
-public:
- ScreenBufferStack();
-
- void push(int x, int y, int width, int height);
- void restore();
-
-private:
- ScreenBuffer _buffer[8];
- ScreenBuffer *_last;
-};
-
-struct SoundSample {
- SoundSample()
- : _buffer(NULL)
- , _length(0)
- {}
-
- ~SoundSample() {
- delete[] _buffer;
- }
-
- byte *_buffer;
- int _length;
-};
-
class GuiElement;
+class ResourceManager;
+class Sound;
+class console;
+class GameManager;
+class Screen;
+
class SupernovaEngine : public Engine {
public:
explicit SupernovaEngine(OSystem *syst);
~SupernovaEngine();
virtual Common::Error run();
+ virtual Common::Error loadGameState(int slot);
+ virtual bool canLoadGameStateCurrently();
+ virtual Common::Error saveGameState(int slot, const Common::String &desc);
+ virtual bool canSaveGameStateCurrently();
+ virtual bool hasFeature(EngineFeature f) const;
+ virtual void pauseEngineIntern(bool pause);
- Common::RandomSource _rnd;
GameManager *_gm;
Console *_console;
- Audio::SoundHandle _soundHandle;
- ScreenBufferStack _screenBuffer;
- byte _mouseNormal[256];
- byte _mouseWait[256];
- MSNImageDecoder *_currentImage;
- SoundSample _soundSamples[kAudioNumSamples];
- Common::MemoryReadStream *_soundMusicIntro;
- Common::MemoryReadStream *_soundMusicOutro;
- int _screenWidth;
- int _screenHeight;
+ Sound *_sound;
+ ResourceManager *_resMan;
+ Screen *_screen;
bool _allowLoadGame;
bool _allowSaveGame;
Common::StringArray _gameStrings;
Common::String _nullString;
- byte _menuBrightness;
- byte _brightness;
uint _delay;
- bool _messageDisplayed;
int _textSpeed;
- int _textCursorX;
- int _textCursorY;
- int _textColor;
- int textWidth(const char *text);
- int textWidth(const uint16 key);
Common::Error loadGameStrings();
- void initData();
- void initPalette();
+ void init();
+ bool loadGame(int slot);
+ bool saveGame(int slot, const Common::String &description);
+ bool quitGameDialog();
+ void errorTempSave(bool saving);
+ void setTextSpeed();
+ const Common::String &getGameString(int idx) const;
+ void setGameString(int idx, const Common::String &string);
+
+ // forwarding calls
+ void playSound(AudioId sample);
+ void playSound(MusicId index);
void paletteFadeIn();
void paletteFadeOut();
void paletteBrightness();
- void updateEvents();
- void playSound(AudioIndex sample);
- void playSoundMod(int filenumber);
- void stopSound();
- void renderImageSection(int section);
void renderImage(int section);
bool setCurrentImage(int filenumber);
void saveScreen(int x, int y, int width, int height);
@@ -145,77 +102,22 @@ public:
void restoreScreen();
void renderRoom(Room &room);
void renderMessage(const char *text, MessagePosition position = kMessageNormal);
+ void renderMessage(const Common::String &text, MessagePosition position = kMessageNormal);
+ void renderMessage(StringId stringId, MessagePosition position = kMessageNormal,
+ Common::String var1 = "", Common::String var2 = "");
void removeMessage();
- void renderText(const char *text, int x, int y, byte color);
- void renderText(const uint16 character, int x, int y, byte color);
- void renderText(const char *text);
void renderText(const uint16 character);
+ void renderText(const char *text);
+ void renderText(const Common::String &text);
+ void renderText(StringId stringId);
+ void renderText(const uint16 character, int x, int y, byte color);
+ void renderText(const char *text, int x, int y, byte color);
+ void renderText(const Common::String &text, int x, int y, byte color);
+ void renderText(StringId stringId, int x, int y, byte color);
void renderText(const GuiElement &guiElement);
void renderBox(int x, int y, int width, int height, byte color);
void renderBox(const GuiElement &guiElement);
void setColor63(byte value);
- bool loadGame(int slot);
- bool saveGame(int slot, const Common::String &description);
- bool quitGameDialog();
- void errorTempSave(bool saving);
- void setTextSpeed();
-
- const Common::String &getGameString(int idx) const {
- if (idx < 0 || idx >= (int)_gameStrings.size())
- return _nullString;
- return _gameStrings[idx];
- }
-
- void setGameString(int idx, const Common::String &string) {
- if (idx < 0)
- return;
- while ((int)_gameStrings.size() <= idx)
- _gameStrings.push_back(Common::String());
- _gameStrings[idx] = string;
- }
-
- int textWidth(const Common::String &text) {
- if (text.empty())
- return 0;
- return textWidth(text.c_str());
- }
- void renderMessage(StringID stringId, MessagePosition position = kMessageNormal, Common::String var1 = "", Common::String var2 = "") {
- Common::String text = getGameString(stringId);
- if (!var1.empty()) {
- if (!var2.empty())
- text = Common::String::format(text.c_str(), var1.c_str(), var2.c_str());
- else
- text = Common::String::format(text.c_str(), var1.c_str());
- }
- renderMessage(text, position);
- }
- void renderMessage(const Common::String &text, MessagePosition position = kMessageNormal) {
- if (!text.empty())
- renderMessage(text.c_str(), position);
- }
- void renderText(StringID stringId, int x, int y, byte color) {
- renderText(getGameString(stringId), x, y, color);
- }
- void renderText(const Common::String &text, int x, int y, byte color) {
- if (!text.empty())
- renderText(text.c_str(), x, y, color);
- }
- void renderText(StringID stringId) {
- renderText(getGameString(stringId));
- }
- void renderText(const Common::String &text) {
- if (!text.empty())
- renderText(text.c_str());
- }
-
- Common::MemoryReadStream *convertToMod(const char *filename, int version = 1);
-
- virtual Common::Error loadGameState(int slot);
- virtual bool canLoadGameStateCurrently();
- virtual Common::Error saveGameState(int slot, const Common::String &desc);
- virtual bool canSaveGameStateCurrently();
- virtual bool hasFeature(EngineFeature f) const;
- virtual void pauseEngineIntern(bool pause);
};
}