20
edits
(→Example: Commented code better and added screenshot) |
|||
Line 39: | Line 39: | ||
==== Example ==== | ==== Example ==== | ||
Here is an example of a simple engine that uses the best color depth available to display | Here is an example of a simple engine that uses the best color depth available to display and color-cycle this gradient: [[Image:QuuxGradientRGB565.png]] | ||
<syntax type="C++"> | <syntax type="C++"> | ||
Common::Error QuuxEngine::run() { | Common::Error QuuxEngine::run() { | ||
Graphics::PixelFormat | // Obtain the best possible format from the backend. | ||
initGraphics(640, 480, true, & | Graphics::PixelFormat ourFormat = _system->getSupportedFormats().front(); | ||
// If our engine could only handle one format, we would specify it here instead of asking the backend: | |||
// // RGB555 | |||
// Graphics::PixelFormat ourFormat(2, 3, 3, 3, 8, 10, 5, 0, 0); | |||
// If our engine could handle only a few formats, this would look quite different: | |||
// Common::List<Graphics::PixelFormat> ourFormatList; | |||
// | |||
// // RGB555 | |||
// Graphics::PixelFormat ourFormat(2, 3, 3, 3, 8, 10, 5, 0, 0); | |||
// ourFormatList.push_back(ourFormat); | |||
// | |||
// // XRGB1555 | |||
// ourFormat(2, 3, 3, 3, 7, 10, 5, 0, 15); | |||
// ourFormatList.push_back(ourFormat); | |||
// | |||
// // Get the best format which is compatible between our engine and the backend | |||
// ourFormat = Graphics::findCompatibleFormat(_system->getSupportedFormats(),ourFormatList); | |||
// Attempt to initialize a 640 x 480 surface with that format | |||
initGraphics(640, 480, true, &ourFormat); | |||
// Use the format the system was able to provide | |||
// in case it cannot support that format at our requested resolution | |||
format = _system->getScreenFormat(); | format = _system->getScreenFormat(); | ||
Line 50: | Line 74: | ||
if (format.bytesPerPixel == 1) { | if (format.bytesPerPixel == 1) { | ||
// Initialize palette to simulate RGB332 | // Initialize palette to simulate RGB332 | ||
// If our engine had no 256 color mode support, we would error out here: | |||
// return Common::kUnsupportedColorMode; | |||
byte palette[1024]; | byte palette[1024]; | ||
memset(&palette,0,1024); | memset(&palette,0,1024); | ||
Line 72: | Line 100: | ||
while (!shouldQuit()) { | while (!shouldQuit()) { | ||
// Draw the actual gradient | |||
for (int16 y = 0; y < 480; y++) { | for (int16 y = 0; y < 480; y++) { | ||
uint8 *dst = offscreenBuffer + (y * 640 * format.bytesPerPixel); | uint8 *dst = offscreenBuffer + (y * 640 * format.bytesPerPixel); | ||
Line 78: | Line 107: | ||
t &= (format.bytesPerPixel << 3) - 1; | t &= (format.bytesPerPixel << 3) - 1; | ||
color = (color << t) | (color >> ((format.bytesPerPixel << 3) - t)); | color = (color << t) | (color >> ((format.bytesPerPixel << 3) - t)); | ||
// Currently we have to jump through hoops to write variable-length data in an endian-safe manner. | |||
// In a real-life implementation, it would probably be better to have an if/else-if tree or | |||
// a switch to determine the correct WRITE_UINT* function to use in the current bitdepth. | |||
// Though, something like this might end up being necessary for 24-bit pixels, anyway. | |||
#ifdef SCUMM_BIG_ENDIAN | #ifdef SCUMM_BIG_ENDIAN | ||
for (int i = 0; i < format.bytesPerPixel; i++) | for (int i = 0; i < format.bytesPerPixel; i++) | ||
Line 93: | Line 128: | ||
} | } | ||
} | } | ||
_system->copyRectToScreen(offscreenBuffer, 640 * format.bytesPerPixel, 0, 0, 640, 480); | _system->copyRectToScreen(offscreenBuffer, 640 * format.bytesPerPixel, 0, 0, 640, 480); | ||
_system->updateScreen(); | _system->updateScreen(); | ||
parseEvents(); | parseEvents(); | ||
// Wait a semi-arbitrary length in order to animate fluidly, but not insanely fast | |||
_system->delayMillis(66); | _system->delayMillis(66); | ||
t++; | t++; | ||
Line 107: | Line 139: | ||
} | } | ||
</syntax> | </syntax> | ||
And a screenshot of it in action: | |||
=== Backend initialization protocol === | === Backend initialization protocol === |
edits